@keeex/projectconfig 4.1.2

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