locter 2.2.0 → 3.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.
Files changed (39) hide show
  1. package/README.MD +188 -6
  2. package/dist/index.d.mts +244 -0
  3. package/dist/index.mjs +688 -672
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +28 -35
  6. package/dist/index.cjs +0 -743
  7. package/dist/index.cjs.map +0 -1
  8. package/dist/index.d.ts +0 -3
  9. package/dist/loader/built-in/conf/index.d.ts +0 -1
  10. package/dist/loader/built-in/conf/module.d.ts +0 -6
  11. package/dist/loader/built-in/index.d.ts +0 -3
  12. package/dist/loader/built-in/json/index.d.ts +0 -1
  13. package/dist/loader/built-in/json/module.d.ts +0 -5
  14. package/dist/loader/built-in/module/index.d.ts +0 -3
  15. package/dist/loader/built-in/module/module.d.ts +0 -15
  16. package/dist/loader/built-in/module/type.d.ts +0 -8
  17. package/dist/loader/built-in/module/utils.d.ts +0 -9
  18. package/dist/loader/built-in/yaml/index.d.ts +0 -1
  19. package/dist/loader/built-in/yaml/module.d.ts +0 -5
  20. package/dist/loader/constants.d.ts +0 -6
  21. package/dist/loader/helpers.d.ts +0 -6
  22. package/dist/loader/index.d.ts +0 -3
  23. package/dist/loader/module.d.ts +0 -18
  24. package/dist/loader/singleton.d.ts +0 -2
  25. package/dist/loader/type.d.ts +0 -8
  26. package/dist/locator/async.d.ts +0 -3
  27. package/dist/locator/index.d.ts +0 -4
  28. package/dist/locator/sync.d.ts +0 -3
  29. package/dist/locator/types.d.ts +0 -15
  30. package/dist/locator/utils.d.ts +0 -7
  31. package/dist/utils/error.d.ts +0 -1
  32. package/dist/utils/file-name.d.ts +0 -2
  33. package/dist/utils/file-path.d.ts +0 -1
  34. package/dist/utils/has-property.d.ts +0 -2
  35. package/dist/utils/index.d.ts +0 -8
  36. package/dist/utils/object.d.ts +0 -2
  37. package/dist/utils/runtime.d.ts +0 -2
  38. package/dist/utils/to-array.d.ts +0 -1
  39. package/dist/utils/typescript.d.ts +0 -1
package/dist/index.mjs CHANGED
@@ -1,718 +1,734 @@
1
- import { destr } from 'destr';
2
- import flat from 'flat';
3
- import fs from 'node:fs';
4
- import fg from 'fast-glob';
5
- import path from 'node:path';
6
- import { BaseError } from 'ebec';
7
- import { createJiti } from 'jiti';
8
- import { pathToFileURL } from 'node:url';
9
- import { parse } from 'yaml';
10
-
11
-
12
- // -- Shims --
13
- import cjsUrl from 'node:url';
14
- import cjsPath from 'node:path';
15
- import cjsModule from 'node:module';
16
- const __filename = cjsUrl.fileURLToPath(import.meta.url);
17
- const __dirname = cjsPath.dirname(__filename);
18
- const require = cjsModule.createRequire(import.meta.url);
1
+ import { createRequire } from "node:module";
2
+ import { BaseError, hasInstanceof, markInstanceof } from "@ebec/core";
3
+ import path from "node:path";
4
+ import { destr } from "destr";
5
+ import { unflatten } from "flat";
6
+ import fs from "node:fs";
7
+ import fg from "fast-glob";
8
+ import { createJiti } from "jiti";
9
+ import { pathToFileURL } from "node:url";
10
+ import { parse } from "yaml";
11
+ //#region src/errors/base.ts
12
+ const LOCTER_ERROR_MARKER = Symbol.for("@locter/error");
13
+ var LocterError = class extends BaseError {
14
+ static [Symbol.hasInstance](input) {
15
+ return hasInstanceof(input, LOCTER_ERROR_MARKER);
16
+ }
17
+ path;
18
+ constructor(input = {}) {
19
+ if (typeof input === "string") super(input);
20
+ else {
21
+ const { path, ...rest } = input;
22
+ super(rest);
23
+ this.path = path;
24
+ }
25
+ markInstanceof(this, LOCTER_ERROR_MARKER);
26
+ }
27
+ };
28
+ //#endregion
29
+ //#region src/errors/load.ts
30
+ const LOCTER_LOAD_ERROR_MARKER = Symbol.for("@locter/load-error");
31
+ var LocterLoadError = class extends LocterError {
32
+ static [Symbol.hasInstance](input) {
33
+ return hasInstanceof(input, LOCTER_LOAD_ERROR_MARKER);
34
+ }
35
+ constructor(input = {}) {
36
+ super(input);
37
+ markInstanceof(this, LOCTER_LOAD_ERROR_MARKER);
38
+ }
39
+ };
40
+ //#endregion
41
+ //#region src/errors/not-found.ts
42
+ const LOCTER_NOT_FOUND_ERROR_MARKER = Symbol.for("@locter/not-found-error");
43
+ var LocterNotFoundError = class extends LocterError {
44
+ static [Symbol.hasInstance](input) {
45
+ return hasInstanceof(input, LOCTER_NOT_FOUND_ERROR_MARKER);
46
+ }
47
+ constructor(input = {}) {
48
+ super(input);
49
+ markInstanceof(this, LOCTER_NOT_FOUND_ERROR_MARKER);
50
+ }
51
+ };
52
+ //#endregion
53
+ //#region src/errors/unknown-extension.ts
54
+ const LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER = Symbol.for("@locter/unknown-extension-error");
55
+ var LocterUnknownExtensionError = class extends LocterError {
56
+ static [Symbol.hasInstance](input) {
57
+ return hasInstanceof(input, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER);
58
+ }
59
+ constructor(input = {}) {
60
+ super(input);
61
+ markInstanceof(this, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER);
62
+ }
63
+ };
64
+ //#endregion
65
+ //#region src/utils/file-name.ts
66
+ function getFileNameExtension(input, allowed) {
67
+ const extension = path.extname(input);
68
+ if (extension === "" || extension === ".") return;
69
+ if (typeof allowed === "undefined" || allowed.includes(extension)) return extension;
70
+ }
71
+ function removeFileNameExtension(input, extensions) {
72
+ const extension = getFileNameExtension(input, extensions);
73
+ if (extension) return input.substring(0, input.length - extension.length);
74
+ return input;
75
+ }
76
+ //#endregion
77
+ //#region src/utils/has-property.ts
19
78
  function hasOwnProperty(obj, prop) {
20
- return Object.prototype.hasOwnProperty.call(obj, prop);
79
+ return Object.prototype.hasOwnProperty.call(obj, prop);
21
80
  }
22
81
  function hasStringProperty(obj, prop) {
23
- return hasOwnProperty(obj, prop) && typeof obj[prop] === 'string';
82
+ return hasOwnProperty(obj, prop) && typeof obj[prop] === "string";
24
83
  }
25
-
26
- /*
27
- * Copyright (c) 2022.
28
- * Author Peter Placzek (tada5hi)
29
- * For the full copyright and license information,
30
- * view the LICENSE file that was distributed with this source code.
31
- */ function isObject(item) {
32
- return !!item && typeof item === 'object' && !Array.isArray(item);
84
+ //#endregion
85
+ //#region src/utils/object.ts
86
+ function isObject(item) {
87
+ return !!item && typeof item === "object" && !Array.isArray(item);
33
88
  }
34
89
  function isSafeObjectKey(key) {
35
- return key !== '__proto__' && key !== 'prototype' && key !== 'constructor';
36
- }
37
-
38
- function handleException(e) {
39
- if (e instanceof Error) {
40
- throw e;
41
- }
42
- const error = new Error('Can not process thrown exception.');
43
- if (isObject(e)) {
44
- if (hasOwnProperty(e, 'message') && typeof e.message === 'string') {
45
- error.message = e.message;
46
- }
47
- if (hasOwnProperty(e, 'stack') && typeof e.stack === 'string') {
48
- error.stack = e.stack;
49
- }
50
- }
51
- throw error;
90
+ return key !== "__proto__" && key !== "prototype" && key !== "constructor";
52
91
  }
53
-
54
- function getFileNameExtension(input, allowed) {
55
- const extension = path.extname(input);
56
- if (extension === '' || extension === '.') {
57
- return undefined;
58
- }
59
- if (typeof allowed === 'undefined' || allowed.indexOf(extension) !== -1) {
60
- return extension;
61
- }
62
- return undefined;
92
+ //#endregion
93
+ //#region src/utils/to-array.ts
94
+ function toArray(input) {
95
+ return Array.isArray(input) ? input : [input];
63
96
  }
64
- function removeFileNameExtension(input, extensions) {
65
- const extension = getFileNameExtension(input, extensions);
66
- if (extension) {
67
- return input.substring(0, input.length - extension.length);
68
- }
69
- return input;
70
- }
71
-
72
- /*
73
- * Copyright (c) 2022.
74
- * Author Peter Placzek (tada5hi)
75
- * For the full copyright and license information,
76
- * view the LICENSE file that was distributed with this source code.
77
- */ function toArray(input) {
78
- return Array.isArray(input) ? input : [
79
- input
80
- ];
81
- }
82
-
97
+ //#endregion
98
+ //#region src/utils/file-path.ts
83
99
  function isFilePath(input) {
84
- const extension = path.extname(input);
85
- return extension && extension !== '';
100
+ const extension = path.extname(input);
101
+ return extension && extension !== "";
86
102
  }
87
-
88
- /*
89
- * Copyright (c) 2024.
90
- * Author Peter Placzek (tada5hi)
91
- * For the full copyright and license information,
92
- * view the LICENSE file that was distributed with this source code.
93
- */ function isJestRuntimeEnvironment() {
94
- return process.env && process.env.JEST_WORKER_ID !== undefined;
103
+ //#endregion
104
+ //#region src/utils/runtime.ts
105
+ function isJestRuntimeEnvironment() {
106
+ return process.env && process.env.JEST_WORKER_ID !== void 0;
107
+ }
108
+ function isVitestRuntimeEnvironment() {
109
+ return typeof process !== "undefined" && process.env.VITEST === "true";
95
110
  }
96
111
  function isTsNodeRuntimeEnvironment() {
97
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
98
- // @ts-ignore
99
- return !!process[Symbol.for('ts-node.register.instance')];
112
+ return !!process[Symbol.for("ts-node.register.instance")];
100
113
  }
101
-
114
+ //#endregion
115
+ //#region src/utils/typescript.ts
102
116
  function isTypeScriptError(input) {
103
- if (!isObject(input)) {
104
- return false;
105
- }
106
- if (typeof input.diagnosticCodes !== 'undefined') {
107
- return true;
108
- }
109
- return typeof input.message === 'string' && /TS\d+/.test(input.message);
110
- }
111
-
117
+ if (!isObject(input)) return false;
118
+ if (typeof input.diagnosticCodes !== "undefined") return true;
119
+ return typeof input.message === "string" && /TS\d+/.test(input.message);
120
+ }
121
+ //#endregion
122
+ //#region src/errors/wrap.ts
123
+ const NOT_FOUND_CODES = new Set([
124
+ "ENOENT",
125
+ "MODULE_NOT_FOUND",
126
+ "ERR_MODULE_NOT_FOUND"
127
+ ]);
128
+ function wrapLoaderError(input, path) {
129
+ if (input instanceof LocterError) return input;
130
+ const code = isObject(input) && hasStringProperty(input, "code") ? input.code : void 0;
131
+ const message = isObject(input) && hasStringProperty(input, "message") ? input.message : `Failed to load: ${path}`;
132
+ if (code && NOT_FOUND_CODES.has(code)) return new LocterNotFoundError({
133
+ message,
134
+ code,
135
+ cause: input,
136
+ path
137
+ });
138
+ return new LocterLoadError({
139
+ message,
140
+ code,
141
+ cause: input,
142
+ path
143
+ });
144
+ }
145
+ //#endregion
146
+ //#region src/locator/utils.ts
112
147
  function buildLocatorPatterns(pattern) {
113
- return Array.isArray(pattern) ? pattern : [
114
- pattern
115
- ];
148
+ return Array.isArray(pattern) ? pattern : [pattern];
116
149
  }
117
150
  function buildLocatorOptions(options = {}) {
118
- const paths = options.path ? toArray(options.path) : [];
119
- const ignore = options.ignore ? toArray(options.ignore) : [];
120
- if (paths.length === 0) {
121
- paths.push(process.cwd());
122
- }
123
- let onlyFiles;
124
- let onlyDirectories;
125
- if (options.onlyDirectories === options.onlyFiles) {
126
- onlyDirectories = false;
127
- onlyFiles = !options.onlyDirectories;
128
- } else if (typeof options.onlyFiles === 'undefined') {
129
- onlyDirectories = options.onlyDirectories ?? false;
130
- onlyFiles = !options.onlyDirectories;
131
- } else {
132
- onlyFiles = options.onlyFiles ?? true;
133
- onlyDirectories = !options.onlyFiles;
134
- }
135
- return {
136
- path: paths,
137
- ignore,
138
- onlyDirectories,
139
- onlyFiles
140
- };
151
+ const cwd = options.cwd ? toArray(options.cwd) : [];
152
+ const ignore = options.ignore ? toArray(options.ignore) : [];
153
+ if (cwd.length === 0) cwd.push(process.cwd());
154
+ let onlyFiles;
155
+ let onlyDirectories;
156
+ if (options.onlyDirectories === options.onlyFiles) {
157
+ onlyDirectories = false;
158
+ onlyFiles = !options.onlyDirectories;
159
+ } else if (typeof options.onlyFiles === "undefined") {
160
+ onlyDirectories = options.onlyDirectories ?? false;
161
+ onlyFiles = !options.onlyDirectories;
162
+ } else {
163
+ onlyFiles = options.onlyFiles ?? true;
164
+ onlyDirectories = !options.onlyFiles;
165
+ }
166
+ return {
167
+ cwd,
168
+ ignore,
169
+ onlyDirectories,
170
+ onlyFiles,
171
+ dot: options.dot ?? false
172
+ };
141
173
  }
142
174
  function pathToLocatorInfo(input, skipResolve) {
143
- if (!skipResolve && !path.isAbsolute(input)) {
144
- input = path.resolve(process.cwd(), input);
145
- }
146
- const info = path.parse(input);
147
- return {
148
- path: info.dir.split('/').join(path.sep),
149
- name: info.name,
150
- extension: info.ext ? info.ext : undefined
151
- };
175
+ if (!skipResolve && !path.isAbsolute(input)) input = path.resolve(process.cwd(), input);
176
+ const info = path.parse(input);
177
+ const directory = info.dir.split("/").join(path.sep);
178
+ const extension = info.ext ? info.ext : void 0;
179
+ const filePath = extension ? path.join(directory, info.name) + extension : path.join(directory, info.name);
180
+ return {
181
+ directory,
182
+ name: info.name,
183
+ extension,
184
+ path: filePath
185
+ };
152
186
  }
153
187
  function isLocatorInfo(input) {
154
- return isObject(input) && typeof input.path === 'string' && typeof input.name === 'string' && typeof input.extension === 'string';
188
+ return isObject(input) && typeof input.directory === "string" && typeof input.name === "string" && (typeof input.extension === "undefined" || typeof input.extension === "string") && typeof input.path === "string";
155
189
  }
156
190
  function buildFilePath(input) {
157
- if (typeof input === 'string') {
158
- return input;
159
- }
160
- if (input.extension) {
161
- return path.join(input.path, input.name) + input.extension;
162
- }
163
- return path.join(input.path, input.name);
191
+ if (typeof input === "string") return input;
192
+ return input.path;
164
193
  }
165
194
  function buildFilePathWithoutExtension(input) {
166
- let info;
167
- if (typeof input === 'string') {
168
- info = pathToLocatorInfo(input);
169
- } else {
170
- info = input;
171
- }
172
- return path.join(info.path, info.name);
195
+ let info;
196
+ if (typeof input === "string") info = pathToLocatorInfo(input);
197
+ else info = input;
198
+ return path.join(info.directory, info.name);
173
199
  }
174
-
200
+ //#endregion
201
+ //#region src/locator/async.ts
175
202
  async function locateMany(pattern, options) {
176
- const patterns = buildLocatorPatterns(pattern);
177
- const opts = buildLocatorOptions(options);
178
- const items = [];
179
- for(let i = 0; i < patterns.length; i++){
180
- for(let j = 0; j < opts.path.length; j++){
181
- const files = await fg(patterns[i], {
182
- absolute: true,
183
- cwd: opts.path[j],
184
- ignore: opts.ignore,
185
- onlyFiles: opts.onlyFiles,
186
- onlyDirectories: opts.onlyDirectories
187
- });
188
- for(let k = 0; k < files.length; k++){
189
- items.push(pathToLocatorInfo(files[k], true));
190
- }
191
- }
192
- }
193
- return items;
203
+ const patterns = buildLocatorPatterns(pattern);
204
+ const opts = buildLocatorOptions(options);
205
+ const items = [];
206
+ for (const p of patterns) for (const cwd of opts.cwd) {
207
+ const files = await fg(p, {
208
+ absolute: true,
209
+ cwd,
210
+ ignore: opts.ignore,
211
+ onlyFiles: opts.onlyFiles,
212
+ onlyDirectories: opts.onlyDirectories,
213
+ dot: opts.dot
214
+ });
215
+ for (const file of files) items.push(pathToLocatorInfo(file, true));
216
+ }
217
+ return items;
194
218
  }
195
219
  async function locate(pattern, options) {
196
- const patterns = buildLocatorPatterns(pattern);
197
- const opts = buildLocatorOptions(options);
198
- for(let i = 0; i < patterns.length; i++){
199
- for(let j = 0; j < opts.path.length; j++){
200
- const files = await fg(patterns[i], {
201
- absolute: true,
202
- cwd: opts.path[j],
203
- ignore: opts.ignore,
204
- onlyFiles: opts.onlyFiles,
205
- onlyDirectories: opts.onlyDirectories
206
- });
207
- const element = files.shift();
208
- if (element) {
209
- return pathToLocatorInfo(element, true);
210
- }
211
- }
212
- }
213
- return undefined;
214
- }
215
-
220
+ const patterns = buildLocatorPatterns(pattern);
221
+ const opts = buildLocatorOptions(options);
222
+ for (const p of patterns) for (const cwd of opts.cwd) {
223
+ const element = (await fg(p, {
224
+ absolute: true,
225
+ cwd,
226
+ ignore: opts.ignore,
227
+ onlyFiles: opts.onlyFiles,
228
+ onlyDirectories: opts.onlyDirectories,
229
+ dot: opts.dot
230
+ })).shift();
231
+ if (element) return pathToLocatorInfo(element, true);
232
+ }
233
+ }
234
+ //#endregion
235
+ //#region src/locator/sync.ts
216
236
  function locateManySync(pattern, options) {
217
- const patterns = buildLocatorPatterns(pattern);
218
- const opts = buildLocatorOptions(options);
219
- const items = [];
220
- for(let i = 0; i < patterns.length; i++){
221
- for(let j = 0; j < opts.path.length; j++){
222
- const files = fg.sync(patterns[i], {
223
- absolute: true,
224
- cwd: opts.path[j],
225
- ignore: opts.ignore,
226
- onlyFiles: opts.onlyFiles,
227
- onlyDirectories: opts.onlyDirectories
228
- });
229
- for(let k = 0; k < files.length; k++){
230
- items.push(pathToLocatorInfo(files[k], true));
231
- }
232
- }
233
- }
234
- return items;
237
+ const patterns = buildLocatorPatterns(pattern);
238
+ const opts = buildLocatorOptions(options);
239
+ const items = [];
240
+ for (const p of patterns) for (const cwd of opts.cwd) {
241
+ const files = fg.sync(p, {
242
+ absolute: true,
243
+ cwd,
244
+ ignore: opts.ignore,
245
+ onlyFiles: opts.onlyFiles,
246
+ onlyDirectories: opts.onlyDirectories,
247
+ dot: opts.dot
248
+ });
249
+ for (const file of files) items.push(pathToLocatorInfo(file, true));
250
+ }
251
+ return items;
235
252
  }
236
253
  function locateSync(pattern, options) {
237
- const patterns = buildLocatorPatterns(pattern);
238
- const opts = buildLocatorOptions(options);
239
- for(let i = 0; i < patterns.length; i++){
240
- for(let j = 0; j < opts.path.length; j++){
241
- const files = fg.sync(patterns[i], {
242
- absolute: true,
243
- cwd: opts.path[j],
244
- ignore: opts.ignore,
245
- onlyFiles: opts.onlyFiles,
246
- onlyDirectories: opts.onlyDirectories
247
- });
248
- const element = files.shift();
249
- if (element) {
250
- return pathToLocatorInfo(element, true);
251
- }
252
- }
253
- }
254
- return undefined;
255
- }
256
-
257
- /*
258
- * Copyright (c) 2022-2023.
259
- * Author Peter Placzek (tada5hi)
260
- * For the full copyright and license information,
261
- * view the LICENSE file that was distributed with this source code.
262
- */ // Based on https://github.com/unjs/rc9 (MIT)
263
- class ConfLoader {
264
- async execute(input) {
265
- const filePath = buildFilePath(input);
266
- try {
267
- const file = await fs.promises.readFile(filePath, {
268
- encoding: 'utf-8'
269
- });
270
- return this.parse(file);
271
- } catch (e) {
272
- return handleException(e);
273
- }
274
- }
275
- executeSync(input) {
276
- const filePath = buildFilePath(input);
277
- try {
278
- const file = fs.readFileSync(filePath, {
279
- encoding: 'utf-8'
280
- });
281
- return this.parse(file);
282
- } catch (e) {
283
- return handleException(e);
284
- }
285
- }
286
- parse(contents) {
287
- const config = {};
288
- const lines = contents.split(/\n|\r|\r\n/);
289
- for(let i = 0; i < lines.length; i++){
290
- const match = lines[i].match(/^\s*([^\s=]+)\s*=\s*(.*)?\s*$/);
291
- if (!match) {
292
- continue;
293
- }
294
- // Key
295
- const key = match[1];
296
- if (!key || !isSafeObjectKey(key)) {
297
- continue;
298
- }
299
- const value = destr(match[2].trim());
300
- if (key.endsWith('[]')) {
301
- const arrKey = key.slice(0, Math.max(0, key.length - 2));
302
- config[arrKey] = (config[arrKey] || []).concat(value);
303
- continue;
304
- }
305
- config[key] = value;
306
- }
307
- return flat.unflatten(config, {
308
- overwrite: true
309
- });
310
- }
311
- }
312
-
254
+ const patterns = buildLocatorPatterns(pattern);
255
+ const opts = buildLocatorOptions(options);
256
+ for (const p of patterns) for (const cwd of opts.cwd) {
257
+ const element = fg.sync(p, {
258
+ absolute: true,
259
+ cwd,
260
+ ignore: opts.ignore,
261
+ onlyFiles: opts.onlyFiles,
262
+ onlyDirectories: opts.onlyDirectories,
263
+ dot: opts.dot
264
+ }).shift();
265
+ if (element) return pathToLocatorInfo(element, true);
266
+ }
267
+ }
268
+ //#endregion
269
+ //#region src/locator/up.ts
270
+ function startWalk(options) {
271
+ const { cwd, stopAt, ...baseOptions } = options;
272
+ const current = path.resolve(cwd ?? process.cwd());
273
+ return {
274
+ current,
275
+ stopAt: stopAt ? path.resolve(current, stopAt) : path.parse(current).root,
276
+ baseOptions
277
+ };
278
+ }
279
+ function nextDirectory(current, stopAt) {
280
+ if (current === stopAt) return;
281
+ const parent = path.dirname(current);
282
+ if (parent === current) return;
283
+ return parent;
284
+ }
285
+ async function locateUp(pattern, options = {}) {
286
+ let walk = startWalk(options);
287
+ while (true) {
288
+ const found = await locate(pattern, {
289
+ ...walk.baseOptions,
290
+ cwd: walk.current
291
+ });
292
+ if (found) return found;
293
+ const next = nextDirectory(walk.current, walk.stopAt);
294
+ if (!next) return;
295
+ walk = {
296
+ ...walk,
297
+ current: next
298
+ };
299
+ }
300
+ }
301
+ function locateUpSync(pattern, options = {}) {
302
+ let walk = startWalk(options);
303
+ while (true) {
304
+ const found = locateSync(pattern, {
305
+ ...walk.baseOptions,
306
+ cwd: walk.current
307
+ });
308
+ if (found) return found;
309
+ const next = nextDirectory(walk.current, walk.stopAt);
310
+ if (!next) return;
311
+ walk = {
312
+ ...walk,
313
+ current: next
314
+ };
315
+ }
316
+ }
317
+ //#endregion
318
+ //#region src/loader/built-in/conf/module.ts
319
+ var ConfLoader = class {
320
+ async execute(input) {
321
+ const filePath = buildFilePath(input);
322
+ try {
323
+ const file = await fs.promises.readFile(filePath, { encoding: "utf-8" });
324
+ return this.parse(file);
325
+ } catch (e) {
326
+ throw wrapLoaderError(e, filePath);
327
+ }
328
+ }
329
+ executeSync(input) {
330
+ const filePath = buildFilePath(input);
331
+ try {
332
+ const file = fs.readFileSync(filePath, { encoding: "utf-8" });
333
+ return this.parse(file);
334
+ } catch (e) {
335
+ throw wrapLoaderError(e, filePath);
336
+ }
337
+ }
338
+ parse(contents) {
339
+ const config = {};
340
+ const lines = contents.split(/\n|\r|\r\n/);
341
+ for (const line of lines) {
342
+ const match = line.match(/^\s*([^\s=]+)\s*=\s*(.*)?\s*$/);
343
+ if (!match) continue;
344
+ const key = match[1];
345
+ const rawValue = match[2];
346
+ if (!key || !isSafeObjectKey(key)) continue;
347
+ const value = destr(rawValue ? rawValue.trim() : "");
348
+ if (key.endsWith("[]")) {
349
+ const arrKey = key.slice(0, Math.max(0, key.length - 2));
350
+ config[arrKey] = (config[arrKey] || []).concat(value);
351
+ continue;
352
+ }
353
+ config[key] = value;
354
+ }
355
+ return unflatten(config, { overwrite: true });
356
+ }
357
+ };
358
+ //#endregion
359
+ //#region src/loader/built-in/json/module.ts
360
+ var JSONLoader = class {
361
+ async execute(input) {
362
+ const filePath = buildFilePath(input);
363
+ try {
364
+ const file = await fs.promises.readFile(filePath, { encoding: "utf-8" });
365
+ return JSON.parse(file);
366
+ } catch (e) {
367
+ throw wrapLoaderError(e, filePath);
368
+ }
369
+ }
370
+ executeSync(input) {
371
+ const filePath = buildFilePath(input);
372
+ try {
373
+ const file = fs.readFileSync(filePath, { encoding: "utf-8" });
374
+ return JSON.parse(file);
375
+ } catch (e) {
376
+ throw wrapLoaderError(e, filePath);
377
+ }
378
+ }
379
+ };
380
+ //#endregion
381
+ //#region src/loader/built-in/module/utils.ts
313
382
  function isESModule(input) {
314
- return isObject(input) && // eslint-disable-next-line no-underscore-dangle
315
- typeof input.__esModule !== 'undefined';
383
+ return isObject(input) && typeof input.__esModule !== "undefined";
316
384
  }
317
- // https://2ality.com/2017/01/babel-esm-spec-mode.html
318
385
  function toModuleRecord(data) {
319
- if (isESModule(data)) {
320
- // @see https://github.com/testing-library/user-event/issues/813
321
- // @see https://stackoverflow.com/questions/62717394/export-default-class-exports-double-nested-default
322
- if (isESModule(data.default) && data.default.default) {
323
- return {
324
- ...data,
325
- default: data.default.default
326
- };
327
- }
328
- return data;
329
- }
330
- const output = Object.create(null, {
331
- __esModule: {
332
- value: true
333
- },
334
- [Symbol.toStringTag]: {
335
- value: 'Module'
336
- }
337
- });
338
- if (isObject(data)) {
339
- // eslint-disable-next-line no-restricted-syntax
340
- for(const key in data){
341
- if (hasOwnProperty(output, key)) {
342
- continue;
343
- }
344
- let descriptor = Object.getOwnPropertyDescriptor(data, key);
345
- if (!descriptor || 'get' in descriptor || descriptor.writable || descriptor.configurable) {
346
- descriptor = {
347
- enumerable: true,
348
- get () {
349
- return data[key];
350
- }
351
- };
352
- }
353
- Object.defineProperty(output, key, descriptor);
354
- }
355
- }
356
- if (!hasOwnProperty(output, 'default')) {
357
- Object.defineProperty(output, 'default', {
358
- value: data,
359
- enumerable: true
360
- });
361
- }
362
- return Object.freeze(output);
386
+ if (isESModule(data)) {
387
+ if (isESModule(data.default) && data.default.default) return {
388
+ ...data,
389
+ default: data.default.default
390
+ };
391
+ return data;
392
+ }
393
+ const output = Object.create(null, {
394
+ __esModule: { value: true },
395
+ [Symbol.toStringTag]: { value: "Module" }
396
+ });
397
+ if (isObject(data)) for (const key in data) {
398
+ if (hasOwnProperty(output, key)) continue;
399
+ let descriptor = Object.getOwnPropertyDescriptor(data, key);
400
+ if (!descriptor || "get" in descriptor || descriptor.writable || descriptor.configurable) descriptor = {
401
+ enumerable: true,
402
+ get() {
403
+ return data[key];
404
+ }
405
+ };
406
+ Object.defineProperty(output, key, descriptor);
407
+ }
408
+ if (!hasOwnProperty(output, "default")) Object.defineProperty(output, "default", {
409
+ value: data,
410
+ enumerable: true
411
+ });
412
+ return Object.freeze(output);
363
413
  }
364
414
  function getModuleExport(data, filterFn) {
365
- const keys = Object.keys(data);
366
- for(let i = 0; i < keys.length; i++){
367
- if (filterFn(keys[i], data[keys[i]])) {
368
- return {
369
- key: keys[i],
370
- value: data[keys[i]]
371
- };
372
- }
373
- }
374
- return undefined;
375
- }
376
-
377
- class ModuleLoader {
378
- async execute(input) {
379
- let output;
380
- try {
381
- output = await this.load(input);
382
- } catch (e) {
383
- if (e instanceof SyntaxError || e instanceof ReferenceError || isTypeScriptError(e)) {
384
- throw e;
385
- }
386
- // jiti + ts-node
387
- // issue: https://github.com/nuxt/bridge/issues/228
388
- if (isTsNodeRuntimeEnvironment()) {
389
- output = this.loadSync(input);
390
- } else {
391
- output = this.instance(input);
392
- }
393
- }
394
- return toModuleRecord(output);
395
- }
396
- executeSync(input) {
397
- let output;
398
- try {
399
- output = this.loadSync(input);
400
- } catch (e) {
401
- if (e instanceof SyntaxError || e instanceof ReferenceError || isTypeScriptError(e)) {
402
- throw e;
403
- }
404
- output = this.instance(input);
405
- }
406
- return toModuleRecord(output);
407
- }
408
- // ---------------------------------------------------------------------------
409
- async load(data, options = {}) {
410
- const id = this.build(data, options);
411
- try {
412
- // segmentation fault
413
- // issue: https://github.com/nodejs/node/issues/35889
414
- if (isJestRuntimeEnvironment()) {
415
- // eslint-disable-next-line global-require,import/no-dynamic-require
416
- return require(id);
417
- }
418
- return await import(id);
419
- } catch (e) {
420
- /* istanbul ignore next */ if (isObject(e) && hasStringProperty(e, 'code')) {
421
- if (!options.withFilePrefix && (e.code === 'ERR_UNSUPPORTED_ESM_URL_SCHEME' || e.code === 'UNSUPPORTED_ESM_URL_SCHEME')) {
422
- return this.load(data, {
423
- ...options,
424
- withFilePrefix: true
425
- });
426
- }
427
- throw new BaseError({
428
- code: e.code,
429
- message: hasStringProperty(e, 'message') ? e.message : undefined,
430
- stack: hasStringProperty(e, 'stack') ? e.stack : undefined
431
- });
432
- }
433
- /* istanbul ignore next */ return handleException(e);
434
- }
435
- }
436
- loadSync(data, options = {}) {
437
- const id = this.build(data, options);
438
- try {
439
- // eslint-disable-next-line global-require,import/no-dynamic-require
440
- return require(id);
441
- } catch (e) {
442
- /* istanbul ignore next */ if (isObject(e) && hasStringProperty(e, 'code')) {
443
- throw new BaseError({
444
- code: e.code,
445
- message: hasStringProperty(e, 'message') ? e.message : undefined,
446
- stack: hasStringProperty(e, 'stack') ? e.stack : undefined
447
- });
448
- }
449
- return handleException(e);
450
- }
451
- }
452
- build(data, options = {}) {
453
- if (isLocatorInfo(data) || isFilePath(data)) {
454
- if (typeof data !== 'string') {
455
- data = buildFilePath(data);
456
- }
457
- if (options.withFilePrefix) {
458
- data = pathToFileURL(data).href;
459
- }
460
- }
461
- return data;
462
- }
463
- constructor(){
464
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
465
- // @ts-ignore
466
- this.instance = createJiti(undefined, {
467
- extensions: [
468
- '.js',
469
- '.mjs',
470
- '.mts',
471
- '.cjs',
472
- '.cts',
473
- '.ts'
474
- ]
475
- });
476
- }
477
- }
478
-
479
- class JSONLoader {
480
- async execute(input) {
481
- const filePath = buildFilePath(input);
482
- try {
483
- const file = await fs.promises.readFile(filePath, {
484
- encoding: 'utf-8'
485
- });
486
- return JSON.parse(file);
487
- } catch (e) {
488
- return handleException(e);
489
- }
490
- }
491
- executeSync(input) {
492
- const filePath = buildFilePath(input);
493
- try {
494
- const file = fs.readFileSync(filePath, {
495
- encoding: 'utf-8'
496
- });
497
- return JSON.parse(file);
498
- } catch (e) {
499
- return handleException(e);
500
- }
501
- }
502
- }
503
-
504
- class YAMLLoader {
505
- async execute(input) {
506
- const filePath = buildFilePath(input);
507
- try {
508
- const file = await fs.promises.readFile(filePath, {
509
- encoding: 'utf-8'
510
- });
511
- return parse(file);
512
- } catch (e) {
513
- return handleException(e);
514
- }
515
- }
516
- executeSync(input) {
517
- const filePath = buildFilePath(input);
518
- try {
519
- const file = fs.readFileSync(filePath, {
520
- encoding: 'utf-8'
521
- });
522
- return parse(file);
523
- } catch (e) {
524
- return handleException(e);
525
- }
526
- }
527
- }
528
-
529
- /*
530
- * Copyright (c) 2023.
531
- * Author Peter Placzek (tada5hi)
532
- * For the full copyright and license information,
533
- * view the LICENSE file that was distributed with this source code.
534
- */ var LoaderId = /*#__PURE__*/ function(LoaderId) {
535
- LoaderId["MODULE"] = "module";
536
- LoaderId["JSON"] = "json";
537
- LoaderId["CONF"] = "conf";
538
- LoaderId["YAML"] = "yaml";
539
- return LoaderId;
540
- }({});
541
-
542
- class LoaderManager {
543
- register(test, loader) {
544
- if (typeof loader !== 'undefined') {
545
- this.rules.push({
546
- test,
547
- loader
548
- });
549
- return;
550
- }
551
- this.rules.push(test);
552
- }
553
- async execute(input) {
554
- const id = this.findLoader(input);
555
- if (!id) {
556
- const info = pathToLocatorInfo(input);
557
- throw new Error(`No loader registered for extension: "${info.extension}"`);
558
- }
559
- const loader = this.resolve(id);
560
- return loader.execute(input);
561
- }
562
- executeSync(input) {
563
- const id = this.findLoader(input);
564
- if (!id) {
565
- const info = pathToLocatorInfo(input);
566
- throw new Error(`No loader registered for extension: ${info.extension || 'unknown'}`);
567
- }
568
- const loader = this.resolve(id);
569
- return loader.executeSync(input);
570
- }
571
- findLoader(input) {
572
- if (!isFilePath(input)) {
573
- return LoaderId.MODULE;
574
- }
575
- const info = pathToLocatorInfo(input);
576
- for(let i = 0; i < this.rules.length; i++){
577
- const { test } = this.rules[i];
578
- if (Array.isArray(test)) {
579
- if (info.extension && test.indexOf(info.extension) !== -1) {
580
- return this.rules[i].loader;
581
- }
582
- } else if (test.test(buildFilePath(info))) {
583
- return this.rules[i].loader;
584
- }
585
- }
586
- return undefined;
587
- }
588
- /**
589
- * Resolve loader by id.
590
- *
591
- * @param id
592
- */ resolve(id) {
593
- if (typeof id !== 'string') {
594
- return id;
595
- }
596
- if (Object.prototype.hasOwnProperty.call(this.loaders, id)) {
597
- return this.loaders[id];
598
- }
599
- let loader;
600
- // built-in
601
- switch(id){
602
- case LoaderId.CONF:
603
- {
604
- loader = new ConfLoader();
605
- break;
606
- }
607
- case LoaderId.MODULE:
608
- {
609
- loader = new ModuleLoader();
610
- break;
611
- }
612
- case LoaderId.JSON:
613
- {
614
- loader = new JSONLoader();
615
- break;
616
- }
617
- case LoaderId.YAML:
618
- {
619
- loader = new YAMLLoader();
620
- break;
621
- }
622
- /* istanbul ignore next */ default:
623
- {
624
- const pluginPath = this.normalizePath(id);
625
- const moduleLoader = this.resolve(LoaderId.MODULE);
626
- loader = moduleLoader.executeSync(pluginPath);
627
- break;
628
- }
629
- }
630
- if (typeof loader !== 'undefined') {
631
- this.loaders[id] = loader;
632
- return loader;
633
- }
634
- throw new Error(`The loader ${id} could not be resolved.`);
635
- }
636
- /* istanbul ignore next */ normalizePath(input) {
637
- if (path.isAbsolute(input) || input.startsWith('./')) {
638
- return input;
639
- }
640
- if (input.startsWith('module:')) {
641
- return input.substring(0, 'module:'.length);
642
- }
643
- if (!input.startsWith('@')) {
644
- return `@locter/${input}`;
645
- }
646
- return input;
647
- }
648
- constructor(){
649
- this.loaders = {};
650
- this.rules = [
651
- {
652
- test: [
653
- '.js',
654
- '.mjs',
655
- '.mts',
656
- '.cjs',
657
- '.cts',
658
- '.ts'
659
- ],
660
- loader: LoaderId.MODULE
661
- },
662
- {
663
- test: [
664
- '.conf'
665
- ],
666
- loader: LoaderId.CONF
667
- },
668
- {
669
- test: [
670
- '.json'
671
- ],
672
- loader: LoaderId.JSON
673
- },
674
- {
675
- test: [
676
- '.yml',
677
- '.yaml'
678
- ],
679
- loader: LoaderId.YAML
680
- }
681
- ];
682
- }
683
- }
684
-
415
+ const keys = Object.keys(data);
416
+ for (const key of keys) if (filterFn(key, data[key])) return {
417
+ key,
418
+ value: data[key]
419
+ };
420
+ }
421
+ //#endregion
422
+ //#region src/loader/built-in/module/module.ts
423
+ const require = createRequire(import.meta.url);
424
+ function originalPath(data) {
425
+ return typeof data === "string" ? data : buildFilePath(data);
426
+ }
427
+ function isUnrecoverableError(error) {
428
+ const underlying = error instanceof LocterError ? error.cause : error;
429
+ return underlying instanceof SyntaxError || underlying instanceof ReferenceError || isTypeScriptError(underlying);
430
+ }
431
+ var ModuleLoader = class {
432
+ instance;
433
+ loadFn;
434
+ loadSyncFn;
435
+ constructor(options = {}) {
436
+ this.instance = createJiti(void 0, { extensions: [
437
+ ".js",
438
+ ".mjs",
439
+ ".mts",
440
+ ".cjs",
441
+ ".cts",
442
+ ".ts"
443
+ ] });
444
+ this.loadFn = options.load;
445
+ this.loadSyncFn = options.loadSync;
446
+ }
447
+ configure(options) {
448
+ if ("load" in options) this.loadFn = options.load;
449
+ if ("loadSync" in options) this.loadSyncFn = options.loadSync;
450
+ }
451
+ async execute(input) {
452
+ let output;
453
+ try {
454
+ output = await this.load(input);
455
+ } catch (e) {
456
+ if (isUnrecoverableError(e)) throw e;
457
+ if (isTsNodeRuntimeEnvironment()) output = this.loadSync(input);
458
+ else output = this.instance(input);
459
+ }
460
+ return toModuleRecord(output);
461
+ }
462
+ executeSync(input) {
463
+ let output;
464
+ try {
465
+ output = this.loadSync(input);
466
+ } catch (e) {
467
+ if (isUnrecoverableError(e)) throw e;
468
+ output = this.instance(input);
469
+ }
470
+ return toModuleRecord(output);
471
+ }
472
+ async load(data, options = {}) {
473
+ const id = this.build(data, options);
474
+ try {
475
+ if (this.loadFn) return await this.loadFn(id);
476
+ if (isJestRuntimeEnvironment()) return require(id);
477
+ return await import(id);
478
+ } catch (e) {
479
+ /* istanbul ignore next */
480
+ if (!options.withFilePrefix && isObject(e) && hasStringProperty(e, "code") && (e.code === "ERR_UNSUPPORTED_ESM_URL_SCHEME" || e.code === "UNSUPPORTED_ESM_URL_SCHEME")) return this.load(data, {
481
+ ...options,
482
+ withFilePrefix: true
483
+ });
484
+ throw wrapLoaderError(e, originalPath(data));
485
+ }
486
+ }
487
+ loadSync(data, options = {}) {
488
+ const id = this.build(data, options);
489
+ try {
490
+ if (this.loadSyncFn) return this.loadSyncFn(id);
491
+ return require(id);
492
+ } catch (e) {
493
+ throw wrapLoaderError(e, originalPath(data));
494
+ }
495
+ }
496
+ build(data, options = {}) {
497
+ if (isLocatorInfo(data) || isFilePath(data)) {
498
+ if (typeof data !== "string") data = buildFilePath(data);
499
+ if (options.withFilePrefix) data = pathToFileURL(data).href;
500
+ }
501
+ return data;
502
+ }
503
+ };
504
+ //#endregion
505
+ //#region src/loader/built-in/yaml/module.ts
506
+ var YAMLLoader = class {
507
+ async execute(input) {
508
+ const filePath = buildFilePath(input);
509
+ try {
510
+ return parse(await fs.promises.readFile(filePath, { encoding: "utf-8" }));
511
+ } catch (e) {
512
+ throw wrapLoaderError(e, filePath);
513
+ }
514
+ }
515
+ executeSync(input) {
516
+ const filePath = buildFilePath(input);
517
+ try {
518
+ return parse(fs.readFileSync(filePath, { encoding: "utf-8" }));
519
+ } catch (e) {
520
+ throw wrapLoaderError(e, filePath);
521
+ }
522
+ }
523
+ };
524
+ //#endregion
525
+ //#region src/loader/module.ts
526
+ var LoaderManager = class {
527
+ loaders;
528
+ rules;
529
+ constructor() {
530
+ this.loaders = {};
531
+ this.rules = [
532
+ {
533
+ test: [
534
+ ".js",
535
+ ".mjs",
536
+ ".mts",
537
+ ".cjs",
538
+ ".cts",
539
+ ".ts"
540
+ ],
541
+ loader: "module"
542
+ },
543
+ {
544
+ test: [".conf"],
545
+ loader: "conf"
546
+ },
547
+ {
548
+ test: [".json"],
549
+ loader: "json"
550
+ },
551
+ {
552
+ test: [".yml", ".yaml"],
553
+ loader: "yaml"
554
+ }
555
+ ];
556
+ }
557
+ register(test, loader) {
558
+ if (typeof loader !== "undefined") {
559
+ this.rules.push({
560
+ test,
561
+ loader
562
+ });
563
+ return;
564
+ }
565
+ this.rules.push(test);
566
+ }
567
+ async execute(input) {
568
+ const id = this.findLoader(input);
569
+ if (!id) throw this.unknownExtensionError(input);
570
+ const loader = this.resolve(id);
571
+ try {
572
+ return await loader.execute(input);
573
+ } catch (e) {
574
+ throw wrapLoaderError(e, input);
575
+ }
576
+ }
577
+ executeSync(input) {
578
+ const id = this.findLoader(input);
579
+ if (!id) throw this.unknownExtensionError(input);
580
+ const loader = this.resolve(id);
581
+ try {
582
+ return loader.executeSync(input);
583
+ } catch (e) {
584
+ throw wrapLoaderError(e, input);
585
+ }
586
+ }
587
+ unknownExtensionError(input) {
588
+ return new LocterUnknownExtensionError({
589
+ message: `No loader registered for extension: ${pathToLocatorInfo(input).extension ?? "unknown"}`,
590
+ path: input
591
+ });
592
+ }
593
+ findLoader(input) {
594
+ if (!isFilePath(input)) return "module";
595
+ const info = pathToLocatorInfo(input);
596
+ for (const rule of this.rules) {
597
+ const { test } = rule;
598
+ if (Array.isArray(test)) {
599
+ if (info.extension && test.includes(info.extension)) return rule.loader;
600
+ } else if (test.test(buildFilePath(info))) return rule.loader;
601
+ }
602
+ }
603
+ /**
604
+ * Resolve loader by id.
605
+ *
606
+ * @param id
607
+ */
608
+ resolve(id) {
609
+ if (typeof id !== "string") return id;
610
+ if (Object.prototype.hasOwnProperty.call(this.loaders, id)) return this.loaders[id];
611
+ let loader;
612
+ switch (id) {
613
+ case "conf":
614
+ loader = new ConfLoader();
615
+ break;
616
+ case "module":
617
+ loader = new ModuleLoader();
618
+ break;
619
+ case "json":
620
+ loader = new JSONLoader();
621
+ break;
622
+ case "yaml":
623
+ loader = new YAMLLoader();
624
+ break;
625
+ /* istanbul ignore next */
626
+ default: {
627
+ const pluginPath = this.normalizePath(id);
628
+ loader = this.resolve("module").executeSync(pluginPath);
629
+ break;
630
+ }
631
+ }
632
+ if (typeof loader !== "undefined") {
633
+ this.loaders[id] = loader;
634
+ return loader;
635
+ }
636
+ throw new LocterError({ message: `The loader ${id} could not be resolved.` });
637
+ }
638
+ /* istanbul ignore next */
639
+ normalizePath(input) {
640
+ if (path.isAbsolute(input) || input.startsWith("./")) return input;
641
+ if (input.startsWith("module:")) return input.substring(0, 7);
642
+ if (!input.startsWith("@")) return `@locter/${input}`;
643
+ return input;
644
+ }
645
+ };
646
+ //#endregion
647
+ //#region src/loader/singleton.ts
685
648
  let instance;
686
649
  function useLoader() {
687
- if (typeof instance !== 'undefined') {
688
- return instance;
689
- }
690
- instance = new LoaderManager();
691
- return instance;
650
+ if (typeof instance !== "undefined") return instance;
651
+ instance = new LoaderManager();
652
+ return instance;
692
653
  }
693
-
654
+ //#endregion
655
+ //#region src/loader/helpers.ts
694
656
  function registerLoader(test, loader) {
695
- const manager = useLoader();
696
- if (typeof loader !== 'undefined') {
697
- manager.register(test, loader);
698
- return;
699
- }
700
- manager.register(test);
657
+ const manager = useLoader();
658
+ if (typeof loader !== "undefined") {
659
+ manager.register(test, loader);
660
+ return;
661
+ }
662
+ manager.register(test);
701
663
  }
702
664
  async function load(input) {
703
- const manager = useLoader();
704
- if (typeof input === 'string') {
705
- return manager.execute(input);
706
- }
707
- return manager.execute(buildFilePath(input));
665
+ const manager = useLoader();
666
+ if (typeof input === "string") return manager.execute(input);
667
+ return manager.execute(buildFilePath(input));
708
668
  }
709
669
  function loadSync(input) {
710
- const manager = useLoader();
711
- if (typeof input === 'string') {
712
- return manager.executeSync(input);
713
- }
714
- return manager.executeSync(buildFilePath(input));
715
- }
670
+ const manager = useLoader();
671
+ if (typeof input === "string") return manager.executeSync(input);
672
+ return manager.executeSync(buildFilePath(input));
673
+ }
674
+ /**
675
+ * Override the built-in module loader's `import` / `require` calls.
676
+ *
677
+ * Useful for test runners (e.g. Vitest) where the dynamic `import()` inside
678
+ * `node_modules/locter` would bypass the runner's module graph. Calling this
679
+ * from user code (e.g. a Vitest setup file) lets the runner rewrite the
680
+ * `import()` so loaded modules share identity with statically imported ones.
681
+ *
682
+ * @example
683
+ * ```ts
684
+ * // vitest setup file
685
+ * import { setModuleLoader } from 'locter';
686
+ *
687
+ * setModuleLoader({
688
+ * load: (id) => import(id),
689
+ * });
690
+ * ```
691
+ */
692
+ function setModuleLoader(options) {
693
+ useLoader().resolve("module").configure(options);
694
+ }
695
+ //#endregion
696
+ //#region src/loader/package-field.ts
697
+ function extractField(pkg, field) {
698
+ if (!isObject(pkg) || !hasOwnProperty(pkg, field)) return;
699
+ return pkg[field];
700
+ }
701
+ async function loadPackageField(field, options = {}) {
702
+ let info;
703
+ if (options.walkUp) info = await locateUp("package.json", {
704
+ cwd: options.cwd,
705
+ stopAt: options.stopAt
706
+ });
707
+ else info = await locate("package.json", { cwd: options.cwd });
708
+ if (!info) return;
709
+ try {
710
+ return extractField(await load(info), field);
711
+ } catch (e) {
712
+ if (e instanceof LocterNotFoundError) return;
713
+ throw e;
714
+ }
715
+ }
716
+ function loadPackageFieldSync(field, options = {}) {
717
+ let info;
718
+ if (options.walkUp) info = locateUpSync("package.json", {
719
+ cwd: options.cwd,
720
+ stopAt: options.stopAt
721
+ });
722
+ else info = locateSync("package.json", { cwd: options.cwd });
723
+ if (!info) return;
724
+ try {
725
+ return extractField(loadSync(info), field);
726
+ } catch (e) {
727
+ if (e instanceof LocterNotFoundError) return;
728
+ throw e;
729
+ }
730
+ }
731
+ //#endregion
732
+ export { ConfLoader, JSONLoader, LOCTER_ERROR_MARKER, LOCTER_LOAD_ERROR_MARKER, LOCTER_NOT_FOUND_ERROR_MARKER, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER, LoaderManager, LocterError, LocterLoadError, LocterNotFoundError, LocterUnknownExtensionError, ModuleLoader, YAMLLoader, buildFilePath, buildFilePathWithoutExtension, buildLocatorOptions, buildLocatorPatterns, getFileNameExtension, getModuleExport, hasOwnProperty, hasStringProperty, isESModule, isFilePath, isJestRuntimeEnvironment, isLocatorInfo, isObject, isSafeObjectKey, isTsNodeRuntimeEnvironment, isTypeScriptError, isVitestRuntimeEnvironment, load, loadPackageField, loadPackageFieldSync, loadSync, locate, locateMany, locateManySync, locateSync, locateUp, locateUpSync, pathToLocatorInfo, registerLoader, removeFileNameExtension, setModuleLoader, toArray, toModuleRecord, wrapLoaderError };
716
733
 
717
- export { ConfLoader, JSONLoader, LoaderManager, ModuleLoader, buildFilePath, buildFilePathWithoutExtension, buildLocatorOptions, buildLocatorPatterns, getFileNameExtension, getModuleExport, handleException, hasOwnProperty, hasStringProperty, isESModule, isFilePath, isJestRuntimeEnvironment, isLocatorInfo, isObject, isSafeObjectKey, isTsNodeRuntimeEnvironment, isTypeScriptError, load, loadSync, locate, locateMany, locateManySync, locateSync, pathToLocatorInfo, registerLoader, removeFileNameExtension, toArray, toModuleRecord };
718
- //# sourceMappingURL=index.mjs.map
734
+ //# sourceMappingURL=index.mjs.map