@keeex/projectconfig 4.1.1

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/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ KeeeX SAS Confidential
2
+ https://keeex.me
3
+ Copyright 2013-2022 KeeeX All Rights Reserved.
4
+
5
+ These computer program listings and specifications, herein,
6
+ are and remain the property of KeeeX SAS. The intellectual
7
+ and technical concepts herein are proprietary to KeeeX SAS
8
+ and may be covered by EU and foreign patents,
9
+ patents in process, trade secrets and copyright law.
10
+
11
+ They shall not be reproduced or copied or used in whole or
12
+ in part as the basis for manufacture or sale of items unless
13
+ prior written permission is obtained from KeeeX SAS.
14
+
15
+ For a license agreement, please contact:
16
+ <mailto: contact@keeex.net>
package/README.md ADDED
@@ -0,0 +1,52 @@
1
+ Project configuration loader
2
+ ============================
3
+
4
+ Load project for a project from the following places, whichever works first:
5
+
6
+ - Command line argument, as a JSON string
7
+ - Command line argument, as a path to a JSON/JS file
8
+ - From a file at the root of the project
9
+
10
+ Additionaly, it will automatically sideload a "secrets" file, for settings that
11
+ should not remain in a shared configuration file.
12
+ The secrets file is expected to be named "secrets.js[on]" at the root of the
13
+ project.
14
+ It can be a symlink.
15
+ If no secret file is found at the root of the project, this library will try to
16
+ load it one directory above the project.
17
+
18
+ Usage
19
+ -----
20
+
21
+ ### Configuration location
22
+ The main configuration should be placed at the root of the project, in a file
23
+ named `config.js` or `config.json`.
24
+ Same for the secrets, using a file named `secrets.js` or `secrets.json`.
25
+
26
+ #### Overriding default file names
27
+ For testing purpose it can be useful to override the file names locally.
28
+ If `NODE_ENV` is set to `test`, file names will be `config-test.js[on]` and
29
+ `secrets-test.js[on]`.
30
+ Alternatively, if `KEEEX_CONFIG_SUFFIX` is set, it will be appended to the base
31
+ names (with no dash).
32
+ The `KEEEX_CONFIG_SUFFIX` option takes precedence over `NODE_ENV`.
33
+
34
+ In any case, the default names (without any suffix) will be used as fallback.
35
+
36
+ ### Command-line configuration
37
+ It is possible to load a different configuration from command line.
38
+ Passing `--config <some json>` will load that JSON instead of the config file.
39
+
40
+ One can also pass `--config <path to json file>` to load a different config from
41
+ another file.
42
+
43
+ It is not possible to specify a different secret file from command line.
44
+
45
+ ### Accessing the configuration
46
+ The loaded configuration is available as the default export of the library:
47
+
48
+ ```JavaScript
49
+ import config from "@keeex/projectconfig";
50
+
51
+ console.log(config.something);
52
+ ```
package/lib/env.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Return the config suffix from env value
3
+ */
4
+ export declare const getConfigSuffix: () => string | undefined;
5
+ /**
6
+ * Return the current NODE_ENV value (default to `production`)
7
+ */
8
+ export declare const getNodeEnv: () => string;
package/lib/env.js ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * @license
3
+ * @preserve
4
+ * KeeeX SAS Confidential
5
+ * https://keeex.me
6
+ * Copyright 2013-2022 KeeeX All Rights Reserved.
7
+ *
8
+ * These computer program listings and specifications, herein,
9
+ * are and remain the property of KeeeX SAS. The intellectual
10
+ * and technical concepts herein are proprietary to KeeeX SAS
11
+ * and may be covered by EU and foreign patents,
12
+ * patents in process, trade secrets and copyright law.
13
+ *
14
+ * They shall not be reproduced or copied or used in whole or
15
+ * in part as the basis for manufacture or sale of items unless
16
+ * prior written permission is obtained from KeeeX SAS.
17
+ *
18
+ * For a license agreement, please contact:
19
+ * <mailto: contact@keeex.net>
20
+ *
21
+ */
22
+ /* eslint-disable no-process-env */
23
+ /**
24
+ * Return the config suffix from env value
25
+ */
26
+ export const getConfigSuffix = () => process.env["KEEEX_CONFIG_SUFFIX"];
27
+ /**
28
+ * Return the current NODE_ENV value (default to `production`)
29
+ */
30
+ export const getNodeEnv = () => { var _a; return (_a = process.env["NODE_ENV"]) !== null && _a !== void 0 ? _a : "production"; };
package/lib/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import { BaseConfig } from "./types.js";
2
+ declare const _default: BaseConfig;
3
+ export default _default;
package/lib/index.js ADDED
@@ -0,0 +1,199 @@
1
+ /**
2
+ * @license
3
+ * @preserve
4
+ * KeeeX SAS Confidential
5
+ * https://keeex.me
6
+ * Copyright 2013-2022 KeeeX All Rights Reserved.
7
+ *
8
+ * These computer program listings and specifications, herein,
9
+ * are and remain the property of KeeeX SAS. The intellectual
10
+ * and technical concepts herein are proprietary to KeeeX SAS
11
+ * and may be covered by EU and foreign patents,
12
+ * patents in process, trade secrets and copyright law.
13
+ *
14
+ * They shall not be reproduced or copied or used in whole or
15
+ * in part as the basis for manufacture or sale of items unless
16
+ * prior written permission is obtained from KeeeX SAS.
17
+ *
18
+ * For a license agreement, please contact:
19
+ * <mailto: contact@keeex.net>
20
+ *
21
+ */
22
+ /**
23
+ * Load configuration from three places, whichever works first:
24
+ * - command line, as a JSON after "--config"
25
+ * - command line, as the path to a JSON file after "--config"
26
+ * - config file, "${CWD}/config.js"
27
+ *
28
+ * It will automatically append a "secrets" property to the config object read
29
+ * from "${CWD}/secrets.js[on]".
30
+ */
31
+ import { existsSync } from "fs";
32
+ import { readFile } from "fs/promises";
33
+ import { join, resolve, extname, } from "path";
34
+ import { getConfigSuffix, getNodeEnv } from "./env.js";
35
+ const defaultCliArgName = "--config";
36
+ const defaultConfigBasename = "config";
37
+ const defaultSecretsBasename = "secrets";
38
+ const acceptableExtensions = [
39
+ ".js",
40
+ ".json",
41
+ ".ts",
42
+ ];
43
+ const configSuffix = (useSuffix) => {
44
+ if (!useSuffix) {
45
+ return "";
46
+ }
47
+ const suffixFromEnv = getConfigSuffix();
48
+ if (suffixFromEnv !== undefined) {
49
+ return suffixFromEnv;
50
+ }
51
+ const nodeEnvValue = getNodeEnv();
52
+ if (nodeEnvValue === "test") {
53
+ return "-test";
54
+ }
55
+ return "";
56
+ };
57
+ /**
58
+ * Config basename with suffix
59
+ */
60
+ const configBasename = (withSuffix) => `${defaultConfigBasename}${configSuffix(withSuffix)}`;
61
+ /**
62
+ * Secrets basename with suffix
63
+ */
64
+ const secretsBasename = (withSuffix) => `${defaultSecretsBasename}${configSuffix(withSuffix)}`;
65
+ /**
66
+ * Initial directory of the app. Hopefully the project root.
67
+ */
68
+ const projectRoot = process.cwd();
69
+ /**
70
+ * Try multiple suffix for a file path, return the first one that exist.
71
+ */
72
+ const getFirstFileFound = (basepath, basename, extensions) => {
73
+ for (const extension of extensions) {
74
+ const candidate = join(basepath, `${basename}${extension}`);
75
+ if (existsSync(candidate)) {
76
+ return candidate;
77
+ }
78
+ }
79
+ };
80
+ /**
81
+ * Return path to the config file
82
+ */
83
+ const getConfigPath = () => {
84
+ const configPath = getFirstFileFound(projectRoot, configBasename(true), acceptableExtensions);
85
+ if (configPath === undefined) {
86
+ const configPathNoSuffix = getFirstFileFound(projectRoot, configBasename(false), acceptableExtensions);
87
+ if (configPathNoSuffix === undefined) {
88
+ throw new Error("No configuration file found");
89
+ }
90
+ return configPathNoSuffix;
91
+ }
92
+ return configPath;
93
+ };
94
+ /**
95
+ * Return path to the secrets file
96
+ */
97
+ const getSecretsPath = () => {
98
+ const secretsPathWithSuffix = getFirstFileFound(projectRoot, secretsBasename(true), acceptableExtensions);
99
+ if (secretsPathWithSuffix) {
100
+ return secretsPathWithSuffix;
101
+ }
102
+ const secretsPathNoSuffix = getFirstFileFound(projectRoot, secretsBasename(false), acceptableExtensions);
103
+ if (secretsPathNoSuffix) {
104
+ return secretsPathNoSuffix;
105
+ }
106
+ const secretsPathAbove = getFirstFileFound(resolve(projectRoot, ".."), secretsBasename(false), acceptableExtensions);
107
+ if (secretsPathAbove) {
108
+ return secretsPathAbove;
109
+ }
110
+ };
111
+ const loadFile = async (path) => {
112
+ const suffix = extname(path);
113
+ if ([".js", ".ts"].includes(suffix)) {
114
+ const module = await import(path);
115
+ if (module.default) {
116
+ return module.default;
117
+ }
118
+ return module;
119
+ }
120
+ if (suffix === ".json") {
121
+ return JSON.parse(await readFile(path, "utf8"));
122
+ }
123
+ throw new Error(`Unexpected suffix: ${suffix}`);
124
+ };
125
+ /**
126
+ * Return the secrets data
127
+ */
128
+ const getSecrets = async () => {
129
+ const secretsPath = getSecretsPath();
130
+ if (secretsPath === undefined) {
131
+ return;
132
+ }
133
+ return loadFile(secretsPath);
134
+ };
135
+ /**
136
+ * Return the configuration object from the command line arguments
137
+ */
138
+ const getConfigFromCLI = async () => {
139
+ const cliArgName = defaultCliArgName;
140
+ const configArgIndex = process.argv.indexOf(cliArgName);
141
+ if (configArgIndex !== -1) {
142
+ const configFromArgs = process.argv[configArgIndex + 1];
143
+ const valuesExtracted = 2;
144
+ process.argv.splice(configArgIndex, valuesExtracted);
145
+ let configObj;
146
+ try {
147
+ configObj = JSON.parse(configFromArgs);
148
+ }
149
+ catch (_error) {
150
+ configObj = JSON.parse(await readFile(configFromArgs, "utf8"));
151
+ }
152
+ return configObj;
153
+ }
154
+ return null;
155
+ };
156
+ /**
157
+ * Load the project configuration from a file
158
+ */
159
+ const getConfigFromFile = async () => {
160
+ const filePath = getConfigPath();
161
+ return loadFile(filePath);
162
+ };
163
+ /**
164
+ * Return the configuration object from the first available source
165
+ */
166
+ const getBaseProjectConfig = async () => {
167
+ const configFromCLI = await getConfigFromCLI();
168
+ if (configFromCLI !== null) {
169
+ return configFromCLI;
170
+ }
171
+ return getConfigFromFile();
172
+ };
173
+ /**
174
+ * Merge the base configuration and the secrets
175
+ */
176
+ const getProjectConfig = async () => {
177
+ const baseConfig = await getBaseProjectConfig();
178
+ const secrets = await getSecrets();
179
+ if (secrets) {
180
+ const merged = {
181
+ ...baseConfig,
182
+ secrets,
183
+ };
184
+ return merged;
185
+ }
186
+ return baseConfig;
187
+ };
188
+ /**
189
+ * Cache of the loaded configuration
190
+ */
191
+ let config = null;
192
+ /** Load the project configuration */
193
+ const loadConfig = async () => {
194
+ const activeConfig = config !== null && config !== void 0 ? config : await getProjectConfig();
195
+ if (!config)
196
+ config = activeConfig;
197
+ return config;
198
+ };
199
+ export default await loadConfig();
package/lib/types.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Base for any returned configuration
3
+ */
4
+ export declare type BaseConfig = Record<string, any>;
package/lib/types.js ADDED
@@ -0,0 +1,22 @@
1
+ /**
2
+ * @license
3
+ * @preserve
4
+ * KeeeX SAS Confidential
5
+ * https://keeex.me
6
+ * Copyright 2013-2022 KeeeX All Rights Reserved.
7
+ *
8
+ * These computer program listings and specifications, herein,
9
+ * are and remain the property of KeeeX SAS. The intellectual
10
+ * and technical concepts herein are proprietary to KeeeX SAS
11
+ * and may be covered by EU and foreign patents,
12
+ * patents in process, trade secrets and copyright law.
13
+ *
14
+ * They shall not be reproduced or copied or used in whole or
15
+ * in part as the basis for manufacture or sale of items unless
16
+ * prior written permission is obtained from KeeeX SAS.
17
+ *
18
+ * For a license agreement, please contact:
19
+ * <mailto: contact@keeex.net>
20
+ *
21
+ */
22
+ export {};
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@keeex/projectconfig",
3
+ "version": "4.1.1",
4
+ "description": "Load project configuration with separate secrets",
5
+ "main": "lib/index.js",
6
+ "scripts": {
7
+ "prepack": "npm run grunt -- clean build",
8
+ "grunt": "npm exec grunt -- --gruntfile Gruntfile.cjs",
9
+ "check": "npx eslint . && npx tsc --noEmit"
10
+ },
11
+ "type": "module",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git2@dev-machine.keeex:keeex/libraries/node/projectconfig"
15
+ },
16
+ "author": "KeeeX SAS",
17
+ "contributors": [],
18
+ "license": "SEE LICENSE IN LICENSE",
19
+ "devDependencies": {
20
+ "@keeex/eslint-config": "^1.7.5",
21
+ "@types/node": "^16.11.26",
22
+ "@typescript-eslint/eslint-plugin": "^5.19.0",
23
+ "@typescript-eslint/parser": "^5.19.0",
24
+ "eslint": "^8.13.0",
25
+ "eslint-plugin-import": "^2.26.0",
26
+ "eslint-plugin-promise": "^6.0.0",
27
+ "grunt": "^1.5.2",
28
+ "grunt-banner": "^0.6.0",
29
+ "grunt-contrib-clean": "^2.0.0",
30
+ "grunt-run": "^0.8.1",
31
+ "load-grunt-tasks": "^5.1.0",
32
+ "typescript": "^4.6.3"
33
+ },
34
+ "files": [
35
+ "lib/**/*.js",
36
+ "lib/**/*.d.ts"
37
+ ]
38
+ }