locter 4.0.0-beta.2 → 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
@@ -391,6 +428,9 @@ built-in formats are pre-registered:
391
428
  - **conf** (`.conf`): `ConfReader` + `ConfWriter`
392
429
  - **json** (`.json`): `JSONReader` + `JSONWriter`
393
430
  - **yaml** (`.yml`, `.yaml`): `YAMLReader` + `YAMLWriter`
431
+ - **text** (`.txt`): `TextReader` + `TextWriter` — raw string content, no
432
+ value coercion (`read('notes.txt')` is the file content; writes accept
433
+ strings only).
394
434
  - **module** (`.js`, `.mjs`, `.mts`, `.cjs`, `.cts`, `.ts`): `ModuleReader`
395
435
  (read-only) — loads modules independent of the environment (cjs or esm).
396
436
 
@@ -481,6 +521,23 @@ The global registry belongs to the **application**. Libraries that need custom
481
521
  formats should create their own isolated instance instead of mutating the
482
522
  singleton: `new FormatRegistry({ rules: [...] })`.
483
523
 
524
+ **Value codec**
525
+
526
+ For env-var / key-value style contexts, the lenient *value* codec the `.conf`
527
+ format uses per value is exported directly — handy for building lenient
528
+ custom formats (or serializing to stores that hold bare strings):
529
+
530
+ ```typescript
531
+ import { deserializeValue, serializeValue } from 'locter';
532
+
533
+ serializeValue(true); // 'true'
534
+ serializeValue(/^a+$/i); // '/^a+$/i'
535
+ serializeValue({ a: 1 }); // '{"a":1}'
536
+
537
+ deserializeValue('123'); // 123
538
+ deserializeValue('{ broken'); // '{ broken' — falls back to the raw string, never throws
539
+ ```
540
+
484
541
  ### Errors
485
542
 
486
543
  `read` / `write` (and every built-in format) throw a typed subclass of
@@ -489,24 +546,24 @@ matching on `.message`:
489
546
 
490
547
  | Class | When it's thrown |
491
548
  |--------------------------------|---------------------------------------------------------|
492
- | `LocterNotFoundError` | File or module does not exist (`ENOENT`, `MODULE_NOT_FOUND`, `ERR_MODULE_NOT_FOUND`) |
493
- | `LocterLoadError` | A reader threw — parse error, runtime/eval error, etc. |
494
- | `LocterWriteError` | A write failed — serialization error, filesystem error, read-only format, corrupt existing YAML target |
495
- | `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 |
496
553
  | `LocterError` | Base class; matches all of the above |
497
554
 
498
555
  Each error exposes the offending `path` and preserves the underlying error
499
556
  on `cause`:
500
557
 
501
558
  ```typescript
502
- import { read, LocterNotFoundError, LocterLoadError } from 'locter';
559
+ import { read, NotFoundError, LoadError } from 'locter';
503
560
 
504
561
  try {
505
562
  await read('config.json');
506
563
  } catch (err) {
507
- if (err instanceof LocterNotFoundError) {
564
+ if (err instanceof NotFoundError) {
508
565
  console.error(`Config file not found: ${err.path}`);
509
- } else if (err instanceof LocterLoadError) {
566
+ } else if (err instanceof LoadError) {
510
567
  console.error(`Failed to parse config: ${err.cause}`);
511
568
  } else {
512
569
  throw err;
@@ -514,11 +571,11 @@ try {
514
571
  }
515
572
  ```
516
573
 
517
- 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
518
575
  parent directory is a write failure, not a lookup miss (and `write` creates
519
576
  missing parents anyway).
520
577
 
521
- `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.
522
579
 
523
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.
524
581
 
@@ -605,6 +662,7 @@ The list below is exhaustive — no other public APIs changed.
605
662
  | `ModuleLoader` | `ModuleReader` |
606
663
  | `setModuleLoader` | `setModuleReader` |
607
664
  | `loadPackageField` / `loadPackageFieldSync` | `readPackageField` / `readPackageFieldSync` |
665
+ | `LocterLoadError` / `LocterNotFoundError` / `LocterUnknownExtensionError` | `LoadError` / `NotFoundError` / `UnknownExtensionError` — the `LocterError` base class keeps its name |
608
666
 
609
667
  **Behavioral changes:**
610
668
 
@@ -669,7 +727,7 @@ The list below is exhaustive — no other public APIs changed.
669
727
  `ConfWriter`), including comment-preserving YAML write-back — see
670
728
  [Writer](#writer).
671
729
  - `writePackageField` / `writePackageFieldSync`.
672
- - `LocterWriteError` + `wrapWriteError`.
730
+ - `WriteError` + `wrapWriteError`.
673
731
  - `isModuleRecord` — brand-based detection of records produced by `read()`.
674
732
  - The ports are exported as `IReader` / `IWriter`, alongside `Rule`,
675
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 {
@@ -263,6 +263,27 @@ declare class ModuleReader implements IReader {
263
263
  declare function isModuleRecord(input: unknown): input is Record<string, any>;
264
264
  declare function getModuleExport(data: Record<string, any>, filterFn: ModuleExportFilterFn): ModuleExport | undefined;
265
265
  //#endregion
266
+ //#region src/format/built-in/text/reader.d.ts
267
+ /**
268
+ * Raw text: the file content, as-is. No value coercion — a .txt
269
+ * containing '123' reads as the string '123' (use deserializeValue
270
+ * for lenient value semantics).
271
+ */
272
+ declare class TextReader extends TextFileReader {
273
+ parse(content: string): string;
274
+ }
275
+ //#endregion
276
+ //#region src/format/built-in/text/writer.d.ts
277
+ /**
278
+ * Raw text: accepts strings only — coercing arbitrary values would be
279
+ * lossy ([object Object]); serialize explicitly (e.g. serializeValue)
280
+ * before writing. Output ends with a single trailing newline, like
281
+ * every text writer.
282
+ */
283
+ declare class TextWriter extends TextFileWriter {
284
+ stringify(value: unknown): string;
285
+ }
286
+ //#endregion
266
287
  //#region src/format/built-in/yaml/reader.d.ts
267
288
  declare class YAMLReader extends TextFileReader {
268
289
  parse(content: string): any;
@@ -275,7 +296,7 @@ type YAMLWriterOptions = ToStringOptions;
275
296
  * target file already exists, the new value is grafted into its parsed
276
297
  * document, so comments and anchors attached to surviving keys survive
277
298
  * the write-back. New files are plain `yaml.stringify` output. An
278
- * existing file that fails to parse throws (wrapped as LocterWriteError)
299
+ * existing file that fails to parse throws (wrapped as WriteError)
279
300
  * instead of being silently overwritten.
280
301
  */
281
302
  declare class YAMLWriter extends TextFileWriter {
@@ -314,6 +335,11 @@ declare const BUILT_IN_PRESETS: {
314
335
  readonly reader: () => YAMLReader;
315
336
  readonly writer: () => YAMLWriter;
316
337
  };
338
+ readonly text: {
339
+ readonly extensions: readonly [".txt"];
340
+ readonly reader: () => TextReader;
341
+ readonly writer: () => TextWriter;
342
+ };
317
343
  };
318
344
  type BuiltInFormatId = keyof typeof BUILT_IN_PRESETS;
319
345
  type BuiltInReaderOf<K extends BuiltInFormatId> = ReturnType<(typeof BUILT_IN_PRESETS)[K]['reader']>;
@@ -353,13 +379,40 @@ type Rule = {
353
379
  /**
354
380
  * Stable identity. Registering an existing id REPLACES that rule in
355
381
  * place (position preserved, cached instance evicted). Built-in ids
356
- * ('module', 'conf', 'json', 'yaml') are reserved. Omitted → auto-generated.
382
+ * ('module', 'conf', 'json', 'yaml', 'text') are reserved.
383
+ * Omitted → auto-generated.
357
384
  */
358
385
  id?: string;
359
386
  test: RegExp | string[];
360
387
  reader?: IReader | ReaderFactory;
361
388
  writer?: IWriter | WriterFactory;
362
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
+ };
363
416
  /**
364
417
  * Normalized registration record — returned by register()/entries().
365
418
  */
@@ -446,36 +499,49 @@ declare class FormatRegistry {
446
499
  * normalized module record — a module IS a record, and the
447
500
  * normalization only irons out the CJS/ESM interop divergence so
448
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).
449
506
  */
450
- read(input: LocatorInfo | string): Promise<any>;
451
- readSync(input: LocatorInfo | string): any;
507
+ read(input: LocatorInfo | string, options?: ReadOptions): Promise<any>;
508
+ readSync(input: LocatorInfo | string, options?: ReadOptions): any;
452
509
  /**
453
510
  * Read a file/module and present the result as a normalized module
454
511
  * record — the uniform, frozen shape regardless of format:
455
512
  * `.default` always holds the loaded value, top-level keys are
456
513
  * re-exposed as named exports.
457
514
  */
458
- readAsModule(input: LocatorInfo | string): Promise<any>;
459
- readAsModuleSync(input: LocatorInfo | string): any;
460
- protected readBody(input: LocatorInfo | string): TwinBody<any>;
461
- 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>;
462
519
  /**
463
520
  * Shared dispatch + execution of both read bodies: resolve the
464
521
  * reader, run it, wrap errors. Normalization is the caller's call.
465
522
  */
466
- protected executeBody(input: LocatorInfo | string): TwinBody<{
523
+ protected executeBody(input: LocatorInfo | string, options: ReadOptions): TwinBody<{
467
524
  output: unknown;
468
525
  reader: IReader;
469
526
  }>;
470
- write(input: LocatorInfo | string, value: unknown): Promise<void>;
471
- 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;
472
533
  /**
473
534
  * Shared body of write/writeSync: dispatch, unwrap records, write, wrap.
474
535
  * The inverse boundary of readAsModuleBody: a record produced by
475
536
  * readAsModule() (brand detected) is unwrapped to its `.default` value;
476
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.
477
543
  */
478
- protected writeBody(input: LocatorInfo | string, value: unknown): TwinBody<void>;
544
+ protected writeBody(input: LocatorInfo | string, value: unknown, options: WriteOptions): TwinBody<void>;
479
545
  /**
480
546
  * The single normalization boundary: every readAsModule result becomes a module
481
547
  * record (`.default` is always the loaded value, top-level keys stay
@@ -500,7 +566,7 @@ declare class FormatRegistry {
500
566
  * 1. bare specifier (no extension) → module reader, always
501
567
  * 2. user rules, registration order → first match wins (can override built-ins)
502
568
  * 3. built-in extension table
503
- * 4. undefined → read/readSync throw LocterUnknownExtensionError
569
+ * 4. undefined → read/readSync throw UnknownExtensionError
504
570
  */
505
571
  findReader(input: string): IReader | undefined;
506
572
  /**
@@ -509,9 +575,22 @@ declare class FormatRegistry {
509
575
  * presets that declare a writer.
510
576
  */
511
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;
512
590
  protected findRule(input: string, filter: (rule: CompiledRule) => boolean): CompiledRule | undefined;
513
591
  protected findBuiltInId(input: string): BuiltInFormatId | undefined;
514
- protected unknownExtensionError(input: string): LocterUnknownExtensionError;
592
+ protected unknownExtensionError(input: string): UnknownExtensionError;
593
+ protected unknownFormatError(id: string): LocterError;
515
594
  protected compile(id: string, rule: Rule): CompiledRule;
516
595
  protected generateRuleId(): string;
517
596
  }
@@ -531,19 +610,28 @@ declare function unregisterFormat(id: string): boolean;
531
610
  * (json/yaml/conf and custom readers — mutable, round-trip-symmetric
532
611
  * with write); for modules the normalized module record (a module IS a
533
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.
534
617
  */
535
- declare function read(input: LocatorInfo | string): Promise<any>;
536
- 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;
537
620
  /**
538
621
  * Read a file/module and present the result as a normalized module
539
622
  * record — the uniform, frozen shape regardless of format: `.default`
540
623
  * always holds the loaded value, top-level keys are re-exposed as
541
624
  * named exports.
542
625
  */
543
- declare function readAsModule(input: LocatorInfo | string): Promise<any>;
544
- declare function readAsModuleSync(input: LocatorInfo | string): any;
545
- declare function write(input: LocatorInfo | string, value: unknown): Promise<void>;
546
- 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;
547
635
  /**
548
636
  * Override the built-in module reader's `import` / `require` calls.
549
637
  *
@@ -583,11 +671,27 @@ declare function readPackageFieldSync<T = unknown>(field: string, options?: Read
583
671
  * Set a top-level field of the nearest `package.json` (same locate
584
672
  * semantics as readPackageField) and write it back, preserving the
585
673
  * file's existing indentation. Passing `undefined` removes the field.
586
- * Throws LocterNotFoundError when no package.json could be located.
674
+ * Throws NotFoundError when no package.json could be located.
587
675
  */
588
676
  declare function writePackageField(field: string, value: unknown, options?: WritePackageFieldOptions): Promise<void>;
589
677
  declare function writePackageFieldSync(field: string, value: unknown, options?: WritePackageFieldOptions): void;
590
678
  //#endregion
679
+ //#region src/format/value.d.ts
680
+ /**
681
+ * Lenient VALUE codec (env-var / key-value philosophy): primitives
682
+ * serialize to their bare string form, RegExp and BigInt to their
683
+ * string representation (also nested), everything else to JSON.
684
+ * The counterpart of deserializeValue — used per value by the conf
685
+ * format, and exported for consumers building lenient custom formats.
686
+ */
687
+ declare function serializeValue(input: unknown): string;
688
+ /**
689
+ * Lenient parse of a serialized value: coerces 'true'/'123'/'null'/
690
+ * 'undefined' to their primitive, parses JSON payloads, and falls back
691
+ * to returning the raw string — it never throws.
692
+ */
693
+ declare function deserializeValue<T = any>(input: string): T;
694
+ //#endregion
591
695
  //#region src/utils/file-name.d.ts
592
696
  declare function getFileNameExtension(input: string, allowed?: string[]): string | undefined;
593
697
  declare function removeFileNameExtension(input: string, extensions?: string[]): string;
@@ -598,5 +702,5 @@ declare function isVitestRuntimeEnvironment(): boolean;
598
702
  declare function isTsNodeRuntimeEnvironment(): boolean;
599
703
  declare function isTsxRuntimeEnvironment(): boolean;
600
704
  //#endregion
601
- export { ConfReader, ConfWriter, type FormatPreset, type FormatRegistration, FormatRegistry, type FormatRegistryOptions, type IReader, type IWriter, JSONReader, JSONWriter, type JSONWriterOptions, LOCTER_ERROR_MARKER, LOCTER_LOAD_ERROR_MARKER, LOCTER_NOT_FOUND_ERROR_MARKER, LOCTER_UNKNOWN_EXTENSION_ERROR_MARKER, LOCTER_WRITE_ERROR_MARKER, type LocatorInfo, type LocatorOptions, type LocatorOptionsInput, type LocatorUpOptionsInput, LocterError, type LocterErrorInput, type LocterErrorOptions, LocterLoadError, LocterNotFoundError, LocterUnknownExtensionError, LocterWriteError, MODULE_FILE_EXTENSIONS, type ModuleExport, type ModuleExportFilterFn, type ModuleLoadFn, type ModuleLoadOptions, type ModuleLoadSyncFn, ModuleReader, type ModuleReaderOptions, type ReadPackageFieldOptions, type ReaderFactory, type Rule, TextFileReader, TextFileWriter, type WritePackageFieldOptions, type WriterFactory, YAMLReader, YAMLWriter, type YAMLWriterOptions, buildFilePath, getFileNameExtension, getModuleExport, isJestRuntimeEnvironment, isLocatorInfo, isModuleRecord, isTsNodeRuntimeEnvironment, isTsxRuntimeEnvironment, isVitestRuntimeEnvironment, locate, locateMany, locateManySync, locateSync, locateUp, locateUpSync, read, readAsModule, readAsModuleSync, readPackageField, readPackageFieldSync, readSync, registerFormat, removeFileNameExtension, 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 };
602
706
  //# sourceMappingURL=index.d.mts.map