locter 4.0.0 → 4.1.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 CHANGED
@@ -39,7 +39,7 @@
39
39
  - ✍️ **Write** — `write()` values back without pulling serializers into your app: comment-preserving YAML, indent-preserving JSON, rc9-style `.conf`.
40
40
  - 🔁 **Sync twins** — every operation ships as `fn` / `fnSync`, derived from one shared implementation.
41
41
  - 🧩 **Extensible** — register custom formats with independent reader/writer slots; override built-ins per extension.
42
- - 🚨 **Typed errors** — `LocterNotFoundError`, `LocterLoadError`, `LocterWriteError`, … each carrying `path` and `cause`.
42
+ - 🚨 **Typed errors** — `NotFoundError`, `LoadError`, `WriteError`, … each carrying `path` and `cause`.
43
43
 
44
44
  **Table of Contents**
45
45
 
@@ -224,6 +224,28 @@ Bare module specifiers (no file extension) are routed to the module reader, so
224
224
  `read('yaml')` behaves like `import('yaml')` — note that reading a module
225
225
  **executes** it.
226
226
 
227
+ **Per-call format override**
228
+
229
+ Every read/write verb accepts an options object with a `format` key — a
230
+ registered format id (a built-in: `module`, `conf`, `json`, `yaml`, `text` —
231
+ or the id of a rule registered via `registerFormat`) used *instead* of
232
+ extension dispatch. The most useful consequence: module files become readable
233
+ **without being executed**:
234
+
235
+ ```typescript
236
+ import { read } from 'locter';
237
+
238
+ (async () => {
239
+ // the source of a module file — no evaluation, no side effects
240
+ const source = await read('vite.config.ts', { format: 'text' });
241
+
242
+ // extensionless files become readable, too
243
+ const license = await read('LICENSE', { format: 'text' });
244
+ })
245
+ ```
246
+
247
+ Unknown format ids throw `LocterError`.
248
+
227
249
  **Module records — `readAsModule`**
228
250
 
229
251
  Every `readAsModule` / `readAsModuleSync` result is a **module record** — a
@@ -293,7 +315,7 @@ import { readPackageField } from 'locter';
293
315
  })
294
316
  ```
295
317
 
296
- Throws `LocterLoadError` if the resolved `package.json` is malformed. A sync variant `readPackageFieldSync` is also available.
318
+ Throws `LoadError` if the resolved `package.json` is malformed. A sync variant `readPackageFieldSync` is also available.
297
319
 
298
320
  ### Writer
299
321
 
@@ -331,7 +353,22 @@ Write semantics:
331
353
  brand — an `__esModule` key in plain data does **not** count) are unwrapped
332
354
  to their `.default` value before serialization.
333
355
  - Module formats (`.js`, `.ts`, …) are **read-only**: `write('config.ts', …)`
334
- throws `LocterWriteError`, as does writing to a bare module specifier.
356
+ throws `WriteError`, as does writing to a bare module specifier.
357
+
358
+ An explicit `format` id lifts both restrictions of the last bullet — naming
359
+ the format resolves the ambiguity those guards exist for:
360
+
361
+ ```typescript
362
+ import { write } from 'locter';
363
+
364
+ (async () => {
365
+ // scaffold a module file from raw source ('text' bypasses read-only)
366
+ await write('generated/config.ts', 'export default {};', { format: 'text' });
367
+
368
+ // extensionless target, explicit format
369
+ await write('.myapprc', { port: 3000 }, { format: 'json' });
370
+ })
371
+ ```
335
372
 
336
373
  Per-format behavior:
337
374
 
@@ -380,7 +417,7 @@ import { writePackageField } from 'locter';
380
417
  })
381
418
  ```
382
419
 
383
- Throws `LocterNotFoundError` when no `package.json` could be located. A sync
420
+ Throws `NotFoundError` when no `package.json` could be located. A sync
384
421
  variant `writePackageFieldSync` is also available.
385
422
 
386
423
  ### Formats
@@ -509,24 +546,24 @@ matching on `.message`:
509
546
 
510
547
  | Class | When it's thrown |
511
548
  |--------------------------------|---------------------------------------------------------|
512
- | `LocterNotFoundError` | File or module does not exist (`ENOENT`, `MODULE_NOT_FOUND`, `ERR_MODULE_NOT_FOUND`) |
513
- | `LocterLoadError` | A reader threw — parse error, runtime/eval error, etc. |
514
- | `LocterWriteError` | A write failed — serialization error, filesystem error, read-only format, corrupt existing YAML target |
515
- | `LocterUnknownExtensionError` | No rule matched the file's extension |
549
+ | `NotFoundError` | File or module does not exist (`ENOENT`, `MODULE_NOT_FOUND`, `ERR_MODULE_NOT_FOUND`) |
550
+ | `LoadError` | A reader threw — parse error, runtime/eval error, etc. |
551
+ | `WriteError` | A write failed — serialization error, filesystem error, read-only format, corrupt existing YAML target |
552
+ | `UnknownExtensionError` | No rule matched the file's extension |
516
553
  | `LocterError` | Base class; matches all of the above |
517
554
 
518
555
  Each error exposes the offending `path` and preserves the underlying error
519
556
  on `cause`:
520
557
 
521
558
  ```typescript
522
- import { read, LocterNotFoundError, LocterLoadError } from 'locter';
559
+ import { read, NotFoundError, LoadError } from 'locter';
523
560
 
524
561
  try {
525
562
  await read('config.json');
526
563
  } catch (err) {
527
- if (err instanceof LocterNotFoundError) {
564
+ if (err instanceof NotFoundError) {
528
565
  console.error(`Config file not found: ${err.path}`);
529
- } else if (err instanceof LocterLoadError) {
566
+ } else if (err instanceof LoadError) {
530
567
  console.error(`Failed to parse config: ${err.cause}`);
531
568
  } else {
532
569
  throw err;
@@ -534,11 +571,11 @@ try {
534
571
  }
535
572
  ```
536
573
 
537
- Note that on the write side `ENOENT` stays a `LocterWriteError` — a missing
574
+ Note that on the write side `ENOENT` stays a `WriteError` — a missing
538
575
  parent directory is a write failure, not a lookup miss (and `write` creates
539
576
  missing parents anyway).
540
577
 
541
- `LocterError` extends [`BaseError`](https://github.com/Tada5hi/ebec) from `@ebec/core`, so each instance also carries a `code` (auto-derived from the class name unless overridden — e.g. `'ENOENT'` for `LocterNotFoundError`s thrown by the JSON reader) and a `toJSON()` for structured logging.
578
+ `LocterError` extends [`BaseError`](https://github.com/Tada5hi/ebec) from `@ebec/core`, so each instance also carries a `code` (auto-derived from the class name unless overridden — e.g. `'ENOENT'` for `NotFoundError`s thrown by the JSON reader) and a `toJSON()` for structured logging.
542
579
 
543
580
  Each error class also publishes its `Symbol.for(...)` marker (`LOCTER_ERROR_MARKER`, `LOCTER_NOT_FOUND_ERROR_MARKER`, …), which makes `instanceof` work across realms — useful when consumers end up with duplicate copies of locter in their dependency tree.
544
581
 
@@ -625,6 +662,7 @@ The list below is exhaustive — no other public APIs changed.
625
662
  | `ModuleLoader` | `ModuleReader` |
626
663
  | `setModuleLoader` | `setModuleReader` |
627
664
  | `loadPackageField` / `loadPackageFieldSync` | `readPackageField` / `readPackageFieldSync` |
665
+ | `LocterLoadError` / `LocterNotFoundError` / `LocterUnknownExtensionError` | `LoadError` / `NotFoundError` / `UnknownExtensionError` — the `LocterError` base class keeps its name |
628
666
 
629
667
  **Behavioral changes:**
630
668
 
@@ -689,7 +727,7 @@ The list below is exhaustive — no other public APIs changed.
689
727
  `ConfWriter`), including comment-preserving YAML write-back — see
690
728
  [Writer](#writer).
691
729
  - `writePackageField` / `writePackageFieldSync`.
692
- - `LocterWriteError` + `wrapWriteError`.
730
+ - `WriteError` + `wrapWriteError`.
693
731
  - `isModuleRecord` — brand-based detection of records produced by `read()`.
694
732
  - The ports are exported as `IReader` / `IWriter`, alongside `Rule`,
695
733
  `ReaderFactory`, `WriterFactory` — so custom formats can be typed against
package/dist/index.d.mts CHANGED
@@ -15,21 +15,21 @@ declare class LocterError extends BaseError {
15
15
  //#endregion
16
16
  //#region src/errors/load.d.ts
17
17
  declare const LOCTER_LOAD_ERROR_MARKER: unique symbol;
18
- declare class LocterLoadError extends LocterError {
18
+ declare class LoadError extends LocterError {
19
19
  static [Symbol.hasInstance](input: unknown): boolean;
20
20
  constructor(input?: LocterErrorInput);
21
21
  }
22
22
  //#endregion
23
23
  //#region src/errors/not-found.d.ts
24
24
  declare const LOCTER_NOT_FOUND_ERROR_MARKER: unique symbol;
25
- declare class LocterNotFoundError extends LocterError {
25
+ declare class NotFoundError extends LocterError {
26
26
  static [Symbol.hasInstance](input: unknown): boolean;
27
27
  constructor(input?: LocterErrorInput);
28
28
  }
29
29
  //#endregion
30
30
  //#region src/errors/unknown-extension.d.ts
31
31
  declare const LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER: unique symbol;
32
- declare class LocterUnknownExtensionError extends LocterError {
32
+ declare class UnknownExtensionError extends LocterError {
33
33
  static [Symbol.hasInstance](input: unknown): boolean;
34
34
  constructor(input?: LocterErrorInput);
35
35
  }
@@ -40,7 +40,7 @@ declare function wrapWriteError(input: unknown, path: string): LocterError;
40
40
  //#endregion
41
41
  //#region src/errors/write.d.ts
42
42
  declare const LOCTER_WRITE_ERROR_MARKER: unique symbol;
43
- declare class LocterWriteError extends LocterError {
43
+ declare class WriteError extends LocterError {
44
44
  static [Symbol.hasInstance](input: unknown): boolean;
45
45
  constructor(input?: LocterErrorInput);
46
46
  }
@@ -131,7 +131,7 @@ declare abstract class TextFileReader implements IReader {
131
131
  * Base class for writers of text-based file formats: serializes via
132
132
  * `stringify`, creates missing parent directories, writes the file as
133
133
  * UTF-8 (always terminated by a single trailing newline), and wraps
134
- * failures in LocterWriteError. Subclasses implement `stringify` only —
134
+ * failures in WriteError. Subclasses implement `stringify` only —
135
135
  * both `write` variants are derived from the same body.
136
136
  */
137
137
  declare abstract class TextFileWriter implements IWriter {
@@ -296,7 +296,7 @@ type YAMLWriterOptions = ToStringOptions;
296
296
  * target file already exists, the new value is grafted into its parsed
297
297
  * document, so comments and anchors attached to surviving keys survive
298
298
  * the write-back. New files are plain `yaml.stringify` output. An
299
- * existing file that fails to parse throws (wrapped as LocterWriteError)
299
+ * existing file that fails to parse throws (wrapped as WriteError)
300
300
  * instead of being silently overwritten.
301
301
  */
302
302
  declare class YAMLWriter extends TextFileWriter {
@@ -379,13 +379,40 @@ type Rule = {
379
379
  /**
380
380
  * Stable identity. Registering an existing id REPLACES that rule in
381
381
  * place (position preserved, cached instance evicted). Built-in ids
382
- * ('module', 'conf', 'json', 'yaml') are reserved. Omitted → auto-generated.
382
+ * ('module', 'conf', 'json', 'yaml', 'text') are reserved.
383
+ * Omitted → auto-generated.
383
384
  */
384
385
  id?: string;
385
386
  test: RegExp | string[];
386
387
  reader?: IReader | ReaderFactory;
387
388
  writer?: IWriter | WriterFactory;
388
389
  };
390
+ /**
391
+ * Per-call options for read / readAsModule (+Sync).
392
+ */
393
+ type ReadOptions = {
394
+ /**
395
+ * Read with the format registered under this id — a built-in id
396
+ * ('module', 'conf', 'json', 'yaml', 'text') or a user rule id —
397
+ * INSTEAD of dispatching by extension. This is the evaluation-free
398
+ * escape hatch for module files: read('config.ts', { format: 'text' })
399
+ * returns the source without executing it. Unknown ids throw.
400
+ */
401
+ format?: string;
402
+ };
403
+ /**
404
+ * Per-call options for write (+Sync).
405
+ */
406
+ type WriteOptions = {
407
+ /**
408
+ * Write with the format registered under this id INSTEAD of
409
+ * dispatching by extension. Skips the bare-specifier guard, so
410
+ * extensionless paths become writable ('LICENSE' with 'text') and
411
+ * read-only extensions become targetable (raw source to a '.ts'
412
+ * file with 'text'). Read-only format ids and unknown ids throw.
413
+ */
414
+ format?: string;
415
+ };
389
416
  /**
390
417
  * Normalized registration record — returned by register()/entries().
391
418
  */
@@ -472,36 +499,49 @@ declare class FormatRegistry {
472
499
  * normalized module record — a module IS a record, and the
473
500
  * normalization only irons out the CJS/ESM interop divergence so
474
501
  * both twin variants agree on one shape.
502
+ *
503
+ * options.format names a registered format id to use instead of
504
+ * extension dispatch (e.g. { format: 'text' } reads module source
505
+ * without evaluating it).
475
506
  */
476
- read(input: LocatorInfo | string): Promise<any>;
477
- readSync(input: LocatorInfo | string): any;
507
+ read(input: LocatorInfo | string, options?: ReadOptions): Promise<any>;
508
+ readSync(input: LocatorInfo | string, options?: ReadOptions): any;
478
509
  /**
479
510
  * Read a file/module and present the result as a normalized module
480
511
  * record — the uniform, frozen shape regardless of format:
481
512
  * `.default` always holds the loaded value, top-level keys are
482
513
  * re-exposed as named exports.
483
514
  */
484
- readAsModule(input: LocatorInfo | string): Promise<any>;
485
- readAsModuleSync(input: LocatorInfo | string): any;
486
- protected readBody(input: LocatorInfo | string): TwinBody<any>;
487
- protected readAsModuleBody(input: LocatorInfo | string): TwinBody<any>;
515
+ readAsModule(input: LocatorInfo | string, options?: ReadOptions): Promise<any>;
516
+ readAsModuleSync(input: LocatorInfo | string, options?: ReadOptions): any;
517
+ protected readBody(input: LocatorInfo | string, options: ReadOptions): TwinBody<any>;
518
+ protected readAsModuleBody(input: LocatorInfo | string, options: ReadOptions): TwinBody<any>;
488
519
  /**
489
520
  * Shared dispatch + execution of both read bodies: resolve the
490
521
  * reader, run it, wrap errors. Normalization is the caller's call.
491
522
  */
492
- protected executeBody(input: LocatorInfo | string): TwinBody<{
523
+ protected executeBody(input: LocatorInfo | string, options: ReadOptions): TwinBody<{
493
524
  output: unknown;
494
525
  reader: IReader;
495
526
  }>;
496
- write(input: LocatorInfo | string, value: unknown): Promise<void>;
497
- writeSync(input: LocatorInfo | string, value: unknown): void;
527
+ /**
528
+ * options.format names a registered format id to use instead of
529
+ * extension dispatch — see writeBody for the boundary semantics.
530
+ */
531
+ write(input: LocatorInfo | string, value: unknown, options?: WriteOptions): Promise<void>;
532
+ writeSync(input: LocatorInfo | string, value: unknown, options?: WriteOptions): void;
498
533
  /**
499
534
  * Shared body of write/writeSync: dispatch, unwrap records, write, wrap.
500
535
  * The inverse boundary of readAsModuleBody: a record produced by
501
536
  * readAsModule() (brand detected) is unwrapped to its `.default` value;
502
537
  * anything else is written as-is.
538
+ *
539
+ * An explicit options.format skips extension dispatch entirely —
540
+ * including the bare-specifier guard: naming the format resolves the
541
+ * ambiguity the guard exists for, so extensionless paths become
542
+ * writable.
503
543
  */
504
- protected writeBody(input: LocatorInfo | string, value: unknown): TwinBody<void>;
544
+ protected writeBody(input: LocatorInfo | string, value: unknown, options: WriteOptions): TwinBody<void>;
505
545
  /**
506
546
  * The single normalization boundary: every readAsModule result becomes a module
507
547
  * record (`.default` is always the loaded value, top-level keys stay
@@ -526,7 +566,7 @@ declare class FormatRegistry {
526
566
  * 1. bare specifier (no extension) → module reader, always
527
567
  * 2. user rules, registration order → first match wins (can override built-ins)
528
568
  * 3. built-in extension table
529
- * 4. undefined → read/readSync throw LocterUnknownExtensionError
569
+ * 4. undefined → read/readSync throw UnknownExtensionError
530
570
  */
531
571
  findReader(input: string): IReader | undefined;
532
572
  /**
@@ -535,9 +575,22 @@ declare class FormatRegistry {
535
575
  * presets that declare a writer.
536
576
  */
537
577
  findWriter(input: string): IWriter | undefined;
578
+ /**
579
+ * Resolve a reader by EXPLICIT format id (the per-call override) —
580
+ * a user rule id or a built-in id — bypassing extension dispatch.
581
+ * Unknown ids and writer-only rules throw.
582
+ */
583
+ protected resolveReader(id: string): IReader;
584
+ /**
585
+ * Write-side counterpart of resolveReader. Reader-only rules and
586
+ * read-only built-ins (module) throw WriteError, mirroring
587
+ * what extension dispatch throws for read-only extensions.
588
+ */
589
+ protected resolveWriter(id: string, path: string): IWriter;
538
590
  protected findRule(input: string, filter: (rule: CompiledRule) => boolean): CompiledRule | undefined;
539
591
  protected findBuiltInId(input: string): BuiltInFormatId | undefined;
540
- protected unknownExtensionError(input: string): LocterUnknownExtensionError;
592
+ protected unknownExtensionError(input: string): UnknownExtensionError;
593
+ protected unknownFormatError(id: string): LocterError;
541
594
  protected compile(id: string, rule: Rule): CompiledRule;
542
595
  protected generateRuleId(): string;
543
596
  }
@@ -557,19 +610,28 @@ declare function unregisterFormat(id: string): boolean;
557
610
  * (json/yaml/conf and custom readers — mutable, round-trip-symmetric
558
611
  * with write); for modules the normalized module record (a module IS a
559
612
  * record; normalization only irons out CJS/ESM interop divergence).
613
+ *
614
+ * options.format forces a registered format id instead of extension
615
+ * dispatch — e.g. { format: 'text' } reads a module file's source
616
+ * WITHOUT evaluating it.
560
617
  */
561
- declare function read(input: LocatorInfo | string): Promise<any>;
562
- declare function readSync(input: LocatorInfo | string): any;
618
+ declare function read(input: LocatorInfo | string, options?: ReadOptions): Promise<any>;
619
+ declare function readSync(input: LocatorInfo | string, options?: ReadOptions): any;
563
620
  /**
564
621
  * Read a file/module and present the result as a normalized module
565
622
  * record — the uniform, frozen shape regardless of format: `.default`
566
623
  * always holds the loaded value, top-level keys are re-exposed as
567
624
  * named exports.
568
625
  */
569
- declare function readAsModule(input: LocatorInfo | string): Promise<any>;
570
- declare function readAsModuleSync(input: LocatorInfo | string): any;
571
- declare function write(input: LocatorInfo | string, value: unknown): Promise<void>;
572
- declare function writeSync(input: LocatorInfo | string, value: unknown): void;
626
+ declare function readAsModule(input: LocatorInfo | string, options?: ReadOptions): Promise<any>;
627
+ declare function readAsModuleSync(input: LocatorInfo | string, options?: ReadOptions): any;
628
+ /**
629
+ * options.format forces a registered format id instead of extension
630
+ * dispatch — this also lifts the bare-specifier guard (extensionless
631
+ * paths) and the read-only block on module extensions.
632
+ */
633
+ declare function write(input: LocatorInfo | string, value: unknown, options?: WriteOptions): Promise<void>;
634
+ declare function writeSync(input: LocatorInfo | string, value: unknown, options?: WriteOptions): void;
573
635
  /**
574
636
  * Override the built-in module reader's `import` / `require` calls.
575
637
  *
@@ -609,7 +671,7 @@ declare function readPackageFieldSync<T = unknown>(field: string, options?: Read
609
671
  * Set a top-level field of the nearest `package.json` (same locate
610
672
  * semantics as readPackageField) and write it back, preserving the
611
673
  * file's existing indentation. Passing `undefined` removes the field.
612
- * Throws LocterNotFoundError when no package.json could be located.
674
+ * Throws NotFoundError when no package.json could be located.
613
675
  */
614
676
  declare function writePackageField(field: string, value: unknown, options?: WritePackageFieldOptions): Promise<void>;
615
677
  declare function writePackageFieldSync(field: string, value: unknown, options?: WritePackageFieldOptions): void;
@@ -640,5 +702,5 @@ declare function isVitestRuntimeEnvironment(): boolean;
640
702
  declare function isTsNodeRuntimeEnvironment(): boolean;
641
703
  declare function isTsxRuntimeEnvironment(): boolean;
642
704
  //#endregion
643
- 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, TextReader, TextWriter, type WritePackageFieldOptions, type WriterFactory, YAMLReader, YAMLWriter, type YAMLWriterOptions, buildFilePath, deserializeValue, getFileNameExtension, getModuleExport, isJestRuntimeEnvironment, isLocatorInfo, isModuleRecord, isTsNodeRuntimeEnvironment, isTsxRuntimeEnvironment, isVitestRuntimeEnvironment, locate, locateMany, locateManySync, locateSync, locateUp, locateUpSync, read, readAsModule, readAsModuleSync, readPackageField, readPackageFieldSync, readSync, registerFormat, removeFileNameExtension, serializeValue, setModuleReader, unregisterFormat, useFormatRegistry, wrapLoaderError, wrapWriteError, write, writePackageField, writePackageFieldSync, writeSync };
705
+ 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, LoadError, type LocatorInfo, type LocatorOptions, type LocatorOptionsInput, type LocatorUpOptionsInput, LocterError, type LocterErrorInput, type LocterErrorOptions, MODULE_FILE_EXTENSIONS, type ModuleExport, type ModuleExportFilterFn, type ModuleLoadFn, type ModuleLoadOptions, type ModuleLoadSyncFn, ModuleReader, type ModuleReaderOptions, NotFoundError, type ReadOptions, type ReadPackageFieldOptions, type ReaderFactory, type Rule, TextFileReader, TextFileWriter, TextReader, TextWriter, UnknownExtensionError, WriteError, type WriteOptions, type WritePackageFieldOptions, type WriterFactory, YAMLReader, YAMLWriter, type YAMLWriterOptions, buildFilePath, deserializeValue, getFileNameExtension, getModuleExport, isJestRuntimeEnvironment, isLocatorInfo, isModuleRecord, isTsNodeRuntimeEnvironment, isTsxRuntimeEnvironment, isVitestRuntimeEnvironment, locate, locateMany, locateManySync, locateSync, locateUp, locateUpSync, read, readAsModule, readAsModuleSync, readPackageField, readPackageFieldSync, readSync, registerFormat, removeFileNameExtension, serializeValue, setModuleReader, unregisterFormat, useFormatRegistry, wrapLoaderError, wrapWriteError, write, writePackageField, writePackageFieldSync, writeSync };
644
706
  //# sourceMappingURL=index.d.mts.map
package/dist/index.mjs CHANGED
@@ -28,7 +28,7 @@ var LocterError = class extends BaseError {
28
28
  //#endregion
29
29
  //#region src/errors/load.ts
30
30
  const LOCTER_LOAD_ERROR_MARKER = Symbol.for("@locter/load-error");
31
- var LocterLoadError = class extends LocterError {
31
+ var LoadError = class extends LocterError {
32
32
  static [Symbol.hasInstance](input) {
33
33
  return hasInstanceof(input, LOCTER_LOAD_ERROR_MARKER);
34
34
  }
@@ -40,7 +40,7 @@ var LocterLoadError = class extends LocterError {
40
40
  //#endregion
41
41
  //#region src/errors/not-found.ts
42
42
  const LOCTER_NOT_FOUND_ERROR_MARKER = Symbol.for("@locter/not-found-error");
43
- var LocterNotFoundError = class extends LocterError {
43
+ var NotFoundError = class extends LocterError {
44
44
  static [Symbol.hasInstance](input) {
45
45
  return hasInstanceof(input, LOCTER_NOT_FOUND_ERROR_MARKER);
46
46
  }
@@ -52,7 +52,7 @@ var LocterNotFoundError = class extends LocterError {
52
52
  //#endregion
53
53
  //#region src/errors/unknown-extension.ts
54
54
  const LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER = Symbol.for("@locter/unknown-extension-error");
55
- var LocterUnknownExtensionError = class extends LocterError {
55
+ var UnknownExtensionError = class extends LocterError {
56
56
  static [Symbol.hasInstance](input) {
57
57
  return hasInstanceof(input, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER);
58
58
  }
@@ -128,7 +128,7 @@ function isTypeScriptError(input) {
128
128
  //#endregion
129
129
  //#region src/errors/write.ts
130
130
  const LOCTER_WRITE_ERROR_MARKER = Symbol.for("@locter/write-error");
131
- var LocterWriteError = class extends LocterError {
131
+ var WriteError = class extends LocterError {
132
132
  static [Symbol.hasInstance](input) {
133
133
  return hasInstanceof(input, LOCTER_WRITE_ERROR_MARKER);
134
134
  }
@@ -148,13 +148,13 @@ function wrapLoaderError(input, path) {
148
148
  if (input instanceof LocterError) return input;
149
149
  const code = isObject(input) && hasStringProperty(input, "code") ? input.code : void 0;
150
150
  const message = isObject(input) && hasStringProperty(input, "message") ? input.message : `Failed to load: ${path}`;
151
- if (code && NOT_FOUND_CODES.has(code)) return new LocterNotFoundError({
151
+ if (code && NOT_FOUND_CODES.has(code)) return new NotFoundError({
152
152
  message,
153
153
  code,
154
154
  cause: input,
155
155
  path
156
156
  });
157
- return new LocterLoadError({
157
+ return new LoadError({
158
158
  message,
159
159
  code,
160
160
  cause: input,
@@ -164,7 +164,7 @@ function wrapLoaderError(input, path) {
164
164
  function wrapWriteError(input, path) {
165
165
  if (input instanceof LocterError) return input;
166
166
  const code = isObject(input) && hasStringProperty(input, "code") ? input.code : void 0;
167
- return new LocterWriteError({
167
+ return new WriteError({
168
168
  message: isObject(input) && hasStringProperty(input, "message") ? input.message : `Failed to write: ${path}`,
169
169
  code,
170
170
  cause: input,
@@ -372,7 +372,7 @@ function isNotFound(e) {
372
372
  * Base class for writers of text-based file formats: serializes via
373
373
  * `stringify`, creates missing parent directories, writes the file as
374
374
  * UTF-8 (always terminated by a single trailing newline), and wraps
375
- * failures in LocterWriteError. Subclasses implement `stringify` only —
375
+ * failures in WriteError. Subclasses implement `stringify` only —
376
376
  * both `write` variants are derived from the same body.
377
377
  */
378
378
  var TextFileWriter = class {
@@ -789,7 +789,7 @@ function graftMap(doc, node, value) {
789
789
  * target file already exists, the new value is grafted into its parsed
790
790
  * document, so comments and anchors attached to surviving keys survive
791
791
  * the write-back. New files are plain `yaml.stringify` output. An
792
- * existing file that fails to parse throws (wrapped as LocterWriteError)
792
+ * existing file that fails to parse throws (wrapped as WriteError)
793
793
  * instead of being silently overwritten.
794
794
  */
795
795
  var YAMLWriter = class extends TextFileWriter {
@@ -953,12 +953,16 @@ var FormatRegistry = class {
953
953
  * normalized module record — a module IS a record, and the
954
954
  * normalization only irons out the CJS/ESM interop divergence so
955
955
  * both twin variants agree on one shape.
956
+ *
957
+ * options.format names a registered format id to use instead of
958
+ * extension dispatch (e.g. { format: 'text' } reads module source
959
+ * without evaluating it).
956
960
  */
957
- async read(input) {
958
- return runTwinAsync(this.readBody(input));
961
+ async read(input, options = {}) {
962
+ return runTwinAsync(this.readBody(input, options));
959
963
  }
960
- readSync(input) {
961
- return runTwinSync(this.readBody(input));
964
+ readSync(input, options = {}) {
965
+ return runTwinSync(this.readBody(input, options));
962
966
  }
963
967
  /**
964
968
  * Read a file/module and present the result as a normalized module
@@ -966,28 +970,30 @@ var FormatRegistry = class {
966
970
  * `.default` always holds the loaded value, top-level keys are
967
971
  * re-exposed as named exports.
968
972
  */
969
- async readAsModule(input) {
970
- return runTwinAsync(this.readAsModuleBody(input));
973
+ async readAsModule(input, options = {}) {
974
+ return runTwinAsync(this.readAsModuleBody(input, options));
971
975
  }
972
- readAsModuleSync(input) {
973
- return runTwinSync(this.readAsModuleBody(input));
976
+ readAsModuleSync(input, options = {}) {
977
+ return runTwinSync(this.readAsModuleBody(input, options));
974
978
  }
975
- *readBody(input) {
976
- const { output, reader } = yield* this.executeBody(input);
979
+ *readBody(input, options) {
980
+ const { output, reader } = yield* this.executeBody(input, options);
977
981
  if (reader instanceof ModuleReader) return toModuleRecord(output);
978
982
  return output;
979
983
  }
980
- *readAsModuleBody(input) {
981
- const { output, reader } = yield* this.executeBody(input);
984
+ *readAsModuleBody(input, options) {
985
+ const { output, reader } = yield* this.executeBody(input, options);
982
986
  return this.toRecord(output, reader);
983
987
  }
984
988
  /**
985
989
  * Shared dispatch + execution of both read bodies: resolve the
986
990
  * reader, run it, wrap errors. Normalization is the caller's call.
987
991
  */
988
- *executeBody(input) {
992
+ *executeBody(input, options) {
989
993
  const filePath = buildFilePath(input);
990
- const reader = this.findReader(filePath);
994
+ let reader;
995
+ if (typeof options.format === "undefined") reader = this.findReader(filePath);
996
+ else reader = this.resolveReader(options.format);
991
997
  if (!reader) throw this.unknownExtensionError(filePath);
992
998
  try {
993
999
  return {
@@ -998,32 +1004,45 @@ var FormatRegistry = class {
998
1004
  throw wrapLoaderError(e, filePath);
999
1005
  }
1000
1006
  }
1001
- async write(input, value) {
1002
- return runTwinAsync(this.writeBody(input, value));
1007
+ /**
1008
+ * options.format names a registered format id to use instead of
1009
+ * extension dispatch — see writeBody for the boundary semantics.
1010
+ */
1011
+ async write(input, value, options = {}) {
1012
+ return runTwinAsync(this.writeBody(input, value, options));
1003
1013
  }
1004
- writeSync(input, value) {
1005
- runTwinSync(this.writeBody(input, value));
1014
+ writeSync(input, value, options = {}) {
1015
+ runTwinSync(this.writeBody(input, value, options));
1006
1016
  }
1007
1017
  /**
1008
1018
  * Shared body of write/writeSync: dispatch, unwrap records, write, wrap.
1009
1019
  * The inverse boundary of readAsModuleBody: a record produced by
1010
1020
  * readAsModule() (brand detected) is unwrapped to its `.default` value;
1011
1021
  * anything else is written as-is.
1022
+ *
1023
+ * An explicit options.format skips extension dispatch entirely —
1024
+ * including the bare-specifier guard: naming the format resolves the
1025
+ * ambiguity the guard exists for, so extensionless paths become
1026
+ * writable.
1012
1027
  */
1013
- *writeBody(input, value) {
1028
+ *writeBody(input, value, options) {
1014
1029
  const filePath = buildFilePath(input);
1015
- if (!isFilePath(filePath)) throw new LocterWriteError({
1016
- message: `Cannot write to a bare module specifier: ${filePath}`,
1017
- path: filePath
1018
- });
1019
- const writer = this.findWriter(filePath);
1020
- if (!writer) {
1021
- if (this.findReader(filePath)) throw new LocterWriteError({
1022
- message: `The format of extension ${pathToLocatorInfo(filePath).extension} is read-only.`,
1030
+ let writer;
1031
+ if (typeof options.format === "undefined") {
1032
+ if (!isFilePath(filePath)) throw new WriteError({
1033
+ message: `Cannot write to a bare module specifier: ${filePath}`,
1023
1034
  path: filePath
1024
1035
  });
1025
- throw this.unknownExtensionError(filePath);
1026
- }
1036
+ const found = this.findWriter(filePath);
1037
+ if (!found) {
1038
+ if (this.findReader(filePath)) throw new WriteError({
1039
+ message: `The format of extension ${pathToLocatorInfo(filePath).extension} is read-only.`,
1040
+ path: filePath
1041
+ });
1042
+ throw this.unknownExtensionError(filePath);
1043
+ }
1044
+ writer = found;
1045
+ } else writer = this.resolveWriter(options.format, filePath);
1027
1046
  const plain = isModuleRecord(value) ? value.default : value;
1028
1047
  try {
1029
1048
  yield* op(() => writer.write(filePath, plain), () => writer.writeSync(filePath, plain));
@@ -1072,7 +1091,7 @@ var FormatRegistry = class {
1072
1091
  * 1. bare specifier (no extension) → module reader, always
1073
1092
  * 2. user rules, registration order → first match wins (can override built-ins)
1074
1093
  * 3. built-in extension table
1075
- * 4. undefined → read/readSync throw LocterUnknownExtensionError
1094
+ * 4. undefined → read/readSync throw UnknownExtensionError
1076
1095
  */
1077
1096
  findReader(input) {
1078
1097
  if (!isFilePath(input)) return this.builtInReader("module");
@@ -1093,6 +1112,43 @@ var FormatRegistry = class {
1093
1112
  const id = this.findBuiltInId(input);
1094
1113
  if (id && "writer" in BUILT_IN_PRESETS[id]) return this.builtInWriter(id);
1095
1114
  }
1115
+ /**
1116
+ * Resolve a reader by EXPLICIT format id (the per-call override) —
1117
+ * a user rule id or a built-in id — bypassing extension dispatch.
1118
+ * Unknown ids and writer-only rules throw.
1119
+ */
1120
+ resolveReader(id) {
1121
+ const rule = this.rules.find((item) => item.id === id);
1122
+ if (rule) {
1123
+ if (rule.getReader) return rule.getReader();
1124
+ throw new LocterError({ message: `The format ${id} has no reader.` });
1125
+ }
1126
+ if (hasOwnProperty(BUILT_IN_PRESETS, id)) return this.builtInReader(id);
1127
+ throw this.unknownFormatError(id);
1128
+ }
1129
+ /**
1130
+ * Write-side counterpart of resolveReader. Reader-only rules and
1131
+ * read-only built-ins (module) throw WriteError, mirroring
1132
+ * what extension dispatch throws for read-only extensions.
1133
+ */
1134
+ resolveWriter(id, path) {
1135
+ const rule = this.rules.find((item) => item.id === id);
1136
+ if (rule) {
1137
+ if (rule.getWriter) return rule.getWriter();
1138
+ throw new WriteError({
1139
+ message: `The format ${id} is read-only.`,
1140
+ path
1141
+ });
1142
+ }
1143
+ if (hasOwnProperty(BUILT_IN_PRESETS, id)) {
1144
+ if ("writer" in BUILT_IN_PRESETS[id]) return this.builtInWriter(id);
1145
+ throw new WriteError({
1146
+ message: `The format ${id} is read-only.`,
1147
+ path
1148
+ });
1149
+ }
1150
+ throw this.unknownFormatError(id);
1151
+ }
1096
1152
  findRule(input, filter) {
1097
1153
  const info = pathToLocatorInfo(input);
1098
1154
  for (const rule of this.rules) {
@@ -1114,11 +1170,14 @@ var FormatRegistry = class {
1114
1170
  return this.builtInExtensions.get(info.extension);
1115
1171
  }
1116
1172
  unknownExtensionError(input) {
1117
- return new LocterUnknownExtensionError({
1173
+ return new UnknownExtensionError({
1118
1174
  message: `No format registered for extension: ${pathToLocatorInfo(input).extension ?? "unknown"}`,
1119
1175
  path: input
1120
1176
  });
1121
1177
  }
1178
+ unknownFormatError(id) {
1179
+ return new LocterError({ message: `No format registered with id: ${id}` });
1180
+ }
1122
1181
  compile(id, rule) {
1123
1182
  return {
1124
1183
  id,
@@ -1161,12 +1220,16 @@ function unregisterFormat(id) {
1161
1220
  * (json/yaml/conf and custom readers — mutable, round-trip-symmetric
1162
1221
  * with write); for modules the normalized module record (a module IS a
1163
1222
  * record; normalization only irons out CJS/ESM interop divergence).
1223
+ *
1224
+ * options.format forces a registered format id instead of extension
1225
+ * dispatch — e.g. { format: 'text' } reads a module file's source
1226
+ * WITHOUT evaluating it.
1164
1227
  */
1165
- async function read(input) {
1166
- return useFormatRegistry().read(input);
1228
+ async function read(input, options) {
1229
+ return useFormatRegistry().read(input, options);
1167
1230
  }
1168
- function readSync(input) {
1169
- return useFormatRegistry().readSync(input);
1231
+ function readSync(input, options) {
1232
+ return useFormatRegistry().readSync(input, options);
1170
1233
  }
1171
1234
  /**
1172
1235
  * Read a file/module and present the result as a normalized module
@@ -1174,17 +1237,22 @@ function readSync(input) {
1174
1237
  * always holds the loaded value, top-level keys are re-exposed as
1175
1238
  * named exports.
1176
1239
  */
1177
- async function readAsModule(input) {
1178
- return useFormatRegistry().readAsModule(input);
1240
+ async function readAsModule(input, options) {
1241
+ return useFormatRegistry().readAsModule(input, options);
1179
1242
  }
1180
- function readAsModuleSync(input) {
1181
- return useFormatRegistry().readAsModuleSync(input);
1243
+ function readAsModuleSync(input, options) {
1244
+ return useFormatRegistry().readAsModuleSync(input, options);
1182
1245
  }
1183
- async function write(input, value) {
1184
- return useFormatRegistry().write(input, value);
1246
+ /**
1247
+ * options.format forces a registered format id instead of extension
1248
+ * dispatch — this also lifts the bare-specifier guard (extensionless
1249
+ * paths) and the read-only block on module extensions.
1250
+ */
1251
+ async function write(input, value, options) {
1252
+ return useFormatRegistry().write(input, value, options);
1185
1253
  }
1186
- function writeSync(input, value) {
1187
- useFormatRegistry().writeSync(input, value);
1254
+ function writeSync(input, value, options) {
1255
+ useFormatRegistry().writeSync(input, value, options);
1188
1256
  }
1189
1257
  /**
1190
1258
  * Override the built-in module reader's `import` / `require` calls.
@@ -1241,7 +1309,7 @@ function* readPackageFieldBody(field, options) {
1241
1309
  try {
1242
1310
  return extractField(yield* op(() => reader.read(filePath), () => reader.readSync(filePath)), field);
1243
1311
  } catch (e) {
1244
- if (e instanceof LocterNotFoundError) return;
1312
+ if (e instanceof NotFoundError) return;
1245
1313
  throw e;
1246
1314
  }
1247
1315
  }
@@ -1254,11 +1322,11 @@ function readPackageFieldSync(field, options = {}) {
1254
1322
  function* writePackageFieldBody(field, value, options) {
1255
1323
  if (!isSafeObjectKey(field)) throw new LocterError({ message: `The field ${field} is not a safe object key.` });
1256
1324
  const info = yield* locatePackageBody(options);
1257
- if (!info) throw new LocterNotFoundError({ message: "No package.json could be located." });
1325
+ if (!info) throw new NotFoundError({ message: "No package.json could be located." });
1258
1326
  const reader = useFormatRegistry().builtInReader("json");
1259
1327
  const filePath = buildFilePath(info);
1260
1328
  const pkg = yield* op(() => reader.read(filePath), () => reader.readSync(filePath));
1261
- if (!isObject(pkg)) throw new LocterWriteError({
1329
+ if (!isObject(pkg)) throw new WriteError({
1262
1330
  message: "The located package.json does not contain an object.",
1263
1331
  path: filePath
1264
1332
  });
@@ -1270,7 +1338,7 @@ function* writePackageFieldBody(field, value, options) {
1270
1338
  * Set a top-level field of the nearest `package.json` (same locate
1271
1339
  * semantics as readPackageField) and write it back, preserving the
1272
1340
  * file's existing indentation. Passing `undefined` removes the field.
1273
- * Throws LocterNotFoundError when no package.json could be located.
1341
+ * Throws NotFoundError when no package.json could be located.
1274
1342
  */
1275
1343
  async function writePackageField(field, value, options = {}) {
1276
1344
  return runTwinAsync(writePackageFieldBody(field, value, options));
@@ -1279,6 +1347,6 @@ function writePackageFieldSync(field, value, options = {}) {
1279
1347
  runTwinSync(writePackageFieldBody(field, value, options));
1280
1348
  }
1281
1349
  //#endregion
1282
- export { ConfReader, ConfWriter, FormatRegistry, JSONReader, JSONWriter, LOCTER_ERROR_MARKER, LOCTER_LOAD_ERROR_MARKER, LOCTER_NOT_FOUND_ERROR_MARKER, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER, LOCTER_WRITE_ERROR_MARKER, LocterError, LocterLoadError, LocterNotFoundError, LocterUnknownExtensionError, LocterWriteError, MODULE_FILE_EXTENSIONS, ModuleReader, TextFileReader, TextFileWriter, TextReader, TextWriter, YAMLReader, YAMLWriter, buildFilePath, deserializeValue, getFileNameExtension, getModuleExport, isJestRuntimeEnvironment, isLocatorInfo, isModuleRecord, isTsNodeRuntimeEnvironment, isTsxRuntimeEnvironment, isVitestRuntimeEnvironment, locate, locateMany, locateManySync, locateSync, locateUp, locateUpSync, read, readAsModule, readAsModuleSync, readPackageField, readPackageFieldSync, readSync, registerFormat, removeFileNameExtension, serializeValue, setModuleReader, unregisterFormat, useFormatRegistry, wrapLoaderError, wrapWriteError, write, writePackageField, writePackageFieldSync, writeSync };
1350
+ export { ConfReader, ConfWriter, FormatRegistry, JSONReader, JSONWriter, LOCTER_ERROR_MARKER, LOCTER_LOAD_ERROR_MARKER, LOCTER_NOT_FOUND_ERROR_MARKER, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER, LOCTER_WRITE_ERROR_MARKER, LoadError, LocterError, MODULE_FILE_EXTENSIONS, ModuleReader, NotFoundError, TextFileReader, TextFileWriter, TextReader, TextWriter, UnknownExtensionError, WriteError, YAMLReader, YAMLWriter, buildFilePath, deserializeValue, getFileNameExtension, getModuleExport, isJestRuntimeEnvironment, isLocatorInfo, isModuleRecord, isTsNodeRuntimeEnvironment, isTsxRuntimeEnvironment, isVitestRuntimeEnvironment, locate, locateMany, locateManySync, locateSync, locateUp, locateUpSync, read, readAsModule, readAsModuleSync, readPackageField, readPackageFieldSync, readSync, registerFormat, removeFileNameExtension, serializeValue, setModuleReader, unregisterFormat, useFormatRegistry, wrapLoaderError, wrapWriteError, write, writePackageField, writePackageFieldSync, writeSync };
1283
1351
 
1284
1352
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["parseYAML","stringifyYAML"],"sources":["../src/errors/base.ts","../src/errors/load.ts","../src/errors/not-found.ts","../src/errors/unknown-extension.ts","../src/utils/file-name.ts","../src/utils/has-property.ts","../src/utils/object.ts","../src/utils/to-array.ts","../src/utils/file-path.ts","../src/utils/runtime.ts","../src/utils/typescript.ts","../src/errors/write.ts","../src/errors/wrap.ts","../src/utils/twin.ts","../src/locator/utils.ts","../src/locator/core.ts","../src/locator/async.ts","../src/locator/sync.ts","../src/locator/up.ts","../src/format/text-file/reader.ts","../src/format/text-file/writer.ts","../src/format/built-in/conf/reader.ts","../src/format/value.ts","../src/format/built-in/conf/writer.ts","../src/format/built-in/json/reader.ts","../src/format/built-in/json/writer.ts","../src/format/built-in/module/constants.ts","../src/format/built-in/module/reader.ts","../src/format/built-in/module/utils.ts","../src/format/built-in/text/reader.ts","../src/format/built-in/text/writer.ts","../src/format/built-in/yaml/reader.ts","../src/format/built-in/yaml/writer.ts","../src/format/built-in/registry.ts","../src/format/registry/module.ts","../src/format/registry/singleton.ts","../src/format/helpers.ts","../src/format/package-field.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n BaseError,\n type ErrorOptions,\n hasInstanceof,\n markInstanceof,\n} from '@ebec/core';\n\nexport type LocterErrorOptions = ErrorOptions & {\n path?: string,\n};\n\nexport type LocterErrorInput = string | LocterErrorOptions;\n\nexport const LOCTER_ERROR_MARKER = Symbol.for('@locter/error');\n\nexport class LocterError extends BaseError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_ERROR_MARKER);\n }\n\n public readonly path?: string;\n\n constructor(input: LocterErrorInput = {}) {\n if (typeof input === 'string') {\n super(input);\n } else {\n const { path, ...rest } = input;\n super(rest);\n this.path = path;\n }\n\n markInstanceof(this, LOCTER_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasInstanceof, markInstanceof } from '@ebec/core';\nimport { LocterError, type LocterErrorInput } from './base';\n\nexport const LOCTER_LOAD_ERROR_MARKER = Symbol.for('@locter/load-error');\n\nexport class LocterLoadError extends LocterError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_LOAD_ERROR_MARKER);\n }\n\n constructor(input: LocterErrorInput = {}) {\n super(input);\n markInstanceof(this, LOCTER_LOAD_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasInstanceof, markInstanceof } from '@ebec/core';\nimport { LocterError, type LocterErrorInput } from './base';\n\nexport const LOCTER_NOT_FOUND_ERROR_MARKER = Symbol.for('@locter/not-found-error');\n\nexport class LocterNotFoundError extends LocterError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_NOT_FOUND_ERROR_MARKER);\n }\n\n constructor(input: LocterErrorInput = {}) {\n super(input);\n markInstanceof(this, LOCTER_NOT_FOUND_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasInstanceof, markInstanceof } from '@ebec/core';\nimport { LocterError, type LocterErrorInput } from './base';\n\nexport const LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER = Symbol.for('@locter/unknown-extension-error');\n\nexport class LocterUnknownExtensionError extends LocterError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER);\n }\n\n constructor(input: LocterErrorInput = {}) {\n super(input);\n markInstanceof(this, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport path from 'node:path';\n\nexport function getFileNameExtension(\n input: string,\n allowed?: string[],\n) : string | undefined {\n const extension = path.extname(input);\n if (extension === '' || extension === '.') {\n return undefined;\n }\n\n if (\n typeof allowed === 'undefined' ||\n allowed.includes(extension)\n ) {\n return extension;\n }\n\n return undefined;\n}\n\nexport function removeFileNameExtension(\n input: string,\n extensions?: string[],\n) {\n const extension = getFileNameExtension(input, extensions);\n if (extension) {\n return input.substring(0, input.length - extension.length);\n }\n\n return input;\n}\n","export function hasOwnProperty<X extends Record<string, any>, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown> {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\nexport function hasStringProperty<X extends Record<string, any>, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, string> {\n return hasOwnProperty(obj, prop) && typeof obj[prop] === 'string';\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function isObject(item: unknown) : item is Record<string, any> {\n return (\n !!item &&\n typeof item === 'object' &&\n !Array.isArray(item)\n );\n}\n\nexport function isSafeObjectKey(key: string) : boolean {\n return key !== '__proto__' &&\n key !== 'prototype' &&\n key !== 'constructor';\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function toArray(input: string | string[]) : string[] {\n return Array.isArray(input) ? input : [input];\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\nimport path from 'node:path';\n\nexport function isFilePath(input: string) {\n const extension = path.extname(input);\n return extension && extension !== '';\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function isJestRuntimeEnvironment() : boolean {\n return process.env &&\n process.env.JEST_WORKER_ID !== undefined;\n}\n\nexport function isVitestRuntimeEnvironment() : boolean {\n return typeof process !== 'undefined' &&\n process.env.VITEST === 'true';\n}\n\nexport function isTsNodeRuntimeEnvironment(): boolean {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return !!process[Symbol.for('ts-node.register.instance')];\n}\n\n// matches the bare `tsx` specifier (node --import tsx), optionally with a\n// subpath (tsx/esm), as well as resolved paths into the tsx package\n// (.../node_modules/tsx/dist/loader.mjs)\nconst TSX_MARKER_REGEX = /(?:^|=|[\\\\/])tsx(?:$|[\\\\/])/;\n\nexport function isTsxRuntimeEnvironment() : boolean {\n if (typeof process === 'undefined') {\n return false;\n }\n\n if (\n Array.isArray(process.execArgv) &&\n process.execArgv.some((arg) => TSX_MARKER_REGEX.test(arg))\n ) {\n return true;\n }\n\n const { _preload_modules: preloadModules } = process as unknown as { _preload_modules?: string[] };\n\n return Array.isArray(preloadModules) &&\n preloadModules.some((el) => TSX_MARKER_REGEX.test(el));\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from './object';\n\nexport function isTypeScriptError(input: unknown) : input is Error {\n if (!isObject(input)) {\n return false;\n }\n\n if (typeof input.diagnosticCodes !== 'undefined') {\n return true;\n }\n\n return typeof input.message === 'string' &&\n /TS\\d+/.test(input.message);\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasInstanceof, markInstanceof } from '@ebec/core';\nimport { LocterError, type LocterErrorInput } from './base';\n\nexport const LOCTER_WRITE_ERROR_MARKER = Symbol.for('@locter/write-error');\n\nexport class LocterWriteError extends LocterError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_WRITE_ERROR_MARKER);\n }\n\n constructor(input: LocterErrorInput = {}) {\n super(input);\n markInstanceof(this, LOCTER_WRITE_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasStringProperty, isObject } from '../utils';\nimport { LocterError } from './base';\nimport { LocterLoadError } from './load';\nimport { LocterNotFoundError } from './not-found';\nimport { LocterWriteError } from './write';\n\nconst NOT_FOUND_CODES = new Set([\n 'ENOENT',\n 'MODULE_NOT_FOUND',\n 'ERR_MODULE_NOT_FOUND',\n]);\n\nexport function wrapLoaderError(input: unknown, path: string) : LocterError {\n if (input instanceof LocterError) {\n return input;\n }\n\n const code = isObject(input) && hasStringProperty(input, 'code') ?\n input.code :\n undefined;\n\n const message = isObject(input) && hasStringProperty(input, 'message') ?\n input.message :\n `Failed to load: ${path}`;\n\n if (code && NOT_FOUND_CODES.has(code)) {\n return new LocterNotFoundError({\n message,\n code,\n cause: input,\n path,\n });\n }\n\n return new LocterLoadError({\n message,\n code,\n cause: input,\n path,\n });\n}\n\nexport function wrapWriteError(input: unknown, path: string) : LocterError {\n if (input instanceof LocterError) {\n return input;\n }\n\n const code = isObject(input) && hasStringProperty(input, 'code') ?\n input.code :\n undefined;\n\n const message = isObject(input) && hasStringProperty(input, 'message') ?\n input.message :\n `Failed to write: ${path}`;\n\n return new LocterWriteError({\n message,\n code,\n cause: input,\n path,\n });\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n/**\n * Internal protocol to derive the parallel sync + async public surfaces\n * from one shared body. A body is a generator that yields effect pairs —\n * an async and a sync thunk for the same operation — and the two drivers\n * (runTwinAsync / runTwinSync) execute the side they stand for. Effect\n * errors are re-entered into the body via `Generator.throw`, so try/catch\n * inside a body behaves identically in both variants.\n *\n * Deliberately NOT exported from the utils barrel — this is internal\n * plumbing, not public API.\n */\n\nexport type TwinOp<T = unknown> = {\n async: () => Promise<T>,\n sync: () => T,\n};\n\nexport type TwinBody<R> = Generator<TwinOp<any>, R, any>;\n\n/**\n * Perform one effect inside a twin body: `const x = yield* op(a, s)`.\n */\nexport function* op<T>(\n asyncFn: () => Promise<T>,\n syncFn: () => T,\n) : Generator<TwinOp<T>, T, T> {\n return yield { async: asyncFn, sync: syncFn };\n}\n\nexport async function runTwinAsync<R>(body: TwinBody<R>) : Promise<R> {\n let step = body.next();\n while (!step.done) {\n let result : unknown;\n try {\n result = await step.value.async();\n } catch (e) {\n step = body.throw(e);\n continue;\n }\n\n step = body.next(result);\n }\n\n return step.value;\n}\n\nexport function runTwinSync<R>(body: TwinBody<R>) : R {\n let step = body.next();\n while (!step.done) {\n let result : unknown;\n try {\n result = step.value.sync();\n } catch (e) {\n step = body.throw(e);\n continue;\n }\n\n step = body.next(result);\n }\n\n return step.value;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport path from 'node:path';\nimport { isObject, toArray } from '../utils';\nimport type { LocatorInfo, LocatorOptions, LocatorOptionsInput } from './types';\n\nexport function buildLocatorPatterns(pattern: string | string[]) : string[] {\n return Array.isArray(pattern) ?\n pattern :\n [pattern];\n}\n\nexport function buildLocatorOptions(options: LocatorOptionsInput = {}) : LocatorOptions {\n const cwd = options.cwd ?\n toArray(options.cwd) :\n [];\n\n const ignore = options.ignore ?\n toArray(options.ignore) :\n [];\n\n if (cwd.length === 0) {\n cwd.push(process.cwd());\n }\n\n // precedence: an explicit `onlyDirectories: true` wins over `onlyFiles`\n // (which defaults to true); when neither restricts, everything matches\n const onlyDirectories = options.onlyDirectories ?? false;\n const onlyFiles = onlyDirectories ?\n false :\n options.onlyFiles ?? true;\n\n return {\n cwd,\n ignore,\n onlyDirectories,\n onlyFiles,\n dot: options.dot ?? false,\n };\n}\n\nexport function pathToLocatorInfo(\n input: string,\n skipResolve?: boolean,\n) : LocatorInfo {\n if (\n !skipResolve &&\n !path.isAbsolute(input)\n ) {\n input = path.resolve(process.cwd(), input);\n }\n\n const info = path.parse(input);\n const directory = info.dir.split('/').join(path.sep);\n const extension = info.ext ? info.ext : undefined;\n const filePath = extension ?\n path.join(directory, info.name) + extension :\n path.join(directory, info.name);\n\n return {\n directory,\n name: info.name,\n extension,\n path: filePath,\n };\n}\n\nexport function isLocatorInfo(\n input: unknown,\n) : input is LocatorInfo {\n return isObject(input) &&\n typeof input.directory === 'string' &&\n typeof input.name === 'string' &&\n (typeof input.extension === 'undefined' || typeof input.extension === 'string') &&\n typeof input.path === 'string';\n}\n\nexport function buildFilePath(input: LocatorInfo | string) {\n if (typeof input === 'string') {\n return input;\n }\n\n return input.path;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport fg from 'fast-glob';\nimport type { TwinBody } from '../utils/twin';\nimport { op } from '../utils/twin';\nimport type { LocatorInfo, LocatorOptionsInput } from './types';\nimport { buildLocatorOptions, buildLocatorPatterns, pathToLocatorInfo } from './utils';\n\ntype GlobJob = {\n pattern: string,\n options: fg.Options,\n};\n\nfunction buildGlobJobs(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : GlobJob[] {\n const patterns = buildLocatorPatterns(pattern);\n const opts = buildLocatorOptions(options);\n\n const jobs : GlobJob[] = [];\n for (const p of patterns) {\n for (const cwd of opts.cwd) {\n jobs.push({\n pattern: p,\n options: {\n absolute: true,\n cwd,\n ignore: opts.ignore,\n onlyFiles: opts.onlyFiles,\n onlyDirectories: opts.onlyDirectories,\n dot: opts.dot,\n },\n });\n }\n }\n\n return jobs;\n}\n\nfunction* glob(job: GlobJob) : Generator<any, string[], any> {\n return yield* op(\n () => fg(job.pattern, job.options),\n () => fg.sync(job.pattern, job.options),\n );\n}\n\nexport function* locateBody(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : TwinBody<LocatorInfo | undefined> {\n for (const job of buildGlobJobs(pattern, options)) {\n const files = yield* glob(job);\n\n const element = files.shift();\n if (element) {\n return pathToLocatorInfo(element, true);\n }\n }\n\n return undefined;\n}\n\nexport function* locateManyBody(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : TwinBody<LocatorInfo[]> {\n const items : LocatorInfo[] = [];\n\n for (const job of buildGlobJobs(pattern, options)) {\n const files = yield* glob(job);\n\n for (const file of files) {\n items.push(pathToLocatorInfo(file, true));\n }\n }\n\n return items;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { runTwinAsync } from '../utils/twin';\nimport { locateBody, locateManyBody } from './core';\nimport type { LocatorInfo, LocatorOptionsInput } from './types';\n\nexport async function locateMany(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : Promise<LocatorInfo[]> {\n return runTwinAsync(locateManyBody(pattern, options));\n}\n\nexport async function locate(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : Promise<LocatorInfo | undefined> {\n return runTwinAsync(locateBody(pattern, options));\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { runTwinSync } from '../utils/twin';\nimport { locateBody, locateManyBody } from './core';\nimport type { LocatorInfo, LocatorOptionsInput } from './types';\n\nexport function locateManySync(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : LocatorInfo[] {\n return runTwinSync(locateManyBody(pattern, options));\n}\n\nexport function locateSync(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : LocatorInfo | undefined {\n return runTwinSync(locateBody(pattern, options));\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport path from 'node:path';\nimport type { TwinBody } from '../utils/twin';\nimport { runTwinAsync, runTwinSync } from '../utils/twin';\nimport { locateBody } from './core';\nimport type { LocatorInfo, LocatorOptionsInput } from './types';\n\nexport type LocatorUpOptionsInput = Omit<LocatorOptionsInput, 'cwd'> & {\n cwd?: string,\n stopAt?: string,\n};\n\ntype WalkStep = {\n current: string,\n stopAt: string,\n baseOptions: Omit<LocatorOptionsInput, 'cwd'>,\n};\n\nfunction startWalk(options: LocatorUpOptionsInput) : WalkStep {\n const {\n cwd,\n stopAt,\n ...baseOptions\n } = options;\n const current = path.resolve(cwd ?? process.cwd());\n const ceiling = stopAt ?\n path.resolve(current, stopAt) :\n path.parse(current).root;\n\n return {\n current,\n stopAt: ceiling,\n baseOptions,\n };\n}\n\nfunction nextDirectory(current: string, stopAt: string) : string | undefined {\n if (current === stopAt) {\n return undefined;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n\n return parent;\n}\n\nfunction* locateUpBody(\n pattern: string | string[],\n options: LocatorUpOptionsInput,\n) : TwinBody<LocatorInfo | undefined> {\n let walk = startWalk(options);\n\n while (true) {\n const found = yield* locateBody(pattern, { ...walk.baseOptions, cwd: walk.current });\n if (found) {\n return found;\n }\n\n const next = nextDirectory(walk.current, walk.stopAt);\n if (!next) {\n return undefined;\n }\n\n walk = { ...walk, current: next };\n }\n}\n\nexport async function locateUp(\n pattern: string | string[],\n options: LocatorUpOptionsInput = {},\n) : Promise<LocatorInfo | undefined> {\n return runTwinAsync(locateUpBody(pattern, options));\n}\n\nexport function locateUpSync(\n pattern: string | string[],\n options: LocatorUpOptionsInput = {},\n) : LocatorInfo | undefined {\n return runTwinSync(locateUpBody(pattern, options));\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport fs from 'node:fs';\nimport { wrapLoaderError } from '../../errors';\nimport type { TwinBody } from '../../utils/twin';\nimport { op, runTwinAsync, runTwinSync } from '../../utils/twin';\nimport type { IReader } from '../type';\n\n/**\n * Base class for readers of text-based file formats: reads the file as\n * UTF-8, delegates to `parse`, and wraps I/O and parse errors in typed\n * LocterError subclasses. Subclasses implement `parse` only — both\n * `read` variants are derived from the same body.\n */\nexport abstract class TextFileReader implements IReader {\n abstract parse(content: string) : any;\n\n async read(input: string) : Promise<any> {\n return runTwinAsync(this.body(input));\n }\n\n readSync(input: string) : any {\n return runTwinSync(this.body(input));\n }\n\n protected* body(input: string) : TwinBody<any> {\n try {\n const content = yield* op(\n () => fs.promises.readFile(input, { encoding: 'utf-8' }),\n () => fs.readFileSync(input, { encoding: 'utf-8' }),\n );\n\n return this.parse(content);\n } catch (e) {\n throw wrapLoaderError(e, input);\n }\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { wrapWriteError } from '../../errors';\nimport type { TwinBody } from '../../utils/twin';\nimport { op, runTwinAsync, runTwinSync } from '../../utils/twin';\nimport type { IWriter } from '../type';\n\nfunction isNotFound(e: unknown) : boolean {\n return e instanceof Error && 'code' in e && e.code === 'ENOENT';\n}\n\n/**\n * Base class for writers of text-based file formats: serializes via\n * `stringify`, creates missing parent directories, writes the file as\n * UTF-8 (always terminated by a single trailing newline), and wraps\n * failures in LocterWriteError. Subclasses implement `stringify` only —\n * both `write` variants are derived from the same body.\n */\nexport abstract class TextFileWriter implements IWriter {\n /**\n * Opt-in: when true, the body reads the target file first (undefined\n * if absent) and passes its content to `stringify` as `existing` —\n * the hook behind format-preserving write-back (YAML comment\n * grafting, JSON indent detection).\n */\n protected get usesExistingContent() : boolean {\n return false;\n }\n\n abstract stringify(value: unknown, existing?: string) : string;\n\n async write(input: string, value: unknown) : Promise<void> {\n return runTwinAsync(this.body(input, value));\n }\n\n writeSync(input: string, value: unknown) : void {\n runTwinSync(this.body(input, value));\n }\n\n protected* body(input: string, value: unknown) : TwinBody<void> {\n const filePath = input;\n\n try {\n let existing : string | undefined;\n if (this.usesExistingContent) {\n existing = yield* op(\n () => fs.promises.readFile(filePath, { encoding: 'utf-8' })\n .catch((e) => {\n if (isNotFound(e)) {\n return undefined;\n }\n throw e;\n }),\n () => {\n try {\n return fs.readFileSync(filePath, { encoding: 'utf-8' });\n } catch (e) {\n if (isNotFound(e)) {\n return undefined;\n }\n throw e;\n }\n },\n );\n }\n\n let content = this.stringify(value, existing);\n if (!content.endsWith('\\n')) {\n content += '\\n';\n }\n\n const directory = path.dirname(filePath);\n yield* op(\n async () => {\n await fs.promises.mkdir(directory, { recursive: true });\n },\n () => {\n fs.mkdirSync(directory, { recursive: true });\n },\n );\n\n yield* op(\n () => fs.promises.writeFile(filePath, content, { encoding: 'utf-8' }),\n () => fs.writeFileSync(filePath, content, { encoding: 'utf-8' }),\n );\n } catch (e) {\n throw wrapWriteError(e, filePath);\n }\n }\n}\n","/*\n * Copyright (c) 2022-2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n// Based on https://github.com/unjs/rc9 (MIT)\n\nimport { destr } from 'destr';\nimport { unflatten } from 'flat';\nimport { isSafeObjectKey } from '../../../utils';\nimport { TextFileReader } from '../../text-file';\n\nexport class ConfReader extends TextFileReader {\n parse(contents: string): Record<string, any> {\n const config: Record<string, any> = {};\n\n const lines = contents.split(/\\n|\\r|\\r\\n/);\n\n for (const line of lines) {\n const match = line.match(/^\\s*([^\\s=]+)\\s*=\\s*(.*)?\\s*$/);\n if (!match) {\n continue;\n }\n\n const key = match[1];\n const rawValue = match[2];\n\n if (!key || !isSafeObjectKey(key)) {\n continue;\n }\n\n const value = destr(rawValue ? rawValue.trim() : '');\n\n if (key.endsWith('[]')) {\n const arrKey = key.slice(0, Math.max(0, key.length - 2));\n config[arrKey] = (config[arrKey] || []).concat(value);\n continue;\n }\n\n config[key] = value;\n }\n\n return unflatten(config, { overwrite: true });\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { destr } from 'destr';\n\n/**\n * Lenient VALUE codec (env-var / key-value philosophy): primitives\n * serialize to their bare string form, RegExp and BigInt to their\n * string representation (also nested), everything else to JSON.\n * The counterpart of deserializeValue — used per value by the conf\n * format, and exported for consumers building lenient custom formats.\n */\nexport function serializeValue(input: unknown) : string {\n if (typeof input === 'string') {\n return input;\n }\n\n if (typeof input === 'undefined') {\n return 'undefined';\n }\n\n if (input === null) {\n return 'null';\n }\n\n if (typeof input === 'boolean') {\n return input ? 'true' : 'false';\n }\n\n if (typeof input === 'number') {\n return `${input}`;\n }\n\n if (typeof input === 'bigint') {\n return input.toString();\n }\n\n if (input instanceof RegExp) {\n return input.toString();\n }\n\n const output = JSON.stringify(input, (_key, item) => {\n if (item instanceof RegExp) {\n return item.toString();\n }\n\n if (typeof item === 'bigint') {\n return item.toString();\n }\n\n return item;\n });\n\n // JSON.stringify yields undefined for top-level Symbol/Function and\n // toJSON() returning undefined — a lenient codec still returns a string\n return output ?? String(input);\n}\n\n/**\n * Lenient parse of a serialized value: coerces 'true'/'123'/'null'/\n * 'undefined' to their primitive, parses JSON payloads, and falls back\n * to returning the raw string — it never throws.\n */\nexport function deserializeValue<T = any>(input: string) : T {\n return destr(input);\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n// Based on https://github.com/unjs/rc9 (MIT)\n\nimport { flatten } from 'flat';\nimport { isObject } from '../../../utils';\nimport { TextFileWriter } from '../../text-file';\nimport { serializeValue } from '../../value';\n\n/**\n * Serializes an object to `key=value` lines (the inverse of ConfReader):\n * nested objects become dot-separated keys, arrays become repeated\n * `key[]=` lines. Round-trips are structural, not textual — comments,\n * blank lines, and line order of an existing file are not preserved,\n * and a string that parses as another type (e.g. '123') reads back as\n * that type.\n */\nexport class ConfWriter extends TextFileWriter {\n stringify(value: unknown) : string {\n if (!isObject(value)) {\n throw new Error('The value must be an object for the conf format.');\n }\n\n const flat : Record<string, unknown> = flatten(value, { safe: true });\n\n const lines : string[] = [];\n for (const key of Object.keys(flat)) {\n const entry = flat[key];\n if (typeof entry === 'undefined') {\n continue;\n }\n\n if (Array.isArray(entry)) {\n for (const item of entry) {\n lines.push(`${key}[]=${serializeValue(item)}`);\n }\n continue;\n }\n\n lines.push(`${key}=${serializeValue(entry)}`);\n }\n\n return lines.join('\\n');\n }\n}\n","/*\n * Copyright (c) 2022-2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TextFileReader } from '../../text-file';\n\nexport class JSONReader extends TextFileReader {\n parse(content: string) {\n return JSON.parse(content);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TextFileWriter } from '../../text-file';\n\nexport type JSONWriterOptions = {\n /**\n * Indentation of the emitted JSON. A number of spaces, a literal\n * indent string, or 'auto' — detect the indentation of the existing\n * target file and keep it (falls back to 4 for new files).\n *\n * @default 4\n */\n indent?: number | string | 'auto'\n};\n\nfunction detectIndent(content: string) : string | undefined {\n const match = /^([ \\t]+)\\S/m.exec(content);\n return match ? match[1] : undefined;\n}\n\nexport class JSONWriter extends TextFileWriter {\n protected options : JSONWriterOptions;\n\n constructor(options: JSONWriterOptions = {}) {\n super();\n this.options = options;\n }\n\n protected override get usesExistingContent() : boolean {\n return this.options.indent === 'auto';\n }\n\n stringify(value: unknown, existing?: string) : string {\n let indent : number | string | undefined;\n if (this.options.indent === 'auto') {\n indent = existing ? detectIndent(existing) : undefined;\n } else {\n indent = this.options.indent;\n }\n\n indent = indent ?? 4;\n\n const output = JSON.stringify(value, null, indent);\n if (typeof output === 'undefined') {\n throw new Error('The value is not JSON-serializable.');\n }\n\n return output;\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n/**\n * Single source of truth for the extensions handled by the module loader:\n * consumed by BOTH the built-in routing registry and the jiti config.\n */\nexport const MODULE_FILE_EXTENSIONS = ['.js', '.mjs', '.mts', '.cjs', '.cts', '.ts'] as const;\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createJiti } from 'jiti';\nimport { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { LocterError, wrapLoaderError } from '../../../errors';\nimport type { LocatorInfo } from '../../../locator';\nimport {\n buildFilePath,\n isLocatorInfo,\n} from '../../../locator';\nimport {\n hasStringProperty,\n isFilePath,\n isJestRuntimeEnvironment,\n isObject,\n isTsNodeRuntimeEnvironment,\n isTypeScriptError,\n} from '../../../utils';\nimport type { IReader } from '../../type';\nimport { MODULE_FILE_EXTENSIONS } from './constants';\nimport type {\n ModuleLoadFn,\n ModuleLoadOptions,\n ModuleLoadSyncFn,\n ModuleReaderOptions,\n} from './type';\n\nconst require = createRequire(import.meta.url);\n\ntype Jiti = ReturnType<typeof createJiti>;\n\nfunction originalPath(data: LocatorInfo | string) : string {\n return typeof data === 'string' ? data : buildFilePath(data);\n}\n\nfunction isUnrecoverableError(error: unknown) : boolean {\n const underlying = error instanceof LocterError ? error.cause : error;\n return underlying instanceof SyntaxError ||\n underlying instanceof ReferenceError ||\n isTypeScriptError(underlying);\n}\n\nexport class ModuleReader implements IReader {\n protected instance : Jiti;\n\n protected loadFn?: ModuleLoadFn;\n\n protected loadSyncFn?: ModuleLoadSyncFn;\n\n constructor(options: ModuleReaderOptions = {}) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.instance = createJiti(undefined, { extensions: [...MODULE_FILE_EXTENSIONS] });\n this.loadFn = options.load;\n this.loadSyncFn = options.loadSync;\n }\n\n /**\n * Returns the previous configuration, so callers can restore it.\n */\n configure(options: ModuleReaderOptions) : ModuleReaderOptions {\n const previous : ModuleReaderOptions = {\n load: this.loadFn,\n loadSync: this.loadSyncFn,\n };\n\n if ('load' in options) {\n this.loadFn = options.load;\n }\n if ('loadSync' in options) {\n this.loadSyncFn = options.loadSync;\n }\n\n return previous;\n }\n\n /**\n * Returns the raw module value (import / require / jiti output) —\n * normalization to a module record happens once, at the\n * FormatRegistry boundary.\n *\n * read/readSync are deliberately NOT derived from a shared body\n * (unlike every other sync/async twin in this package): their\n * recovery paths differ. The async variant falls back to loadSync\n * under ts-node (jiti's async path does not cooperate with ts-node)\n * and to the jiti instance otherwise; the sync variant only has the\n * jiti fallback. The divergence is pinned by the fallback tests in\n * test/unit/format/module.spec.ts.\n */\n async read(input: string) {\n try {\n return await this.load(input);\n } catch (e) {\n if (isUnrecoverableError(e)) {\n throw e;\n }\n\n // jiti + ts-node\n // issue: https://github.com/nuxt/bridge/issues/228\n if (isTsNodeRuntimeEnvironment()) {\n return this.loadSync(input);\n }\n\n return this.instance(input);\n }\n }\n\n readSync(input: string) {\n try {\n return this.loadSync(input);\n } catch (e) {\n if (isUnrecoverableError(e)) {\n throw e;\n }\n\n return this.instance(input);\n }\n }\n\n // ---------------------------------------------------------------------------\n\n async load(\n data: LocatorInfo | string,\n options: ModuleLoadOptions = {},\n ) : Promise<unknown> {\n const id = this.build(data, options);\n\n try {\n if (this.loadFn) {\n return await this.loadFn(id);\n }\n\n // segmentation fault\n // issue: https://github.com/nodejs/node/issues/35889\n if (isJestRuntimeEnvironment()) {\n return require(id);\n }\n\n return await import(id);\n } catch (e) {\n /* istanbul ignore next */\n if (\n !options.withFilePrefix &&\n isObject(e) &&\n hasStringProperty(e, 'code') &&\n (\n e.code === 'ERR_UNSUPPORTED_ESM_URL_SCHEME' ||\n e.code === 'UNSUPPORTED_ESM_URL_SCHEME'\n )\n ) {\n return this.load(data, {\n ...options,\n withFilePrefix: true,\n });\n }\n\n throw wrapLoaderError(e, originalPath(data));\n }\n }\n\n loadSync(\n data: LocatorInfo | string,\n options: ModuleLoadOptions = {},\n ) : unknown {\n const id = this.build(data, options);\n\n try {\n if (this.loadSyncFn) {\n return this.loadSyncFn(id);\n }\n\n return require(id);\n } catch (e) {\n throw wrapLoaderError(e, originalPath(data));\n }\n }\n\n private build(\n data: LocatorInfo | string,\n options: ModuleLoadOptions = {},\n ) : string {\n if (isLocatorInfo(data) || isFilePath(data)) {\n if (typeof data !== 'string') {\n data = buildFilePath(data);\n }\n\n if (options.withFilePrefix) {\n data = pathToFileURL(data).href;\n }\n }\n\n return data;\n }\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasOwnProperty, isObject } from '../../../utils';\nimport type { ModuleExport, ModuleExportFilterFn } from './type';\n\ntype ESModule = { [key: string]: any, __esModule: boolean };\n\n/**\n * Brand carried by every record locter's read() produces. Deliberately a\n * module-private Symbol (NOT Symbol.for) so arbitrary parsed data cannot\n * forge it — unlike `__esModule`, its presence is trustworthy. write()\n * uses it to unwrap `.default` on round-trips.\n */\nconst MODULE_RECORD = Symbol('locter.record');\n\n/**\n * True when the value is a record produced by locter's read()/toModuleRecord.\n * Detection is brand-based; a plain object with an `__esModule` key is NOT\n * a module record.\n */\nexport function isModuleRecord(input: unknown) : input is Record<string, any> {\n return isObject(input) && MODULE_RECORD in input;\n}\n\nfunction brand<T>(input: T) : T {\n if (isObject(input) && Object.isExtensible(input)) {\n Object.defineProperty(input, MODULE_RECORD, { value: true });\n }\n\n return input;\n}\n\n/**\n * Detect the transpiler interop marker (`__esModule`). Only meaningful for\n * values that came out of a module system — arbitrary parsed data can carry\n * an `__esModule` key without being a module, so callers must decide by\n * provenance whether this check applies (see FormatRegistry).\n */\nexport function isESModule(input: unknown) : input is ESModule {\n return isObject(input) &&\n typeof input.__esModule !== 'undefined';\n}\n\n/**\n * Wrap an arbitrary value in a frozen module record: enumerable keys are\n * re-exposed as named exports and `default` is the value itself.\n */\nexport function createModuleRecord(data: unknown) {\n const output = Object.create(null, {\n __esModule: { value: true },\n [Symbol.toStringTag]: { value: 'Module' },\n [MODULE_RECORD]: { value: true },\n });\n\n if (isObject(data)) {\n for (const key in data) {\n if (hasOwnProperty(output, key)) {\n continue;\n }\n\n let descriptor = Object.getOwnPropertyDescriptor(data, key);\n if (\n !descriptor ||\n ('get' in descriptor || descriptor.writable || descriptor.configurable)\n ) {\n descriptor = {\n enumerable: true,\n get() {\n return data[key];\n },\n };\n }\n\n Object.defineProperty(output, key, descriptor);\n }\n }\n\n if (!hasOwnProperty(output, 'default')) {\n Object.defineProperty(output, 'default', {\n value: data,\n enumerable: true,\n });\n }\n\n return Object.freeze(output);\n}\n\n/**\n * Normalize module-loader output to a module record. Values already carrying\n * the `__esModule` marker pass through (module provenance makes the marker\n * trustworthy); everything else is wrapped via createModuleRecord.\n *\n * https://2ality.com/2017/01/babel-esm-spec-mode.html\n */\nexport function toModuleRecord(\n data: unknown,\n) {\n if (isESModule(data)) {\n // @see https://github.com/testing-library/user-event/issues/813\n // @see https://stackoverflow.com/questions/62717394/export-default-class-exports-double-nested-default\n if (\n isESModule(data.default) &&\n data.default.default\n ) {\n return brand({\n ...data,\n default: data.default.default,\n });\n }\n\n // best-effort: module namespace objects are non-extensible and\n // stay unbranded — they have no writable format anyway\n return brand(data);\n }\n\n return createModuleRecord(data);\n}\n\nexport function getModuleExport(\n data: Record<string, any>,\n filterFn: ModuleExportFilterFn,\n): ModuleExport | undefined {\n const keys = Object.keys(data);\n for (const key of keys) {\n if (filterFn(key as string, data[key as string])) {\n return {\n key: key as string,\n value: data[key as string],\n };\n }\n }\n\n return undefined;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TextFileReader } from '../../text-file';\n\n/**\n * Raw text: the file content, as-is. No value coercion — a .txt\n * containing '123' reads as the string '123' (use deserializeValue\n * for lenient value semantics).\n */\nexport class TextReader extends TextFileReader {\n parse(content: string) {\n return content;\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TextFileWriter } from '../../text-file';\n\n/**\n * Raw text: accepts strings only — coercing arbitrary values would be\n * lossy ([object Object]); serialize explicitly (e.g. serializeValue)\n * before writing. Output ends with a single trailing newline, like\n * every text writer.\n */\nexport class TextWriter extends TextFileWriter {\n stringify(value: unknown) : string {\n if (typeof value !== 'string') {\n throw new Error('The value must be a string for the text format.');\n }\n\n return value;\n }\n}\n","/*\n * Copyright (c) 2022-2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { parse as parseYAML } from 'yaml';\nimport { TextFileReader } from '../../text-file';\n\nexport class YAMLReader extends TextFileReader {\n parse(content: string) {\n return parseYAML(content);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Document, ToStringOptions, YAMLMap } from 'yaml';\nimport {\n isMap,\n isNode,\n isScalar,\n parseDocument,\n stringify as stringifyYAML,\n} from 'yaml';\nimport { hasOwnProperty, isObject } from '../../../utils';\nimport { TextFileWriter } from '../../text-file';\n\nexport type YAMLWriterOptions = ToStringOptions;\n\nfunction pairKey(key: unknown) : string {\n return isScalar(key) ? String(key.value) : String(key);\n}\n\n/**\n * Merge a plain object into an existing YAML map node: added/changed keys\n * are set, absent keys are deleted, and nested objects recurse — so\n * comments, anchors, and formatting attached to surviving keys are\n * preserved. Arrays, scalars, and type changes replace the node wholesale\n * (comments inside the replaced subtree are lost).\n */\nfunction graftMap(doc: Document, node: YAMLMap, value: Record<string, unknown>) : void {\n for (const pair of [...node.items]) {\n if (!hasOwnProperty(value, pairKey(pair.key))) {\n node.delete(pair.key);\n }\n }\n\n for (const key of Object.keys(value)) {\n const entry = value[key];\n const current = node.get(key, true);\n\n if (isMap(current) && isObject(entry)) {\n graftMap(doc, current, entry);\n continue;\n }\n\n const replacement = doc.createNode(entry);\n if (isNode(current)) {\n // keep comments anchored to the value node itself\n // (`key: value # trailing`, standalone lines above the value)\n replacement.commentBefore = current.commentBefore;\n replacement.comment = current.comment;\n replacement.spaceBefore = current.spaceBefore;\n }\n\n node.set(doc.createNode(key), replacement);\n }\n}\n\n/**\n * Writes YAML preserving hand-edited structure where possible: when the\n * target file already exists, the new value is grafted into its parsed\n * document, so comments and anchors attached to surviving keys survive\n * the write-back. New files are plain `yaml.stringify` output. An\n * existing file that fails to parse throws (wrapped as LocterWriteError)\n * instead of being silently overwritten.\n */\nexport class YAMLWriter extends TextFileWriter {\n protected options : YAMLWriterOptions;\n\n constructor(options: YAMLWriterOptions = {}) {\n super();\n this.options = options;\n }\n\n protected override get usesExistingContent() : boolean {\n return true;\n }\n\n stringify(value: unknown, existing?: string) : string {\n if (typeof existing === 'undefined') {\n return stringifyYAML(value, this.options);\n }\n\n // widen from Document.Parsed: contents is replaced with\n // freshly created (non-parsed) nodes while grafting\n const doc : Document = parseDocument(existing);\n if (doc.errors.length > 0) {\n throw doc.errors[0];\n }\n\n if (isMap(doc.contents) && isObject(value)) {\n graftMap(doc, doc.contents, value);\n } else {\n doc.contents = doc.createNode(value);\n }\n\n return doc.toString(this.options);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { FormatPreset } from '../registry/type';\nimport type { IWriter } from '../type';\nimport { ConfReader, ConfWriter } from './conf';\nimport { JSONReader, JSONWriter } from './json';\nimport { ModuleReader } from './module';\nimport { TextReader, TextWriter } from './text';\nimport { MODULE_FILE_EXTENSIONS } from './module/constants';\nimport { YAMLReader, YAMLWriter } from './yaml';\n\n/**\n * Every built-in format, in one place. Keys are the format ids; each entry\n * couples routing and construction. The id union, the extension → format\n * table, lazy caching, and the typed `builtInReader()` accessor are all\n * DERIVED from this object. Adding a format = adding one entry.\n *\n * Intentionally NOT re-exported from any barrel (internal API).\n */\nexport const BUILT_IN_PRESETS = {\n module: { extensions: MODULE_FILE_EXTENSIONS, reader: () => new ModuleReader() },\n conf: {\n extensions: ['.conf'],\n reader: () => new ConfReader(),\n writer: () => new ConfWriter(),\n },\n json: {\n extensions: ['.json'],\n reader: () => new JSONReader(),\n writer: () => new JSONWriter(),\n },\n yaml: {\n extensions: ['.yml', '.yaml'],\n reader: () => new YAMLReader(),\n writer: () => new YAMLWriter(),\n },\n text: {\n extensions: ['.txt'],\n reader: () => new TextReader(),\n writer: () => new TextWriter(),\n },\n} as const satisfies Record<string, FormatPreset>;\n\nexport type BuiltInFormatId = keyof typeof BUILT_IN_PRESETS;\n\nexport type BuiltInReaderOf<K extends BuiltInFormatId> = ReturnType<(typeof BUILT_IN_PRESETS)[K]['reader']>;\n\n/**\n * Built-in format ids whose preset declares a writer — derived at the type\n * level, so builtInWriter('module') is a compile error, not a runtime one.\n */\nexport type WritableBuiltInFormatId = {\n [K in BuiltInFormatId]: (typeof BUILT_IN_PRESETS)[K] extends { writer: () => IWriter } ? K : never\n}[BuiltInFormatId];\n\nexport type BuiltInWriterOf<K extends WritableBuiltInFormatId> = ReturnType<(typeof BUILT_IN_PRESETS)[K]['writer']>;\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n LocterError,\n LocterUnknownExtensionError,\n LocterWriteError,\n wrapLoaderError,\n wrapWriteError,\n} from '../../errors';\nimport type { LocatorInfo } from '../../locator';\nimport { buildFilePath, pathToLocatorInfo } from '../../locator';\nimport { hasOwnProperty, isFilePath } from '../../utils';\nimport type { TwinBody } from '../../utils/twin';\nimport { op, runTwinAsync, runTwinSync } from '../../utils/twin';\nimport {\n ModuleReader, \n createModuleRecord, \n isModuleRecord, \n toModuleRecord,\n} from '../built-in';\nimport type {\n BuiltInFormatId,\n BuiltInReaderOf,\n BuiltInWriterOf,\n WritableBuiltInFormatId,\n} from '../built-in/registry';\nimport { BUILT_IN_PRESETS } from '../built-in/registry';\nimport type { IReader, IWriter } from '../type';\nimport type {\n FormatRegistration,\n Rule,\n} from './type';\n\nexport type FormatRegistryOptions = {\n /**\n * Seed user rules (matched before built-ins, in array order).\n */\n rules?: Rule[]\n};\n\n/**\n * A rule compiled to memoizing per-slot accessors. Caller-owned Rule\n * objects are never mutated; factory caching lives in the closures.\n */\ntype CompiledRule = {\n id: string,\n test: RegExp | string[],\n getReader?: () => IReader,\n getWriter?: () => IWriter\n};\n\nfunction compileSlot<T>(slot: T | (() => T) | undefined) : (() => T) | undefined {\n if (typeof slot === 'undefined') {\n return undefined;\n }\n\n if (typeof slot !== 'function') {\n return () => slot;\n }\n\n const factory = slot as () => T;\n let cached : T | undefined;\n return () => {\n if (!cached) {\n cached = factory();\n }\n\n return cached;\n };\n}\n\nexport class FormatRegistry {\n /**\n * User rules only — built-ins live in the extension table instead.\n */\n protected rules : CompiledRule[];\n\n /**\n * Lazy per-instance cache of built-in reader instances.\n */\n protected builtInReaderCache : Map<BuiltInFormatId, IReader>;\n\n /**\n * Lazy per-instance cache of built-in writer instances.\n */\n protected builtInWriterCache : Map<BuiltInFormatId, IWriter>;\n\n /**\n * extension → built-in format id, precomputed once from BUILT_IN_PRESETS.\n */\n protected builtInExtensions : Map<string, BuiltInFormatId>;\n\n protected ruleCounter : number;\n\n constructor(options: FormatRegistryOptions = {}) {\n this.rules = [];\n this.builtInReaderCache = new Map();\n this.builtInWriterCache = new Map();\n this.builtInExtensions = new Map();\n this.ruleCounter = 0;\n\n const ids = Object.keys(BUILT_IN_PRESETS) as BuiltInFormatId[];\n for (const id of ids) {\n for (const extension of BUILT_IN_PRESETS[id].extensions) {\n const existing = this.builtInExtensions.get(extension);\n if (existing) {\n throw new LocterError({ message: `Extension ${extension} is claimed by two built-in formats: ${existing}, ${id}.` });\n }\n\n this.builtInExtensions.set(extension, id);\n }\n }\n\n if (options.rules) {\n for (const rule of options.rules) {\n this.register(rule);\n }\n }\n }\n\n register(rule: Rule) : FormatRegistration {\n if (\n typeof rule.id !== 'undefined' &&\n hasOwnProperty(BUILT_IN_PRESETS, rule.id)\n ) {\n throw new LocterError({ message: `The id ${rule.id} is reserved by a built-in format.` });\n }\n\n if (\n typeof rule.reader === 'undefined' &&\n typeof rule.writer === 'undefined'\n ) {\n throw new LocterError({ message: 'A rule requires at least one of: reader, writer.' });\n }\n\n const id = rule.id ?? this.generateRuleId();\n const entry = this.compile(id, rule);\n\n const index = this.rules.findIndex((item) => item.id === id);\n if (index === -1) {\n this.rules.push(entry);\n } else {\n // replace in place: position preserved, cached instance evicted\n this.rules[index] = entry;\n }\n\n return {\n id,\n test: rule.test,\n builtIn: false,\n };\n }\n\n /**\n * Remove a user-registered rule by id. Built-in ids cannot be\n * unregistered (returns false).\n */\n unregister(id: string) : boolean {\n const index = this.rules.findIndex((item) => item.id === id);\n if (index === -1) {\n return false;\n }\n\n this.rules.splice(index, 1);\n return true;\n }\n\n has(id: string) : boolean {\n if (this.rules.some((item) => item.id === id)) {\n return true;\n }\n\n return hasOwnProperty(BUILT_IN_PRESETS, id);\n }\n\n /**\n * All registrations in effective match order: user rules\n * (registration order) first, then the built-ins.\n */\n entries() : FormatRegistration[] {\n const output : FormatRegistration[] = this.rules.map(\n (item) => ({\n id: item.id,\n test: item.test,\n builtIn: false,\n }),\n );\n\n const ids = Object.keys(BUILT_IN_PRESETS) as BuiltInFormatId[];\n for (const id of ids) {\n output.push({\n id,\n test: [...BUILT_IN_PRESETS[id].extensions],\n builtIn: true,\n });\n }\n\n return output;\n }\n\n /**\n * Restore the registry to its construction state: drop all user rules\n * and evict every cached reader instance (including a module reader\n * configured via setModuleReader / configure).\n */\n reset() : void {\n this.rules = [];\n this.builtInReaderCache.clear();\n this.builtInWriterCache.clear();\n this.ruleCounter = 0;\n }\n\n /**\n * Read a file/module RAW: the plain parsed value for data formats\n * (mutable, round-trip-symmetric with write); for modules the\n * normalized module record — a module IS a record, and the\n * normalization only irons out the CJS/ESM interop divergence so\n * both twin variants agree on one shape.\n */\n async read(input: LocatorInfo | string) : Promise<any> {\n return runTwinAsync(this.readBody(input));\n }\n\n readSync(input: LocatorInfo | string) : any {\n return runTwinSync(this.readBody(input));\n }\n\n /**\n * Read a file/module and present the result as a normalized module\n * record — the uniform, frozen shape regardless of format:\n * `.default` always holds the loaded value, top-level keys are\n * re-exposed as named exports.\n */\n async readAsModule(input: LocatorInfo | string) : Promise<any> {\n return runTwinAsync(this.readAsModuleBody(input));\n }\n\n readAsModuleSync(input: LocatorInfo | string) : any {\n return runTwinSync(this.readAsModuleBody(input));\n }\n\n protected* readBody(input: LocatorInfo | string) : TwinBody<any> {\n const { output, reader } = yield* this.executeBody(input);\n if (reader instanceof ModuleReader) {\n return toModuleRecord(output);\n }\n\n return output;\n }\n\n protected* readAsModuleBody(input: LocatorInfo | string) : TwinBody<any> {\n const { output, reader } = yield* this.executeBody(input);\n return this.toRecord(output, reader);\n }\n\n /**\n * Shared dispatch + execution of both read bodies: resolve the\n * reader, run it, wrap errors. Normalization is the caller's call.\n */\n protected* executeBody(\n input: LocatorInfo | string,\n ) : TwinBody<{ output: unknown, reader: IReader }> {\n const filePath = buildFilePath(input);\n const reader = this.findReader(filePath);\n if (!reader) {\n throw this.unknownExtensionError(filePath);\n }\n\n try {\n const output = yield* op(\n () => reader.read(filePath),\n () => reader.readSync(filePath),\n );\n\n return { output, reader };\n } catch (e) {\n throw wrapLoaderError(e, filePath);\n }\n }\n\n async write(input: LocatorInfo | string, value: unknown) : Promise<void> {\n return runTwinAsync(this.writeBody(input, value));\n }\n\n writeSync(input: LocatorInfo | string, value: unknown) : void {\n runTwinSync(this.writeBody(input, value));\n }\n\n /**\n * Shared body of write/writeSync: dispatch, unwrap records, write, wrap.\n * The inverse boundary of readAsModuleBody: a record produced by\n * readAsModule() (brand detected) is unwrapped to its `.default` value;\n * anything else is written as-is.\n */\n protected* writeBody(input: LocatorInfo | string, value: unknown) : TwinBody<void> {\n const filePath = buildFilePath(input);\n if (!isFilePath(filePath)) {\n throw new LocterWriteError({\n message: `Cannot write to a bare module specifier: ${filePath}`,\n path: filePath,\n });\n }\n\n const writer = this.findWriter(filePath);\n if (!writer) {\n if (this.findReader(filePath)) {\n const info = pathToLocatorInfo(filePath);\n throw new LocterWriteError({\n message: `The format of extension ${info.extension} is read-only.`,\n path: filePath,\n });\n }\n\n throw this.unknownExtensionError(filePath);\n }\n\n const plain = isModuleRecord(value) ? value.default : value;\n\n try {\n yield* op(\n () => writer.write(filePath, plain),\n () => writer.writeSync(filePath, plain),\n );\n } catch (e) {\n throw wrapWriteError(e, filePath);\n }\n }\n\n /**\n * The single normalization boundary: every readAsModule result becomes a module\n * record (`.default` is always the loaded value, top-level keys stay\n * accessible as named exports). Provenance decides how: module-reader\n * output may legitimately already be a record (`__esModule` is meaningful\n * there); any other reader returns arbitrary parsed data, which is always\n * wrapped — even if it happens to contain an `__esModule` key.\n */\n protected toRecord(output: unknown, reader: IReader) : any {\n if (reader instanceof ModuleReader) {\n return toModuleRecord(output);\n }\n\n return createModuleRecord(output);\n }\n\n /**\n * Typed accessor for the LIVE built-in reader instance (lazy, cached).\n */\n builtInReader<K extends BuiltInFormatId>(id: K) : BuiltInReaderOf<K> {\n let reader = this.builtInReaderCache.get(id);\n if (!reader) {\n reader = BUILT_IN_PRESETS[id].reader();\n this.builtInReaderCache.set(id, reader);\n }\n\n return reader as BuiltInReaderOf<K>;\n }\n\n /**\n * Typed accessor for the LIVE built-in writer instance (lazy, cached).\n * Only writable format ids are accepted — read-only formats (module)\n * are a compile error.\n */\n builtInWriter<K extends WritableBuiltInFormatId>(id: K) : BuiltInWriterOf<K> {\n let writer = this.builtInWriterCache.get(id);\n if (!writer) {\n writer = BUILT_IN_PRESETS[id].writer();\n this.builtInWriterCache.set(id, writer);\n }\n\n return writer as BuiltInWriterOf<K>;\n }\n\n /**\n * Dispatch order:\n * 1. bare specifier (no extension) → module reader, always\n * 2. user rules, registration order → first match wins (can override built-ins)\n * 3. built-in extension table\n * 4. undefined → read/readSync throw LocterUnknownExtensionError\n */\n findReader(input: string) : IReader | undefined {\n if (!isFilePath(input)) {\n return this.builtInReader('module');\n }\n\n const rule = this.findRule(input, (item) => typeof item.getReader !== 'undefined');\n if (rule && rule.getReader) {\n return rule.getReader();\n }\n\n const id = this.findBuiltInId(input);\n if (id) {\n return this.builtInReader(id);\n }\n\n return undefined;\n }\n\n /**\n * Write-side dispatch. No bare-specifier step (there is nothing to\n * write to); only rules with a writer slot participate, then built-in\n * presets that declare a writer.\n */\n findWriter(input: string) : IWriter | undefined {\n if (!isFilePath(input)) {\n return undefined;\n }\n\n const rule = this.findRule(input, (item) => typeof item.getWriter !== 'undefined');\n if (rule && rule.getWriter) {\n return rule.getWriter();\n }\n\n const id = this.findBuiltInId(input);\n if (id && 'writer' in BUILT_IN_PRESETS[id]) {\n return this.builtInWriter(id as WritableBuiltInFormatId);\n }\n\n return undefined;\n }\n\n protected findRule(\n input: string,\n filter: (rule: CompiledRule) => boolean,\n ) : CompiledRule | undefined {\n const info = pathToLocatorInfo(input);\n\n for (const rule of this.rules) {\n if (!filter(rule)) {\n continue;\n }\n\n const { test } = rule;\n if (Array.isArray(test)) {\n if (\n info.extension &&\n test.includes(info.extension)\n ) {\n return rule;\n }\n } else {\n // reset before AND after: a g/y regex mutates lastIndex on\n // test(), which would make repeated dispatch alternate and\n // leak state back into the caller-owned RegExp\n test.lastIndex = 0;\n const matched = test.test(buildFilePath(info));\n test.lastIndex = 0;\n if (matched) {\n return rule;\n }\n }\n }\n\n return undefined;\n }\n\n protected findBuiltInId(input: string) : BuiltInFormatId | undefined {\n const info = pathToLocatorInfo(input);\n if (!info.extension) {\n return undefined;\n }\n\n return this.builtInExtensions.get(info.extension);\n }\n\n protected unknownExtensionError(input: string) : LocterUnknownExtensionError {\n const info = pathToLocatorInfo(input);\n return new LocterUnknownExtensionError({\n message: `No format registered for extension: ${info.extension ?? 'unknown'}`,\n path: input,\n });\n }\n\n protected compile(id: string, rule: Rule) : CompiledRule {\n return {\n id,\n test: rule.test,\n getReader: compileSlot<IReader>(rule.reader),\n getWriter: compileSlot<IWriter>(rule.writer),\n };\n }\n\n protected generateRuleId() : string {\n let id : string;\n do {\n this.ruleCounter++;\n id = `rule:${this.ruleCounter}`;\n } while (this.rules.some((item) => item.id === id));\n\n return id;\n }\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { FormatRegistry } from './module';\n\nlet instance : FormatRegistry;\nexport function useFormatRegistry() {\n if (typeof instance !== 'undefined') {\n return instance;\n }\n\n instance = new FormatRegistry();\n\n return instance;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { LocatorInfo } from '../locator';\nimport type { ModuleReaderOptions } from './built-in/module/type';\nimport {\n type FormatRegistration,\n type Rule,\n useFormatRegistry,\n} from './registry';\n\nexport function registerFormat(rule: Rule) : FormatRegistration {\n return useFormatRegistry().register(rule);\n}\n\n/**\n * Remove a rule from the process-global registry by its id\n * (as returned by registerFormat). Built-in ids cannot be unregistered.\n */\nexport function unregisterFormat(id: string) : boolean {\n return useFormatRegistry().unregister(id);\n}\n\n/**\n * Read a file/module RAW: the plain parsed value for data formats\n * (json/yaml/conf and custom readers — mutable, round-trip-symmetric\n * with write); for modules the normalized module record (a module IS a\n * record; normalization only irons out CJS/ESM interop divergence).\n */\nexport async function read(input: LocatorInfo | string) : Promise<any> {\n return useFormatRegistry().read(input);\n}\n\nexport function readSync(input: LocatorInfo | string) : any {\n return useFormatRegistry().readSync(input);\n}\n\n/**\n * Read a file/module and present the result as a normalized module\n * record — the uniform, frozen shape regardless of format: `.default`\n * always holds the loaded value, top-level keys are re-exposed as\n * named exports.\n */\nexport async function readAsModule(input: LocatorInfo | string) : Promise<any> {\n return useFormatRegistry().readAsModule(input);\n}\n\nexport function readAsModuleSync(input: LocatorInfo | string) : any {\n return useFormatRegistry().readAsModuleSync(input);\n}\n\nexport async function write(input: LocatorInfo | string, value: unknown) : Promise<void> {\n return useFormatRegistry().write(input, value);\n}\n\nexport function writeSync(input: LocatorInfo | string, value: unknown) : void {\n useFormatRegistry().writeSync(input, value);\n}\n\n/**\n * Override the built-in module reader's `import` / `require` calls.\n *\n * Useful for test runners (e.g. Vitest) where the dynamic `import()` inside\n * `node_modules/locter` would bypass the runner's module graph. Calling this\n * from user code (e.g. a Vitest setup file) lets the runner rewrite the\n * `import()` so loaded modules share identity with statically imported ones.\n *\n * Returns a restore function that re-applies the previous configuration —\n * handy for scoped overrides (e.g. test teardown). The restore function is\n * scoped to the exact reader instance it configured: after a registry\n * reset() (which discards that instance) it becomes a no-op instead of\n * re-applying stale configuration to the fresh instance.\n *\n * @example\n * ```ts\n * // vitest setup file\n * import { setModuleReader } from 'locter';\n *\n * setModuleReader({\n * load: (id) => import(id),\n * });\n * ```\n */\nexport function setModuleReader(options: ModuleReaderOptions) : () => void {\n const reader = useFormatRegistry().builtInReader('module');\n const previous = reader.configure(options);\n\n return () => {\n reader.configure(previous);\n };\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { LocterError, LocterNotFoundError, LocterWriteError } from '../errors';\nimport type { LocatorInfo } from '../locator';\nimport {\n buildFilePath,\n locate,\n locateSync,\n locateUp,\n locateUpSync,\n} from '../locator';\nimport { hasOwnProperty, isObject, isSafeObjectKey } from '../utils';\nimport type { TwinBody } from '../utils/twin';\nimport { op, runTwinAsync, runTwinSync } from '../utils/twin';\nimport { JSONWriter } from './built-in';\nimport { useFormatRegistry } from './registry';\n\nexport type ReadPackageFieldOptions = {\n cwd?: string,\n walkUp?: boolean,\n stopAt?: string,\n};\n\nexport type WritePackageFieldOptions = ReadPackageFieldOptions;\n\nfunction extractField<T>(pkg: unknown, field: string) : T | undefined {\n if (!isObject(pkg) || !hasOwnProperty(pkg, field)) {\n return undefined;\n }\n return pkg[field] as T;\n}\n\nfunction* locatePackageBody(\n options: ReadPackageFieldOptions,\n) : TwinBody<LocatorInfo | undefined> {\n if (options.walkUp) {\n return yield* op(\n () => locateUp('package.json', { cwd: options.cwd, stopAt: options.stopAt }),\n () => locateUpSync('package.json', { cwd: options.cwd, stopAt: options.stopAt }),\n );\n }\n\n return yield* op(\n () => locate('package.json', { cwd: options.cwd }),\n () => locateSync('package.json', { cwd: options.cwd }),\n );\n}\n\nfunction* readPackageFieldBody<T>(\n field: string,\n options: ReadPackageFieldOptions,\n) : TwinBody<T | undefined> {\n const info = yield* locatePackageBody(options);\n if (!info) {\n return undefined;\n }\n\n // Read the raw parsed package.json via the built-in JSON reader —\n // not the normalized record read() returns — so synthetic record\n // keys (`default`, `__esModule`) can never resolve as package fields.\n const reader = useFormatRegistry().builtInReader('json');\n const filePath = buildFilePath(info);\n\n try {\n const pkg = yield* op(\n () => reader.read(filePath),\n () => reader.readSync(filePath),\n );\n\n return extractField<T>(pkg, field);\n } catch (e) {\n if (e instanceof LocterNotFoundError) {\n return undefined;\n }\n throw e;\n }\n}\n\nexport async function readPackageField<T = unknown>(\n field: string,\n options: ReadPackageFieldOptions = {},\n) : Promise<T | undefined> {\n return runTwinAsync(readPackageFieldBody<T>(field, options));\n}\n\nexport function readPackageFieldSync<T = unknown>(\n field: string,\n options: ReadPackageFieldOptions = {},\n) : T | undefined {\n return runTwinSync(readPackageFieldBody<T>(field, options));\n}\n\nfunction* writePackageFieldBody(\n field: string,\n value: unknown,\n options: WritePackageFieldOptions,\n) : TwinBody<void> {\n if (!isSafeObjectKey(field)) {\n throw new LocterError({ message: `The field ${field} is not a safe object key.` });\n }\n\n const info = yield* locatePackageBody(options);\n if (!info) {\n // unlike the reader, there is nothing sensible to return —\n // a write without a target is an error\n throw new LocterNotFoundError({ message: 'No package.json could be located.' });\n }\n\n const reader = useFormatRegistry().builtInReader('json');\n const filePath = buildFilePath(info);\n\n const pkg = yield* op(\n () => reader.read(filePath),\n () => reader.readSync(filePath),\n );\n\n if (!isObject(pkg)) {\n throw new LocterWriteError({\n message: 'The located package.json does not contain an object.',\n path: filePath,\n });\n }\n\n pkg[field] = value;\n\n // dedicated writer instance: keeps the indentation (and the built-in\n // registry writer's configuration untouched)\n const writer = new JSONWriter({ indent: 'auto' });\n yield* op(\n () => writer.write(filePath, pkg),\n () => writer.writeSync(filePath, pkg),\n );\n}\n\n/**\n * Set a top-level field of the nearest `package.json` (same locate\n * semantics as readPackageField) and write it back, preserving the\n * file's existing indentation. Passing `undefined` removes the field.\n * Throws LocterNotFoundError when no package.json could be located.\n */\nexport async function writePackageField(\n field: string,\n value: unknown,\n options: WritePackageFieldOptions = {},\n) : Promise<void> {\n return runTwinAsync(writePackageFieldBody(field, value, options));\n}\n\nexport function writePackageFieldSync(\n field: string,\n value: unknown,\n options: WritePackageFieldOptions = {},\n) : void {\n runTwinSync(writePackageFieldBody(field, value, options));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["parseYAML","stringifyYAML"],"sources":["../src/errors/base.ts","../src/errors/load.ts","../src/errors/not-found.ts","../src/errors/unknown-extension.ts","../src/utils/file-name.ts","../src/utils/has-property.ts","../src/utils/object.ts","../src/utils/to-array.ts","../src/utils/file-path.ts","../src/utils/runtime.ts","../src/utils/typescript.ts","../src/errors/write.ts","../src/errors/wrap.ts","../src/utils/twin.ts","../src/locator/utils.ts","../src/locator/core.ts","../src/locator/async.ts","../src/locator/sync.ts","../src/locator/up.ts","../src/format/text-file/reader.ts","../src/format/text-file/writer.ts","../src/format/built-in/conf/reader.ts","../src/format/value.ts","../src/format/built-in/conf/writer.ts","../src/format/built-in/json/reader.ts","../src/format/built-in/json/writer.ts","../src/format/built-in/module/constants.ts","../src/format/built-in/module/reader.ts","../src/format/built-in/module/utils.ts","../src/format/built-in/text/reader.ts","../src/format/built-in/text/writer.ts","../src/format/built-in/yaml/reader.ts","../src/format/built-in/yaml/writer.ts","../src/format/built-in/registry.ts","../src/format/registry/module.ts","../src/format/registry/singleton.ts","../src/format/helpers.ts","../src/format/package-field.ts"],"sourcesContent":["/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n BaseError,\n type ErrorOptions,\n hasInstanceof,\n markInstanceof,\n} from '@ebec/core';\n\nexport type LocterErrorOptions = ErrorOptions & {\n path?: string,\n};\n\nexport type LocterErrorInput = string | LocterErrorOptions;\n\nexport const LOCTER_ERROR_MARKER = Symbol.for('@locter/error');\n\nexport class LocterError extends BaseError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_ERROR_MARKER);\n }\n\n public readonly path?: string;\n\n constructor(input: LocterErrorInput = {}) {\n if (typeof input === 'string') {\n super(input);\n } else {\n const { path, ...rest } = input;\n super(rest);\n this.path = path;\n }\n\n markInstanceof(this, LOCTER_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasInstanceof, markInstanceof } from '@ebec/core';\nimport { LocterError, type LocterErrorInput } from './base';\n\nexport const LOCTER_LOAD_ERROR_MARKER = Symbol.for('@locter/load-error');\n\nexport class LoadError extends LocterError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_LOAD_ERROR_MARKER);\n }\n\n constructor(input: LocterErrorInput = {}) {\n super(input);\n markInstanceof(this, LOCTER_LOAD_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasInstanceof, markInstanceof } from '@ebec/core';\nimport { LocterError, type LocterErrorInput } from './base';\n\nexport const LOCTER_NOT_FOUND_ERROR_MARKER = Symbol.for('@locter/not-found-error');\n\nexport class NotFoundError extends LocterError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_NOT_FOUND_ERROR_MARKER);\n }\n\n constructor(input: LocterErrorInput = {}) {\n super(input);\n markInstanceof(this, LOCTER_NOT_FOUND_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasInstanceof, markInstanceof } from '@ebec/core';\nimport { LocterError, type LocterErrorInput } from './base';\n\nexport const LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER = Symbol.for('@locter/unknown-extension-error');\n\nexport class UnknownExtensionError extends LocterError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER);\n }\n\n constructor(input: LocterErrorInput = {}) {\n super(input);\n markInstanceof(this, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport path from 'node:path';\n\nexport function getFileNameExtension(\n input: string,\n allowed?: string[],\n) : string | undefined {\n const extension = path.extname(input);\n if (extension === '' || extension === '.') {\n return undefined;\n }\n\n if (\n typeof allowed === 'undefined' ||\n allowed.includes(extension)\n ) {\n return extension;\n }\n\n return undefined;\n}\n\nexport function removeFileNameExtension(\n input: string,\n extensions?: string[],\n) {\n const extension = getFileNameExtension(input, extensions);\n if (extension) {\n return input.substring(0, input.length - extension.length);\n }\n\n return input;\n}\n","export function hasOwnProperty<X extends Record<string, any>, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, unknown> {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n}\n\nexport function hasStringProperty<X extends Record<string, any>, Y extends PropertyKey>(obj: X, prop: Y): obj is X & Record<Y, string> {\n return hasOwnProperty(obj, prop) && typeof obj[prop] === 'string';\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function isObject(item: unknown) : item is Record<string, any> {\n return (\n !!item &&\n typeof item === 'object' &&\n !Array.isArray(item)\n );\n}\n\nexport function isSafeObjectKey(key: string) : boolean {\n return key !== '__proto__' &&\n key !== 'prototype' &&\n key !== 'constructor';\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function toArray(input: string | string[]) : string[] {\n return Array.isArray(input) ? input : [input];\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\nimport path from 'node:path';\n\nexport function isFilePath(input: string) {\n const extension = path.extname(input);\n return extension && extension !== '';\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nexport function isJestRuntimeEnvironment() : boolean {\n return process.env &&\n process.env.JEST_WORKER_ID !== undefined;\n}\n\nexport function isVitestRuntimeEnvironment() : boolean {\n return typeof process !== 'undefined' &&\n process.env.VITEST === 'true';\n}\n\nexport function isTsNodeRuntimeEnvironment(): boolean {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n return !!process[Symbol.for('ts-node.register.instance')];\n}\n\n// matches the bare `tsx` specifier (node --import tsx), optionally with a\n// subpath (tsx/esm), as well as resolved paths into the tsx package\n// (.../node_modules/tsx/dist/loader.mjs)\nconst TSX_MARKER_REGEX = /(?:^|=|[\\\\/])tsx(?:$|[\\\\/])/;\n\nexport function isTsxRuntimeEnvironment() : boolean {\n if (typeof process === 'undefined') {\n return false;\n }\n\n if (\n Array.isArray(process.execArgv) &&\n process.execArgv.some((arg) => TSX_MARKER_REGEX.test(arg))\n ) {\n return true;\n }\n\n const { _preload_modules: preloadModules } = process as unknown as { _preload_modules?: string[] };\n\n return Array.isArray(preloadModules) &&\n preloadModules.some((el) => TSX_MARKER_REGEX.test(el));\n}\n","/*\n * Copyright (c) 2024.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { isObject } from './object';\n\nexport function isTypeScriptError(input: unknown) : input is Error {\n if (!isObject(input)) {\n return false;\n }\n\n if (typeof input.diagnosticCodes !== 'undefined') {\n return true;\n }\n\n return typeof input.message === 'string' &&\n /TS\\d+/.test(input.message);\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasInstanceof, markInstanceof } from '@ebec/core';\nimport { LocterError, type LocterErrorInput } from './base';\n\nexport const LOCTER_WRITE_ERROR_MARKER = Symbol.for('@locter/write-error');\n\nexport class WriteError extends LocterError {\n static override [Symbol.hasInstance](input: unknown) : boolean {\n return hasInstanceof(input, LOCTER_WRITE_ERROR_MARKER);\n }\n\n constructor(input: LocterErrorInput = {}) {\n super(input);\n markInstanceof(this, LOCTER_WRITE_ERROR_MARKER);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasStringProperty, isObject } from '../utils';\nimport { LocterError } from './base';\nimport { LoadError } from './load';\nimport { NotFoundError } from './not-found';\nimport { WriteError } from './write';\n\nconst NOT_FOUND_CODES = new Set([\n 'ENOENT',\n 'MODULE_NOT_FOUND',\n 'ERR_MODULE_NOT_FOUND',\n]);\n\nexport function wrapLoaderError(input: unknown, path: string) : LocterError {\n if (input instanceof LocterError) {\n return input;\n }\n\n const code = isObject(input) && hasStringProperty(input, 'code') ?\n input.code :\n undefined;\n\n const message = isObject(input) && hasStringProperty(input, 'message') ?\n input.message :\n `Failed to load: ${path}`;\n\n if (code && NOT_FOUND_CODES.has(code)) {\n return new NotFoundError({\n message,\n code,\n cause: input,\n path,\n });\n }\n\n return new LoadError({\n message,\n code,\n cause: input,\n path,\n });\n}\n\nexport function wrapWriteError(input: unknown, path: string) : LocterError {\n if (input instanceof LocterError) {\n return input;\n }\n\n const code = isObject(input) && hasStringProperty(input, 'code') ?\n input.code :\n undefined;\n\n const message = isObject(input) && hasStringProperty(input, 'message') ?\n input.message :\n `Failed to write: ${path}`;\n\n return new WriteError({\n message,\n code,\n cause: input,\n path,\n });\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n/**\n * Internal protocol to derive the parallel sync + async public surfaces\n * from one shared body. A body is a generator that yields effect pairs —\n * an async and a sync thunk for the same operation — and the two drivers\n * (runTwinAsync / runTwinSync) execute the side they stand for. Effect\n * errors are re-entered into the body via `Generator.throw`, so try/catch\n * inside a body behaves identically in both variants.\n *\n * Deliberately NOT exported from the utils barrel — this is internal\n * plumbing, not public API.\n */\n\nexport type TwinOp<T = unknown> = {\n async: () => Promise<T>,\n sync: () => T,\n};\n\nexport type TwinBody<R> = Generator<TwinOp<any>, R, any>;\n\n/**\n * Perform one effect inside a twin body: `const x = yield* op(a, s)`.\n */\nexport function* op<T>(\n asyncFn: () => Promise<T>,\n syncFn: () => T,\n) : Generator<TwinOp<T>, T, T> {\n return yield { async: asyncFn, sync: syncFn };\n}\n\nexport async function runTwinAsync<R>(body: TwinBody<R>) : Promise<R> {\n let step = body.next();\n while (!step.done) {\n let result : unknown;\n try {\n result = await step.value.async();\n } catch (e) {\n step = body.throw(e);\n continue;\n }\n\n step = body.next(result);\n }\n\n return step.value;\n}\n\nexport function runTwinSync<R>(body: TwinBody<R>) : R {\n let step = body.next();\n while (!step.done) {\n let result : unknown;\n try {\n result = step.value.sync();\n } catch (e) {\n step = body.throw(e);\n continue;\n }\n\n step = body.next(result);\n }\n\n return step.value;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport path from 'node:path';\nimport { isObject, toArray } from '../utils';\nimport type { LocatorInfo, LocatorOptions, LocatorOptionsInput } from './types';\n\nexport function buildLocatorPatterns(pattern: string | string[]) : string[] {\n return Array.isArray(pattern) ?\n pattern :\n [pattern];\n}\n\nexport function buildLocatorOptions(options: LocatorOptionsInput = {}) : LocatorOptions {\n const cwd = options.cwd ?\n toArray(options.cwd) :\n [];\n\n const ignore = options.ignore ?\n toArray(options.ignore) :\n [];\n\n if (cwd.length === 0) {\n cwd.push(process.cwd());\n }\n\n // precedence: an explicit `onlyDirectories: true` wins over `onlyFiles`\n // (which defaults to true); when neither restricts, everything matches\n const onlyDirectories = options.onlyDirectories ?? false;\n const onlyFiles = onlyDirectories ?\n false :\n options.onlyFiles ?? true;\n\n return {\n cwd,\n ignore,\n onlyDirectories,\n onlyFiles,\n dot: options.dot ?? false,\n };\n}\n\nexport function pathToLocatorInfo(\n input: string,\n skipResolve?: boolean,\n) : LocatorInfo {\n if (\n !skipResolve &&\n !path.isAbsolute(input)\n ) {\n input = path.resolve(process.cwd(), input);\n }\n\n const info = path.parse(input);\n const directory = info.dir.split('/').join(path.sep);\n const extension = info.ext ? info.ext : undefined;\n const filePath = extension ?\n path.join(directory, info.name) + extension :\n path.join(directory, info.name);\n\n return {\n directory,\n name: info.name,\n extension,\n path: filePath,\n };\n}\n\nexport function isLocatorInfo(\n input: unknown,\n) : input is LocatorInfo {\n return isObject(input) &&\n typeof input.directory === 'string' &&\n typeof input.name === 'string' &&\n (typeof input.extension === 'undefined' || typeof input.extension === 'string') &&\n typeof input.path === 'string';\n}\n\nexport function buildFilePath(input: LocatorInfo | string) {\n if (typeof input === 'string') {\n return input;\n }\n\n return input.path;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport fg from 'fast-glob';\nimport type { TwinBody } from '../utils/twin';\nimport { op } from '../utils/twin';\nimport type { LocatorInfo, LocatorOptionsInput } from './types';\nimport { buildLocatorOptions, buildLocatorPatterns, pathToLocatorInfo } from './utils';\n\ntype GlobJob = {\n pattern: string,\n options: fg.Options,\n};\n\nfunction buildGlobJobs(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : GlobJob[] {\n const patterns = buildLocatorPatterns(pattern);\n const opts = buildLocatorOptions(options);\n\n const jobs : GlobJob[] = [];\n for (const p of patterns) {\n for (const cwd of opts.cwd) {\n jobs.push({\n pattern: p,\n options: {\n absolute: true,\n cwd,\n ignore: opts.ignore,\n onlyFiles: opts.onlyFiles,\n onlyDirectories: opts.onlyDirectories,\n dot: opts.dot,\n },\n });\n }\n }\n\n return jobs;\n}\n\nfunction* glob(job: GlobJob) : Generator<any, string[], any> {\n return yield* op(\n () => fg(job.pattern, job.options),\n () => fg.sync(job.pattern, job.options),\n );\n}\n\nexport function* locateBody(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : TwinBody<LocatorInfo | undefined> {\n for (const job of buildGlobJobs(pattern, options)) {\n const files = yield* glob(job);\n\n const element = files.shift();\n if (element) {\n return pathToLocatorInfo(element, true);\n }\n }\n\n return undefined;\n}\n\nexport function* locateManyBody(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : TwinBody<LocatorInfo[]> {\n const items : LocatorInfo[] = [];\n\n for (const job of buildGlobJobs(pattern, options)) {\n const files = yield* glob(job);\n\n for (const file of files) {\n items.push(pathToLocatorInfo(file, true));\n }\n }\n\n return items;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { runTwinAsync } from '../utils/twin';\nimport { locateBody, locateManyBody } from './core';\nimport type { LocatorInfo, LocatorOptionsInput } from './types';\n\nexport async function locateMany(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : Promise<LocatorInfo[]> {\n return runTwinAsync(locateManyBody(pattern, options));\n}\n\nexport async function locate(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : Promise<LocatorInfo | undefined> {\n return runTwinAsync(locateBody(pattern, options));\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { runTwinSync } from '../utils/twin';\nimport { locateBody, locateManyBody } from './core';\nimport type { LocatorInfo, LocatorOptionsInput } from './types';\n\nexport function locateManySync(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : LocatorInfo[] {\n return runTwinSync(locateManyBody(pattern, options));\n}\n\nexport function locateSync(\n pattern: string | string[],\n options?: LocatorOptionsInput,\n) : LocatorInfo | undefined {\n return runTwinSync(locateBody(pattern, options));\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport path from 'node:path';\nimport type { TwinBody } from '../utils/twin';\nimport { runTwinAsync, runTwinSync } from '../utils/twin';\nimport { locateBody } from './core';\nimport type { LocatorInfo, LocatorOptionsInput } from './types';\n\nexport type LocatorUpOptionsInput = Omit<LocatorOptionsInput, 'cwd'> & {\n cwd?: string,\n stopAt?: string,\n};\n\ntype WalkStep = {\n current: string,\n stopAt: string,\n baseOptions: Omit<LocatorOptionsInput, 'cwd'>,\n};\n\nfunction startWalk(options: LocatorUpOptionsInput) : WalkStep {\n const {\n cwd,\n stopAt,\n ...baseOptions\n } = options;\n const current = path.resolve(cwd ?? process.cwd());\n const ceiling = stopAt ?\n path.resolve(current, stopAt) :\n path.parse(current).root;\n\n return {\n current,\n stopAt: ceiling,\n baseOptions,\n };\n}\n\nfunction nextDirectory(current: string, stopAt: string) : string | undefined {\n if (current === stopAt) {\n return undefined;\n }\n\n const parent = path.dirname(current);\n if (parent === current) {\n return undefined;\n }\n\n return parent;\n}\n\nfunction* locateUpBody(\n pattern: string | string[],\n options: LocatorUpOptionsInput,\n) : TwinBody<LocatorInfo | undefined> {\n let walk = startWalk(options);\n\n while (true) {\n const found = yield* locateBody(pattern, { ...walk.baseOptions, cwd: walk.current });\n if (found) {\n return found;\n }\n\n const next = nextDirectory(walk.current, walk.stopAt);\n if (!next) {\n return undefined;\n }\n\n walk = { ...walk, current: next };\n }\n}\n\nexport async function locateUp(\n pattern: string | string[],\n options: LocatorUpOptionsInput = {},\n) : Promise<LocatorInfo | undefined> {\n return runTwinAsync(locateUpBody(pattern, options));\n}\n\nexport function locateUpSync(\n pattern: string | string[],\n options: LocatorUpOptionsInput = {},\n) : LocatorInfo | undefined {\n return runTwinSync(locateUpBody(pattern, options));\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport fs from 'node:fs';\nimport { wrapLoaderError } from '../../errors';\nimport type { TwinBody } from '../../utils/twin';\nimport { op, runTwinAsync, runTwinSync } from '../../utils/twin';\nimport type { IReader } from '../type';\n\n/**\n * Base class for readers of text-based file formats: reads the file as\n * UTF-8, delegates to `parse`, and wraps I/O and parse errors in typed\n * LocterError subclasses. Subclasses implement `parse` only — both\n * `read` variants are derived from the same body.\n */\nexport abstract class TextFileReader implements IReader {\n abstract parse(content: string) : any;\n\n async read(input: string) : Promise<any> {\n return runTwinAsync(this.body(input));\n }\n\n readSync(input: string) : any {\n return runTwinSync(this.body(input));\n }\n\n protected* body(input: string) : TwinBody<any> {\n try {\n const content = yield* op(\n () => fs.promises.readFile(input, { encoding: 'utf-8' }),\n () => fs.readFileSync(input, { encoding: 'utf-8' }),\n );\n\n return this.parse(content);\n } catch (e) {\n throw wrapLoaderError(e, input);\n }\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { wrapWriteError } from '../../errors';\nimport type { TwinBody } from '../../utils/twin';\nimport { op, runTwinAsync, runTwinSync } from '../../utils/twin';\nimport type { IWriter } from '../type';\n\nfunction isNotFound(e: unknown) : boolean {\n return e instanceof Error && 'code' in e && e.code === 'ENOENT';\n}\n\n/**\n * Base class for writers of text-based file formats: serializes via\n * `stringify`, creates missing parent directories, writes the file as\n * UTF-8 (always terminated by a single trailing newline), and wraps\n * failures in WriteError. Subclasses implement `stringify` only —\n * both `write` variants are derived from the same body.\n */\nexport abstract class TextFileWriter implements IWriter {\n /**\n * Opt-in: when true, the body reads the target file first (undefined\n * if absent) and passes its content to `stringify` as `existing` —\n * the hook behind format-preserving write-back (YAML comment\n * grafting, JSON indent detection).\n */\n protected get usesExistingContent() : boolean {\n return false;\n }\n\n abstract stringify(value: unknown, existing?: string) : string;\n\n async write(input: string, value: unknown) : Promise<void> {\n return runTwinAsync(this.body(input, value));\n }\n\n writeSync(input: string, value: unknown) : void {\n runTwinSync(this.body(input, value));\n }\n\n protected* body(input: string, value: unknown) : TwinBody<void> {\n const filePath = input;\n\n try {\n let existing : string | undefined;\n if (this.usesExistingContent) {\n existing = yield* op(\n () => fs.promises.readFile(filePath, { encoding: 'utf-8' })\n .catch((e) => {\n if (isNotFound(e)) {\n return undefined;\n }\n throw e;\n }),\n () => {\n try {\n return fs.readFileSync(filePath, { encoding: 'utf-8' });\n } catch (e) {\n if (isNotFound(e)) {\n return undefined;\n }\n throw e;\n }\n },\n );\n }\n\n let content = this.stringify(value, existing);\n if (!content.endsWith('\\n')) {\n content += '\\n';\n }\n\n const directory = path.dirname(filePath);\n yield* op(\n async () => {\n await fs.promises.mkdir(directory, { recursive: true });\n },\n () => {\n fs.mkdirSync(directory, { recursive: true });\n },\n );\n\n yield* op(\n () => fs.promises.writeFile(filePath, content, { encoding: 'utf-8' }),\n () => fs.writeFileSync(filePath, content, { encoding: 'utf-8' }),\n );\n } catch (e) {\n throw wrapWriteError(e, filePath);\n }\n }\n}\n","/*\n * Copyright (c) 2022-2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n// Based on https://github.com/unjs/rc9 (MIT)\n\nimport { destr } from 'destr';\nimport { unflatten } from 'flat';\nimport { isSafeObjectKey } from '../../../utils';\nimport { TextFileReader } from '../../text-file';\n\nexport class ConfReader extends TextFileReader {\n parse(contents: string): Record<string, any> {\n const config: Record<string, any> = {};\n\n const lines = contents.split(/\\n|\\r|\\r\\n/);\n\n for (const line of lines) {\n const match = line.match(/^\\s*([^\\s=]+)\\s*=\\s*(.*)?\\s*$/);\n if (!match) {\n continue;\n }\n\n const key = match[1];\n const rawValue = match[2];\n\n if (!key || !isSafeObjectKey(key)) {\n continue;\n }\n\n const value = destr(rawValue ? rawValue.trim() : '');\n\n if (key.endsWith('[]')) {\n const arrKey = key.slice(0, Math.max(0, key.length - 2));\n config[arrKey] = (config[arrKey] || []).concat(value);\n continue;\n }\n\n config[key] = value;\n }\n\n return unflatten(config, { overwrite: true });\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { destr } from 'destr';\n\n/**\n * Lenient VALUE codec (env-var / key-value philosophy): primitives\n * serialize to their bare string form, RegExp and BigInt to their\n * string representation (also nested), everything else to JSON.\n * The counterpart of deserializeValue — used per value by the conf\n * format, and exported for consumers building lenient custom formats.\n */\nexport function serializeValue(input: unknown) : string {\n if (typeof input === 'string') {\n return input;\n }\n\n if (typeof input === 'undefined') {\n return 'undefined';\n }\n\n if (input === null) {\n return 'null';\n }\n\n if (typeof input === 'boolean') {\n return input ? 'true' : 'false';\n }\n\n if (typeof input === 'number') {\n return `${input}`;\n }\n\n if (typeof input === 'bigint') {\n return input.toString();\n }\n\n if (input instanceof RegExp) {\n return input.toString();\n }\n\n const output = JSON.stringify(input, (_key, item) => {\n if (item instanceof RegExp) {\n return item.toString();\n }\n\n if (typeof item === 'bigint') {\n return item.toString();\n }\n\n return item;\n });\n\n // JSON.stringify yields undefined for top-level Symbol/Function and\n // toJSON() returning undefined — a lenient codec still returns a string\n return output ?? String(input);\n}\n\n/**\n * Lenient parse of a serialized value: coerces 'true'/'123'/'null'/\n * 'undefined' to their primitive, parses JSON payloads, and falls back\n * to returning the raw string — it never throws.\n */\nexport function deserializeValue<T = any>(input: string) : T {\n return destr(input);\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n// Based on https://github.com/unjs/rc9 (MIT)\n\nimport { flatten } from 'flat';\nimport { isObject } from '../../../utils';\nimport { TextFileWriter } from '../../text-file';\nimport { serializeValue } from '../../value';\n\n/**\n * Serializes an object to `key=value` lines (the inverse of ConfReader):\n * nested objects become dot-separated keys, arrays become repeated\n * `key[]=` lines. Round-trips are structural, not textual — comments,\n * blank lines, and line order of an existing file are not preserved,\n * and a string that parses as another type (e.g. '123') reads back as\n * that type.\n */\nexport class ConfWriter extends TextFileWriter {\n stringify(value: unknown) : string {\n if (!isObject(value)) {\n throw new Error('The value must be an object for the conf format.');\n }\n\n const flat : Record<string, unknown> = flatten(value, { safe: true });\n\n const lines : string[] = [];\n for (const key of Object.keys(flat)) {\n const entry = flat[key];\n if (typeof entry === 'undefined') {\n continue;\n }\n\n if (Array.isArray(entry)) {\n for (const item of entry) {\n lines.push(`${key}[]=${serializeValue(item)}`);\n }\n continue;\n }\n\n lines.push(`${key}=${serializeValue(entry)}`);\n }\n\n return lines.join('\\n');\n }\n}\n","/*\n * Copyright (c) 2022-2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TextFileReader } from '../../text-file';\n\nexport class JSONReader extends TextFileReader {\n parse(content: string) {\n return JSON.parse(content);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TextFileWriter } from '../../text-file';\n\nexport type JSONWriterOptions = {\n /**\n * Indentation of the emitted JSON. A number of spaces, a literal\n * indent string, or 'auto' — detect the indentation of the existing\n * target file and keep it (falls back to 4 for new files).\n *\n * @default 4\n */\n indent?: number | string | 'auto'\n};\n\nfunction detectIndent(content: string) : string | undefined {\n const match = /^([ \\t]+)\\S/m.exec(content);\n return match ? match[1] : undefined;\n}\n\nexport class JSONWriter extends TextFileWriter {\n protected options : JSONWriterOptions;\n\n constructor(options: JSONWriterOptions = {}) {\n super();\n this.options = options;\n }\n\n protected override get usesExistingContent() : boolean {\n return this.options.indent === 'auto';\n }\n\n stringify(value: unknown, existing?: string) : string {\n let indent : number | string | undefined;\n if (this.options.indent === 'auto') {\n indent = existing ? detectIndent(existing) : undefined;\n } else {\n indent = this.options.indent;\n }\n\n indent = indent ?? 4;\n\n const output = JSON.stringify(value, null, indent);\n if (typeof output === 'undefined') {\n throw new Error('The value is not JSON-serializable.');\n }\n\n return output;\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\n/**\n * Single source of truth for the extensions handled by the module loader:\n * consumed by BOTH the built-in routing registry and the jiti config.\n */\nexport const MODULE_FILE_EXTENSIONS = ['.js', '.mjs', '.mts', '.cjs', '.cts', '.ts'] as const;\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { createJiti } from 'jiti';\nimport { createRequire } from 'node:module';\nimport { pathToFileURL } from 'node:url';\nimport { LocterError, wrapLoaderError } from '../../../errors';\nimport type { LocatorInfo } from '../../../locator';\nimport {\n buildFilePath,\n isLocatorInfo,\n} from '../../../locator';\nimport {\n hasStringProperty,\n isFilePath,\n isJestRuntimeEnvironment,\n isObject,\n isTsNodeRuntimeEnvironment,\n isTypeScriptError,\n} from '../../../utils';\nimport type { IReader } from '../../type';\nimport { MODULE_FILE_EXTENSIONS } from './constants';\nimport type {\n ModuleLoadFn,\n ModuleLoadOptions,\n ModuleLoadSyncFn,\n ModuleReaderOptions,\n} from './type';\n\nconst require = createRequire(import.meta.url);\n\ntype Jiti = ReturnType<typeof createJiti>;\n\nfunction originalPath(data: LocatorInfo | string) : string {\n return typeof data === 'string' ? data : buildFilePath(data);\n}\n\nfunction isUnrecoverableError(error: unknown) : boolean {\n const underlying = error instanceof LocterError ? error.cause : error;\n return underlying instanceof SyntaxError ||\n underlying instanceof ReferenceError ||\n isTypeScriptError(underlying);\n}\n\nexport class ModuleReader implements IReader {\n protected instance : Jiti;\n\n protected loadFn?: ModuleLoadFn;\n\n protected loadSyncFn?: ModuleLoadSyncFn;\n\n constructor(options: ModuleReaderOptions = {}) {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n this.instance = createJiti(undefined, { extensions: [...MODULE_FILE_EXTENSIONS] });\n this.loadFn = options.load;\n this.loadSyncFn = options.loadSync;\n }\n\n /**\n * Returns the previous configuration, so callers can restore it.\n */\n configure(options: ModuleReaderOptions) : ModuleReaderOptions {\n const previous : ModuleReaderOptions = {\n load: this.loadFn,\n loadSync: this.loadSyncFn,\n };\n\n if ('load' in options) {\n this.loadFn = options.load;\n }\n if ('loadSync' in options) {\n this.loadSyncFn = options.loadSync;\n }\n\n return previous;\n }\n\n /**\n * Returns the raw module value (import / require / jiti output) —\n * normalization to a module record happens once, at the\n * FormatRegistry boundary.\n *\n * read/readSync are deliberately NOT derived from a shared body\n * (unlike every other sync/async twin in this package): their\n * recovery paths differ. The async variant falls back to loadSync\n * under ts-node (jiti's async path does not cooperate with ts-node)\n * and to the jiti instance otherwise; the sync variant only has the\n * jiti fallback. The divergence is pinned by the fallback tests in\n * test/unit/format/module.spec.ts.\n */\n async read(input: string) {\n try {\n return await this.load(input);\n } catch (e) {\n if (isUnrecoverableError(e)) {\n throw e;\n }\n\n // jiti + ts-node\n // issue: https://github.com/nuxt/bridge/issues/228\n if (isTsNodeRuntimeEnvironment()) {\n return this.loadSync(input);\n }\n\n return this.instance(input);\n }\n }\n\n readSync(input: string) {\n try {\n return this.loadSync(input);\n } catch (e) {\n if (isUnrecoverableError(e)) {\n throw e;\n }\n\n return this.instance(input);\n }\n }\n\n // ---------------------------------------------------------------------------\n\n async load(\n data: LocatorInfo | string,\n options: ModuleLoadOptions = {},\n ) : Promise<unknown> {\n const id = this.build(data, options);\n\n try {\n if (this.loadFn) {\n return await this.loadFn(id);\n }\n\n // segmentation fault\n // issue: https://github.com/nodejs/node/issues/35889\n if (isJestRuntimeEnvironment()) {\n return require(id);\n }\n\n return await import(id);\n } catch (e) {\n /* istanbul ignore next */\n if (\n !options.withFilePrefix &&\n isObject(e) &&\n hasStringProperty(e, 'code') &&\n (\n e.code === 'ERR_UNSUPPORTED_ESM_URL_SCHEME' ||\n e.code === 'UNSUPPORTED_ESM_URL_SCHEME'\n )\n ) {\n return this.load(data, {\n ...options,\n withFilePrefix: true,\n });\n }\n\n throw wrapLoaderError(e, originalPath(data));\n }\n }\n\n loadSync(\n data: LocatorInfo | string,\n options: ModuleLoadOptions = {},\n ) : unknown {\n const id = this.build(data, options);\n\n try {\n if (this.loadSyncFn) {\n return this.loadSyncFn(id);\n }\n\n return require(id);\n } catch (e) {\n throw wrapLoaderError(e, originalPath(data));\n }\n }\n\n private build(\n data: LocatorInfo | string,\n options: ModuleLoadOptions = {},\n ) : string {\n if (isLocatorInfo(data) || isFilePath(data)) {\n if (typeof data !== 'string') {\n data = buildFilePath(data);\n }\n\n if (options.withFilePrefix) {\n data = pathToFileURL(data).href;\n }\n }\n\n return data;\n }\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { hasOwnProperty, isObject } from '../../../utils';\nimport type { ModuleExport, ModuleExportFilterFn } from './type';\n\ntype ESModule = { [key: string]: any, __esModule: boolean };\n\n/**\n * Brand carried by every record locter's read() produces. Deliberately a\n * module-private Symbol (NOT Symbol.for) so arbitrary parsed data cannot\n * forge it — unlike `__esModule`, its presence is trustworthy. write()\n * uses it to unwrap `.default` on round-trips.\n */\nconst MODULE_RECORD = Symbol('locter.record');\n\n/**\n * True when the value is a record produced by locter's read()/toModuleRecord.\n * Detection is brand-based; a plain object with an `__esModule` key is NOT\n * a module record.\n */\nexport function isModuleRecord(input: unknown) : input is Record<string, any> {\n return isObject(input) && MODULE_RECORD in input;\n}\n\nfunction brand<T>(input: T) : T {\n if (isObject(input) && Object.isExtensible(input)) {\n Object.defineProperty(input, MODULE_RECORD, { value: true });\n }\n\n return input;\n}\n\n/**\n * Detect the transpiler interop marker (`__esModule`). Only meaningful for\n * values that came out of a module system — arbitrary parsed data can carry\n * an `__esModule` key without being a module, so callers must decide by\n * provenance whether this check applies (see FormatRegistry).\n */\nexport function isESModule(input: unknown) : input is ESModule {\n return isObject(input) &&\n typeof input.__esModule !== 'undefined';\n}\n\n/**\n * Wrap an arbitrary value in a frozen module record: enumerable keys are\n * re-exposed as named exports and `default` is the value itself.\n */\nexport function createModuleRecord(data: unknown) {\n const output = Object.create(null, {\n __esModule: { value: true },\n [Symbol.toStringTag]: { value: 'Module' },\n [MODULE_RECORD]: { value: true },\n });\n\n if (isObject(data)) {\n for (const key in data) {\n if (hasOwnProperty(output, key)) {\n continue;\n }\n\n let descriptor = Object.getOwnPropertyDescriptor(data, key);\n if (\n !descriptor ||\n ('get' in descriptor || descriptor.writable || descriptor.configurable)\n ) {\n descriptor = {\n enumerable: true,\n get() {\n return data[key];\n },\n };\n }\n\n Object.defineProperty(output, key, descriptor);\n }\n }\n\n if (!hasOwnProperty(output, 'default')) {\n Object.defineProperty(output, 'default', {\n value: data,\n enumerable: true,\n });\n }\n\n return Object.freeze(output);\n}\n\n/**\n * Normalize module-loader output to a module record. Values already carrying\n * the `__esModule` marker pass through (module provenance makes the marker\n * trustworthy); everything else is wrapped via createModuleRecord.\n *\n * https://2ality.com/2017/01/babel-esm-spec-mode.html\n */\nexport function toModuleRecord(\n data: unknown,\n) {\n if (isESModule(data)) {\n // @see https://github.com/testing-library/user-event/issues/813\n // @see https://stackoverflow.com/questions/62717394/export-default-class-exports-double-nested-default\n if (\n isESModule(data.default) &&\n data.default.default\n ) {\n return brand({\n ...data,\n default: data.default.default,\n });\n }\n\n // best-effort: module namespace objects are non-extensible and\n // stay unbranded — they have no writable format anyway\n return brand(data);\n }\n\n return createModuleRecord(data);\n}\n\nexport function getModuleExport(\n data: Record<string, any>,\n filterFn: ModuleExportFilterFn,\n): ModuleExport | undefined {\n const keys = Object.keys(data);\n for (const key of keys) {\n if (filterFn(key as string, data[key as string])) {\n return {\n key: key as string,\n value: data[key as string],\n };\n }\n }\n\n return undefined;\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TextFileReader } from '../../text-file';\n\n/**\n * Raw text: the file content, as-is. No value coercion — a .txt\n * containing '123' reads as the string '123' (use deserializeValue\n * for lenient value semantics).\n */\nexport class TextReader extends TextFileReader {\n parse(content: string) {\n return content;\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { TextFileWriter } from '../../text-file';\n\n/**\n * Raw text: accepts strings only — coercing arbitrary values would be\n * lossy ([object Object]); serialize explicitly (e.g. serializeValue)\n * before writing. Output ends with a single trailing newline, like\n * every text writer.\n */\nexport class TextWriter extends TextFileWriter {\n stringify(value: unknown) : string {\n if (typeof value !== 'string') {\n throw new Error('The value must be a string for the text format.');\n }\n\n return value;\n }\n}\n","/*\n * Copyright (c) 2022-2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { parse as parseYAML } from 'yaml';\nimport { TextFileReader } from '../../text-file';\n\nexport class YAMLReader extends TextFileReader {\n parse(content: string) {\n return parseYAML(content);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { Document, ToStringOptions, YAMLMap } from 'yaml';\nimport {\n isMap,\n isNode,\n isScalar,\n parseDocument,\n stringify as stringifyYAML,\n} from 'yaml';\nimport { hasOwnProperty, isObject } from '../../../utils';\nimport { TextFileWriter } from '../../text-file';\n\nexport type YAMLWriterOptions = ToStringOptions;\n\nfunction pairKey(key: unknown) : string {\n return isScalar(key) ? String(key.value) : String(key);\n}\n\n/**\n * Merge a plain object into an existing YAML map node: added/changed keys\n * are set, absent keys are deleted, and nested objects recurse — so\n * comments, anchors, and formatting attached to surviving keys are\n * preserved. Arrays, scalars, and type changes replace the node wholesale\n * (comments inside the replaced subtree are lost).\n */\nfunction graftMap(doc: Document, node: YAMLMap, value: Record<string, unknown>) : void {\n for (const pair of [...node.items]) {\n if (!hasOwnProperty(value, pairKey(pair.key))) {\n node.delete(pair.key);\n }\n }\n\n for (const key of Object.keys(value)) {\n const entry = value[key];\n const current = node.get(key, true);\n\n if (isMap(current) && isObject(entry)) {\n graftMap(doc, current, entry);\n continue;\n }\n\n const replacement = doc.createNode(entry);\n if (isNode(current)) {\n // keep comments anchored to the value node itself\n // (`key: value # trailing`, standalone lines above the value)\n replacement.commentBefore = current.commentBefore;\n replacement.comment = current.comment;\n replacement.spaceBefore = current.spaceBefore;\n }\n\n node.set(doc.createNode(key), replacement);\n }\n}\n\n/**\n * Writes YAML preserving hand-edited structure where possible: when the\n * target file already exists, the new value is grafted into its parsed\n * document, so comments and anchors attached to surviving keys survive\n * the write-back. New files are plain `yaml.stringify` output. An\n * existing file that fails to parse throws (wrapped as WriteError)\n * instead of being silently overwritten.\n */\nexport class YAMLWriter extends TextFileWriter {\n protected options : YAMLWriterOptions;\n\n constructor(options: YAMLWriterOptions = {}) {\n super();\n this.options = options;\n }\n\n protected override get usesExistingContent() : boolean {\n return true;\n }\n\n stringify(value: unknown, existing?: string) : string {\n if (typeof existing === 'undefined') {\n return stringifyYAML(value, this.options);\n }\n\n // widen from Document.Parsed: contents is replaced with\n // freshly created (non-parsed) nodes while grafting\n const doc : Document = parseDocument(existing);\n if (doc.errors.length > 0) {\n throw doc.errors[0];\n }\n\n if (isMap(doc.contents) && isObject(value)) {\n graftMap(doc, doc.contents, value);\n } else {\n doc.contents = doc.createNode(value);\n }\n\n return doc.toString(this.options);\n }\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { FormatPreset } from '../registry/type';\nimport type { IWriter } from '../type';\nimport { ConfReader, ConfWriter } from './conf';\nimport { JSONReader, JSONWriter } from './json';\nimport { ModuleReader } from './module';\nimport { TextReader, TextWriter } from './text';\nimport { MODULE_FILE_EXTENSIONS } from './module/constants';\nimport { YAMLReader, YAMLWriter } from './yaml';\n\n/**\n * Every built-in format, in one place. Keys are the format ids; each entry\n * couples routing and construction. The id union, the extension → format\n * table, lazy caching, and the typed `builtInReader()` accessor are all\n * DERIVED from this object. Adding a format = adding one entry.\n *\n * Intentionally NOT re-exported from any barrel (internal API).\n */\nexport const BUILT_IN_PRESETS = {\n module: { extensions: MODULE_FILE_EXTENSIONS, reader: () => new ModuleReader() },\n conf: {\n extensions: ['.conf'],\n reader: () => new ConfReader(),\n writer: () => new ConfWriter(),\n },\n json: {\n extensions: ['.json'],\n reader: () => new JSONReader(),\n writer: () => new JSONWriter(),\n },\n yaml: {\n extensions: ['.yml', '.yaml'],\n reader: () => new YAMLReader(),\n writer: () => new YAMLWriter(),\n },\n text: {\n extensions: ['.txt'],\n reader: () => new TextReader(),\n writer: () => new TextWriter(),\n },\n} as const satisfies Record<string, FormatPreset>;\n\nexport type BuiltInFormatId = keyof typeof BUILT_IN_PRESETS;\n\nexport type BuiltInReaderOf<K extends BuiltInFormatId> = ReturnType<(typeof BUILT_IN_PRESETS)[K]['reader']>;\n\n/**\n * Built-in format ids whose preset declares a writer — derived at the type\n * level, so builtInWriter('module') is a compile error, not a runtime one.\n */\nexport type WritableBuiltInFormatId = {\n [K in BuiltInFormatId]: (typeof BUILT_IN_PRESETS)[K] extends { writer: () => IWriter } ? K : never\n}[BuiltInFormatId];\n\nexport type BuiltInWriterOf<K extends WritableBuiltInFormatId> = ReturnType<(typeof BUILT_IN_PRESETS)[K]['writer']>;\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport {\n LocterError,\n UnknownExtensionError,\n WriteError,\n wrapLoaderError,\n wrapWriteError,\n} from '../../errors';\nimport type { LocatorInfo } from '../../locator';\nimport { buildFilePath, pathToLocatorInfo } from '../../locator';\nimport { hasOwnProperty, isFilePath } from '../../utils';\nimport type { TwinBody } from '../../utils/twin';\nimport { op, runTwinAsync, runTwinSync } from '../../utils/twin';\nimport {\n ModuleReader, \n createModuleRecord, \n isModuleRecord, \n toModuleRecord,\n} from '../built-in';\nimport type {\n BuiltInFormatId,\n BuiltInReaderOf,\n BuiltInWriterOf,\n WritableBuiltInFormatId,\n} from '../built-in/registry';\nimport { BUILT_IN_PRESETS } from '../built-in/registry';\nimport type { IReader, IWriter } from '../type';\nimport type {\n FormatRegistration,\n ReadOptions,\n Rule,\n WriteOptions,\n} from './type';\n\nexport type FormatRegistryOptions = {\n /**\n * Seed user rules (matched before built-ins, in array order).\n */\n rules?: Rule[]\n};\n\n/**\n * A rule compiled to memoizing per-slot accessors. Caller-owned Rule\n * objects are never mutated; factory caching lives in the closures.\n */\ntype CompiledRule = {\n id: string,\n test: RegExp | string[],\n getReader?: () => IReader,\n getWriter?: () => IWriter\n};\n\nfunction compileSlot<T>(slot: T | (() => T) | undefined) : (() => T) | undefined {\n if (typeof slot === 'undefined') {\n return undefined;\n }\n\n if (typeof slot !== 'function') {\n return () => slot;\n }\n\n const factory = slot as () => T;\n let cached : T | undefined;\n return () => {\n if (!cached) {\n cached = factory();\n }\n\n return cached;\n };\n}\n\nexport class FormatRegistry {\n /**\n * User rules only — built-ins live in the extension table instead.\n */\n protected rules : CompiledRule[];\n\n /**\n * Lazy per-instance cache of built-in reader instances.\n */\n protected builtInReaderCache : Map<BuiltInFormatId, IReader>;\n\n /**\n * Lazy per-instance cache of built-in writer instances.\n */\n protected builtInWriterCache : Map<BuiltInFormatId, IWriter>;\n\n /**\n * extension → built-in format id, precomputed once from BUILT_IN_PRESETS.\n */\n protected builtInExtensions : Map<string, BuiltInFormatId>;\n\n protected ruleCounter : number;\n\n constructor(options: FormatRegistryOptions = {}) {\n this.rules = [];\n this.builtInReaderCache = new Map();\n this.builtInWriterCache = new Map();\n this.builtInExtensions = new Map();\n this.ruleCounter = 0;\n\n const ids = Object.keys(BUILT_IN_PRESETS) as BuiltInFormatId[];\n for (const id of ids) {\n for (const extension of BUILT_IN_PRESETS[id].extensions) {\n const existing = this.builtInExtensions.get(extension);\n if (existing) {\n throw new LocterError({ message: `Extension ${extension} is claimed by two built-in formats: ${existing}, ${id}.` });\n }\n\n this.builtInExtensions.set(extension, id);\n }\n }\n\n if (options.rules) {\n for (const rule of options.rules) {\n this.register(rule);\n }\n }\n }\n\n register(rule: Rule) : FormatRegistration {\n if (\n typeof rule.id !== 'undefined' &&\n hasOwnProperty(BUILT_IN_PRESETS, rule.id)\n ) {\n throw new LocterError({ message: `The id ${rule.id} is reserved by a built-in format.` });\n }\n\n if (\n typeof rule.reader === 'undefined' &&\n typeof rule.writer === 'undefined'\n ) {\n throw new LocterError({ message: 'A rule requires at least one of: reader, writer.' });\n }\n\n const id = rule.id ?? this.generateRuleId();\n const entry = this.compile(id, rule);\n\n const index = this.rules.findIndex((item) => item.id === id);\n if (index === -1) {\n this.rules.push(entry);\n } else {\n // replace in place: position preserved, cached instance evicted\n this.rules[index] = entry;\n }\n\n return {\n id,\n test: rule.test,\n builtIn: false,\n };\n }\n\n /**\n * Remove a user-registered rule by id. Built-in ids cannot be\n * unregistered (returns false).\n */\n unregister(id: string) : boolean {\n const index = this.rules.findIndex((item) => item.id === id);\n if (index === -1) {\n return false;\n }\n\n this.rules.splice(index, 1);\n return true;\n }\n\n has(id: string) : boolean {\n if (this.rules.some((item) => item.id === id)) {\n return true;\n }\n\n return hasOwnProperty(BUILT_IN_PRESETS, id);\n }\n\n /**\n * All registrations in effective match order: user rules\n * (registration order) first, then the built-ins.\n */\n entries() : FormatRegistration[] {\n const output : FormatRegistration[] = this.rules.map(\n (item) => ({\n id: item.id,\n test: item.test,\n builtIn: false,\n }),\n );\n\n const ids = Object.keys(BUILT_IN_PRESETS) as BuiltInFormatId[];\n for (const id of ids) {\n output.push({\n id,\n test: [...BUILT_IN_PRESETS[id].extensions],\n builtIn: true,\n });\n }\n\n return output;\n }\n\n /**\n * Restore the registry to its construction state: drop all user rules\n * and evict every cached reader instance (including a module reader\n * configured via setModuleReader / configure).\n */\n reset() : void {\n this.rules = [];\n this.builtInReaderCache.clear();\n this.builtInWriterCache.clear();\n this.ruleCounter = 0;\n }\n\n /**\n * Read a file/module RAW: the plain parsed value for data formats\n * (mutable, round-trip-symmetric with write); for modules the\n * normalized module record — a module IS a record, and the\n * normalization only irons out the CJS/ESM interop divergence so\n * both twin variants agree on one shape.\n *\n * options.format names a registered format id to use instead of\n * extension dispatch (e.g. { format: 'text' } reads module source\n * without evaluating it).\n */\n async read(input: LocatorInfo | string, options: ReadOptions = {}) : Promise<any> {\n return runTwinAsync(this.readBody(input, options));\n }\n\n readSync(input: LocatorInfo | string, options: ReadOptions = {}) : any {\n return runTwinSync(this.readBody(input, options));\n }\n\n /**\n * Read a file/module and present the result as a normalized module\n * record — the uniform, frozen shape regardless of format:\n * `.default` always holds the loaded value, top-level keys are\n * re-exposed as named exports.\n */\n async readAsModule(input: LocatorInfo | string, options: ReadOptions = {}) : Promise<any> {\n return runTwinAsync(this.readAsModuleBody(input, options));\n }\n\n readAsModuleSync(input: LocatorInfo | string, options: ReadOptions = {}) : any {\n return runTwinSync(this.readAsModuleBody(input, options));\n }\n\n protected* readBody(input: LocatorInfo | string, options: ReadOptions) : TwinBody<any> {\n const { output, reader } = yield* this.executeBody(input, options);\n if (reader instanceof ModuleReader) {\n return toModuleRecord(output);\n }\n\n return output;\n }\n\n protected* readAsModuleBody(input: LocatorInfo | string, options: ReadOptions) : TwinBody<any> {\n const { output, reader } = yield* this.executeBody(input, options);\n return this.toRecord(output, reader);\n }\n\n /**\n * Shared dispatch + execution of both read bodies: resolve the\n * reader, run it, wrap errors. Normalization is the caller's call.\n */\n protected* executeBody(\n input: LocatorInfo | string,\n options: ReadOptions,\n ) : TwinBody<{ output: unknown, reader: IReader }> {\n const filePath = buildFilePath(input);\n\n let reader : IReader | undefined;\n if (typeof options.format === 'undefined') {\n reader = this.findReader(filePath);\n } else {\n reader = this.resolveReader(options.format);\n }\n\n if (!reader) {\n throw this.unknownExtensionError(filePath);\n }\n\n try {\n const output = yield* op(\n () => reader.read(filePath),\n () => reader.readSync(filePath),\n );\n\n return { output, reader };\n } catch (e) {\n throw wrapLoaderError(e, filePath);\n }\n }\n\n /**\n * options.format names a registered format id to use instead of\n * extension dispatch — see writeBody for the boundary semantics.\n */\n async write(input: LocatorInfo | string, value: unknown, options: WriteOptions = {}) : Promise<void> {\n return runTwinAsync(this.writeBody(input, value, options));\n }\n\n writeSync(input: LocatorInfo | string, value: unknown, options: WriteOptions = {}) : void {\n runTwinSync(this.writeBody(input, value, options));\n }\n\n /**\n * Shared body of write/writeSync: dispatch, unwrap records, write, wrap.\n * The inverse boundary of readAsModuleBody: a record produced by\n * readAsModule() (brand detected) is unwrapped to its `.default` value;\n * anything else is written as-is.\n *\n * An explicit options.format skips extension dispatch entirely —\n * including the bare-specifier guard: naming the format resolves the\n * ambiguity the guard exists for, so extensionless paths become\n * writable.\n */\n protected* writeBody(\n input: LocatorInfo | string,\n value: unknown,\n options: WriteOptions,\n ) : TwinBody<void> {\n const filePath = buildFilePath(input);\n\n let writer : IWriter;\n if (typeof options.format === 'undefined') {\n if (!isFilePath(filePath)) {\n throw new WriteError({\n message: `Cannot write to a bare module specifier: ${filePath}`,\n path: filePath,\n });\n }\n\n const found = this.findWriter(filePath);\n if (!found) {\n if (this.findReader(filePath)) {\n const info = pathToLocatorInfo(filePath);\n throw new WriteError({\n message: `The format of extension ${info.extension} is read-only.`,\n path: filePath,\n });\n }\n\n throw this.unknownExtensionError(filePath);\n }\n\n writer = found;\n } else {\n writer = this.resolveWriter(options.format, filePath);\n }\n\n const plain = isModuleRecord(value) ? value.default : value;\n\n try {\n yield* op(\n () => writer.write(filePath, plain),\n () => writer.writeSync(filePath, plain),\n );\n } catch (e) {\n throw wrapWriteError(e, filePath);\n }\n }\n\n /**\n * The single normalization boundary: every readAsModule result becomes a module\n * record (`.default` is always the loaded value, top-level keys stay\n * accessible as named exports). Provenance decides how: module-reader\n * output may legitimately already be a record (`__esModule` is meaningful\n * there); any other reader returns arbitrary parsed data, which is always\n * wrapped — even if it happens to contain an `__esModule` key.\n */\n protected toRecord(output: unknown, reader: IReader) : any {\n if (reader instanceof ModuleReader) {\n return toModuleRecord(output);\n }\n\n return createModuleRecord(output);\n }\n\n /**\n * Typed accessor for the LIVE built-in reader instance (lazy, cached).\n */\n builtInReader<K extends BuiltInFormatId>(id: K) : BuiltInReaderOf<K> {\n let reader = this.builtInReaderCache.get(id);\n if (!reader) {\n reader = BUILT_IN_PRESETS[id].reader();\n this.builtInReaderCache.set(id, reader);\n }\n\n return reader as BuiltInReaderOf<K>;\n }\n\n /**\n * Typed accessor for the LIVE built-in writer instance (lazy, cached).\n * Only writable format ids are accepted — read-only formats (module)\n * are a compile error.\n */\n builtInWriter<K extends WritableBuiltInFormatId>(id: K) : BuiltInWriterOf<K> {\n let writer = this.builtInWriterCache.get(id);\n if (!writer) {\n writer = BUILT_IN_PRESETS[id].writer();\n this.builtInWriterCache.set(id, writer);\n }\n\n return writer as BuiltInWriterOf<K>;\n }\n\n /**\n * Dispatch order:\n * 1. bare specifier (no extension) → module reader, always\n * 2. user rules, registration order → first match wins (can override built-ins)\n * 3. built-in extension table\n * 4. undefined → read/readSync throw UnknownExtensionError\n */\n findReader(input: string) : IReader | undefined {\n if (!isFilePath(input)) {\n return this.builtInReader('module');\n }\n\n const rule = this.findRule(input, (item) => typeof item.getReader !== 'undefined');\n if (rule && rule.getReader) {\n return rule.getReader();\n }\n\n const id = this.findBuiltInId(input);\n if (id) {\n return this.builtInReader(id);\n }\n\n return undefined;\n }\n\n /**\n * Write-side dispatch. No bare-specifier step (there is nothing to\n * write to); only rules with a writer slot participate, then built-in\n * presets that declare a writer.\n */\n findWriter(input: string) : IWriter | undefined {\n if (!isFilePath(input)) {\n return undefined;\n }\n\n const rule = this.findRule(input, (item) => typeof item.getWriter !== 'undefined');\n if (rule && rule.getWriter) {\n return rule.getWriter();\n }\n\n const id = this.findBuiltInId(input);\n if (id && 'writer' in BUILT_IN_PRESETS[id]) {\n return this.builtInWriter(id as WritableBuiltInFormatId);\n }\n\n return undefined;\n }\n\n /**\n * Resolve a reader by EXPLICIT format id (the per-call override) —\n * a user rule id or a built-in id — bypassing extension dispatch.\n * Unknown ids and writer-only rules throw.\n */\n protected resolveReader(id: string) : IReader {\n const rule = this.rules.find((item) => item.id === id);\n if (rule) {\n if (rule.getReader) {\n return rule.getReader();\n }\n\n throw new LocterError({ message: `The format ${id} has no reader.` });\n }\n\n if (hasOwnProperty(BUILT_IN_PRESETS, id)) {\n return this.builtInReader(id as BuiltInFormatId);\n }\n\n throw this.unknownFormatError(id);\n }\n\n /**\n * Write-side counterpart of resolveReader. Reader-only rules and\n * read-only built-ins (module) throw WriteError, mirroring\n * what extension dispatch throws for read-only extensions.\n */\n protected resolveWriter(id: string, path: string) : IWriter {\n const rule = this.rules.find((item) => item.id === id);\n if (rule) {\n if (rule.getWriter) {\n return rule.getWriter();\n }\n\n throw new WriteError({\n message: `The format ${id} is read-only.`,\n path,\n });\n }\n\n if (hasOwnProperty(BUILT_IN_PRESETS, id)) {\n if ('writer' in BUILT_IN_PRESETS[id as BuiltInFormatId]) {\n return this.builtInWriter(id as WritableBuiltInFormatId);\n }\n\n throw new WriteError({\n message: `The format ${id} is read-only.`,\n path,\n });\n }\n\n throw this.unknownFormatError(id);\n }\n\n protected findRule(\n input: string,\n filter: (rule: CompiledRule) => boolean,\n ) : CompiledRule | undefined {\n const info = pathToLocatorInfo(input);\n\n for (const rule of this.rules) {\n if (!filter(rule)) {\n continue;\n }\n\n const { test } = rule;\n if (Array.isArray(test)) {\n if (\n info.extension &&\n test.includes(info.extension)\n ) {\n return rule;\n }\n } else {\n // reset before AND after: a g/y regex mutates lastIndex on\n // test(), which would make repeated dispatch alternate and\n // leak state back into the caller-owned RegExp\n test.lastIndex = 0;\n const matched = test.test(buildFilePath(info));\n test.lastIndex = 0;\n if (matched) {\n return rule;\n }\n }\n }\n\n return undefined;\n }\n\n protected findBuiltInId(input: string) : BuiltInFormatId | undefined {\n const info = pathToLocatorInfo(input);\n if (!info.extension) {\n return undefined;\n }\n\n return this.builtInExtensions.get(info.extension);\n }\n\n protected unknownExtensionError(input: string) : UnknownExtensionError {\n const info = pathToLocatorInfo(input);\n return new UnknownExtensionError({\n message: `No format registered for extension: ${info.extension ?? 'unknown'}`,\n path: input,\n });\n }\n\n protected unknownFormatError(id: string) : LocterError {\n return new LocterError({ message: `No format registered with id: ${id}` });\n }\n\n protected compile(id: string, rule: Rule) : CompiledRule {\n return {\n id,\n test: rule.test,\n getReader: compileSlot<IReader>(rule.reader),\n getWriter: compileSlot<IWriter>(rule.writer),\n };\n }\n\n protected generateRuleId() : string {\n let id : string;\n do {\n this.ruleCounter++;\n id = `rule:${this.ruleCounter}`;\n } while (this.rules.some((item) => item.id === id));\n\n return id;\n }\n}\n","/*\n * Copyright (c) 2023.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { FormatRegistry } from './module';\n\nlet instance : FormatRegistry;\nexport function useFormatRegistry() {\n if (typeof instance !== 'undefined') {\n return instance;\n }\n\n instance = new FormatRegistry();\n\n return instance;\n}\n","/*\n * Copyright (c) 2022.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport type { LocatorInfo } from '../locator';\nimport type { ModuleReaderOptions } from './built-in/module/type';\nimport {\n type FormatRegistration,\n type ReadOptions,\n type Rule,\n type WriteOptions,\n useFormatRegistry,\n} from './registry';\n\nexport function registerFormat(rule: Rule) : FormatRegistration {\n return useFormatRegistry().register(rule);\n}\n\n/**\n * Remove a rule from the process-global registry by its id\n * (as returned by registerFormat). Built-in ids cannot be unregistered.\n */\nexport function unregisterFormat(id: string) : boolean {\n return useFormatRegistry().unregister(id);\n}\n\n/**\n * Read a file/module RAW: the plain parsed value for data formats\n * (json/yaml/conf and custom readers — mutable, round-trip-symmetric\n * with write); for modules the normalized module record (a module IS a\n * record; normalization only irons out CJS/ESM interop divergence).\n *\n * options.format forces a registered format id instead of extension\n * dispatch — e.g. { format: 'text' } reads a module file's source\n * WITHOUT evaluating it.\n */\nexport async function read(input: LocatorInfo | string, options?: ReadOptions) : Promise<any> {\n return useFormatRegistry().read(input, options);\n}\n\nexport function readSync(input: LocatorInfo | string, options?: ReadOptions) : any {\n return useFormatRegistry().readSync(input, options);\n}\n\n/**\n * Read a file/module and present the result as a normalized module\n * record — the uniform, frozen shape regardless of format: `.default`\n * always holds the loaded value, top-level keys are re-exposed as\n * named exports.\n */\nexport async function readAsModule(input: LocatorInfo | string, options?: ReadOptions) : Promise<any> {\n return useFormatRegistry().readAsModule(input, options);\n}\n\nexport function readAsModuleSync(input: LocatorInfo | string, options?: ReadOptions) : any {\n return useFormatRegistry().readAsModuleSync(input, options);\n}\n\n/**\n * options.format forces a registered format id instead of extension\n * dispatch — this also lifts the bare-specifier guard (extensionless\n * paths) and the read-only block on module extensions.\n */\nexport async function write(input: LocatorInfo | string, value: unknown, options?: WriteOptions) : Promise<void> {\n return useFormatRegistry().write(input, value, options);\n}\n\nexport function writeSync(input: LocatorInfo | string, value: unknown, options?: WriteOptions) : void {\n useFormatRegistry().writeSync(input, value, options);\n}\n\n/**\n * Override the built-in module reader's `import` / `require` calls.\n *\n * Useful for test runners (e.g. Vitest) where the dynamic `import()` inside\n * `node_modules/locter` would bypass the runner's module graph. Calling this\n * from user code (e.g. a Vitest setup file) lets the runner rewrite the\n * `import()` so loaded modules share identity with statically imported ones.\n *\n * Returns a restore function that re-applies the previous configuration —\n * handy for scoped overrides (e.g. test teardown). The restore function is\n * scoped to the exact reader instance it configured: after a registry\n * reset() (which discards that instance) it becomes a no-op instead of\n * re-applying stale configuration to the fresh instance.\n *\n * @example\n * ```ts\n * // vitest setup file\n * import { setModuleReader } from 'locter';\n *\n * setModuleReader({\n * load: (id) => import(id),\n * });\n * ```\n */\nexport function setModuleReader(options: ModuleReaderOptions) : () => void {\n const reader = useFormatRegistry().builtInReader('module');\n const previous = reader.configure(options);\n\n return () => {\n reader.configure(previous);\n };\n}\n","/*\n * Copyright (c) 2026.\n * Author Peter Placzek (tada5hi)\n * For the full copyright and license information,\n * view the LICENSE file that was distributed with this source code.\n */\n\nimport { LocterError, NotFoundError, WriteError } from '../errors';\nimport type { LocatorInfo } from '../locator';\nimport {\n buildFilePath,\n locate,\n locateSync,\n locateUp,\n locateUpSync,\n} from '../locator';\nimport { hasOwnProperty, isObject, isSafeObjectKey } from '../utils';\nimport type { TwinBody } from '../utils/twin';\nimport { op, runTwinAsync, runTwinSync } from '../utils/twin';\nimport { JSONWriter } from './built-in';\nimport { useFormatRegistry } from './registry';\n\nexport type ReadPackageFieldOptions = {\n cwd?: string,\n walkUp?: boolean,\n stopAt?: string,\n};\n\nexport type WritePackageFieldOptions = ReadPackageFieldOptions;\n\nfunction extractField<T>(pkg: unknown, field: string) : T | undefined {\n if (!isObject(pkg) || !hasOwnProperty(pkg, field)) {\n return undefined;\n }\n return pkg[field] as T;\n}\n\nfunction* locatePackageBody(\n options: ReadPackageFieldOptions,\n) : TwinBody<LocatorInfo | undefined> {\n if (options.walkUp) {\n return yield* op(\n () => locateUp('package.json', { cwd: options.cwd, stopAt: options.stopAt }),\n () => locateUpSync('package.json', { cwd: options.cwd, stopAt: options.stopAt }),\n );\n }\n\n return yield* op(\n () => locate('package.json', { cwd: options.cwd }),\n () => locateSync('package.json', { cwd: options.cwd }),\n );\n}\n\nfunction* readPackageFieldBody<T>(\n field: string,\n options: ReadPackageFieldOptions,\n) : TwinBody<T | undefined> {\n const info = yield* locatePackageBody(options);\n if (!info) {\n return undefined;\n }\n\n // Read the raw parsed package.json via the built-in JSON reader —\n // not the normalized record read() returns — so synthetic record\n // keys (`default`, `__esModule`) can never resolve as package fields.\n const reader = useFormatRegistry().builtInReader('json');\n const filePath = buildFilePath(info);\n\n try {\n const pkg = yield* op(\n () => reader.read(filePath),\n () => reader.readSync(filePath),\n );\n\n return extractField<T>(pkg, field);\n } catch (e) {\n if (e instanceof NotFoundError) {\n return undefined;\n }\n throw e;\n }\n}\n\nexport async function readPackageField<T = unknown>(\n field: string,\n options: ReadPackageFieldOptions = {},\n) : Promise<T | undefined> {\n return runTwinAsync(readPackageFieldBody<T>(field, options));\n}\n\nexport function readPackageFieldSync<T = unknown>(\n field: string,\n options: ReadPackageFieldOptions = {},\n) : T | undefined {\n return runTwinSync(readPackageFieldBody<T>(field, options));\n}\n\nfunction* writePackageFieldBody(\n field: string,\n value: unknown,\n options: WritePackageFieldOptions,\n) : TwinBody<void> {\n if (!isSafeObjectKey(field)) {\n throw new LocterError({ message: `The field ${field} is not a safe object key.` });\n }\n\n const info = yield* locatePackageBody(options);\n if (!info) {\n // unlike the reader, there is nothing sensible to return —\n // a write without a target is an error\n throw new NotFoundError({ message: 'No package.json could be located.' });\n }\n\n const reader = useFormatRegistry().builtInReader('json');\n const filePath = buildFilePath(info);\n\n const pkg = yield* op(\n () => reader.read(filePath),\n () => reader.readSync(filePath),\n );\n\n if (!isObject(pkg)) {\n throw new WriteError({\n message: 'The located package.json does not contain an object.',\n path: filePath,\n });\n }\n\n pkg[field] = value;\n\n // dedicated writer instance: keeps the indentation (and the built-in\n // registry writer's configuration untouched)\n const writer = new JSONWriter({ indent: 'auto' });\n yield* op(\n () => writer.write(filePath, pkg),\n () => writer.writeSync(filePath, pkg),\n );\n}\n\n/**\n * Set a top-level field of the nearest `package.json` (same locate\n * semantics as readPackageField) and write it back, preserving the\n * file's existing indentation. Passing `undefined` removes the field.\n * Throws NotFoundError when no package.json could be located.\n */\nexport async function writePackageField(\n field: string,\n value: unknown,\n options: WritePackageFieldOptions = {},\n) : Promise<void> {\n return runTwinAsync(writePackageFieldBody(field, value, options));\n}\n\nexport function writePackageFieldSync(\n field: string,\n value: unknown,\n options: WritePackageFieldOptions = {},\n) : void {\n runTwinSync(writePackageFieldBody(field, value, options));\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "locter",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "type": "module",
5
5
  "description": "A library to locate files/modules by criteria, read them and write them back!",
6
6
  "author": {