locter 4.1.0 → 4.1.1
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/dist/index.d.mts +1 -18
- package/dist/index.mjs +21 -45
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -5
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseError, ErrorOptions } from "@ebec/core";
|
|
2
|
+
import { TwinBody } from "twinop";
|
|
2
3
|
import { createJiti } from "jiti";
|
|
3
4
|
import { ToStringOptions } from "yaml";
|
|
4
5
|
//#region src/errors/base.d.ts
|
|
@@ -84,24 +85,6 @@ declare function locateUpSync(pattern: string | string[], options?: LocatorUpOpt
|
|
|
84
85
|
declare function isLocatorInfo(input: unknown): input is LocatorInfo;
|
|
85
86
|
declare function buildFilePath(input: LocatorInfo | string): string;
|
|
86
87
|
//#endregion
|
|
87
|
-
//#region src/utils/twin.d.ts
|
|
88
|
-
/**
|
|
89
|
-
* Internal protocol to derive the parallel sync + async public surfaces
|
|
90
|
-
* from one shared body. A body is a generator that yields effect pairs —
|
|
91
|
-
* an async and a sync thunk for the same operation — and the two drivers
|
|
92
|
-
* (runTwinAsync / runTwinSync) execute the side they stand for. Effect
|
|
93
|
-
* errors are re-entered into the body via `Generator.throw`, so try/catch
|
|
94
|
-
* inside a body behaves identically in both variants.
|
|
95
|
-
*
|
|
96
|
-
* Deliberately NOT exported from the utils barrel — this is internal
|
|
97
|
-
* plumbing, not public API.
|
|
98
|
-
*/
|
|
99
|
-
type TwinOp<T = unknown> = {
|
|
100
|
-
async: () => Promise<T>;
|
|
101
|
-
sync: () => T;
|
|
102
|
-
};
|
|
103
|
-
type TwinBody<R> = Generator<TwinOp<any>, R, any>;
|
|
104
|
-
//#endregion
|
|
105
88
|
//#region src/format/type.d.ts
|
|
106
89
|
interface IReader {
|
|
107
90
|
read: (input: string) => Promise<any>;
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import { BaseError, hasInstanceof, markInstanceof } from "@ebec/core";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { op, runTwinAsync, runTwinSync } from "twinop";
|
|
4
5
|
import fg from "fast-glob";
|
|
5
6
|
import { destr } from "destr";
|
|
6
7
|
import { flatten, unflatten } from "flat";
|
|
@@ -108,15 +109,29 @@ function isJestRuntimeEnvironment() {
|
|
|
108
109
|
function isVitestRuntimeEnvironment() {
|
|
109
110
|
return typeof process !== "undefined" && process.env.VITEST === "true";
|
|
110
111
|
}
|
|
112
|
+
const MODULE_OPTION_REGEX = /^(?:-r|--require|--import|--(?:experimental-)?loader)(?:=(.*))?$/;
|
|
113
|
+
function matchesProcessMarker(regex) {
|
|
114
|
+
if (typeof process === "undefined") return false;
|
|
115
|
+
const { execArgv } = process;
|
|
116
|
+
if (Array.isArray(execArgv)) for (let i = 0; i < execArgv.length; i++) {
|
|
117
|
+
const arg = execArgv[i];
|
|
118
|
+
if (typeof arg !== "string") continue;
|
|
119
|
+
const option = MODULE_OPTION_REGEX.exec(arg);
|
|
120
|
+
if (!option) continue;
|
|
121
|
+
const value = typeof option[1] === "string" ? option[1] : execArgv[i + 1];
|
|
122
|
+
if (typeof value === "string" && regex.test(value)) return true;
|
|
123
|
+
}
|
|
124
|
+
const { _preload_modules: preloadModules } = process;
|
|
125
|
+
return Array.isArray(preloadModules) && preloadModules.some((el) => regex.test(el));
|
|
126
|
+
}
|
|
127
|
+
const TS_NODE_MARKER_REGEX = /(?:^|=|[\\/"'])ts-node(?:$|[\\/"'])/;
|
|
111
128
|
function isTsNodeRuntimeEnvironment() {
|
|
112
|
-
|
|
129
|
+
if (process[Symbol.for("ts-node.register.instance")]) return true;
|
|
130
|
+
return matchesProcessMarker(TS_NODE_MARKER_REGEX);
|
|
113
131
|
}
|
|
114
|
-
const TSX_MARKER_REGEX = /(?:^|=|[\\/])tsx(?:$|[\\/])/;
|
|
132
|
+
const TSX_MARKER_REGEX = /(?:^|=|[\\/"'])tsx(?:$|[\\/"'])/;
|
|
115
133
|
function isTsxRuntimeEnvironment() {
|
|
116
|
-
|
|
117
|
-
if (Array.isArray(process.execArgv) && process.execArgv.some((arg) => TSX_MARKER_REGEX.test(arg))) return true;
|
|
118
|
-
const { _preload_modules: preloadModules } = process;
|
|
119
|
-
return Array.isArray(preloadModules) && preloadModules.some((el) => TSX_MARKER_REGEX.test(el));
|
|
134
|
+
return matchesProcessMarker(TSX_MARKER_REGEX);
|
|
120
135
|
}
|
|
121
136
|
//#endregion
|
|
122
137
|
//#region src/utils/typescript.ts
|
|
@@ -172,45 +187,6 @@ function wrapWriteError(input, path) {
|
|
|
172
187
|
});
|
|
173
188
|
}
|
|
174
189
|
//#endregion
|
|
175
|
-
//#region src/utils/twin.ts
|
|
176
|
-
/**
|
|
177
|
-
* Perform one effect inside a twin body: `const x = yield* op(a, s)`.
|
|
178
|
-
*/
|
|
179
|
-
function* op(asyncFn, syncFn) {
|
|
180
|
-
return yield {
|
|
181
|
-
async: asyncFn,
|
|
182
|
-
sync: syncFn
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
async function runTwinAsync(body) {
|
|
186
|
-
let step = body.next();
|
|
187
|
-
while (!step.done) {
|
|
188
|
-
let result;
|
|
189
|
-
try {
|
|
190
|
-
result = await step.value.async();
|
|
191
|
-
} catch (e) {
|
|
192
|
-
step = body.throw(e);
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
step = body.next(result);
|
|
196
|
-
}
|
|
197
|
-
return step.value;
|
|
198
|
-
}
|
|
199
|
-
function runTwinSync(body) {
|
|
200
|
-
let step = body.next();
|
|
201
|
-
while (!step.done) {
|
|
202
|
-
let result;
|
|
203
|
-
try {
|
|
204
|
-
result = step.value.sync();
|
|
205
|
-
} catch (e) {
|
|
206
|
-
step = body.throw(e);
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
step = body.next(result);
|
|
210
|
-
}
|
|
211
|
-
return step.value;
|
|
212
|
-
}
|
|
213
|
-
//#endregion
|
|
214
190
|
//#region src/locator/utils.ts
|
|
215
191
|
function buildLocatorPatterns(pattern) {
|
|
216
192
|
return Array.isArray(pattern) ? pattern : [pattern];
|
package/dist/index.mjs.map
CHANGED
|
@@ -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 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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"}
|
|
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/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\n// Module-loading options whose VALUE names a loader: --require (-r),\n// --import, --loader / --experimental-loader; both the `=` and the\n// separated form. Only their values are tested against a marker, so an\n// unrelated option carrying the same string (a custom export condition\n// like --conditions=ts-node) never counts as an active runtime.\nconst MODULE_OPTION_REGEX = /^(?:-r|--require|--import|--(?:experimental-)?loader)(?:=(.*))?$/;\n\n// A loader marker in a module-loading option value: the bare specifier\n// (node --import tsx, node --loader ts-node/esm), optionally with a\n// subpath (tsx/esm, ts-node/register), a resolved path into the package\n// (.../node_modules/tsx/dist/loader.mjs), or the specifier quoted inside a\n// data: URL (node --import 'data:text/javascript,...register(\"ts-node/esm\")').\nfunction matchesProcessMarker(regex: RegExp) : boolean {\n if (typeof process === 'undefined') {\n return false;\n }\n\n const { execArgv } = process;\n if (Array.isArray(execArgv)) {\n for (let i = 0; i < execArgv.length; i++) {\n const arg = execArgv[i];\n if (typeof arg !== 'string') {\n continue;\n }\n\n const option = MODULE_OPTION_REGEX.exec(arg);\n if (!option) {\n continue;\n }\n\n const value = typeof option[1] === 'string' ? option[1] : execArgv[i + 1];\n if (typeof value === 'string' && regex.test(value)) {\n return true;\n }\n }\n }\n\n const { _preload_modules: preloadModules } = process as unknown as { _preload_modules?: string[] };\n\n return Array.isArray(preloadModules) &&\n preloadModules.some((el) => regex.test(el));\n}\n\nconst TS_NODE_MARKER_REGEX = /(?:^|=|[\\\\/\"'])ts-node(?:$|[\\\\/\"'])/;\n\nexport function isTsNodeRuntimeEnvironment(): boolean {\n // The bare `ts-node` bin and `--require ts-node/register` set this on the\n // main thread. The ESM hooks (`--loader ts-node/esm`, or\n // `module.register('ts-node/esm')` via `--import`) run on a separate\n // loader thread since Node 20, so they set it on THAT thread's process\n // object and the main thread has to read the arguments instead.\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-ignore\n if (process[Symbol.for('ts-node.register.instance')]) {\n return true;\n }\n\n return matchesProcessMarker(TS_NODE_MARKER_REGEX);\n}\n\nconst TSX_MARKER_REGEX = /(?:^|=|[\\\\/\"'])tsx(?:$|[\\\\/\"'])/;\n\nexport function isTsxRuntimeEnvironment() : boolean {\n return matchesProcessMarker(TSX_MARKER_REGEX);\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) 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 'twinop';\nimport { op } from 'twinop';\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 'twinop';\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 'twinop';\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 'twinop';\nimport { runTwinAsync, runTwinSync } from 'twinop';\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 'twinop';\nimport { op, runTwinAsync, runTwinSync } from 'twinop';\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 'twinop';\nimport { op, runTwinAsync, runTwinSync } from 'twinop';\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 'twinop';\nimport { op, runTwinAsync, runTwinSync } from 'twinop';\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 'twinop';\nimport { op, runTwinAsync, runTwinSync } from 'twinop';\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.1.
|
|
3
|
+
"version": "4.1.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A library to locate files/modules by criteria, read them and write them back!",
|
|
6
6
|
"author": {
|
|
@@ -61,19 +61,20 @@
|
|
|
61
61
|
"@tada5hi/eslint-config": "^2.3.1",
|
|
62
62
|
"@tada5hi/tsconfig": "^0.7.2",
|
|
63
63
|
"@vitest/coverage-v8": "^4.1.10",
|
|
64
|
-
"eslint": "^10.
|
|
64
|
+
"eslint": "^10.8.0",
|
|
65
65
|
"husky": "^9.1.7",
|
|
66
|
-
"tsdown": "^0.22.
|
|
66
|
+
"tsdown": "^0.22.14",
|
|
67
67
|
"typescript": "^6.0.3",
|
|
68
|
-
"typescript-eslint": "^8.
|
|
68
|
+
"typescript-eslint": "^8.65.0",
|
|
69
69
|
"vitest": "^4.1.5"
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
|
-
"@ebec/core": "^1.1
|
|
72
|
+
"@ebec/core": "^1.3.1",
|
|
73
73
|
"destr": "^2.0.5",
|
|
74
74
|
"fast-glob": "^3.3.3",
|
|
75
75
|
"flat": "^6.0.1",
|
|
76
76
|
"jiti": "^2.6.1",
|
|
77
|
+
"twinop": "^1.0.0",
|
|
77
78
|
"yaml": "^2.8.1"
|
|
78
79
|
}
|
|
79
80
|
}
|