locter 3.0.0 → 4.0.0-beta.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.
- package/README.MD +446 -91
- package/dist/index.d.mts +420 -101
- package/dist/index.mjs +774 -344
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -12
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseError, ErrorOptions } from "@ebec/core";
|
|
2
2
|
import { createJiti } from "jiti";
|
|
3
|
-
|
|
3
|
+
import { ToStringOptions } from "yaml";
|
|
4
4
|
//#region src/errors/base.d.ts
|
|
5
5
|
type LocterErrorOptions = ErrorOptions & {
|
|
6
6
|
path?: string;
|
|
@@ -36,28 +36,13 @@ declare class LocterUnknownExtensionError extends LocterError {
|
|
|
36
36
|
//#endregion
|
|
37
37
|
//#region src/errors/wrap.d.ts
|
|
38
38
|
declare function wrapLoaderError(input: unknown, path: string): LocterError;
|
|
39
|
+
declare function wrapWriteError(input: unknown, path: string): LocterError;
|
|
39
40
|
//#endregion
|
|
40
|
-
//#region src/
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
type Rule = {
|
|
46
|
-
test: RegExp | string[];
|
|
47
|
-
loader: Loader | string;
|
|
48
|
-
};
|
|
49
|
-
//#endregion
|
|
50
|
-
//#region src/loader/built-in/conf/module.d.ts
|
|
51
|
-
declare class ConfLoader implements Loader {
|
|
52
|
-
execute(input: string): Promise<Record<string, any>>;
|
|
53
|
-
executeSync(input: string): Record<string, any>;
|
|
54
|
-
parse(contents: string): Record<string, any>;
|
|
55
|
-
}
|
|
56
|
-
//#endregion
|
|
57
|
-
//#region src/loader/built-in/json/module.d.ts
|
|
58
|
-
declare class JSONLoader implements Loader {
|
|
59
|
-
execute(input: string): Promise<any>;
|
|
60
|
-
executeSync(input: string): any;
|
|
41
|
+
//#region src/errors/write.d.ts
|
|
42
|
+
declare const LOCTER_WRITE_ERROR_MARKER: unique symbol;
|
|
43
|
+
declare class LocterWriteError extends LocterError {
|
|
44
|
+
static [Symbol.hasInstance](input: unknown): boolean;
|
|
45
|
+
constructor(input?: LocterErrorInput);
|
|
61
46
|
}
|
|
62
47
|
//#endregion
|
|
63
48
|
//#region src/locator/types.d.ts
|
|
@@ -96,15 +81,123 @@ declare function locateUp(pattern: string | string[], options?: LocatorUpOptions
|
|
|
96
81
|
declare function locateUpSync(pattern: string | string[], options?: LocatorUpOptionsInput): LocatorInfo | undefined;
|
|
97
82
|
//#endregion
|
|
98
83
|
//#region src/locator/utils.d.ts
|
|
99
|
-
declare function buildLocatorPatterns(pattern: string | string[]): string[];
|
|
100
|
-
declare function buildLocatorOptions(options?: LocatorOptionsInput): LocatorOptions;
|
|
101
|
-
declare function pathToLocatorInfo(input: string, skipResolve?: boolean): LocatorInfo;
|
|
102
84
|
declare function isLocatorInfo(input: unknown): input is LocatorInfo;
|
|
103
85
|
declare function buildFilePath(input: LocatorInfo | string): string;
|
|
104
|
-
declare function buildFilePathWithoutExtension(input: LocatorInfo | string): string;
|
|
105
86
|
//#endregion
|
|
106
|
-
//#region src/
|
|
107
|
-
|
|
87
|
+
//#region src/utils/twin.d.ts
|
|
88
|
+
/**
|
|
89
|
+
* Internal protocol to derive the parallel sync + async public surfaces
|
|
90
|
+
* from one shared body. A body is a generator that yields effect pairs —
|
|
91
|
+
* an async and a sync thunk for the same operation — and the two drivers
|
|
92
|
+
* (runTwinAsync / runTwinSync) execute the side they stand for. Effect
|
|
93
|
+
* errors are re-entered into the body via `Generator.throw`, so try/catch
|
|
94
|
+
* inside a body behaves identically in both variants.
|
|
95
|
+
*
|
|
96
|
+
* Deliberately NOT exported from the utils barrel — this is internal
|
|
97
|
+
* plumbing, not public API.
|
|
98
|
+
*/
|
|
99
|
+
type TwinOp<T = unknown> = {
|
|
100
|
+
async: () => Promise<T>;
|
|
101
|
+
sync: () => T;
|
|
102
|
+
};
|
|
103
|
+
type TwinBody<R> = Generator<TwinOp<any>, R, any>;
|
|
104
|
+
//#endregion
|
|
105
|
+
//#region src/format/type.d.ts
|
|
106
|
+
interface IReader {
|
|
107
|
+
read: (input: string) => Promise<any>;
|
|
108
|
+
readSync: (input: string) => any;
|
|
109
|
+
}
|
|
110
|
+
interface IWriter {
|
|
111
|
+
write: (path: string, value: unknown) => Promise<void>;
|
|
112
|
+
writeSync: (path: string, value: unknown) => void;
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
//#region src/format/text-file/reader.d.ts
|
|
116
|
+
/**
|
|
117
|
+
* Base class for readers of text-based file formats: reads the file as
|
|
118
|
+
* UTF-8, delegates to `parse`, and wraps I/O and parse errors in typed
|
|
119
|
+
* LocterError subclasses. Subclasses implement `parse` only — both
|
|
120
|
+
* `read` variants are derived from the same body.
|
|
121
|
+
*/
|
|
122
|
+
declare abstract class TextFileReader implements IReader {
|
|
123
|
+
abstract parse(content: string): any;
|
|
124
|
+
read(input: string): Promise<any>;
|
|
125
|
+
readSync(input: string): any;
|
|
126
|
+
protected body(input: string): TwinBody<any>;
|
|
127
|
+
}
|
|
128
|
+
//#endregion
|
|
129
|
+
//#region src/format/text-file/writer.d.ts
|
|
130
|
+
/**
|
|
131
|
+
* Base class for writers of text-based file formats: serializes via
|
|
132
|
+
* `stringify`, creates missing parent directories, writes the file as
|
|
133
|
+
* UTF-8 (always terminated by a single trailing newline), and wraps
|
|
134
|
+
* failures in LocterWriteError. Subclasses implement `stringify` only —
|
|
135
|
+
* both `write` variants are derived from the same body.
|
|
136
|
+
*/
|
|
137
|
+
declare abstract class TextFileWriter implements IWriter {
|
|
138
|
+
/**
|
|
139
|
+
* Opt-in: when true, the body reads the target file first (undefined
|
|
140
|
+
* if absent) and passes its content to `stringify` as `existing` —
|
|
141
|
+
* the hook behind format-preserving write-back (YAML comment
|
|
142
|
+
* grafting, JSON indent detection).
|
|
143
|
+
*/
|
|
144
|
+
protected get usesExistingContent(): boolean;
|
|
145
|
+
abstract stringify(value: unknown, existing?: string): string;
|
|
146
|
+
write(input: string, value: unknown): Promise<void>;
|
|
147
|
+
writeSync(input: string, value: unknown): void;
|
|
148
|
+
protected body(input: string, value: unknown): TwinBody<void>;
|
|
149
|
+
}
|
|
150
|
+
//#endregion
|
|
151
|
+
//#region src/format/built-in/conf/reader.d.ts
|
|
152
|
+
declare class ConfReader extends TextFileReader {
|
|
153
|
+
parse(contents: string): Record<string, any>;
|
|
154
|
+
}
|
|
155
|
+
//#endregion
|
|
156
|
+
//#region src/format/built-in/conf/writer.d.ts
|
|
157
|
+
/**
|
|
158
|
+
* Serializes an object to `key=value` lines (the inverse of ConfReader):
|
|
159
|
+
* nested objects become dot-separated keys, arrays become repeated
|
|
160
|
+
* `key[]=` lines. Round-trips are structural, not textual — comments,
|
|
161
|
+
* blank lines, and line order of an existing file are not preserved,
|
|
162
|
+
* and a string that parses as another type (e.g. '123') reads back as
|
|
163
|
+
* that type.
|
|
164
|
+
*/
|
|
165
|
+
declare class ConfWriter extends TextFileWriter {
|
|
166
|
+
stringify(value: unknown): string;
|
|
167
|
+
}
|
|
168
|
+
//#endregion
|
|
169
|
+
//#region src/format/built-in/json/reader.d.ts
|
|
170
|
+
declare class JSONReader extends TextFileReader {
|
|
171
|
+
parse(content: string): any;
|
|
172
|
+
}
|
|
173
|
+
//#endregion
|
|
174
|
+
//#region src/format/built-in/json/writer.d.ts
|
|
175
|
+
type JSONWriterOptions = {
|
|
176
|
+
/**
|
|
177
|
+
* Indentation of the emitted JSON. A number of spaces, a literal
|
|
178
|
+
* indent string, or 'auto' — detect the indentation of the existing
|
|
179
|
+
* target file and keep it (falls back to 4 for new files).
|
|
180
|
+
*
|
|
181
|
+
* @default 4
|
|
182
|
+
*/
|
|
183
|
+
indent?: number | string | 'auto';
|
|
184
|
+
};
|
|
185
|
+
declare class JSONWriter extends TextFileWriter {
|
|
186
|
+
protected options: JSONWriterOptions;
|
|
187
|
+
constructor(options?: JSONWriterOptions);
|
|
188
|
+
protected get usesExistingContent(): boolean;
|
|
189
|
+
stringify(value: unknown, existing?: string): string;
|
|
190
|
+
}
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region src/format/built-in/module/constants.d.ts
|
|
193
|
+
/**
|
|
194
|
+
* Single source of truth for the extensions handled by the module loader:
|
|
195
|
+
* consumed by BOTH the built-in routing registry and the jiti config.
|
|
196
|
+
*/
|
|
197
|
+
declare const MODULE_FILE_EXTENSIONS: readonly [".js", ".mjs", ".mts", ".cjs", ".cts", ".ts"];
|
|
198
|
+
//#endregion
|
|
199
|
+
//#region src/format/built-in/module/type.d.ts
|
|
200
|
+
type ModuleExportFilterFn = (key: string, value: unknown) => boolean;
|
|
108
201
|
type ModuleExport = {
|
|
109
202
|
key: string;
|
|
110
203
|
value: any;
|
|
@@ -114,7 +207,7 @@ type ModuleLoadOptions = {
|
|
|
114
207
|
};
|
|
115
208
|
type ModuleLoadFn = (id: string) => unknown | Promise<unknown>;
|
|
116
209
|
type ModuleLoadSyncFn = (id: string) => unknown;
|
|
117
|
-
type
|
|
210
|
+
type ModuleReaderOptions = {
|
|
118
211
|
/**
|
|
119
212
|
* Custom asynchronous module loader. When set, this replaces the
|
|
120
213
|
* built-in `await import(id)` call. Useful for test runners (e.g. Vitest)
|
|
@@ -130,115 +223,341 @@ type ModuleLoaderOptions = {
|
|
|
130
223
|
loadSync?: ModuleLoadSyncFn;
|
|
131
224
|
};
|
|
132
225
|
//#endregion
|
|
133
|
-
//#region src/
|
|
226
|
+
//#region src/format/built-in/module/reader.d.ts
|
|
134
227
|
type Jiti = ReturnType<typeof createJiti>;
|
|
135
|
-
declare class
|
|
228
|
+
declare class ModuleReader implements IReader {
|
|
136
229
|
protected instance: Jiti;
|
|
137
230
|
protected loadFn?: ModuleLoadFn;
|
|
138
231
|
protected loadSyncFn?: ModuleLoadSyncFn;
|
|
139
|
-
constructor(options?:
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
232
|
+
constructor(options?: ModuleReaderOptions);
|
|
233
|
+
/**
|
|
234
|
+
* Returns the previous configuration, so callers can restore it.
|
|
235
|
+
*/
|
|
236
|
+
configure(options: ModuleReaderOptions): ModuleReaderOptions;
|
|
237
|
+
/**
|
|
238
|
+
* Returns the raw module value (import / require / jiti output) —
|
|
239
|
+
* normalization to a module record happens once, at the
|
|
240
|
+
* FormatRegistry boundary.
|
|
241
|
+
*
|
|
242
|
+
* read/readSync are deliberately NOT derived from a shared body
|
|
243
|
+
* (unlike every other sync/async twin in this package): their
|
|
244
|
+
* recovery paths differ. The async variant falls back to loadSync
|
|
245
|
+
* under ts-node (jiti's async path does not cooperate with ts-node)
|
|
246
|
+
* and to the jiti instance otherwise; the sync variant only has the
|
|
247
|
+
* jiti fallback. The divergence is pinned by the fallback tests in
|
|
248
|
+
* test/unit/format/module.spec.ts.
|
|
249
|
+
*/
|
|
250
|
+
read(input: string): Promise<any>;
|
|
251
|
+
readSync(input: string): any;
|
|
143
252
|
load(data: LocatorInfo | string, options?: ModuleLoadOptions): Promise<unknown>;
|
|
144
253
|
loadSync(data: LocatorInfo | string, options?: ModuleLoadOptions): unknown;
|
|
145
254
|
private build;
|
|
146
255
|
}
|
|
147
256
|
//#endregion
|
|
148
|
-
//#region src/
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
257
|
+
//#region src/format/built-in/module/utils.d.ts
|
|
258
|
+
/**
|
|
259
|
+
* True when the value is a record produced by locter's read()/toModuleRecord.
|
|
260
|
+
* Detection is brand-based; a plain object with an `__esModule` key is NOT
|
|
261
|
+
* a module record.
|
|
262
|
+
*/
|
|
263
|
+
declare function isModuleRecord(input: unknown): input is Record<string, any>;
|
|
264
|
+
declare function getModuleExport(data: Record<string, any>, filterFn: ModuleExportFilterFn): ModuleExport | undefined;
|
|
265
|
+
//#endregion
|
|
266
|
+
//#region src/format/built-in/yaml/reader.d.ts
|
|
267
|
+
declare class YAMLReader extends TextFileReader {
|
|
268
|
+
parse(content: string): any;
|
|
269
|
+
}
|
|
270
|
+
//#endregion
|
|
271
|
+
//#region src/format/built-in/yaml/writer.d.ts
|
|
272
|
+
type YAMLWriterOptions = ToStringOptions;
|
|
273
|
+
/**
|
|
274
|
+
* Writes YAML preserving hand-edited structure where possible: when the
|
|
275
|
+
* target file already exists, the new value is grafted into its parsed
|
|
276
|
+
* document, so comments and anchors attached to surviving keys survive
|
|
277
|
+
* the write-back. New files are plain `yaml.stringify` output. An
|
|
278
|
+
* existing file that fails to parse throws (wrapped as LocterWriteError)
|
|
279
|
+
* instead of being silently overwritten.
|
|
280
|
+
*/
|
|
281
|
+
declare class YAMLWriter extends TextFileWriter {
|
|
282
|
+
protected options: YAMLWriterOptions;
|
|
283
|
+
constructor(options?: YAMLWriterOptions);
|
|
284
|
+
protected get usesExistingContent(): boolean;
|
|
285
|
+
stringify(value: unknown, existing?: string): string;
|
|
286
|
+
}
|
|
287
|
+
//#endregion
|
|
288
|
+
//#region src/format/built-in/registry.d.ts
|
|
289
|
+
/**
|
|
290
|
+
* Every built-in format, in one place. Keys are the format ids; each entry
|
|
291
|
+
* couples routing and construction. The id union, the extension → format
|
|
292
|
+
* table, lazy caching, and the typed `builtInReader()` accessor are all
|
|
293
|
+
* DERIVED from this object. Adding a format = adding one entry.
|
|
294
|
+
*
|
|
295
|
+
* Intentionally NOT re-exported from any barrel (internal API).
|
|
296
|
+
*/
|
|
297
|
+
declare const BUILT_IN_PRESETS: {
|
|
298
|
+
readonly module: {
|
|
299
|
+
readonly extensions: readonly [".js", ".mjs", ".mts", ".cjs", ".cts", ".ts"];
|
|
300
|
+
readonly reader: () => ModuleReader;
|
|
301
|
+
};
|
|
302
|
+
readonly conf: {
|
|
303
|
+
readonly extensions: readonly [".conf"];
|
|
304
|
+
readonly reader: () => ConfReader;
|
|
305
|
+
readonly writer: () => ConfWriter;
|
|
306
|
+
};
|
|
307
|
+
readonly json: {
|
|
308
|
+
readonly extensions: readonly [".json"];
|
|
309
|
+
readonly reader: () => JSONReader;
|
|
310
|
+
readonly writer: () => JSONWriter;
|
|
311
|
+
};
|
|
312
|
+
readonly yaml: {
|
|
313
|
+
readonly extensions: readonly [".yml", ".yaml"];
|
|
314
|
+
readonly reader: () => YAMLReader;
|
|
315
|
+
readonly writer: () => YAMLWriter;
|
|
316
|
+
};
|
|
317
|
+
};
|
|
318
|
+
type BuiltInFormatId = keyof typeof BUILT_IN_PRESETS;
|
|
319
|
+
type BuiltInReaderOf<K extends BuiltInFormatId> = ReturnType<(typeof BUILT_IN_PRESETS)[K]['reader']>;
|
|
320
|
+
/**
|
|
321
|
+
* Built-in format ids whose preset declares a writer — derived at the type
|
|
322
|
+
* level, so builtInWriter('module') is a compile error, not a runtime one.
|
|
323
|
+
*/
|
|
324
|
+
type WritableBuiltInFormatId = { [K in BuiltInFormatId]: (typeof BUILT_IN_PRESETS)[K] extends {
|
|
325
|
+
writer: () => IWriter;
|
|
326
|
+
} ? K : never; }[BuiltInFormatId];
|
|
327
|
+
type BuiltInWriterOf<K extends WritableBuiltInFormatId> = ReturnType<(typeof BUILT_IN_PRESETS)[K]['writer']>;
|
|
328
|
+
//#endregion
|
|
329
|
+
//#region src/format/registry/type.d.ts
|
|
330
|
+
/**
|
|
331
|
+
* Lazy reader construction. Invoked on the first input that matches the
|
|
332
|
+
* rule it was registered for; the first successfully constructed reader
|
|
333
|
+
* is cached (a factory that throws is retried on the next match).
|
|
334
|
+
*/
|
|
335
|
+
type ReaderFactory = () => IReader;
|
|
336
|
+
/**
|
|
337
|
+
* Lazy writer construction — same lifecycle as ReaderFactory.
|
|
338
|
+
*/
|
|
339
|
+
type WriterFactory = () => IWriter;
|
|
340
|
+
/**
|
|
341
|
+
* A user-registered dispatch rule. Rules are matched in registration order,
|
|
342
|
+
* BEFORE the built-in extension table (i.e. user rules override built-ins).
|
|
343
|
+
* Rules only ever see file paths — bare module specifiers (no extension)
|
|
344
|
+
* are always routed to the module reader first.
|
|
345
|
+
*
|
|
346
|
+
* The reader and writer slots are independent: read dispatch only
|
|
347
|
+
* considers rules with a reader, write dispatch only rules with a writer.
|
|
348
|
+
* A reader-only rule for '.json' overrides how '.json' is read without
|
|
349
|
+
* shadowing the built-in JSON writer (and vice versa). At least one slot
|
|
350
|
+
* is required.
|
|
351
|
+
*/
|
|
352
|
+
type Rule = {
|
|
353
|
+
/**
|
|
354
|
+
* Stable identity. Registering an existing id REPLACES that rule in
|
|
355
|
+
* place (position preserved, cached instance evicted). Built-in ids
|
|
356
|
+
* ('module', 'conf', 'json', 'yaml') are reserved. Omitted → auto-generated.
|
|
357
|
+
*/
|
|
358
|
+
id?: string;
|
|
359
|
+
test: RegExp | string[];
|
|
360
|
+
reader?: IReader | ReaderFactory;
|
|
361
|
+
writer?: IWriter | WriterFactory;
|
|
362
|
+
};
|
|
363
|
+
/**
|
|
364
|
+
* Normalized registration record — returned by register()/entries().
|
|
365
|
+
*/
|
|
366
|
+
type FormatRegistration = {
|
|
367
|
+
id: string;
|
|
368
|
+
test: RegExp | string[];
|
|
369
|
+
/**
|
|
370
|
+
* true for entries derived from the built-in registry; those cannot
|
|
371
|
+
* be unregistered (but can be shadowed by user rules).
|
|
372
|
+
*/
|
|
373
|
+
builtIn: boolean;
|
|
374
|
+
};
|
|
375
|
+
/**
|
|
376
|
+
* One built-in format: routing (extensions) + instantiation (reader and
|
|
377
|
+
* optional writer), inseparable by construction. A preset without a
|
|
378
|
+
* writer is a read-only format (e.g. module).
|
|
379
|
+
*/
|
|
380
|
+
type FormatPreset = {
|
|
381
|
+
/** Extensions (with leading dot) routed to this format. Must be disjoint across presets. */
|
|
382
|
+
extensions: readonly string[];
|
|
383
|
+
/** Lazy reader factory — invoked at most once per FormatRegistry instance. */
|
|
384
|
+
reader: () => IReader;
|
|
385
|
+
/** Lazy writer factory — invoked at most once per FormatRegistry instance. */
|
|
386
|
+
writer?: () => IWriter;
|
|
152
387
|
};
|
|
153
|
-
declare function isESModule(input: unknown): input is ESModule;
|
|
154
|
-
declare function toModuleRecord(data: unknown): any;
|
|
155
|
-
declare function getModuleExport(data: Record<string, any>, filterFn: LoaderFilterFn): ModuleExport | undefined;
|
|
156
388
|
//#endregion
|
|
157
|
-
//#region src/
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
389
|
+
//#region src/format/registry/module.d.ts
|
|
390
|
+
type FormatRegistryOptions = {
|
|
391
|
+
/**
|
|
392
|
+
* Seed user rules (matched before built-ins, in array order).
|
|
393
|
+
*/
|
|
394
|
+
rules?: Rule[];
|
|
395
|
+
};
|
|
396
|
+
/**
|
|
397
|
+
* A rule compiled to memoizing per-slot accessors. Caller-owned Rule
|
|
398
|
+
* objects are never mutated; factory caching lives in the closures.
|
|
399
|
+
*/
|
|
400
|
+
type CompiledRule = {
|
|
401
|
+
id: string;
|
|
402
|
+
test: RegExp | string[];
|
|
403
|
+
getReader?: () => IReader;
|
|
404
|
+
getWriter?: () => IWriter;
|
|
405
|
+
};
|
|
406
|
+
declare class FormatRegistry {
|
|
407
|
+
/**
|
|
408
|
+
* User rules only — built-ins live in the extension table instead.
|
|
409
|
+
*/
|
|
410
|
+
protected rules: CompiledRule[];
|
|
411
|
+
/**
|
|
412
|
+
* Lazy per-instance cache of built-in reader instances.
|
|
413
|
+
*/
|
|
414
|
+
protected builtInReaderCache: Map<BuiltInFormatId, IReader>;
|
|
415
|
+
/**
|
|
416
|
+
* Lazy per-instance cache of built-in writer instances.
|
|
417
|
+
*/
|
|
418
|
+
protected builtInWriterCache: Map<BuiltInFormatId, IWriter>;
|
|
419
|
+
/**
|
|
420
|
+
* extension → built-in format id, precomputed once from BUILT_IN_PRESETS.
|
|
421
|
+
*/
|
|
422
|
+
protected builtInExtensions: Map<string, BuiltInFormatId>;
|
|
423
|
+
protected ruleCounter: number;
|
|
424
|
+
constructor(options?: FormatRegistryOptions);
|
|
425
|
+
register(rule: Rule): FormatRegistration;
|
|
426
|
+
/**
|
|
427
|
+
* Remove a user-registered rule by id. Built-in ids cannot be
|
|
428
|
+
* unregistered (returns false).
|
|
429
|
+
*/
|
|
430
|
+
unregister(id: string): boolean;
|
|
431
|
+
has(id: string): boolean;
|
|
432
|
+
/**
|
|
433
|
+
* All registrations in effective match order: user rules
|
|
434
|
+
* (registration order) first, then the built-ins.
|
|
435
|
+
*/
|
|
436
|
+
entries(): FormatRegistration[];
|
|
437
|
+
/**
|
|
438
|
+
* Restore the registry to its construction state: drop all user rules
|
|
439
|
+
* and evict every cached reader instance (including a module reader
|
|
440
|
+
* configured via setModuleReader / configure).
|
|
441
|
+
*/
|
|
442
|
+
reset(): void;
|
|
443
|
+
read(input: LocatorInfo | string): Promise<any>;
|
|
444
|
+
readSync(input: LocatorInfo | string): any;
|
|
445
|
+
/**
|
|
446
|
+
* Shared body of read/readSync: dispatch, read, normalize, wrap.
|
|
447
|
+
*/
|
|
448
|
+
protected readBody(input: LocatorInfo | string): TwinBody<any>;
|
|
449
|
+
write(input: LocatorInfo | string, value: unknown): Promise<void>;
|
|
450
|
+
writeSync(input: LocatorInfo | string, value: unknown): void;
|
|
451
|
+
/**
|
|
452
|
+
* Shared body of write/writeSync: dispatch, unwrap records, write, wrap.
|
|
453
|
+
* The inverse boundary of readBody: a record produced by read() (brand
|
|
454
|
+
* detected) is unwrapped to its `.default` value; anything else is
|
|
455
|
+
* written as-is.
|
|
456
|
+
*/
|
|
457
|
+
protected writeBody(input: LocatorInfo | string, value: unknown): TwinBody<void>;
|
|
458
|
+
/**
|
|
459
|
+
* The single normalization boundary: every read result becomes a module
|
|
460
|
+
* record (`.default` is always the loaded value, top-level keys stay
|
|
461
|
+
* accessible as named exports). Provenance decides how: module-reader
|
|
462
|
+
* output may legitimately already be a record (`__esModule` is meaningful
|
|
463
|
+
* there); any other reader returns arbitrary parsed data, which is always
|
|
464
|
+
* wrapped — even if it happens to contain an `__esModule` key.
|
|
465
|
+
*/
|
|
466
|
+
protected toRecord(output: unknown, reader: IReader): any;
|
|
467
|
+
/**
|
|
468
|
+
* Typed accessor for the LIVE built-in reader instance (lazy, cached).
|
|
469
|
+
*/
|
|
470
|
+
builtInReader<K extends BuiltInFormatId>(id: K): BuiltInReaderOf<K>;
|
|
471
|
+
/**
|
|
472
|
+
* Typed accessor for the LIVE built-in writer instance (lazy, cached).
|
|
473
|
+
* Only writable format ids are accepted — read-only formats (module)
|
|
474
|
+
* are a compile error.
|
|
475
|
+
*/
|
|
476
|
+
builtInWriter<K extends WritableBuiltInFormatId>(id: K): BuiltInWriterOf<K>;
|
|
477
|
+
/**
|
|
478
|
+
* Dispatch order:
|
|
479
|
+
* 1. bare specifier (no extension) → module reader, always
|
|
480
|
+
* 2. user rules, registration order → first match wins (can override built-ins)
|
|
481
|
+
* 3. built-in extension table
|
|
482
|
+
* 4. undefined → read/readSync throw LocterUnknownExtensionError
|
|
483
|
+
*/
|
|
484
|
+
findReader(input: string): IReader | undefined;
|
|
485
|
+
/**
|
|
486
|
+
* Write-side dispatch. No bare-specifier step (there is nothing to
|
|
487
|
+
* write to); only rules with a writer slot participate, then built-in
|
|
488
|
+
* presets that declare a writer.
|
|
489
|
+
*/
|
|
490
|
+
findWriter(input: string): IWriter | undefined;
|
|
491
|
+
protected findRule(input: string, filter: (rule: CompiledRule) => boolean): CompiledRule | undefined;
|
|
492
|
+
protected findBuiltInId(input: string): BuiltInFormatId | undefined;
|
|
493
|
+
protected unknownExtensionError(input: string): LocterUnknownExtensionError;
|
|
494
|
+
protected compile(id: string, rule: Rule): CompiledRule;
|
|
495
|
+
protected generateRuleId(): string;
|
|
161
496
|
}
|
|
162
497
|
//#endregion
|
|
163
|
-
//#region src/
|
|
164
|
-
declare function
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
declare function
|
|
498
|
+
//#region src/format/registry/singleton.d.ts
|
|
499
|
+
declare function useFormatRegistry(): FormatRegistry;
|
|
500
|
+
//#endregion
|
|
501
|
+
//#region src/format/helpers.d.ts
|
|
502
|
+
declare function registerFormat(rule: Rule): FormatRegistration;
|
|
503
|
+
/**
|
|
504
|
+
* Remove a rule from the process-global registry by its id
|
|
505
|
+
* (as returned by registerFormat). Built-in ids cannot be unregistered.
|
|
506
|
+
*/
|
|
507
|
+
declare function unregisterFormat(id: string): boolean;
|
|
508
|
+
declare function read(input: LocatorInfo | string): Promise<any>;
|
|
509
|
+
declare function readSync(input: LocatorInfo | string): any;
|
|
510
|
+
declare function write(input: LocatorInfo | string, value: unknown): Promise<void>;
|
|
511
|
+
declare function writeSync(input: LocatorInfo | string, value: unknown): void;
|
|
168
512
|
/**
|
|
169
|
-
* Override the built-in module
|
|
513
|
+
* Override the built-in module reader's `import` / `require` calls.
|
|
170
514
|
*
|
|
171
515
|
* Useful for test runners (e.g. Vitest) where the dynamic `import()` inside
|
|
172
516
|
* `node_modules/locter` would bypass the runner's module graph. Calling this
|
|
173
517
|
* from user code (e.g. a Vitest setup file) lets the runner rewrite the
|
|
174
518
|
* `import()` so loaded modules share identity with statically imported ones.
|
|
175
519
|
*
|
|
520
|
+
* Returns a restore function that re-applies the previous configuration —
|
|
521
|
+
* handy for scoped overrides (e.g. test teardown). The restore function is
|
|
522
|
+
* scoped to the exact reader instance it configured: after a registry
|
|
523
|
+
* reset() (which discards that instance) it becomes a no-op instead of
|
|
524
|
+
* re-applying stale configuration to the fresh instance.
|
|
525
|
+
*
|
|
176
526
|
* @example
|
|
177
527
|
* ```ts
|
|
178
528
|
* // vitest setup file
|
|
179
|
-
* import {
|
|
529
|
+
* import { setModuleReader } from 'locter';
|
|
180
530
|
*
|
|
181
|
-
*
|
|
531
|
+
* setModuleReader({
|
|
182
532
|
* load: (id) => import(id),
|
|
183
533
|
* });
|
|
184
534
|
* ```
|
|
185
535
|
*/
|
|
186
|
-
declare function
|
|
187
|
-
//#endregion
|
|
188
|
-
//#region src/loader/module.d.ts
|
|
189
|
-
declare class LoaderManager implements Loader {
|
|
190
|
-
protected loaders: Record<string, Loader>;
|
|
191
|
-
protected rules: Rule[];
|
|
192
|
-
constructor();
|
|
193
|
-
register(rule: Rule): void;
|
|
194
|
-
register(test: string[] | RegExp, loader: Loader): void;
|
|
195
|
-
execute(input: string): Promise<any>;
|
|
196
|
-
executeSync(input: string): any;
|
|
197
|
-
protected unknownExtensionError(input: string): LocterUnknownExtensionError;
|
|
198
|
-
findLoader(input: string): Loader | string | undefined;
|
|
199
|
-
/**
|
|
200
|
-
* Resolve loader by id.
|
|
201
|
-
*
|
|
202
|
-
* @param id
|
|
203
|
-
*/
|
|
204
|
-
resolve(id: string | Loader): Loader;
|
|
205
|
-
normalizePath(input: string): string;
|
|
206
|
-
}
|
|
536
|
+
declare function setModuleReader(options: ModuleReaderOptions): () => void;
|
|
207
537
|
//#endregion
|
|
208
|
-
//#region src/
|
|
209
|
-
type
|
|
538
|
+
//#region src/format/package-field.d.ts
|
|
539
|
+
type ReadPackageFieldOptions = {
|
|
210
540
|
cwd?: string;
|
|
211
541
|
walkUp?: boolean;
|
|
212
542
|
stopAt?: string;
|
|
213
543
|
};
|
|
214
|
-
|
|
215
|
-
declare function
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
declare function
|
|
224
|
-
|
|
225
|
-
//#region src/utils/object.d.ts
|
|
226
|
-
declare function isObject(item: unknown): item is Record<string, any>;
|
|
227
|
-
declare function isSafeObjectKey(key: string): boolean;
|
|
228
|
-
//#endregion
|
|
229
|
-
//#region src/utils/to-array.d.ts
|
|
230
|
-
declare function toArray(input: string | string[]): string[];
|
|
231
|
-
//#endregion
|
|
232
|
-
//#region src/utils/file-path.d.ts
|
|
233
|
-
declare function isFilePath(input: string): boolean | "";
|
|
544
|
+
type WritePackageFieldOptions = ReadPackageFieldOptions;
|
|
545
|
+
declare function readPackageField<T = unknown>(field: string, options?: ReadPackageFieldOptions): Promise<T | undefined>;
|
|
546
|
+
declare function readPackageFieldSync<T = unknown>(field: string, options?: ReadPackageFieldOptions): T | undefined;
|
|
547
|
+
/**
|
|
548
|
+
* Set a top-level field of the nearest `package.json` (same locate
|
|
549
|
+
* semantics as readPackageField) and write it back, preserving the
|
|
550
|
+
* file's existing indentation. Passing `undefined` removes the field.
|
|
551
|
+
* Throws LocterNotFoundError when no package.json could be located.
|
|
552
|
+
*/
|
|
553
|
+
declare function writePackageField(field: string, value: unknown, options?: WritePackageFieldOptions): Promise<void>;
|
|
554
|
+
declare function writePackageFieldSync(field: string, value: unknown, options?: WritePackageFieldOptions): void;
|
|
234
555
|
//#endregion
|
|
235
556
|
//#region src/utils/runtime.d.ts
|
|
236
557
|
declare function isJestRuntimeEnvironment(): boolean;
|
|
237
558
|
declare function isVitestRuntimeEnvironment(): boolean;
|
|
238
559
|
declare function isTsNodeRuntimeEnvironment(): boolean;
|
|
560
|
+
declare function isTsxRuntimeEnvironment(): boolean;
|
|
239
561
|
//#endregion
|
|
240
|
-
|
|
241
|
-
declare function isTypeScriptError(input: unknown): input is Error;
|
|
242
|
-
//#endregion
|
|
243
|
-
export { ConfLoader, JSONLoader, LOCTER_ERROR_MARKER, LOCTER_LOAD_ERROR_MARKER, LOCTER_NOT_FOUND_ERROR_MARKER, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER, LoadPackageFieldOptions, LoaderFilterFn, LoaderManager, LocatorInfo, LocatorOptions, LocatorOptionsInput, LocatorUpOptionsInput, LocterError, LocterErrorInput, LocterErrorOptions, LocterLoadError, LocterNotFoundError, LocterUnknownExtensionError, ModuleExport, ModuleLoadFn, ModuleLoadOptions, ModuleLoadSyncFn, ModuleLoader, ModuleLoaderOptions, 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 };
|
|
562
|
+
export { ConfReader, ConfWriter, type FormatPreset, type FormatRegistration, FormatRegistry, type FormatRegistryOptions, type IReader, type IWriter, JSONReader, JSONWriter, type JSONWriterOptions, LOCTER_ERROR_MARKER, LOCTER_LOAD_ERROR_MARKER, LOCTER_NOT_FOUND_ERROR_MARKER, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER, LOCTER_WRITE_ERROR_MARKER, type LocatorInfo, type LocatorOptions, type LocatorOptionsInput, type LocatorUpOptionsInput, LocterError, type LocterErrorInput, type LocterErrorOptions, LocterLoadError, LocterNotFoundError, LocterUnknownExtensionError, LocterWriteError, MODULE_FILE_EXTENSIONS, type ModuleExport, type ModuleExportFilterFn, type ModuleLoadFn, type ModuleLoadOptions, type ModuleLoadSyncFn, ModuleReader, type ModuleReaderOptions, type ReadPackageFieldOptions, type ReaderFactory, type Rule, TextFileReader, TextFileWriter, type WritePackageFieldOptions, type WriterFactory, YAMLReader, YAMLWriter, type YAMLWriterOptions, buildFilePath, getModuleExport, isJestRuntimeEnvironment, isLocatorInfo, isModuleRecord, isTsNodeRuntimeEnvironment, isTsxRuntimeEnvironment, isVitestRuntimeEnvironment, locate, locateMany, locateManySync, locateSync, locateUp, locateUpSync, read, readPackageField, readPackageFieldSync, readSync, registerFormat, setModuleReader, unregisterFormat, useFormatRegistry, wrapLoaderError, wrapWriteError, write, writePackageField, writePackageFieldSync, writeSync };
|
|
244
563
|
//# sourceMappingURL=index.d.mts.map
|