@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 +21 -0
- package/README.md +54 -0
- package/lib/env.d.ts +35 -0
- package/lib/env.js +35 -0
- package/lib/index.d.ts +30 -0
- package/lib/index.js +209 -0
- package/lib/types.d.ts +31 -0
- package/lib/types.js +28 -0
- package/package.json +1 -0
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"}
|