@yongdall/load-configuration 0.6.2 → 0.6.4
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/index.d.mts +11 -34
- package/index.mjs +45 -91
- package/index.mjs.map +1 -1
- package/package.json +1 -1
package/index.d.mts
CHANGED
|
@@ -1,36 +1,13 @@
|
|
|
1
1
|
//#region cli/load-configuration/index.d.mts
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
declare function
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
* @param {'script' | 'data'} [type]
|
|
13
|
-
* @returns {Promise<T | null>}
|
|
14
|
-
*/
|
|
15
|
-
declare function loadConfiguration<T extends object>(path: string, type?: "script" | "data"): Promise<T | null>;
|
|
16
|
-
/**
|
|
17
|
-
* @template {object} T
|
|
18
|
-
* @overload
|
|
19
|
-
* @param {string} root
|
|
20
|
-
* @param {string | string[]} name
|
|
21
|
-
* @param {'script' | 'data'} [type]
|
|
22
|
-
* @returns {AsyncIterableIterator<[config: T, path: string]>}
|
|
23
|
-
*/
|
|
24
|
-
declare function loadProfiles<T extends object>(root: string, name: string | string[], type?: "script" | "data" | undefined): AsyncIterableIterator<[config: T, path: string]>;
|
|
25
|
-
/**
|
|
26
|
-
* @template {object} T
|
|
27
|
-
* @overload
|
|
28
|
-
* @param {string} root
|
|
29
|
-
* @param {string | string[]} name
|
|
30
|
-
* @param {(config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>} preprocess
|
|
31
|
-
* @param {'script' | 'data'} [type]
|
|
32
|
-
* @returns {AsyncIterableIterator<T>}
|
|
33
|
-
*/
|
|
34
|
-
declare function loadProfiles<T extends object>(root: string, name: string | string[], preprocess: (config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>, type?: "script" | "data" | undefined): AsyncIterableIterator<T>;
|
|
2
|
+
declare function loadConfigurationWithPath<T extends object>(path: string, type?: 'script' | 'data'): Promise<[string, T | null] | null>;
|
|
3
|
+
declare function loadConfiguration<T extends object>(path: string, type?: 'script' | 'data'): Promise<T | null>;
|
|
4
|
+
interface ProfileFinder<T extends object = object> {
|
|
5
|
+
find?(data: T): Iterable<string> | AsyncIterable<string> | PromiseLike<Iterable<string> | AsyncIterable<string>>;
|
|
6
|
+
type?: 'script' | 'data';
|
|
7
|
+
}
|
|
8
|
+
declare function findProfiles(root: string, finders: Record<string, ProfileFinder>): AsyncGenerator<[path: string, ext?: string]>;
|
|
9
|
+
declare function loadProfiles<T extends object>(root: string | string[], name: string | string[], type?: 'script' | 'data'): AsyncIterableIterator<[config: T, path: string]>;
|
|
10
|
+
declare function loadProfiles<T extends object>(root: string | string[], name: string | string[], preprocess?: (config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>, type?: 'script' | 'data'): AsyncIterableIterator<T>;
|
|
11
|
+
declare function loadProfiles<T extends object>(root: string | string[], name: string | string[], preprocess?: ((config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>) | 'script' | 'data', type?: 'script' | 'data'): AsyncIterableIterator<[config: T, path: string] | T>;
|
|
35
12
|
//#endregion
|
|
36
|
-
export { loadConfiguration as default, loadConfigurationWithPath, loadProfiles };
|
|
13
|
+
export { ProfileFinder, loadConfiguration as default, findProfiles, loadConfigurationWithPath, loadProfiles };
|
package/index.mjs
CHANGED
|
@@ -3,47 +3,23 @@ import * as pathFn from "node:path";
|
|
|
3
3
|
import * as yaml from "yaml";
|
|
4
4
|
import * as toml from "smol-toml";
|
|
5
5
|
|
|
6
|
-
//#region cli/load-configuration/index.
|
|
7
|
-
/**
|
|
8
|
-
*
|
|
9
|
-
* @template T
|
|
10
|
-
* @param {string} path
|
|
11
|
-
* @returns {Promise<T>}
|
|
12
|
-
*/
|
|
6
|
+
//#region cli/load-configuration/index.mts
|
|
13
7
|
async function loadToml(path) {
|
|
14
8
|
return toml.parse(await fsPromises.readFile(path, "utf-8"));
|
|
15
9
|
}
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* @template T
|
|
19
|
-
* @param {string} path
|
|
20
|
-
* @returns {Promise<T>}
|
|
21
|
-
*/
|
|
22
10
|
async function loadYaml(path) {
|
|
23
11
|
return yaml.parse(await fsPromises.readFile(path, "utf-8"));
|
|
24
12
|
}
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
* @template T
|
|
28
|
-
* @param {string} path
|
|
29
|
-
* @returns {Promise<T>}
|
|
30
|
-
*/
|
|
31
13
|
async function loadJson(path) {
|
|
32
14
|
return JSON.parse(await fsPromises.readFile(path, "utf-8"));
|
|
33
15
|
}
|
|
34
|
-
/**
|
|
35
|
-
*
|
|
36
|
-
* @template T
|
|
37
|
-
* @param {string} path
|
|
38
|
-
* @returns {Promise<T>}
|
|
39
|
-
*/
|
|
40
16
|
function loadMjs(path) {
|
|
41
17
|
return import(path).then((v) => {
|
|
42
|
-
|
|
18
|
+
const keys = Object.keys(v);
|
|
19
|
+
if (keys.length === 1 && keys[0] === "default") return v.default;
|
|
43
20
|
return v;
|
|
44
21
|
});
|
|
45
22
|
}
|
|
46
|
-
/** @type {[string, <T>(path: string) => Promise<T | null>, script?: boolean][]} */
|
|
47
23
|
const loaders = [
|
|
48
24
|
[
|
|
49
25
|
".mjs",
|
|
@@ -63,12 +39,6 @@ const loaders = [
|
|
|
63
39
|
const scriptExts = new Set(loaders.filter((v) => v[2]).map((v) => v[0]));
|
|
64
40
|
const dataExts = new Set(loaders.filter((v) => !v[2]).map((v) => v[0]));
|
|
65
41
|
const allExts = new Set(loaders.map((v) => v[0]));
|
|
66
|
-
/**
|
|
67
|
-
* @template {object} T
|
|
68
|
-
* @param {string} path
|
|
69
|
-
* @param {'script' | 'data'} [type]
|
|
70
|
-
* @returns {Promise<[path: string, loader: <T>(path: string) => Promise<T | null>] | null>}
|
|
71
|
-
*/
|
|
72
42
|
async function find(path, type) {
|
|
73
43
|
const exts = type === "script" ? scriptExts : type === "data" ? dataExts : allExts;
|
|
74
44
|
const ext = (await fsPromises.stat(path).catch(() => null))?.isFile() ? pathFn.extname(path).toLowerCase() : "";
|
|
@@ -82,47 +52,64 @@ async function find(path, type) {
|
|
|
82
52
|
}
|
|
83
53
|
return null;
|
|
84
54
|
}
|
|
85
|
-
/**
|
|
86
|
-
* @template {object} T
|
|
87
|
-
* @param {string} path
|
|
88
|
-
* @param {'script' | 'data'} [type]
|
|
89
|
-
* @returns {Promise<[string, T | null] | null>}
|
|
90
|
-
*/
|
|
91
55
|
async function loadConfigurationWithPath(path, type) {
|
|
92
56
|
const result = await find(path, type);
|
|
93
57
|
if (!result) return null;
|
|
94
58
|
const [filepath, loader] = result;
|
|
95
59
|
return Promise.all([fsPromises.realpath(filepath), loader(filepath).then((v) => typeof v === "object" ? v : null)]);
|
|
96
60
|
}
|
|
97
|
-
/**
|
|
98
|
-
* @template {object} T
|
|
99
|
-
* @param {string} path
|
|
100
|
-
* @param {'script' | 'data'} [type]
|
|
101
|
-
* @returns {Promise<T | null>}
|
|
102
|
-
*/
|
|
103
61
|
async function loadConfiguration(path, type) {
|
|
104
62
|
const result = await find(path, type);
|
|
105
63
|
if (!result) return null;
|
|
106
64
|
const [filepath, loader] = result;
|
|
107
65
|
return loader(filepath).then((v) => typeof v === "object" ? v : null);
|
|
108
66
|
}
|
|
109
|
-
/**
|
|
110
|
-
* @template {object} T
|
|
111
|
-
* @param {string} root
|
|
112
|
-
* @param {string | string[]} name
|
|
113
|
-
* @param {'script' | 'data'} [type]
|
|
114
|
-
* @returns {AsyncIterableIterator<[config: T, path: string]>}
|
|
115
|
-
*/
|
|
116
67
|
async function* loadProfileAndPaths(root, name, type) {
|
|
117
|
-
for (const n of [name].flat()) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (!result) return;
|
|
68
|
+
for (const r of [root].flat()) for (const n of [name].flat()) {
|
|
69
|
+
const result = await loadConfigurationWithPath(pathFn.resolve(r, `${n}.yongdall`), type) || await loadConfigurationWithPath(pathFn.resolve(r, `yongdall/${n}`), type) || await loadConfigurationWithPath(pathFn.resolve(r, `${n}/yongdall`), type);
|
|
70
|
+
if (!result) continue;
|
|
121
71
|
const [path, config] = result;
|
|
122
|
-
if (!config)
|
|
72
|
+
if (!config) continue;
|
|
123
73
|
yield [config, path];
|
|
124
74
|
}
|
|
125
75
|
}
|
|
76
|
+
const mergedPattern = "{*/yongdall,yongdall/*,*.yongdall}.{mjs,mts,yml,yaml,json,toml}";
|
|
77
|
+
async function* findProfiles(root, finders) {
|
|
78
|
+
for await (const file of fsPromises.glob(mergedPattern, { cwd: root })) {
|
|
79
|
+
if (!await fsPromises.stat(pathFn.join(root, file)).then((s) => s.isFile(), () => false)) continue;
|
|
80
|
+
const ext = pathFn.extname(file);
|
|
81
|
+
const filename = file.slice(0, -ext.length);
|
|
82
|
+
const dir = pathFn.dirname(filename) || ".";
|
|
83
|
+
const key = (dir === "." ? filename.slice(0, Math.max(filename.lastIndexOf("."), 0)) : dir === "yongdall" ? pathFn.basename(filename) : dir).replace(/@.*/, "");
|
|
84
|
+
const profile = Object.hasOwn(finders, key) ? finders[key] : null;
|
|
85
|
+
if (!profile) continue;
|
|
86
|
+
if (!(profile.type === "script" ? scriptExts : profile.type === "data" ? dataExts : allExts).has(ext)) continue;
|
|
87
|
+
if (scriptExts.has(ext)) yield [filename, ext];
|
|
88
|
+
else yield [file];
|
|
89
|
+
const find = profile.find;
|
|
90
|
+
if (typeof find !== "function") continue;
|
|
91
|
+
const loaderFn = loaders.find((v) => v[0] === ext)?.[1];
|
|
92
|
+
if (typeof loaderFn !== "function") continue;
|
|
93
|
+
const data = await loaderFn(pathFn.resolve(root, file));
|
|
94
|
+
if (!data || typeof data !== "object") continue;
|
|
95
|
+
for await (const file of await find(data)) {
|
|
96
|
+
if (!file) continue;
|
|
97
|
+
const path = pathFn.join(".", pathFn.join("/", dir, file));
|
|
98
|
+
if (!path || path[0] === "." || ["\\", "/"].includes(path[path.length - 1])) continue;
|
|
99
|
+
const ext = pathFn.extname(file);
|
|
100
|
+
if (scriptExts.has(ext)) {
|
|
101
|
+
yield [path.slice(0, -ext.length), ext];
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (scriptExtNames.includes(ext)) continue;
|
|
105
|
+
for (const ext of scriptExts) {
|
|
106
|
+
if (!await fsPromises.stat(pathFn.join(root, path + ext)).then((s) => s.isFile(), () => false)) continue;
|
|
107
|
+
yield [path, ext];
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
126
113
|
const scriptExtNames = [
|
|
127
114
|
".mjs",
|
|
128
115
|
".mts",
|
|
@@ -131,14 +118,6 @@ const scriptExtNames = [
|
|
|
131
118
|
".js",
|
|
132
119
|
".ts"
|
|
133
120
|
];
|
|
134
|
-
/**
|
|
135
|
-
* @template {object} T
|
|
136
|
-
* @param {string} root
|
|
137
|
-
* @param {string | string[]} name
|
|
138
|
-
* @param {(config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>} preprocess
|
|
139
|
-
* @param {'script' | 'data'} [type]
|
|
140
|
-
* @returns {AsyncIterableIterator<T>}
|
|
141
|
-
*/
|
|
142
121
|
async function* loadByPreprocess(root, name, preprocess, type) {
|
|
143
122
|
for await (const [config, path] of loadProfileAndPaths(root, name, type)) {
|
|
144
123
|
const basePath = pathFn.dirname(path);
|
|
@@ -168,36 +147,11 @@ async function* loadByPreprocess(root, name, preprocess, type) {
|
|
|
168
147
|
});
|
|
169
148
|
}
|
|
170
149
|
}
|
|
171
|
-
/**
|
|
172
|
-
* @template {object} T
|
|
173
|
-
* @overload
|
|
174
|
-
* @param {string} root
|
|
175
|
-
* @param {string | string[]} name
|
|
176
|
-
* @param {'script' | 'data'} [type]
|
|
177
|
-
* @returns {AsyncIterableIterator<[config: T, path: string]>}
|
|
178
|
-
*/
|
|
179
|
-
/**
|
|
180
|
-
* @template {object} T
|
|
181
|
-
* @overload
|
|
182
|
-
* @param {string} root
|
|
183
|
-
* @param {string | string[]} name
|
|
184
|
-
* @param {(config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>} preprocess
|
|
185
|
-
* @param {'script' | 'data'} [type]
|
|
186
|
-
* @returns {AsyncIterableIterator<T>}
|
|
187
|
-
*/
|
|
188
|
-
/**
|
|
189
|
-
* @template {object} T
|
|
190
|
-
* @param {string} root
|
|
191
|
-
* @param {string | string[]} name
|
|
192
|
-
* @param {((config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>) | 'script' | 'data'} [preprocess]
|
|
193
|
-
* @param {'script' | 'data'} [type]
|
|
194
|
-
* @returns {AsyncIterableIterator<[config: T, path: string] | T>}
|
|
195
|
-
*/
|
|
196
150
|
function loadProfiles(root, name, preprocess, type) {
|
|
197
151
|
if (typeof preprocess === "function") return loadByPreprocess(root, name, preprocess, type);
|
|
198
152
|
return loadProfileAndPaths(root, name, preprocess);
|
|
199
153
|
}
|
|
200
154
|
|
|
201
155
|
//#endregion
|
|
202
|
-
export { loadConfiguration as default, loadConfigurationWithPath, loadProfiles };
|
|
156
|
+
export { loadConfiguration as default, findProfiles, loadConfigurationWithPath, loadProfiles };
|
|
203
157
|
//# sourceMappingURL=index.mjs.map
|
package/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../cli/load-configuration/index.mjs"],"sourcesContent":["import * as fsPromises from 'node:fs/promises';\nimport * as pathFn from 'node:path';\nimport * as yaml from 'yaml';\nimport * as toml from 'smol-toml';\n\n/**\n * \n * @template T\n * @param {string} path\n * @returns {Promise<T>}\n */\nasync function loadToml(path) {\n\t/** @type {any} */\n\tconst value = toml.parse(await fsPromises.readFile(path, 'utf-8'));\n\treturn value;\n}\n/**\n * \n * @template T\n * @param {string} path\n * @returns {Promise<T>}\n */\nasync function loadYaml(path) {\n\treturn yaml.parse(await fsPromises.readFile(path, 'utf-8'));\n}\n/**\n * \n * @template T\n * @param {string} path\n * @returns {Promise<T>}\n */\nasync function loadJson(path) {\n\treturn JSON.parse(await fsPromises.readFile(path, 'utf-8'));\n}\n/**\n * \n * @template T\n * @param {string} path\n * @returns {Promise<T>}\n */\nfunction loadMjs(path) {\n\treturn import(path).then(v => {\n\t\tif ('default' in v) { return v.default; }\n\t\treturn v;\n\t});\n}\n/** @type {[string, <T>(path: string) => Promise<T | null>, script?: boolean][]} */\nconst loaders = [\n\t['.mjs', loadMjs, true],\n\t['.mts', loadMjs, true],\n\t['.json', loadJson],\n\t['.yml', loadYaml],\n\t['.yaml', loadYaml],\n\t['.toml', loadToml],\n];\n\nconst scriptExts = new Set(loaders.filter(v => v[2]).map(v => v[0]));\nconst dataExts = new Set(loaders.filter(v => !v[2]).map(v => v[0]));\nconst allExts = new Set(loaders.map(v => v[0]));\n/**\n * @template {object} T\n * @param {string} path \n * @param {'script' | 'data'} [type] \n * @returns {Promise<[path: string, loader: <T>(path: string) => Promise<T | null>] | null>}\n */\nasync function find(path, type) {\n\tconst exts = type === 'script' ? scriptExts : type === 'data' ? dataExts : allExts;\n\tconst stat = await fsPromises.stat(path).catch(() => null);\n\tconst ext = stat?.isFile() ? pathFn.extname(path).toLowerCase() : '';\n\tlet loader = loaders.find(v => v[0] === ext);\n\tlet loaderFn = loader && (exts.has(loader[0])) && loader[1];\n\tif (loaderFn) { return [path, loaderFn]; }\n\tfor (const [e, l, script] of loaders) {\n\t\tif (!exts.has(e)) { continue; }\n\t\tconst p = path + e;\n\t\tconst stat = await fsPromises.stat(p).catch(() => null);\n\t\tif (stat?.isFile()) {\n\t\t\treturn [p, l];\n\t\t}\n\t}\n\treturn null;\n}\n\n/**\n * @template {object} T\n * @param {string} path \n * @param {'script' | 'data'} [type] \n * @returns {Promise<[string, T | null] | null>}\n */\nexport async function loadConfigurationWithPath(path, type) {\n\tconst result = await find(path, type);\n\tif (!result) { return null; }\n\tconst [filepath, loader] = result;\n\treturn Promise.all([\n\t\tfsPromises.realpath(filepath),\n\t\tloader(filepath).then(v => typeof v === 'object' ? v : null),\n\t]);\n}\n\n/**\n * @template {object} T\n * @param {string} path \n * @param {'script' | 'data'} [type] \n * @returns {Promise<T | null>}\n */\nexport default async function loadConfiguration(path, type) {\n\tconst result = await find(path, type);\n\tif (!result) { return null; }\n\tconst [filepath, loader] = result;\n\treturn loader(filepath).then(v => typeof v === 'object' ? v : null);\n}\n\n\n\n\n\n\n\n/** \n * @template {object} T\n * @param {string} root\n * @param {string | string[]} name\n * @param {'script' | 'data'} [type] \n * @returns {AsyncIterableIterator<[config: T, path: string]>}\n */\nasync function* loadProfileAndPaths(root, name, type) {\n\tfor (const n of [name].flat()) {\n\t\t/** @type {[string, T | null] | null} */\n\t\tconst result = await loadConfigurationWithPath(pathFn.resolve(root, `${n}.yongdall`), type)\n\t\t\t|| await loadConfigurationWithPath(pathFn.resolve(root, `yongdall/${n}`), type)\n\t\t\t|| await loadConfigurationWithPath(pathFn.resolve(root, `${n}/yongdall`), type);\n\t\tif (!result) { return; }\n\t\tconst [path, config] = result;\n\t\tif (!config) { return; }\n\t\tyield [config, path];\n\t}\n}\n\nconst scriptExtNames = ['.mjs', '.mts', '.cjs', '.cts', '.js', '.ts'];\n\n/** \n * @template {object} T\n * @param {string} root\n * @param {string | string[]} name\n * @param {(config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>} preprocess\n * @param {'script' | 'data'} [type] \n * @returns {AsyncIterableIterator<T>}\n */\nasync function* loadByPreprocess(root, name, preprocess, type) {\n\tfor await (const [config, path] of loadProfileAndPaths(root, name, type)) {\n\t\tconst basePath = pathFn.dirname(path);\n\t\tyield* preprocess(config, path, async path => {\n\t\t\tconst index = path.indexOf('#');\n\t\t\tconst file = index < 0 ? path : path.slice(0, index);\n\t\t\tlet resolvePath = pathFn.resolve(basePath, file);\n\t\t\tif (!scriptExtNames.includes(pathFn.extname(resolvePath))) {\n\t\t\t\tfor (const ext of scriptExtNames) {\n\t\t\t\t\tconst resolvePathWithExt = resolvePath + ext;\n\t\t\t\t\tif (await fsPromises.stat(resolvePathWithExt).then(s => s.isFile(), () => false)) {\n\t\t\t\t\t\tresolvePath = resolvePathWithExt;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn import(resolvePath).then(mod => {\n\t\t\t\tconst key = index < 0 ? '' : path.slice(index + 1);\n\t\t\t\tlet val = mod;\n\t\t\t\tfor (const k of key.split('.').filter(Boolean)) {\n\t\t\t\t\tif (!val || typeof val !== 'object') { return; }\n\t\t\t\t\tif (!Object.hasOwn(val, k)) { return; }\n\t\t\t\t\tval = val[k];\n\t\t\t\t}\n\t\t\t\treturn val;\n\t\t\t}, (e) => {\n\t\t\t\tconsole.error(e);\n\t\t\t});\n\t\t});\n\t}\n}\n\n\n/** \n * @template {object} T\n * @overload\n * @param {string} root\n * @param {string | string[]} name\n * @param {'script' | 'data'} [type] \n * @returns {AsyncIterableIterator<[config: T, path: string]>}\n */\n/** \n * @template {object} T\n * @overload\n * @param {string} root\n * @param {string | string[]} name\n * @param {(config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>} preprocess\n * @param {'script' | 'data'} [type] \n * @returns {AsyncIterableIterator<T>}\n */\n/** \n * @template {object} T\n * @param {string} root\n * @param {string | string[]} name\n * @param {((config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>) | 'script' | 'data'} [preprocess]\n * @param {'script' | 'data'} [type] \n * @returns {AsyncIterableIterator<[config: T, path: string] | T>}\n */\nexport function loadProfiles(root, name, preprocess, type) {\n\tif (typeof preprocess === 'function') {\n\t\treturn loadByPreprocess(root, name, preprocess, type);\n\t}\n\treturn loadProfileAndPaths(root, name, preprocess);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../cli/load-configuration/index.mts"],"sourcesContent":["import * as fsPromises from 'node:fs/promises';\nimport * as pathFn from 'node:path';\nimport * as yaml from 'yaml';\nimport * as toml from 'smol-toml';\n\nasync function loadToml<T>(path: string): Promise<T> {\n\tconst value: any = toml.parse(await fsPromises.readFile(path, 'utf-8'));\n\treturn value;\n}\nasync function loadYaml<T>(path: string): Promise<T> {\n\treturn yaml.parse(await fsPromises.readFile(path, 'utf-8'));\n}\nasync function loadJson<T>(path: string): Promise<T> {\n\treturn JSON.parse(await fsPromises.readFile(path, 'utf-8'));\n}\n\nfunction loadMjs<T>(path: string): Promise<T> {\n\treturn import(path).then(v => {\n\t\tconst keys = Object.keys(v);\n\t\tif (keys.length === 1 && keys[0] === 'default') { return v.default; }\n\t\treturn v;\n\t});\n}\nconst loaders: [string, <T>(path: string) => Promise<T | null>, script?: boolean][] = [\n\t['.mjs', loadMjs, true],\n\t['.mts', loadMjs, true],\n\t['.json', loadJson],\n\t['.yml', loadYaml],\n\t['.yaml', loadYaml],\n\t['.toml', loadToml],\n];\n\nconst scriptExts = new Set(loaders.filter(v => v[2]).map(v => v[0]));\nconst dataExts = new Set(loaders.filter(v => !v[2]).map(v => v[0]));\nconst allExts = new Set(loaders.map(v => v[0]));\n\nasync function find<T extends object>(\n\tpath: string,\n\ttype?: 'script' | 'data',\n): Promise<[path: string, loader: <T>(path: string) => Promise<T | null>] | null> {\n\tconst exts = type === 'script' ? scriptExts : type === 'data' ? dataExts : allExts;\n\tconst stat = await fsPromises.stat(path).catch(() => null);\n\tconst ext = stat?.isFile() ? pathFn.extname(path).toLowerCase() : '';\n\tlet loader = loaders.find(v => v[0] === ext);\n\tlet loaderFn = loader && (exts.has(loader[0])) && loader[1];\n\tif (loaderFn) { return [path, loaderFn]; }\n\tfor (const [e, l, script] of loaders) {\n\t\tif (!exts.has(e)) { continue; }\n\t\tconst p = path + e;\n\t\tconst stat = await fsPromises.stat(p).catch(() => null);\n\t\tif (stat?.isFile()) {\n\t\t\treturn [p, l];\n\t\t}\n\t}\n\treturn null;\n}\n\nexport async function loadConfigurationWithPath<T extends object>(\n\tpath: string,\n\ttype?: 'script' | 'data',\n): Promise<[string, T | null] | null> {\n\tconst result = await find(path, type);\n\tif (!result) { return null; }\n\tconst [filepath, loader] = result;\n\treturn Promise.all([\n\t\tfsPromises.realpath(filepath),\n\t\tloader<T>(filepath).then(v => typeof v === 'object' ? v : null),\n\t]);\n}\n\nexport default async function loadConfiguration<T extends object>(\n\tpath: string,\n\ttype?: 'script' | 'data',\n): Promise<T | null> {\n\tconst result = await find(path, type);\n\tif (!result) { return null; }\n\tconst [filepath, loader] = result;\n\treturn loader<T>(filepath).then(v => typeof v === 'object' ? v : null);\n}\n\n\n\n\n\n\nasync function* loadProfileAndPaths<T extends object>(\n\troot: string | string[],\n\tname: string | string[],\n\ttype?: 'script' | 'data',\n): AsyncIterableIterator<[config: T, path: string]> {\n\tfor (const r of [root].flat()) {\n\t\tfor (const n of [name].flat()) {\n\t\t\tconst result: [string, T | null] | null\n\t\t\t\t= await loadConfigurationWithPath(pathFn.resolve(r, `${n}.yongdall`), type)\n\t\t\t\t|| await loadConfigurationWithPath(pathFn.resolve(r, `yongdall/${n}`), type)\n\t\t\t\t|| await loadConfigurationWithPath(pathFn.resolve(r, `${n}/yongdall`), type);\n\t\t\tif (!result) { continue; }\n\t\t\tconst [path, config] = result;\n\t\t\tif (!config) { continue; }\n\t\t\tyield [config, path];\n\t\t}\n\t}\n}\nconst mergedPattern = '{*/yongdall,yongdall/*,*.yongdall}.{mjs,mts,yml,yaml,json,toml}';\n\n\nexport interface ProfileFinder<T extends object = object> {\n\tfind?(data: T): Iterable<string> | AsyncIterable<string> | PromiseLike<Iterable<string> | AsyncIterable<string>>;\n\ttype?: 'script' | 'data';\n}\nexport async function* findProfiles(\n\troot: string,\n\tfinders: Record<string, ProfileFinder>,\n): AsyncGenerator<[path: string, ext?: string]> {\n\tfor await (const file of fsPromises.glob(mergedPattern, { cwd: root })) {\n\t\tif (!await fsPromises.stat(pathFn.join(root, file)).then(s => s.isFile(), () => false)) { continue; }\n\t\tconst ext = pathFn.extname(file);\n\t\tconst filename = file.slice(0, -ext.length);\n\t\tconst dir = pathFn.dirname(filename) || '.';\n\t\tconst name = dir === '.'\n\t\t\t? filename.slice(0, Math.max(filename.lastIndexOf('.'), 0))\n\t\t\t: dir === 'yongdall' ? pathFn.basename(filename) : dir;\n\t\tconst key = name.replace(/@.*/, '');\n\t\tconst profile = Object.hasOwn(finders, key) ? finders[key] : null;\n\t\tif (!profile) { continue; }\n\n\t\tconst exts = profile.type === 'script' ? scriptExts : profile.type === 'data' ? dataExts : allExts;\n\t\tif (!exts.has(ext)) { continue; }\n\t\tif (scriptExts.has(ext)) {\n\t\t\tyield [filename, ext];\n\t\t} else {\n\t\t\tyield [file];\n\t\t}\n\t\tconst find = profile.find;\n\t\tif (typeof find !== 'function') { continue; }\n\t\tconst loaderFn = loaders.find(v => v[0] === ext)?.[1];\n\t\tif (typeof loaderFn !== 'function') { continue; }\n\t\tconst data = await loaderFn(pathFn.resolve(root, file));\n\t\tif (!data || typeof data !== 'object') { continue; }\n\n\t\tfor await (const file of await find(data)) {\n\t\t\tif (!file) { continue; }\n\t\t\tconst path = pathFn.join('.', pathFn.join('/', dir, file));\n\t\t\tif (!path || path[0] === '.' || ['\\\\', '/'].includes(path[path.length - 1])) { continue }\n\t\t\tconst ext = pathFn.extname(file);\n\t\t\tif (scriptExts.has(ext)) {\n\t\t\t\tyield [path.slice(0, -ext.length), ext];\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (scriptExtNames.includes(ext)) { continue; }\n\t\t\tfor (const ext of scriptExts) {\n\t\t\t\tif (!await fsPromises.stat(pathFn.join(root, path + ext)).then(s => s.isFile(), () => false)) { continue; }\n\t\t\t\tyield [path, ext];\n\t\t\t\tbreak;\n\n\t\t\t}\n\t\t}\n\t}\n}\n\nconst scriptExtNames = ['.mjs', '.mts', '.cjs', '.cts', '.js', '.ts'];\n\nasync function* loadByPreprocess<T extends object>(\n\troot: string | string[],\n\tname: string | string[],\n\tpreprocess: (config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>,\n\ttype?: 'script' | 'data',\n): AsyncIterableIterator<T> {\n\tfor await (const [config, path] of loadProfileAndPaths(root, name, type)) {\n\t\tconst basePath = pathFn.dirname(path);\n\t\tyield* preprocess(config, path, async path => {\n\t\t\tconst index = path.indexOf('#');\n\t\t\tconst file = index < 0 ? path : path.slice(0, index);\n\t\t\tlet resolvePath = pathFn.resolve(basePath, file);\n\t\t\tif (!scriptExtNames.includes(pathFn.extname(resolvePath))) {\n\t\t\t\tfor (const ext of scriptExtNames) {\n\t\t\t\t\tconst resolvePathWithExt = resolvePath + ext;\n\t\t\t\t\tif (await fsPromises.stat(resolvePathWithExt).then(s => s.isFile(), () => false)) {\n\t\t\t\t\t\tresolvePath = resolvePathWithExt;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn import(resolvePath).then(mod => {\n\t\t\t\tconst key = index < 0 ? '' : path.slice(index + 1);\n\t\t\t\tlet val = mod;\n\t\t\t\tfor (const k of key.split('.').filter(Boolean)) {\n\t\t\t\t\tif (!val || typeof val !== 'object') { return; }\n\t\t\t\t\tif (!Object.hasOwn(val, k)) { return; }\n\t\t\t\t\tval = val[k];\n\t\t\t\t}\n\t\t\t\treturn val;\n\t\t\t}, (e) => {\n\t\t\t\tconsole.error(e);\n\t\t\t});\n\t\t});\n\t}\n}\n\n\n\n\nexport function loadProfiles<T extends object>(\n\troot: string | string[],\n\tname: string | string[],\n\ttype?: 'script' | 'data',\n): AsyncIterableIterator<[config: T, path: string]>\nexport function loadProfiles<T extends object>(\n\troot: string | string[],\n\tname: string | string[],\n\tpreprocess?: (config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>,\n\ttype?: 'script' | 'data',\n): AsyncIterableIterator<T>\n\nexport function loadProfiles<T extends object>(\n\troot: string | string[],\n\tname: string | string[],\n\tpreprocess?: ((config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>) | 'script' | 'data',\n\ttype?: 'script' | 'data',\n): AsyncIterableIterator<[config: T, path: string] | T>\nexport function loadProfiles<T extends object>(\n\troot: string | string[],\n\tname: string | string[],\n\tpreprocess?: ((config: any, path: string, load: (path: string) => Promise<any>) => Iterable<T> | AsyncIterable<T>) | 'script' | 'data',\n\ttype?: 'script' | 'data',\n): AsyncIterableIterator<[config: T, path: string] | T> {\n\tif (typeof preprocess === 'function') {\n\t\treturn loadByPreprocess(root, name, preprocess, type);\n\t}\n\treturn loadProfileAndPaths(root, name, preprocess);\n}\n"],"mappings":"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"}
|