Compare commits
No commits in common. "master" and "v0.1.7" have entirely different histories.
|
@ -0,0 +1,152 @@
|
||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"es6": true,
|
||||||
|
"node": true
|
||||||
|
},
|
||||||
|
"extends": "eslint:recommended",
|
||||||
|
"globals": {
|
||||||
|
"Atomics": "readable",
|
||||||
|
"BigInt": "readable",
|
||||||
|
"BigInt64Array": "readable",
|
||||||
|
"BigUint64Array": "readable",
|
||||||
|
"queueMicrotask": "readable",
|
||||||
|
"SharedArrayBuffer": "readable",
|
||||||
|
"TextEncoder": "readable",
|
||||||
|
"TextDecoder": "readable"
|
||||||
|
},
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["*.mjs"],
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "module"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["*.cjs"],
|
||||||
|
"parserOptions": {
|
||||||
|
"sourceType": "script"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"test/{,**/}*.{mjs,cjs,js}"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"mocha": true
|
||||||
|
},
|
||||||
|
"globals": {
|
||||||
|
"register": "readable"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"max-len": "off",
|
||||||
|
"prefer-arrow-callback": "off"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parser": "babel-eslint",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": 10,
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"globalReturn": true
|
||||||
|
},
|
||||||
|
"requireConfigFile": false,
|
||||||
|
"sourceType": "script"
|
||||||
|
},
|
||||||
|
"root": true,
|
||||||
|
"rules": {
|
||||||
|
"array-bracket-spacing": ["error", "never"],
|
||||||
|
"arrow-parens": ["error", "as-needed", {
|
||||||
|
"requireForBlockBody": true
|
||||||
|
}],
|
||||||
|
"arrow-spacing": "error",
|
||||||
|
"block-spacing": ["error", "always"],
|
||||||
|
"brace-style": ["error", "1tbs"],
|
||||||
|
"camelcase": ["error", {
|
||||||
|
"properties": "never"
|
||||||
|
}],
|
||||||
|
"comma-dangle": ["error", "never"],
|
||||||
|
"consistent-return": "error",
|
||||||
|
"eol-last": ["error", "always"],
|
||||||
|
"eqeqeq": ["error", "always", {
|
||||||
|
"null": "ignore"
|
||||||
|
}],
|
||||||
|
"func-name-matching": "error",
|
||||||
|
"indent": ["off", 2, {
|
||||||
|
"ArrayExpression": "off",
|
||||||
|
"SwitchCase": 1,
|
||||||
|
"CallExpression": {
|
||||||
|
"arguments": "off"
|
||||||
|
},
|
||||||
|
"FunctionDeclaration": {
|
||||||
|
"parameters": "off"
|
||||||
|
},
|
||||||
|
"FunctionExpression": {
|
||||||
|
"parameters": "off"
|
||||||
|
},
|
||||||
|
"MemberExpression": "off",
|
||||||
|
"ObjectExpression": "off",
|
||||||
|
"ImportDeclaration": "off"
|
||||||
|
}],
|
||||||
|
"handle-callback-err": "off",
|
||||||
|
"linebreak-style": ["error", "unix"],
|
||||||
|
"max-len": ["error", {
|
||||||
|
"code": 80,
|
||||||
|
"ignorePattern": "function \\w+\\(",
|
||||||
|
"ignoreUrls": true
|
||||||
|
}],
|
||||||
|
"max-statements-per-line": ["error", {
|
||||||
|
"max": 1
|
||||||
|
}],
|
||||||
|
"new-cap": ["error", {
|
||||||
|
"newIsCap": true,
|
||||||
|
"capIsNew": false
|
||||||
|
}],
|
||||||
|
"new-parens": "error",
|
||||||
|
"no-buffer-constructor": "error",
|
||||||
|
"no-console": "off",
|
||||||
|
"no-extra-semi": "off",
|
||||||
|
"no-fallthrough": "off",
|
||||||
|
"no-func-assign": "off",
|
||||||
|
"no-implicit-coercion": "error",
|
||||||
|
"no-multi-assign": "error",
|
||||||
|
"no-multiple-empty-lines": ["error", {
|
||||||
|
"max": 1
|
||||||
|
}],
|
||||||
|
"no-nested-ternary": "error",
|
||||||
|
"no-param-reassign": "off",
|
||||||
|
"no-return-assign": "error",
|
||||||
|
"no-return-await": "off",
|
||||||
|
"no-shadow-restricted-names": "error",
|
||||||
|
"no-tabs": "error",
|
||||||
|
"no-trailing-spaces": "error",
|
||||||
|
"no-unused-vars": ["error", {
|
||||||
|
"vars": "all",
|
||||||
|
"args": "none",
|
||||||
|
"ignoreRestSiblings": false
|
||||||
|
}],
|
||||||
|
"no-use-before-define": ["error", {
|
||||||
|
"functions": false,
|
||||||
|
"classes": false
|
||||||
|
}],
|
||||||
|
"no-useless-escape": "off",
|
||||||
|
"no-var": "error",
|
||||||
|
"nonblock-statement-body-position": ["error", "below"],
|
||||||
|
"padded-blocks": ["error", "never"],
|
||||||
|
"prefer-arrow-callback": "error",
|
||||||
|
"prefer-const": ["error", {
|
||||||
|
"destructuring": "all",
|
||||||
|
"ignoreReadBeforeAssign": true
|
||||||
|
}],
|
||||||
|
"prefer-template": "off",
|
||||||
|
"quotes": ["error", "single"],
|
||||||
|
"semi": ["error", "always"],
|
||||||
|
"spaced-comment": ["error", "always", {
|
||||||
|
"exceptions": ["!"]
|
||||||
|
}],
|
||||||
|
"space-before-blocks": "error",
|
||||||
|
"strict": "error",
|
||||||
|
"unicode-bom": ["error", "never"],
|
||||||
|
"valid-jsdoc": "error",
|
||||||
|
"wrap-iife": ["error", "inside"]
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,13 +0,0 @@
|
||||||
name: Build/Publish
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
- develop
|
|
||||||
- develop-*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
main:
|
|
||||||
uses: lumeweb/github-node-deploy-workflow/.github/workflows/main.yml@master
|
|
||||||
secrets: inherit
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
build/
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
|
@ -0,0 +1,17 @@
|
||||||
|
.babel*
|
||||||
|
.bmocharc*
|
||||||
|
.bpkgignore
|
||||||
|
.editorconfig
|
||||||
|
.eslint*
|
||||||
|
.git*
|
||||||
|
.mocharc*
|
||||||
|
.yarnignore
|
||||||
|
bench/
|
||||||
|
build/
|
||||||
|
docs/
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log
|
||||||
|
package-lock.json
|
||||||
|
test/
|
||||||
|
webpack.*.js
|
||||||
|
yarn.lock
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"preset": [
|
|
||||||
"presetter-preset-hybrid",
|
|
||||||
"@lumeweb/node-library-preset"
|
|
||||||
]
|
|
||||||
}
|
|
35
CHANGELOG.md
35
CHANGELOG.md
|
@ -1,35 +0,0 @@
|
||||||
## [0.1.15](https://git.lumeweb.com/LumeWeb/relay-cfg/compare/v0.1.14...v0.1.15) (2023-07-07)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* need to use set, not objectPath directly ([82f603c](https://git.lumeweb.com/LumeWeb/relay-cfg/commit/82f603c00a44f6bf82da8b26acb4e37ad2df33ae))
|
|
||||||
|
|
||||||
## [0.1.14](https://git.lumeweb.com/LumeWeb/relay-cfg/compare/v0.1.13...v0.1.14) (2023-07-07)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* use regex ([4475f12](https://git.lumeweb.com/LumeWeb/relay-cfg/commit/4475f122f12ccd7ecbaf055eb8ffc2596d4c71aa))
|
|
||||||
|
|
||||||
## [0.1.13](https://git.lumeweb.com/LumeWeb/relay-cfg/compare/v0.1.12...v0.1.13) (2023-07-07)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* bad for loop ([ecb2990](https://git.lumeweb.com/LumeWeb/relay-cfg/commit/ecb29905726324165548f06ac505d0edfa3c4028))
|
|
||||||
|
|
||||||
## [0.1.12](https://git.lumeweb.com/LumeWeb/relay-cfg/compare/v0.1.11...v0.1.12) (2023-07-07)
|
|
||||||
|
|
||||||
## [0.1.11](https://git.lumeweb.com/LumeWeb/relay-cfg/compare/v0.1.10...v0.1.11) (2023-07-07)
|
|
||||||
|
|
||||||
## [0.1.10](https://git.lumeweb.com/LumeWeb/relay-cfg/compare/v0.1.9...v0.1.10) (2023-07-07)
|
|
||||||
|
|
||||||
## [0.1.9](https://git.lumeweb.com/LumeWeb/relay-cfg/compare/v0.1.8...v0.1.9) (2023-07-04)
|
|
||||||
|
|
||||||
## [0.1.8](https://git.lumeweb.com/LumeWeb/relay-cfg/compare/v0.1.7...v0.1.8) (2023-07-04)
|
|
||||||
|
|
||||||
|
|
||||||
### Bug Fixes
|
|
||||||
|
|
||||||
* fix or disable errors in eslint ([1b5a7c0](https://git.lumeweb.com/LumeWeb/relay-cfg/commit/1b5a7c0605e2dcda3f379c0b61baccf0a3dfc257))
|
|
2
LICENSE
2
LICENSE
|
@ -1,6 +1,6 @@
|
||||||
This software is licensed under the MIT License.
|
This software is licensed under the MIT License.
|
||||||
|
|
||||||
Copyright (c) 2017, Christopher Jeffrey (https://github.com/chjj), 2022 Hammer Technologies LLC
|
Copyright (c) 2017, Christopher Jeffrey (https://github.com/chjj)
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|
56
README.md
56
README.md
|
@ -1 +1,55 @@
|
||||||
# relay-cfg
|
# bcfg
|
||||||
|
|
||||||
|
Config parser (used for bcoin).
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
``` js
|
||||||
|
const Config = require('bcfg');
|
||||||
|
|
||||||
|
// Will consider ~/.my-module the prefix directory.
|
||||||
|
const config = new Config('my-module', {
|
||||||
|
alias: {
|
||||||
|
'n': 'network'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inject some custom options first.
|
||||||
|
config.inject({
|
||||||
|
some: 'user',
|
||||||
|
options: 'here'
|
||||||
|
});
|
||||||
|
|
||||||
|
config.load({
|
||||||
|
// Parse URL hash
|
||||||
|
hash: true,
|
||||||
|
// Parse querystring
|
||||||
|
query: true,
|
||||||
|
// Parse environment
|
||||||
|
env: true,
|
||||||
|
// Parse args
|
||||||
|
argv: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Will parse ~/.my-module/my-config.conf (throws on FS error).
|
||||||
|
config.open('my-config.conf');
|
||||||
|
|
||||||
|
// These will cast types and throw on incorrect type.
|
||||||
|
console.log(config.str('username'));
|
||||||
|
console.log(config.str('password'));
|
||||||
|
console.log(config.uint('userid'));
|
||||||
|
console.log(config.float('percent'));
|
||||||
|
console.log(config.bool('initialize'));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contribution and License Agreement
|
||||||
|
|
||||||
|
If you contribute code to this project, you are implicitly allowing your code
|
||||||
|
to be distributed under the MIT license. You are also implicitly verifying that
|
||||||
|
all code is your original work. `</legalese>`
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
- Copyright (c) 2017, Christopher Jeffrey (MIT License).
|
||||||
|
|
||||||
|
See LICENSE for more info.
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
/*!
|
||||||
|
* bcfg.js - configuration parsing for bcoin
|
||||||
|
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
||||||
|
* https://github.com/bcoin-org/bcoin
|
||||||
|
*/
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
module.exports = require('./config');
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,3 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
exports.unsupported = true;
|
File diff suppressed because it is too large
Load Diff
60
package.json
60
package.json
|
@ -1,47 +1,33 @@
|
||||||
{
|
{
|
||||||
"name": "@lumeweb/relay-cfg",
|
"name": "bcfg",
|
||||||
"version": "0.1.15",
|
"version": "0.1.7",
|
||||||
"main": "lib/index.js",
|
"description": "Config parser for bcoin",
|
||||||
"license": "MIT",
|
"keywords": [
|
||||||
"type": "module",
|
"conf",
|
||||||
"types": "lib/index.d.ts",
|
"config"
|
||||||
"module": "lib/index.mjs",
|
|
||||||
"exports": {
|
|
||||||
".": {
|
|
||||||
"require": "./lib/index.js",
|
|
||||||
"import": "./lib/index.mjs"
|
|
||||||
},
|
|
||||||
"./package.json": "./package.json"
|
|
||||||
},
|
|
||||||
"authors": [
|
|
||||||
"Christopher Jeffrey <chjjeffrey@gmail.com>",
|
|
||||||
"Hammer Technologies LLC <contact@lumeweb.com>"
|
|
||||||
],
|
],
|
||||||
"repository": {
|
"license": "MIT",
|
||||||
"type": "git",
|
"repository": "git://github.com/bcoin-org/bcfg.git",
|
||||||
"url": "gitea@git.lumeweb.com:LumeWeb/relay-cfg.git"
|
"homepage": "https://github.com/bcoin-org/bcfg",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/bcoin-org/bcfg/issues"
|
||||||
},
|
},
|
||||||
|
"author": "Christopher Jeffrey <chjjeffrey@gmail.com>",
|
||||||
|
"main": "./lib/bcfg.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "presetter bootstrap",
|
"lint": "eslint lib/ || exit 0",
|
||||||
"build": "run build",
|
"test": "bmocha --reporter spec test/*-test.js"
|
||||||
"semantic-release": "semantic-release"
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bsert": "~0.0.10"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lumeweb/node-library-preset": "^0.2.7",
|
"bmocha": "^2.1.0"
|
||||||
"presetter": "*",
|
|
||||||
"presetter-preset-hybrid": "^4.0.1"
|
|
||||||
},
|
},
|
||||||
"readme": "ERROR: No README data found!",
|
"engines": {
|
||||||
"dependencies": {
|
"node": ">=8.0.0"
|
||||||
"arg": "^5.0.2",
|
|
||||||
"bsert": "^0.0.12",
|
|
||||||
"deep-to-flat-object": "^1.0.1",
|
|
||||||
"object-path": "^0.11.8"
|
|
||||||
},
|
},
|
||||||
"files": [
|
"browser": {
|
||||||
"lib"
|
"./lib/fs": "./lib/fs-browser.js"
|
||||||
],
|
|
||||||
"publishConfig": {
|
|
||||||
"access": "public"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
591
src/index.ts
591
src/index.ts
|
@ -1,591 +0,0 @@
|
||||||
/* eslint-disable eslint-comments/disable-enable-pair */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
||||||
/* eslint-disable @typescript-eslint/restrict-template-expressions */
|
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
|
||||||
/* eslint-disable sonarjs/no-duplicate-string */
|
|
||||||
/* eslint-disable no-param-reassign */
|
|
||||||
/* eslint-disable @typescript-eslint/member-ordering */
|
|
||||||
/* eslint-disable sonarjs/cognitive-complexity */
|
|
||||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
||||||
/* eslint-disable jsdoc/require-jsdoc */
|
|
||||||
/* !
|
|
||||||
* config.js - configuration parsing for bcoin
|
|
||||||
* Copyright (c) 2016-2017, Christopher Jeffrey (MIT License).
|
|
||||||
* https://github.com/bcoin-org/bcoin
|
|
||||||
*/
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
import fs from "fs";
|
|
||||||
import Path from "path";
|
|
||||||
|
|
||||||
import arg from "arg";
|
|
||||||
import assert from "bsert";
|
|
||||||
import deepToFlatObject from "deep-to-flat-object";
|
|
||||||
import objectPath from "object-path";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Config Parser
|
|
||||||
*/
|
|
||||||
|
|
||||||
export class Config {
|
|
||||||
private module: string;
|
|
||||||
private data = {};
|
|
||||||
private configProperty;
|
|
||||||
|
|
||||||
constructor(module: string, configProperty: string) {
|
|
||||||
assert(typeof module === "string");
|
|
||||||
assert(module.length > 0);
|
|
||||||
|
|
||||||
this.module = module;
|
|
||||||
this.configProperty = configProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public inject(options: object) {
|
|
||||||
for (const key of Object.keys(options)) {
|
|
||||||
const value = options[key];
|
|
||||||
|
|
||||||
// eslint-disable-next-line default-case
|
|
||||||
switch (key) {
|
|
||||||
case "env":
|
|
||||||
case "argv":
|
|
||||||
case "config":
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.set(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public load() {
|
|
||||||
const args = arg({}, { permissive: true });
|
|
||||||
|
|
||||||
this.parseArg(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
public openDir(dir: string) {
|
|
||||||
assert(fs.existsSync(dir), `Directory ${dir} does not exist`);
|
|
||||||
|
|
||||||
let files = fs
|
|
||||||
.readdirSync(dir)
|
|
||||||
.filter((item) => item.endsWith(".json"))
|
|
||||||
.map((item) => Path.join(dir, item));
|
|
||||||
files.forEach(this.open.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
public open(file: string) {
|
|
||||||
let json;
|
|
||||||
try {
|
|
||||||
json = fs.readFileSync(file, "utf8");
|
|
||||||
json = JSON.parse(json);
|
|
||||||
} catch (e) {
|
|
||||||
if (e.code === "ENOENT") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new Error(`Error parsing file ${file}: ${e.message}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(typeof json === "object", `Config file ${file} must be an object`);
|
|
||||||
|
|
||||||
const settings = deepToFlatObject(json);
|
|
||||||
|
|
||||||
for (const key of Object.keys(settings)) {
|
|
||||||
const value = settings[key];
|
|
||||||
this.set(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public save(file: string, data: object): void {
|
|
||||||
assert(typeof data === "object");
|
|
||||||
assert(!Array.isArray(data));
|
|
||||||
|
|
||||||
const configDir = this.str(this.configProperty) as string;
|
|
||||||
const fullPath = Path.join(configDir, `${file}.json`);
|
|
||||||
|
|
||||||
if (!fs.existsSync(configDir)) {
|
|
||||||
fs.mkdirSync(configDir, { recursive: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(fullPath, JSON.stringify(data));
|
|
||||||
this.open(fullPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public savePath(file: string, path: string): void {
|
|
||||||
this.save(file, this.get(path));
|
|
||||||
}
|
|
||||||
|
|
||||||
public set(key: string, value: any) {
|
|
||||||
assert(typeof key === "string", "Key must be a string.");
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = this.normalize(key);
|
|
||||||
|
|
||||||
objectPath.set(this.data, key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public has(key: string) {
|
|
||||||
assert(typeof key === "string", "Key must be a string.");
|
|
||||||
|
|
||||||
key = key.replace(/-/g, "");
|
|
||||||
key = key.toLowerCase();
|
|
||||||
|
|
||||||
return objectPath.has(this.data, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private normalize(key: string, env = false): string {
|
|
||||||
assert(typeof key === "string", "Key must be a string.");
|
|
||||||
|
|
||||||
if (env) {
|
|
||||||
key = key.replace(/__/g, ".");
|
|
||||||
key = key.replace(/_/g, "");
|
|
||||||
} else {
|
|
||||||
key = key.replace(/-/g, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
key = key.toLowerCase();
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public get(key: string, fallback = null) {
|
|
||||||
if (Array.isArray(key)) {
|
|
||||||
const keys = key;
|
|
||||||
for (const key of keys) {
|
|
||||||
const value = this.get(key);
|
|
||||||
if (value !== null) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(typeof key === "string", "Key must be a string.");
|
|
||||||
|
|
||||||
key = this.normalize(key);
|
|
||||||
|
|
||||||
return objectPath.get(this.data, key, fallback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public typeOf(key: string) {
|
|
||||||
const value = this.get(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return "null";
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeof value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public str(key: string, fallback = null) {
|
|
||||||
const value = this.get(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value !== "string") {
|
|
||||||
throw new Error(`${fmt(key)} must be a string.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int(key, fallback = null) {
|
|
||||||
const value = this.get(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value !== "string") {
|
|
||||||
if (typeof value !== "number") {
|
|
||||||
throw new Error(`${fmt(key)} must be an int.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Number.isSafeInteger(value)) {
|
|
||||||
throw new Error(`${fmt(key)} must be an int.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/^-?\d+$/.test(value)) {
|
|
||||||
throw new Error(`${fmt(key)} must be an int.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const num = parseInt(value, 10);
|
|
||||||
|
|
||||||
if (!Number.isSafeInteger(num)) {
|
|
||||||
throw new Error(`${fmt(key)} must be an int.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
public uint(key, fallback = null) {
|
|
||||||
const value = this.int(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value < 0) {
|
|
||||||
throw new Error(`${fmt(key)} must be a uint.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public float(key, fallback = null) {
|
|
||||||
const value = this.get(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value !== "string") {
|
|
||||||
if (typeof value !== "number") {
|
|
||||||
throw new Error(`${fmt(key)} must be a float.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isFinite(value)) {
|
|
||||||
throw new Error(`${fmt(key)} must be a float.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/^-?\d*(?:\.\d*)?$/.test(value)) {
|
|
||||||
throw new Error(`${fmt(key)} must be a float.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!/\d/.test(value)) {
|
|
||||||
throw new Error(`${fmt(key)} must be a float.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const num = parseFloat(value);
|
|
||||||
|
|
||||||
if (!isFinite(num)) {
|
|
||||||
throw new Error(`${fmt(key)} must be a float.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return num;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ufloat(key, fallback = null) {
|
|
||||||
const value = this.float(key);
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value < 0) {
|
|
||||||
throw new Error(`${fmt(key)} must be a positive float.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public fixed(key, exp, fallback = null) {
|
|
||||||
const value = this.float(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
return fromFloat(value, exp || 0);
|
|
||||||
} catch (e) {
|
|
||||||
throw new Error(`${fmt(key)} must be a fixed number.`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ufixed(key, exp, fallback = null) {
|
|
||||||
const value = this.fixed(key, exp);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value < 0) {
|
|
||||||
throw new Error(`${fmt(key)} must be a positive fixed number.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool(key, fallback = null) {
|
|
||||||
const value = this.get(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bitcoin Core compat.
|
|
||||||
if (typeof value === "number") {
|
|
||||||
if (value === 1) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value === 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value !== "string") {
|
|
||||||
if (typeof value !== "boolean") {
|
|
||||||
throw new Error(`${fmt(key)} must be a boolean.`);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value === "true" || value === "1") {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value === "false" || value === "0") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(`${fmt(key)} must be a boolean.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
public buf(key: string, fallback = null, enc: BufferEncoding = "hex") {
|
|
||||||
const value = this.get(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value !== "string") {
|
|
||||||
if (!Buffer.isBuffer(value)) {
|
|
||||||
throw new Error(`${fmt(key)} must be a buffer.`);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const data = Buffer.from(value, enc);
|
|
||||||
|
|
||||||
if (data.length !== Buffer.byteLength(value, enc)) {
|
|
||||||
throw new Error(`${fmt(key)} must be a ${enc} string.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public array(key: string, fallback = null) {
|
|
||||||
const value = this.get(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value !== "string") {
|
|
||||||
if (!Array.isArray(value)) {
|
|
||||||
throw new Error(`${fmt(key)} must be an array.`);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parts = value.trim().split(/\s*,\s*/);
|
|
||||||
const result: string[] = [];
|
|
||||||
for (const part of parts) {
|
|
||||||
if (part.length === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.push(part);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public obj(key: string, fallback = null) {
|
|
||||||
const value = this.get(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value !== "object" || Array.isArray(value)) {
|
|
||||||
throw new Error(`${fmt(key)} must be an object.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public func(key: string, fallback = null) {
|
|
||||||
const value = this.get(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof value !== "function") {
|
|
||||||
throw new Error(`${fmt(key)} must be a function.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public mb(key: string, fallback = null) {
|
|
||||||
const value = this.uint(key);
|
|
||||||
|
|
||||||
if (value === null) {
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-magic-numbers
|
|
||||||
return value * 1024 * 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
public parseArg(args: arg.Result<any>) {
|
|
||||||
const argPairs = args._.reduce((prev: any, item: any) => {
|
|
||||||
const parts = item.split("=");
|
|
||||||
const key = parts[0].replace(/-/g, "");
|
|
||||||
prev[key] = parts[1];
|
|
||||||
|
|
||||||
return prev;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-for-in-array
|
|
||||||
for (const key in argPairs) {
|
|
||||||
this.set(key, argPairs[key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public parseEnv(env?: object) {
|
|
||||||
let prefix = this.module;
|
|
||||||
|
|
||||||
prefix = prefix.toUpperCase();
|
|
||||||
prefix = prefix.replace(/-/g, "_");
|
|
||||||
prefix += "_";
|
|
||||||
|
|
||||||
if (!env || typeof env !== "object") {
|
|
||||||
env = process.env;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(typeof env === "object");
|
|
||||||
|
|
||||||
for (let key of Object.keys(env)) {
|
|
||||||
const value = env[key];
|
|
||||||
|
|
||||||
assert(typeof value === "string");
|
|
||||||
|
|
||||||
if (key.indexOf(prefix) !== 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isUpperKey(key)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
key = key.substring(prefix.length);
|
|
||||||
key = this.normalize(key, true);
|
|
||||||
|
|
||||||
if (value.length === 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
objectPath.set(this.data, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Helpers
|
|
||||||
*/
|
|
||||||
|
|
||||||
function fmt(key: string[] | string | number) {
|
|
||||||
if (Array.isArray(key)) {
|
|
||||||
key = key[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof key === "number") {
|
|
||||||
return `Argument #${key}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isAlpha(str: string) {
|
|
||||||
return /^[a-z0-9_-]+$/i.test(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isKey(key: string) {
|
|
||||||
return /^[a-zA-Z0-9]+$/.test(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function isUpperKey(key: string) {
|
|
||||||
if (!isKey(key)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !/[a-z]/.test(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
function fromFloat(num: number, exp: number) {
|
|
||||||
assert(typeof num === "number" && isFinite(num));
|
|
||||||
assert(Number.isSafeInteger(exp));
|
|
||||||
|
|
||||||
let str = num.toFixed(exp);
|
|
||||||
let sign = 1;
|
|
||||||
|
|
||||||
if (str.length > 0 && str[0] === "-") {
|
|
||||||
str = str.substring(1);
|
|
||||||
sign = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
let hi: number | string = str;
|
|
||||||
let lo: number | string = "0";
|
|
||||||
|
|
||||||
const index = str.indexOf(".");
|
|
||||||
|
|
||||||
if (index !== -1) {
|
|
||||||
hi = str.substring(0, index);
|
|
||||||
lo = str.substring(index + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
hi = hi.replace(/^0+/, "");
|
|
||||||
lo = lo.replace(/0+$/, "");
|
|
||||||
|
|
||||||
assert(hi.length <= 16 - exp, "Fixed number string exceeds 2^53-1.");
|
|
||||||
|
|
||||||
assert(lo.length <= exp, "Too many decimal places in fixed number string.");
|
|
||||||
|
|
||||||
if (hi.length === 0) {
|
|
||||||
hi = "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
while (lo.length < exp) {
|
|
||||||
lo += "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lo.length === 0) {
|
|
||||||
lo = "0";
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(
|
|
||||||
/^\d+$/.test(hi) && /^\d+$/.test(lo),
|
|
||||||
"Non-numeric characters in fixed number string.",
|
|
||||||
);
|
|
||||||
|
|
||||||
hi = parseInt(hi, 10);
|
|
||||||
lo = parseInt(lo, 10);
|
|
||||||
|
|
||||||
const mult = Math.pow(10, exp);
|
|
||||||
const maxLo = Number.MAX_SAFE_INTEGER % mult;
|
|
||||||
const maxHi = (Number.MAX_SAFE_INTEGER - maxLo) / mult;
|
|
||||||
|
|
||||||
assert(
|
|
||||||
hi < maxHi || (hi === maxHi && lo <= maxLo),
|
|
||||||
"Fixed number string exceeds 2^53-1.",
|
|
||||||
);
|
|
||||||
|
|
||||||
return sign * (hi * mult + lo);
|
|
||||||
}
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const assert = require('bsert');
|
||||||
|
const Config = require('../lib/config');
|
||||||
|
|
||||||
|
describe('bcfg', function() {
|
||||||
|
it('should filter options', () => {
|
||||||
|
const options = {
|
||||||
|
testString: 'hello',
|
||||||
|
childTestString: 'goodbye'
|
||||||
|
};
|
||||||
|
|
||||||
|
const parent = new Config('bcfg');
|
||||||
|
parent.inject(options);
|
||||||
|
parent.load(options);
|
||||||
|
|
||||||
|
assert.strictEqual(parent.str('test-string'), 'hello');
|
||||||
|
|
||||||
|
const child = parent.filter('child');
|
||||||
|
|
||||||
|
assert.strictEqual(child.str('test-string'), 'goodbye');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should filter argv', () => {
|
||||||
|
const parent = new Config('bcfg');
|
||||||
|
|
||||||
|
// process.argv
|
||||||
|
parent.parseArg([
|
||||||
|
'node',
|
||||||
|
'bcfg',
|
||||||
|
'--test-string=hello',
|
||||||
|
'--child-test-string=goodbye'
|
||||||
|
]);
|
||||||
|
|
||||||
|
assert.strictEqual(parent.str('test-string'), 'hello');
|
||||||
|
|
||||||
|
const child = parent.filter('child');
|
||||||
|
|
||||||
|
assert.strictEqual(child.str('test-string'), 'goodbye');
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue