@reimorg/config 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@reimorg/config",
3
+ "version": "1.0.0",
4
+ "author": "Reimorg",
5
+ "description": "Configuration manager",
6
+ "main": "index.js",
7
+ "types": "index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./index.d.ts",
11
+ "require": "./index.js",
12
+ "default": "./index.js"
13
+ },
14
+ "./lib/get.js": "./lib/get.js",
15
+ "./lib/get.d.ts": "./lib/get.d.ts",
16
+ "./lib/raw.js": "./lib/raw.js",
17
+ "./lib/raw.d.ts": "./lib/raw.d.ts",
18
+ "./lib/util.js": "./lib/util.js",
19
+ "./lib/util.d.ts": "./lib/util.d.ts"
20
+ },
21
+ "keywords": [
22
+ "config",
23
+ "configuration",
24
+ "env",
25
+ "environment",
26
+ "environment-variables"
27
+ ],
28
+ "directories": {
29
+ "lib": "./lib"
30
+ },
31
+ "license": "MIT",
32
+ "devDependencies": {
33
+ "@types/node": "^7.0.8",
34
+ "c8": "^10.1.3",
35
+ "coffeescript": "2.2.4",
36
+ "cson": "^3.0.1",
37
+ "hjson": "^1.2.0",
38
+ "properties": "~1.2.1",
39
+ "request": "^2.88.2",
40
+ "semver": "5.3.0",
41
+ "toml": "^2.0.6",
42
+ "ts-node": "^3.3.0",
43
+ "typescript": "^2.4.2",
44
+ "underscore": "^1.8.3",
45
+ "x2js": "^2.0.1",
46
+ "yaml": "^2.8.2"
47
+ },
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "http://github.com/reimorg/config.git"
51
+ },
52
+ "engines": {
53
+ "node": ">= 20.0.0"
54
+ },
55
+ "c8": {
56
+ "include": [
57
+ "*.js",
58
+ "*.d.ts",
59
+ "lib/**/*.js",
60
+ "lib/**/*.d.ts"
61
+ ],
62
+ "report-dir": "./coverage",
63
+ "reporter": "lcov"
64
+ },
65
+ "scripts": {
66
+ "test": "NODE_OPTIONS='--no-experimental-strip-types' c8 node --test"
67
+ }
68
+ }
package/parser.d.ts ADDED
@@ -0,0 +1,134 @@
1
+ /**
2
+ * Parser function type for parsing configuration files
3
+ */
4
+ type ParserFunction = (filename: string, content: string) => any;
5
+
6
+ /**
7
+ * Parser object with methods for parsing various configuration file formats
8
+ */
9
+ declare namespace Parser {
10
+ /**
11
+ * Parse a configuration file based on its extension
12
+ * @param filename The filename (used to determine file type)
13
+ * @param content The file content to parse
14
+ * @returns Parsed configuration object
15
+ */
16
+ function parse(filename: string, content: string): any;
17
+
18
+ /**
19
+ * Parse XML configuration files
20
+ */
21
+ function xmlParser(filename: string, content: string): any;
22
+
23
+ /**
24
+ * Parse JavaScript configuration files (.js, .cjs, .mjs)
25
+ */
26
+ function jsParser(filename: string, content: string): any;
27
+
28
+ /**
29
+ * Parse TypeScript configuration files (.ts)
30
+ */
31
+ function tsParser(filename: string, content: string): any;
32
+
33
+ /**
34
+ * Parse CoffeeScript configuration files (.coffee)
35
+ */
36
+ function coffeeParser(filename: string, content: string): any;
37
+
38
+ /**
39
+ * Parse Iced CoffeeScript configuration files (.iced)
40
+ */
41
+ function icedParser(filename: string, content: string): any;
42
+
43
+ /**
44
+ * Parse YAML configuration files (.yaml, .yml)
45
+ */
46
+ function yamlParser(filename: string, content: string): any;
47
+
48
+ /**
49
+ * Parse JSON configuration files (.json, .jsonc)
50
+ */
51
+ function jsonParser(filename: string, content: string): any;
52
+
53
+ /**
54
+ * Parse JSON5 configuration files (.json5)
55
+ */
56
+ function json5Parser(filename: string, content: string): any;
57
+
58
+ /**
59
+ * Parse HJSON configuration files (.hjson)
60
+ */
61
+ function hjsonParser(filename: string, content: string): any;
62
+
63
+ /**
64
+ * Parse TOML configuration files (.toml)
65
+ */
66
+ function tomlParser(filename: string, content: string): any;
67
+
68
+ /**
69
+ * Parse CSON configuration files (.cson)
70
+ */
71
+ function csonParser(filename: string, content: string): any;
72
+
73
+ /**
74
+ * Parse Properties configuration files (.properties)
75
+ */
76
+ function propertiesParser(filename: string, content: string): any;
77
+
78
+ /**
79
+ * Strip YAML comments from the string
80
+ * @param fileStr The string to strip comments from
81
+ * @returns The string with comments stripped
82
+ */
83
+ function stripYamlComments(fileStr: string): string;
84
+
85
+ /**
86
+ * Parses the environment variable to the boolean equivalent.
87
+ * Defaults to false
88
+ * @param filename The filename (unused but required for consistency)
89
+ * @param content Environment variable value
90
+ * @returns Boolean value of the passed variable value
91
+ */
92
+ function booleanParser(filename: string, content: string): boolean;
93
+
94
+ /**
95
+ * Parses the environment variable to the number equivalent.
96
+ * Defaults to undefined
97
+ * @param filename The filename (unused but required for consistency)
98
+ * @param content Environment variable value
99
+ * @returns Number value of the passed variable value, or undefined if not a number
100
+ */
101
+ function numberParser(filename: string, content: string): number | undefined;
102
+
103
+ /**
104
+ * Get a parser function by name
105
+ * @param name The parser name (e.g., 'json', 'yaml', 'toml')
106
+ * @returns The parser function, or undefined if not found
107
+ */
108
+ function getParser(name: string): ParserFunction | undefined;
109
+
110
+ /**
111
+ * Set a custom parser function for a file extension
112
+ * @param name The file extension name (e.g., 'json', 'yaml')
113
+ * @param parser The parser function to use
114
+ */
115
+ function setParser(name: string, parser: ParserFunction): void;
116
+
117
+ /**
118
+ * Get the file order array or the index of a specific file type
119
+ * @param name Optional file type name to get index for
120
+ * @returns If name is provided, returns the index. Otherwise returns the full order array
121
+ */
122
+ function getFilesOrder(name?: string): number | string[];
123
+
124
+ /**
125
+ * Set the file order
126
+ * @param name File type name or array of file types
127
+ * @param newIndex Optional new index position (if name is a string)
128
+ * @returns The updated order array
129
+ */
130
+ function setFilesOrder(name: string | string[], newIndex?: number): string[];
131
+ }
132
+
133
+ export = Parser;
134
+
package/parser.js ADDED
@@ -0,0 +1,299 @@
1
+ // External libraries are lazy-loaded only if these file types exist.
2
+
3
+ // webpack can't solve dynamic module
4
+ // @see https://github.com/node-config/node-config/issues/755
5
+ // @see https://webpack.js.org/guides/dependency-management/#require-with-expression
6
+ const JSON5Module = require('json5');
7
+
8
+ // webpack resolves json5 with module field out of the box which lead to this usage
9
+ // @see https://github.com/node-config/node-config/issues/755
10
+ // @see https://github.com/json5/json5/issues/240
11
+ const JSON5 = JSON5Module.default || JSON5Module;
12
+
13
+ var Yaml = null,
14
+ JSYaml = null,
15
+ Coffee = null,
16
+ Iced = null,
17
+ CSON = null,
18
+ PPARSER = null,
19
+ TOML = null,
20
+ HJSON = null,
21
+ XML = null;
22
+
23
+ // Define soft dependencies so transpilers don't include everything
24
+ var COFFEE_2_DEP = 'coffeescript',
25
+ COFFEE_DEP = 'coffee-script',
26
+ ICED_DEP = 'iced-coffee-script',
27
+ JS_YAML_DEP = 'js-yaml',
28
+ YAML_DEP = 'yaml',
29
+ JSON5_DEP = 'json5',
30
+ HJSON_DEP = 'hjson',
31
+ TOML_DEP = 'toml',
32
+ CSON_DEP = 'cson',
33
+ PPARSER_DEP = 'properties',
34
+ XML_DEP = 'x2js',
35
+ TS_DEP = 'ts-node';
36
+
37
+ /**
38
+ * @typedef Parser {Object}
39
+ */
40
+ var Parser = module.exports;
41
+
42
+ Parser.parse = function(filename, content) {
43
+ var parserName = filename.substr(filename.lastIndexOf('.') +1); // file extension
44
+ if (typeof definitions[parserName] === 'function') {
45
+ return definitions[parserName](filename, content);
46
+ }
47
+ // TODO: decide what to do in case of a missing parser
48
+ };
49
+
50
+ Parser.xmlParser = function(filename, content) {
51
+ if (!XML) {
52
+ XML = require(XML_DEP);
53
+ }
54
+ var x2js = new XML();
55
+ var configObject = x2js.xml2js(content);
56
+ var rootKeys = Object.keys(configObject);
57
+ if(rootKeys.length === 1) {
58
+ return configObject[rootKeys[0]];
59
+ }
60
+ return configObject;
61
+ };
62
+
63
+ Parser.jsParser = function(filename, content) {
64
+ var configObject = require(filename);
65
+
66
+ if (configObject.__esModule && isObject(configObject.default)) {
67
+ return configObject.default
68
+ }
69
+ return configObject;
70
+ };
71
+
72
+ Parser.tsParser = function(filename, content) {
73
+ if (!require.extensions['.ts']) {
74
+ require(TS_DEP).register({
75
+ lazy: true,
76
+ ignore: ['(?:^|/)node_modules/', '.*(?<!\.ts)$'],
77
+ transpileOnly: true,
78
+ compilerOptions: {
79
+ allowJs: true,
80
+ }
81
+ });
82
+ }
83
+
84
+ // Imports config if it is exported via module.exports = ...
85
+ // See https://github.com/node-config/node-config/issues/524
86
+ var configObject = require(filename);
87
+
88
+ // Because of ES6 modules usage, `default` is treated as named export (like any other)
89
+ // Therefore config is a value of `default` key.
90
+ if (configObject.default) {
91
+ return configObject.default
92
+ }
93
+ return configObject;
94
+ };
95
+
96
+ Parser.coffeeParser = function(filename, content) {
97
+ // .coffee files can be loaded with either coffee-script or iced-coffee-script.
98
+ // Prefer iced-coffee-script, if it exists.
99
+ // Lazy load the appropriate extension
100
+ if (!Coffee) {
101
+ Coffee = {};
102
+
103
+ // The following enables iced-coffee-script on .coffee files, if iced-coffee-script is available.
104
+ // This is commented as per a decision on a pull request.
105
+ //try {
106
+ // Coffee = require('iced-coffee-script');
107
+ //}
108
+ //catch (e) {
109
+ // Coffee = require('coffee-script');
110
+ //}
111
+ try {
112
+ // Try to load coffeescript
113
+ Coffee = require(COFFEE_2_DEP);
114
+ }
115
+ catch (e) {
116
+ // If it doesn't exist, try to load it using the deprecated module name
117
+ Coffee = require(COFFEE_DEP);
118
+ }
119
+ // coffee-script >= 1.7.0 requires explicit registration for require() to work
120
+ if (Coffee.register) {
121
+ Coffee.register();
122
+ }
123
+ }
124
+ // Use the built-in parser for .coffee files with coffee-script
125
+ return require(filename);
126
+ };
127
+
128
+ Parser.icedParser = function(filename, content) {
129
+ Iced = require(ICED_DEP);
130
+
131
+ // coffee-script >= 1.7.0 requires explicit registration for require() to work
132
+ if (Iced.register) {
133
+ Iced.register();
134
+ }
135
+ };
136
+
137
+ Parser.yamlParser = function(filename, content) {
138
+ if (!Yaml && !JSYaml) {
139
+ // Lazy loading
140
+ try {
141
+ Yaml = require(YAML_DEP);
142
+ } catch (e) {
143
+ try {
144
+ JSYaml = require(JS_YAML_DEP);
145
+ } catch (e) {}
146
+ }
147
+ }
148
+
149
+ if (Yaml) {
150
+ return Yaml.parse(content);
151
+ } else if (JSYaml) {
152
+ return JSYaml.load(content);
153
+ } else {
154
+ console.error('No YAML parser loaded. Suggest adding yaml dependency to your package.json file.')
155
+ }
156
+ };
157
+
158
+ Parser.jsonParser = function(filename, content) {
159
+ /**
160
+ * Default JSON parsing to JSON5 parser.
161
+ * This is due to issues with removing supported comments.
162
+ * More information can be found here: https://github.com/node-config/node-config/issues/715
163
+ */
164
+ return JSON5.parse(content);
165
+ };
166
+
167
+ Parser.json5Parser = function(filename, content) {
168
+ return JSON5.parse(content);
169
+ };
170
+
171
+ Parser.hjsonParser = function(filename, content) {
172
+ if (!HJSON) {
173
+ HJSON = require(HJSON_DEP);
174
+ }
175
+ return HJSON.parse(content);
176
+ };
177
+
178
+ Parser.tomlParser = function(filename, content) {
179
+ if(!TOML) {
180
+ TOML = require(TOML_DEP);
181
+ }
182
+ return TOML.parse(content);
183
+ };
184
+
185
+ Parser.csonParser = function(filename, content) {
186
+ if (!CSON) {
187
+ CSON = require(CSON_DEP);
188
+ }
189
+ // Allow comments in CSON files
190
+ if (typeof CSON.parseSync === 'function') {
191
+ return CSON.parseSync(content);
192
+ }
193
+ return CSON.parse(content);
194
+ };
195
+
196
+ Parser.propertiesParser = function(filename, content) {
197
+ if (!PPARSER) {
198
+ PPARSER = require(PPARSER_DEP);
199
+ }
200
+ return PPARSER.parse(content, { namespaces: true, variables: true, sections: true });
201
+ };
202
+
203
+ /**
204
+ * Strip YAML comments from the string
205
+ *
206
+ * The 2.0 yaml parser doesn't allow comment-only or blank lines. Strip them.
207
+ *
208
+ * @protected
209
+ * @method stripYamlComments
210
+ * @param fileStr {string} The string to strip comments from
211
+ * @return {string} The string with comments stripped.
212
+ */
213
+ Parser.stripYamlComments = function(fileStr) {
214
+ // First replace removes comment-only lines
215
+ // Second replace removes blank lines
216
+ return fileStr.replace(/^\s*#.*/mg,'').replace(/^\s*[\n|\r]+/mg,'');
217
+ };
218
+
219
+ /**
220
+ * Parses the environment variable to the boolean equivalent.
221
+ * Defaults to false
222
+ *
223
+ * @param {String} content - Environment variable value
224
+ * @return {boolean} - Boolean value fo the passed variable value
225
+ */
226
+ Parser.booleanParser = function(filename, content) {
227
+ return content === 'true';
228
+ };
229
+
230
+ /**
231
+ * Parses the environment variable to the number equivalent.
232
+ * Defaults to undefined
233
+ *
234
+ * @param {String} content - Environment variable value
235
+ * @return {Number} - Number value fo the passed variable value
236
+ */
237
+ Parser.numberParser = function(filename, content) {
238
+ const numberValue = Number(content);
239
+ return Number.isNaN(numberValue) ? undefined : numberValue;
240
+ };
241
+
242
+ var order = ['js', 'cjs', 'mjs', 'ts', 'json', 'jsonc', 'json5', 'hjson', 'toml', 'coffee', 'iced', 'yaml', 'yml', 'cson', 'properties', 'xml',
243
+ 'boolean', 'number'];
244
+ var definitions = {
245
+ cjs: Parser.jsParser,
246
+ coffee: Parser.coffeeParser,
247
+ cson: Parser.csonParser,
248
+ hjson: Parser.hjsonParser,
249
+ iced: Parser.icedParser,
250
+ js: Parser.jsParser,
251
+ json: Parser.jsonParser,
252
+ jsonc: Parser.jsonParser,
253
+ json5: Parser.json5Parser,
254
+ mjs: Parser.jsParser,
255
+ properties: Parser.propertiesParser,
256
+ toml: Parser.tomlParser,
257
+ ts: Parser.tsParser,
258
+ xml: Parser.xmlParser,
259
+ yaml: Parser.yamlParser,
260
+ yml: Parser.yamlParser,
261
+ boolean: Parser.booleanParser,
262
+ number: Parser.numberParser
263
+ };
264
+
265
+ Parser.getParser = function(name) {
266
+ return definitions[name];
267
+ };
268
+
269
+ Parser.setParser = function(name, parser) {
270
+ definitions[name] = parser;
271
+ if (order.indexOf(name) === -1) {
272
+ order.push(name);
273
+ }
274
+ };
275
+
276
+ Parser.getFilesOrder = function(name) {
277
+ if (name) {
278
+ return order.indexOf(name);
279
+ }
280
+ return order;
281
+ };
282
+
283
+ Parser.setFilesOrder = function(name, newIndex) {
284
+ if (Array.isArray(name)) {
285
+ return order = name;
286
+ }
287
+ if (typeof newIndex === 'number') {
288
+ var index = order.indexOf(name);
289
+ order.splice(newIndex, 0, name);
290
+ if (index > -1) {
291
+ order.splice(index >= newIndex ? index +1 : index, 1);
292
+ }
293
+ }
294
+ return order;
295
+ };
296
+
297
+ function isObject(arg) {
298
+ return (arg !== null) && (typeof arg === 'object');
299
+ }
package/raw.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * RawConfig prototype class
3
+ * This is meant to wrap configuration objects that should be left as is,
4
+ * meaning that the object or its prototype will not be modified in any way
5
+ */
6
+ declare class RawConfig {
7
+ resolve(): any;
8
+ }
9
+
10
+ /**
11
+ * Wraps a configuration object to mark it as raw/unmodified
12
+ * @param rawObj The configuration object to wrap
13
+ * @returns A RawConfig object with a resolve method that returns the original object
14
+ */
15
+ declare function raw(rawObj: any): RawConfig;
16
+
17
+ export { raw, RawConfig };
18
+
package/raw.js ADDED
@@ -0,0 +1,15 @@
1
+ /**
2
+ * This is meant to wrap configuration objects that should be left as is,
3
+ * meaning that the object or its prototype will not be modified in any way
4
+ */
5
+ function RawConfig () {
6
+ }
7
+
8
+ function raw(rawObj) {
9
+ var obj = Object.create(RawConfig.prototype);
10
+ obj.resolve = function () { return rawObj; }
11
+ return obj;
12
+ }
13
+
14
+ module.exports.RawConfig = RawConfig;
15
+ module.exports.raw = raw;