locter 2.2.1 → 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 +581 -44
- package/dist/index.d.mts +563 -0
- package/dist/index.mjs +1117 -671
- package/dist/index.mjs.map +1 -1
- package/package.json +36 -40
- package/dist/index.cjs +0 -743
- package/dist/index.cjs.map +0 -1
- package/dist/index.d.ts +0 -3
- package/dist/loader/built-in/conf/index.d.ts +0 -1
- package/dist/loader/built-in/conf/module.d.ts +0 -6
- package/dist/loader/built-in/index.d.ts +0 -3
- package/dist/loader/built-in/json/index.d.ts +0 -1
- package/dist/loader/built-in/json/module.d.ts +0 -5
- package/dist/loader/built-in/module/index.d.ts +0 -3
- package/dist/loader/built-in/module/module.d.ts +0 -15
- package/dist/loader/built-in/module/type.d.ts +0 -8
- package/dist/loader/built-in/module/utils.d.ts +0 -9
- package/dist/loader/built-in/yaml/index.d.ts +0 -1
- package/dist/loader/built-in/yaml/module.d.ts +0 -5
- package/dist/loader/constants.d.ts +0 -6
- package/dist/loader/helpers.d.ts +0 -6
- package/dist/loader/index.d.ts +0 -3
- package/dist/loader/module.d.ts +0 -18
- package/dist/loader/singleton.d.ts +0 -2
- package/dist/loader/type.d.ts +0 -8
- package/dist/locator/async.d.ts +0 -3
- package/dist/locator/index.d.ts +0 -4
- package/dist/locator/sync.d.ts +0 -3
- package/dist/locator/types.d.ts +0 -15
- package/dist/locator/utils.d.ts +0 -7
- package/dist/utils/error.d.ts +0 -1
- package/dist/utils/file-name.d.ts +0 -2
- package/dist/utils/file-path.d.ts +0 -1
- package/dist/utils/has-property.d.ts +0 -2
- package/dist/utils/index.d.ts +0 -8
- package/dist/utils/object.d.ts +0 -2
- package/dist/utils/runtime.d.ts +0 -2
- package/dist/utils/to-array.d.ts +0 -1
- package/dist/utils/typescript.d.ts +0 -1
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
import { BaseError, ErrorOptions } from "@ebec/core";
|
|
2
|
+
import { createJiti } from "jiti";
|
|
3
|
+
import { ToStringOptions } from "yaml";
|
|
4
|
+
//#region src/errors/base.d.ts
|
|
5
|
+
type LocterErrorOptions = ErrorOptions & {
|
|
6
|
+
path?: string;
|
|
7
|
+
};
|
|
8
|
+
type LocterErrorInput = string | LocterErrorOptions;
|
|
9
|
+
declare const LOCTER_ERROR_MARKER: unique symbol;
|
|
10
|
+
declare class LocterError extends BaseError {
|
|
11
|
+
static [Symbol.hasInstance](input: unknown): boolean;
|
|
12
|
+
readonly path?: string;
|
|
13
|
+
constructor(input?: LocterErrorInput);
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
//#region src/errors/load.d.ts
|
|
17
|
+
declare const LOCTER_LOAD_ERROR_MARKER: unique symbol;
|
|
18
|
+
declare class LocterLoadError extends LocterError {
|
|
19
|
+
static [Symbol.hasInstance](input: unknown): boolean;
|
|
20
|
+
constructor(input?: LocterErrorInput);
|
|
21
|
+
}
|
|
22
|
+
//#endregion
|
|
23
|
+
//#region src/errors/not-found.d.ts
|
|
24
|
+
declare const LOCTER_NOT_FOUND_ERROR_MARKER: unique symbol;
|
|
25
|
+
declare class LocterNotFoundError extends LocterError {
|
|
26
|
+
static [Symbol.hasInstance](input: unknown): boolean;
|
|
27
|
+
constructor(input?: LocterErrorInput);
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region src/errors/unknown-extension.d.ts
|
|
31
|
+
declare const LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER: unique symbol;
|
|
32
|
+
declare class LocterUnknownExtensionError extends LocterError {
|
|
33
|
+
static [Symbol.hasInstance](input: unknown): boolean;
|
|
34
|
+
constructor(input?: LocterErrorInput);
|
|
35
|
+
}
|
|
36
|
+
//#endregion
|
|
37
|
+
//#region src/errors/wrap.d.ts
|
|
38
|
+
declare function wrapLoaderError(input: unknown, path: string): LocterError;
|
|
39
|
+
declare function wrapWriteError(input: unknown, path: string): LocterError;
|
|
40
|
+
//#endregion
|
|
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);
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/locator/types.d.ts
|
|
49
|
+
type LocatorInfo = {
|
|
50
|
+
directory: string;
|
|
51
|
+
name: string;
|
|
52
|
+
extension?: string;
|
|
53
|
+
path: string;
|
|
54
|
+
};
|
|
55
|
+
type LocatorOptions = {
|
|
56
|
+
cwd: string[];
|
|
57
|
+
ignore: string[];
|
|
58
|
+
onlyFiles: boolean;
|
|
59
|
+
onlyDirectories: boolean;
|
|
60
|
+
dot: boolean;
|
|
61
|
+
};
|
|
62
|
+
type LocatorOptionsInput = Partial<Omit<LocatorOptions, 'cwd' | 'ignore'>> & {
|
|
63
|
+
cwd?: string | string[];
|
|
64
|
+
ignore?: string | string[];
|
|
65
|
+
};
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/locator/async.d.ts
|
|
68
|
+
declare function locateMany(pattern: string | string[], options?: LocatorOptionsInput): Promise<LocatorInfo[]>;
|
|
69
|
+
declare function locate(pattern: string | string[], options?: LocatorOptionsInput): Promise<LocatorInfo | undefined>;
|
|
70
|
+
//#endregion
|
|
71
|
+
//#region src/locator/sync.d.ts
|
|
72
|
+
declare function locateManySync(pattern: string | string[], options?: LocatorOptionsInput): LocatorInfo[];
|
|
73
|
+
declare function locateSync(pattern: string | string[], options?: LocatorOptionsInput): LocatorInfo | undefined;
|
|
74
|
+
//#endregion
|
|
75
|
+
//#region src/locator/up.d.ts
|
|
76
|
+
type LocatorUpOptionsInput = Omit<LocatorOptionsInput, 'cwd'> & {
|
|
77
|
+
cwd?: string;
|
|
78
|
+
stopAt?: string;
|
|
79
|
+
};
|
|
80
|
+
declare function locateUp(pattern: string | string[], options?: LocatorUpOptionsInput): Promise<LocatorInfo | undefined>;
|
|
81
|
+
declare function locateUpSync(pattern: string | string[], options?: LocatorUpOptionsInput): LocatorInfo | undefined;
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/locator/utils.d.ts
|
|
84
|
+
declare function isLocatorInfo(input: unknown): input is LocatorInfo;
|
|
85
|
+
declare function buildFilePath(input: LocatorInfo | string): string;
|
|
86
|
+
//#endregion
|
|
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;
|
|
201
|
+
type ModuleExport = {
|
|
202
|
+
key: string;
|
|
203
|
+
value: any;
|
|
204
|
+
};
|
|
205
|
+
type ModuleLoadOptions = {
|
|
206
|
+
withFilePrefix?: boolean;
|
|
207
|
+
};
|
|
208
|
+
type ModuleLoadFn = (id: string) => unknown | Promise<unknown>;
|
|
209
|
+
type ModuleLoadSyncFn = (id: string) => unknown;
|
|
210
|
+
type ModuleReaderOptions = {
|
|
211
|
+
/**
|
|
212
|
+
* Custom asynchronous module loader. When set, this replaces the
|
|
213
|
+
* built-in `await import(id)` call. Useful for test runners (e.g. Vitest)
|
|
214
|
+
* where dynamic imports inside `node_modules/locter` would otherwise
|
|
215
|
+
* escape the runner's module graph — defining this in user space lets
|
|
216
|
+
* the runner rewrite the `import()`.
|
|
217
|
+
*/
|
|
218
|
+
load?: ModuleLoadFn;
|
|
219
|
+
/**
|
|
220
|
+
* Custom synchronous module loader. When set, this replaces the built-in
|
|
221
|
+
* `require(id)` call.
|
|
222
|
+
*/
|
|
223
|
+
loadSync?: ModuleLoadSyncFn;
|
|
224
|
+
};
|
|
225
|
+
//#endregion
|
|
226
|
+
//#region src/format/built-in/module/reader.d.ts
|
|
227
|
+
type Jiti = ReturnType<typeof createJiti>;
|
|
228
|
+
declare class ModuleReader implements IReader {
|
|
229
|
+
protected instance: Jiti;
|
|
230
|
+
protected loadFn?: ModuleLoadFn;
|
|
231
|
+
protected loadSyncFn?: ModuleLoadSyncFn;
|
|
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;
|
|
252
|
+
load(data: LocatorInfo | string, options?: ModuleLoadOptions): Promise<unknown>;
|
|
253
|
+
loadSync(data: LocatorInfo | string, options?: ModuleLoadOptions): unknown;
|
|
254
|
+
private build;
|
|
255
|
+
}
|
|
256
|
+
//#endregion
|
|
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;
|
|
387
|
+
};
|
|
388
|
+
//#endregion
|
|
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;
|
|
496
|
+
}
|
|
497
|
+
//#endregion
|
|
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;
|
|
512
|
+
/**
|
|
513
|
+
* Override the built-in module reader's `import` / `require` calls.
|
|
514
|
+
*
|
|
515
|
+
* Useful for test runners (e.g. Vitest) where the dynamic `import()` inside
|
|
516
|
+
* `node_modules/locter` would bypass the runner's module graph. Calling this
|
|
517
|
+
* from user code (e.g. a Vitest setup file) lets the runner rewrite the
|
|
518
|
+
* `import()` so loaded modules share identity with statically imported ones.
|
|
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
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* ```ts
|
|
528
|
+
* // vitest setup file
|
|
529
|
+
* import { setModuleReader } from 'locter';
|
|
530
|
+
*
|
|
531
|
+
* setModuleReader({
|
|
532
|
+
* load: (id) => import(id),
|
|
533
|
+
* });
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
declare function setModuleReader(options: ModuleReaderOptions): () => void;
|
|
537
|
+
//#endregion
|
|
538
|
+
//#region src/format/package-field.d.ts
|
|
539
|
+
type ReadPackageFieldOptions = {
|
|
540
|
+
cwd?: string;
|
|
541
|
+
walkUp?: boolean;
|
|
542
|
+
stopAt?: string;
|
|
543
|
+
};
|
|
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;
|
|
555
|
+
//#endregion
|
|
556
|
+
//#region src/utils/runtime.d.ts
|
|
557
|
+
declare function isJestRuntimeEnvironment(): boolean;
|
|
558
|
+
declare function isVitestRuntimeEnvironment(): boolean;
|
|
559
|
+
declare function isTsNodeRuntimeEnvironment(): boolean;
|
|
560
|
+
declare function isTsxRuntimeEnvironment(): boolean;
|
|
561
|
+
//#endregion
|
|
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 };
|
|
563
|
+
//# sourceMappingURL=index.d.mts.map
|