@epsilon-asi/foundation 0.0.10 → 0.0.12

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.
Files changed (33) hide show
  1. package/build/decorators/environment/defaultSystem.d.ts +6 -0
  2. package/build/decorators/environment/defaultSystem.js +12 -0
  3. package/build/decorators/environment/dotenv.d.ts +48 -0
  4. package/build/decorators/environment/dotenv.js +77 -0
  5. package/build/decorators/environment/errors.d.ts +12 -0
  6. package/build/decorators/environment/errors.js +13 -0
  7. package/build/decorators/environment/index.d.ts +7 -164
  8. package/build/decorators/environment/index.js +19 -221
  9. package/build/decorators/environment/parse.d.ts +9 -0
  10. package/build/decorators/environment/parse.js +88 -0
  11. package/build/decorators/environment/system.d.ts +4 -0
  12. package/build/decorators/environment/system.js +133 -0
  13. package/build/decorators/environment/types.d.ts +160 -0
  14. package/build/decorators/environment/types.js +2 -0
  15. package/build/files/index.d.ts +11 -0
  16. package/build/files/index.js +36 -0
  17. package/build/files/init.d.ts +33 -0
  18. package/build/files/init.js +62 -0
  19. package/build/files/layered.d.ts +44 -0
  20. package/build/files/layered.js +133 -0
  21. package/build/files/load.d.ts +9 -0
  22. package/build/files/load.js +33 -0
  23. package/build/files/parse.d.ts +5 -0
  24. package/build/files/parse.js +27 -0
  25. package/build/files/save.d.ts +5 -0
  26. package/build/files/save.js +30 -0
  27. package/build/files/serialize.d.ts +6 -0
  28. package/build/files/serialize.js +24 -0
  29. package/build/files/types.d.ts +133 -0
  30. package/build/files/types.js +18 -0
  31. package/build/files/util.d.ts +42 -0
  32. package/build/files/util.js +495 -0
  33. package/package.json +22 -6
@@ -0,0 +1,133 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.discoverLayers = discoverLayers;
16
+ exports.discoverLayersSync = discoverLayersSync;
17
+ exports.loadMergedFiles = loadMergedFiles;
18
+ exports.loadMergedFilesSync = loadMergedFilesSync;
19
+ exports.loadLayeredFile = loadLayeredFile;
20
+ exports.loadLayeredFileSync = loadLayeredFileSync;
21
+ exports.safeLoadLayeredFile = safeLoadLayeredFile;
22
+ exports.safeLoadLayeredFileSync = safeLoadLayeredFileSync;
23
+ exports.createLayeredFile = createLayeredFile;
24
+ const node_fs_1 = require("node:fs");
25
+ const node_path_1 = __importDefault(require("node:path"));
26
+ const types_1 = require("./types");
27
+ const util_1 = require("./util");
28
+ /**
29
+ * Every place `fileName` may live, highest precedence first: the start directory, each ancestor up to
30
+ * `stopDir` (or the root), then the fallbacks. Duplicates keep their highest-precedence slot.
31
+ */
32
+ function candidates(fileName, options) {
33
+ var _a, _b;
34
+ const start = node_path_1.default.resolve((0, util_1.expandHome)((_a = options.startDir) !== null && _a !== void 0 ? _a : process.cwd()));
35
+ const stopAt = options.stopDir === undefined ? undefined : node_path_1.default.resolve((0, util_1.expandHome)(options.stopDir));
36
+ const all = [];
37
+ for (let dir = start;; dir = node_path_1.default.dirname(dir)) {
38
+ all.push({ filePath: node_path_1.default.join(dir, fileName), origin: dir === start ? "local" : "ancestor" });
39
+ if (dir === stopAt || dir === node_path_1.default.dirname(dir))
40
+ break;
41
+ }
42
+ for (const fallback of (_b = options.fallbacks) !== null && _b !== void 0 ? _b : []) {
43
+ all.push({ filePath: node_path_1.default.resolve((0, util_1.expandHome)(fallback)), origin: "fallback" });
44
+ }
45
+ const seen = new Set();
46
+ return all.filter(({ filePath }) => !seen.has(filePath) && Boolean(seen.add(filePath)));
47
+ }
48
+ /**
49
+ * Find every existing `fileName` (a name or a relative path such as `.tool/config.yaml`) from
50
+ * `startDir` upwards, then among `fallbacks`. Results are ordered highest precedence first.
51
+ */
52
+ function discoverLayers(fileName_1) {
53
+ return __awaiter(this, arguments, void 0, function* (fileName, options = {}) {
54
+ const all = candidates(fileName, options);
55
+ const present = yield Promise.all(all.map(({ filePath }) => (0, util_1.pathExists)(filePath)));
56
+ return all.filter((_, i) => present[i]);
57
+ });
58
+ }
59
+ function discoverLayersSync(fileName, options = {}) {
60
+ return candidates(fileName, options).filter(({ filePath }) => (0, node_fs_1.existsSync)(filePath));
61
+ }
62
+ /** A layer must be a mapping to merge; an empty file contributes nothing. */
63
+ function asLayer(raw, filePath) {
64
+ if (raw === undefined || (0, util_1.isPlainObject)(raw))
65
+ return raw;
66
+ throw new types_1.SchemaFileError("validate", `Cannot merge ${filePath}: its top level must be a mapping`, { filePath });
67
+ }
68
+ /** Validation runs on the merged value, so errors name every file that went into it. */
69
+ function mergedOptions(filePaths, options) {
70
+ const filePath = filePaths.length > 1 ? `merged ${filePaths.join(", ")}` : filePaths[0];
71
+ return Object.assign(Object.assign({}, options), { filePath });
72
+ }
73
+ /**
74
+ * Load several JSON/YAML files, deep-merge them and validate the result once.
75
+ * `filePaths` is highest precedence first. Each file is read raw (no schema defaults), so a
76
+ * lower layer's value is never masked by a default; defaults apply only to keys no layer sets.
77
+ */
78
+ function loadMergedFiles(filePaths_1, schema_1) {
79
+ return __awaiter(this, arguments, void 0, function* (filePaths, schema, options = {}) {
80
+ const layers = yield Promise.all(filePaths.map((filePath) => __awaiter(this, void 0, void 0, function* () { return asLayer(yield (0, util_1.readRawAsync)(filePath, options), filePath); })));
81
+ return (0, util_1.validateAsync)(schema, (0, util_1.deepMerge)(...layers.reverse()), mergedOptions(filePaths, options));
82
+ });
83
+ }
84
+ function loadMergedFilesSync(filePaths, schema, options = {}) {
85
+ const layers = filePaths.map((filePath) => asLayer((0, util_1.readRawSync)(filePath, options), filePath));
86
+ return (0, util_1.validateSync)(schema, (0, util_1.deepMerge)(...layers.reverse()), mergedOptions(filePaths, options));
87
+ }
88
+ /**
89
+ * Discover every `fileName` layer (see discoverLayers), merge them and validate.
90
+ * Precedence: start directory > nearer ancestors > farther ancestors > fallbacks, in order.
91
+ * With no layers found, the schema validates `{}`, so its defaults apply.
92
+ */
93
+ function loadLayeredFile(fileName_1, schema_1) {
94
+ return __awaiter(this, arguments, void 0, function* (fileName, schema, options = {}) {
95
+ const layers = yield discoverLayers(fileName, options);
96
+ const value = yield loadMergedFiles(layers.map((layer) => layer.filePath), schema, options);
97
+ return { value, layers };
98
+ });
99
+ }
100
+ /** Synchronous variant. Fails if the schema contains async refinements/transforms. */
101
+ function loadLayeredFileSync(fileName, schema, options = {}) {
102
+ const layers = discoverLayersSync(fileName, options);
103
+ const value = loadMergedFilesSync(layers.map((layer) => layer.filePath), schema, options);
104
+ return { value, layers };
105
+ }
106
+ /** Like loadLayeredFile, but returns a result object instead of throwing SchemaFileError. */
107
+ function safeLoadLayeredFile(fileName, schema, options = {}) {
108
+ return (0, util_1.safely)(() => loadLayeredFile(fileName, schema, options));
109
+ }
110
+ function safeLoadLayeredFileSync(fileName, schema, options = {}) {
111
+ return (0, util_1.safelySync)(() => loadLayeredFileSync(fileName, schema, options));
112
+ }
113
+ /**
114
+ * Bind a schema, file name and default options once, reuse everywhere.
115
+ * Per-call options are shallow-merged over the defaults, e.g. `config.load({startDir})`.
116
+ *
117
+ * @example
118
+ * const Config = createLayeredFile(ConfigSchema, "tool.yaml", {fallbacks: ["~/.tool/tool.yaml"]});
119
+ * const {value, layers} = await Config.load();
120
+ */
121
+ function createLayeredFile(schema, fileName, defaults = {}) {
122
+ const o = (options) => (Object.assign(Object.assign({}, defaults), options));
123
+ return {
124
+ schema,
125
+ fileName,
126
+ discover: (options) => discoverLayers(fileName, o(options)),
127
+ discoverSync: (options) => discoverLayersSync(fileName, o(options)),
128
+ load: (options) => loadLayeredFile(fileName, schema, o(options)),
129
+ loadSync: (options) => loadLayeredFileSync(fileName, schema, o(options)),
130
+ safeLoad: (options) => safeLoadLayeredFile(fileName, schema, o(options)),
131
+ safeLoadSync: (options) => safeLoadLayeredFileSync(fileName, schema, o(options)),
132
+ };
133
+ }
@@ -0,0 +1,9 @@
1
+ import * as z from "zod";
2
+ import { LoadOptions, SafeResult } from "./types";
3
+ /** Read a JSON/YAML file and return a validated, typed value. */
4
+ export declare function loadFile<S extends z.ZodType>(filePath: string, schema: S, options?: LoadOptions): Promise<z.output<S>>;
5
+ /** Synchronous variant. Fails if the schema contains async refinements/transforms. */
6
+ export declare function loadFileSync<S extends z.ZodType>(filePath: string, schema: S, options?: LoadOptions): z.output<S>;
7
+ /** Like loadFile, but returns a result object instead of throwing SchemaFileError. */
8
+ export declare function safeLoadFile<S extends z.ZodType>(filePath: string, schema: S, options?: LoadOptions): Promise<SafeResult<z.output<S>>>;
9
+ export declare function safeLoadFileSync<S extends z.ZodType>(filePath: string, schema: S, options?: LoadOptions): SafeResult<z.output<S>>;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.loadFile = loadFile;
13
+ exports.loadFileSync = loadFileSync;
14
+ exports.safeLoadFile = safeLoadFile;
15
+ exports.safeLoadFileSync = safeLoadFileSync;
16
+ const util_1 = require("./util");
17
+ /** Read a JSON/YAML file and return a validated, typed value. */
18
+ function loadFile(filePath_1, schema_1) {
19
+ return __awaiter(this, arguments, void 0, function* (filePath, schema, options = {}) {
20
+ return (0, util_1.validateAsync)(schema, yield (0, util_1.readRawAsync)(filePath, options), Object.assign(Object.assign({}, options), { filePath }));
21
+ });
22
+ }
23
+ /** Synchronous variant. Fails if the schema contains async refinements/transforms. */
24
+ function loadFileSync(filePath, schema, options = {}) {
25
+ return (0, util_1.validateSync)(schema, (0, util_1.readRawSync)(filePath, options), Object.assign(Object.assign({}, options), { filePath }));
26
+ }
27
+ /** Like loadFile, but returns a result object instead of throwing SchemaFileError. */
28
+ function safeLoadFile(filePath, schema, options = {}) {
29
+ return (0, util_1.safely)(() => loadFile(filePath, schema, options));
30
+ }
31
+ function safeLoadFileSync(filePath, schema, options = {}) {
32
+ return (0, util_1.safelySync)(() => loadFileSync(filePath, schema, options));
33
+ }
@@ -0,0 +1,5 @@
1
+ import * as z from "zod";
2
+ import { ParseOptions } from "./types";
3
+ /** Parse and validate a string already in memory. */
4
+ export declare function parseString<S extends z.ZodType>(schema: S, text: string, options?: ParseOptions): Promise<z.output<S>>;
5
+ export declare function parseStringSync<S extends z.ZodType>(schema: S, text: string, options?: ParseOptions): z.output<S>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.parseString = parseString;
13
+ exports.parseStringSync = parseStringSync;
14
+ const util_1 = require("./util");
15
+ /** Parse and validate a string already in memory. */
16
+ function parseString(schema_1, text_1) {
17
+ return __awaiter(this, arguments, void 0, function* (schema, text, options = {}) {
18
+ const format = (0, util_1.resolveFormat)(options.format, options.filePath, text);
19
+ const raw = yield (0, util_1.runPreprocess)((0, util_1.decodeText)(text, format, options), format, options);
20
+ return (0, util_1.validateAsync)(schema, raw, options);
21
+ });
22
+ }
23
+ function parseStringSync(schema, text, options = {}) {
24
+ const format = (0, util_1.resolveFormat)(options.format, options.filePath, text);
25
+ const raw = (0, util_1.runPreprocessSync)((0, util_1.decodeText)(text, format, options), format, options);
26
+ return (0, util_1.validateSync)(schema, raw, options);
27
+ }
@@ -0,0 +1,5 @@
1
+ import * as z from "zod";
2
+ import { SaveOptions } from "./types";
3
+ export declare function saveFileSync<S extends z.ZodType>(filePath: string, schema: S, value: z.output<S>, options?: SaveOptions): string;
4
+ /** Serialize and write to disk. Returns the text that was written. */
5
+ export declare function saveFile<S extends z.ZodType>(filePath: string, schema: S, value: z.output<S>, options?: SaveOptions): Promise<string>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.saveFileSync = saveFileSync;
13
+ exports.saveFile = saveFile;
14
+ const serialize_1 = require("./serialize");
15
+ const util_1 = require("./util");
16
+ function saveFileSync(filePath, schema, value, options = {}) {
17
+ const format = (0, util_1.resolveFormat)(options.format, filePath);
18
+ const text = (0, serialize_1.serialize)(schema, value, Object.assign(Object.assign({}, options), { format, filePath }));
19
+ (0, util_1.writeTextSync)(filePath, text, options);
20
+ return text;
21
+ }
22
+ /** Serialize and write to disk. Returns the text that was written. */
23
+ function saveFile(filePath_1, schema_1, value_1) {
24
+ return __awaiter(this, arguments, void 0, function* (filePath, schema, value, options = {}) {
25
+ const format = (0, util_1.resolveFormat)(options.format, filePath);
26
+ const text = yield (0, serialize_1.serializeAsync)(schema, value, Object.assign(Object.assign({}, options), { format, filePath }));
27
+ yield (0, util_1.writeTextAsync)(filePath, text, options);
28
+ return text;
29
+ });
30
+ }
@@ -0,0 +1,6 @@
1
+ import * as z from "zod";
2
+ import { SerializeOptions } from "./types";
3
+ /** Validate/encode a value with the schema and render it as JSON or YAML text. */
4
+ export declare function serialize<S extends z.ZodType>(schema: S, value: z.output<S>, options: SerializeOptions): string;
5
+ /** Async variant; required when the schema has async refinements or codecs. */
6
+ export declare function serializeAsync<S extends z.ZodType>(schema: S, value: z.output<S>, options: SerializeOptions): Promise<string>;
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.serialize = serialize;
13
+ exports.serializeAsync = serializeAsync;
14
+ const util_1 = require("./util");
15
+ /** Validate/encode a value with the schema and render it as JSON or YAML text. */
16
+ function serialize(schema, value, options) {
17
+ return (0, util_1.render)((0, util_1.toWireSync)(schema, value, options), options);
18
+ }
19
+ /** Async variant; required when the schema has async refinements or codecs. */
20
+ function serializeAsync(schema, value, options) {
21
+ return __awaiter(this, void 0, void 0, function* () {
22
+ return (0, util_1.render)(yield (0, util_1.toWireAsync)(schema, value, options), options);
23
+ });
24
+ }
@@ -0,0 +1,133 @@
1
+ import * as z from "zod";
2
+ import * as YAML from "yaml";
3
+ export type FileFormat = "json" | "yaml";
4
+ export type ParseParams = Parameters<z.ZodType["safeParse"]>[1];
5
+ export type ErrorFormatter = (error: z.core.$ZodError) => string;
6
+ export type SchemaFileErrorKind = "format" | "read" | "parse" | "preprocess" | "validate" | "encode" | "serialize" | "write";
7
+ export declare class SchemaFileError extends Error {
8
+ readonly kind: SchemaFileErrorKind;
9
+ readonly filePath?: string;
10
+ /** Present for "validate" / "encode" errors that came from Zod. */
11
+ readonly issues?: z.core.$ZodIssue[];
12
+ constructor(kind: SchemaFileErrorKind, message: string, details?: {
13
+ filePath?: string;
14
+ issues?: z.core.$ZodIssue[];
15
+ cause?: unknown;
16
+ });
17
+ }
18
+ export type SafeResult<T> = {
19
+ success: true;
20
+ data: T;
21
+ } | {
22
+ success: false;
23
+ error: SchemaFileError;
24
+ };
25
+ export interface PreprocessContext {
26
+ format: FileFormat;
27
+ filePath?: string;
28
+ }
29
+ export interface ParseOptions {
30
+ /** Force a format. "auto" (default) uses the file extension, then sniffs content. */
31
+ format?: FileFormat | "auto";
32
+ /** Only used for error messages and extension-based format detection. */
33
+ filePath?: string;
34
+ /** Strip a leading UTF-8 BOM. Default: true. */
35
+ stripBom?: boolean;
36
+ /** Value handed to the schema when the content is empty/whitespace. Default: undefined. */
37
+ emptyValue?: unknown;
38
+ /** Hook to transform raw parsed data before validation (env interpolation, migrations, ...). */
39
+ preprocess?: (raw: unknown, ctx: PreprocessContext) => unknown | Promise<unknown>;
40
+ /** Extra params forwarded to schema.safeParse (e.g. custom error map). */
41
+ parseParams?: ParseParams;
42
+ /** Customize the human-readable validation message. Default: z.prettifyError. */
43
+ formatError?: ErrorFormatter;
44
+ json?: {
45
+ reviver?: (this: unknown, key: string, value: unknown) => unknown;
46
+ };
47
+ /** Passed straight to YAML.parse (uniqueKeys, maxAliasCount, merge, version, strict, ...). */
48
+ yaml?: YAML.ParseOptions & YAML.DocumentOptions & YAML.SchemaOptions & YAML.ToJSOptions;
49
+ }
50
+ export interface LoadOptions extends ParseOptions {
51
+ encoding?: BufferEncoding;
52
+ /** If the file does not exist, validate `missingValue` instead of throwing. Default: false. */
53
+ allowMissing?: boolean;
54
+ /** Input used when the file is missing and allowMissing is true. Default: {} (so schema defaults apply). */
55
+ missingValue?: unknown;
56
+ }
57
+ /**
58
+ * How the in-memory (output-typed) value is turned back into plain data:
59
+ * - "encode": z.encode(schema, value). Runs codecs in reverse (e.g. Date -> ISO string)
60
+ * and validates. Throws on one-way .transform(). Default.
61
+ * - "parse": schema.parse(value). Validates and writes the *output* shape. Use for schemas
62
+ * with one-way transforms whose output is still valid input.
63
+ * - "none": write the value as-is with no validation.
64
+ */
65
+ export type SerializeStrategy = "encode" | "parse" | "none";
66
+ export interface SerializeOptions {
67
+ format: FileFormat;
68
+ strategy?: SerializeStrategy;
69
+ /** Spaces of indentation. Default: 2. */
70
+ indent?: number;
71
+ /** Deterministic output: sort object keys recursively (true = default string order). */
72
+ sortKeys?: boolean | ((a: string, b: string) => number);
73
+ /** Ensure output ends with a newline. Default: true. */
74
+ trailingNewline?: boolean;
75
+ /** Customize the human-readable validation message. Default: z.prettifyError. */
76
+ formatError?: ErrorFormatter;
77
+ /** Only used for error messages. */
78
+ filePath?: string;
79
+ json?: {
80
+ replacer?: (this: unknown, key: string, value: unknown) => unknown;
81
+ };
82
+ yaml?: {
83
+ /** Options for new YAML.Document(...) (version, schema, aliasDuplicateObjects, keepUndefined, ...). */
84
+ document?: YAML.DocumentOptions & YAML.SchemaOptions & YAML.CreateNodeOptions;
85
+ /**
86
+ * Options for doc.toString(...) (lineWidth, defaultStringType, flowCollectionPadding, ...).
87
+ * Not named `toString`: every object literal inherits that, so TypeScript would reject any
88
+ * `yaml` options that leave it out.
89
+ */
90
+ stringify?: YAML.ToStringOptions;
91
+ /** Header comment written at the top of the file (multi-line allowed, no leading "#"). */
92
+ comment?: string;
93
+ };
94
+ }
95
+ export interface SaveOptions extends Omit<SerializeOptions, "format" | "filePath"> {
96
+ /** "auto" (default) picks by extension: .json / .yaml / .yml. */
97
+ format?: FileFormat | "auto";
98
+ encoding?: BufferEncoding;
99
+ /** Create parent directories. Default: true. */
100
+ createDirs?: boolean;
101
+ /** Write to a temp file then rename, so readers never see a half-written file. Default: true. */
102
+ atomic?: boolean;
103
+ /** Allow replacing an existing file. Default: true. */
104
+ overwrite?: boolean;
105
+ /** File permission bits for the written file, e.g. 0o600 for secrets. */
106
+ mode?: number;
107
+ }
108
+ /** Where a layer was found: the start directory, one of its ancestors, or a fallback path. */
109
+ export type LayerOrigin = "local" | "ancestor" | "fallback";
110
+ /** One file discovered by discoverLayers(). */
111
+ export interface FileLayer {
112
+ /** Absolute path of the file. */
113
+ filePath: string;
114
+ origin: LayerOrigin;
115
+ }
116
+ export interface DiscoverOptions {
117
+ /** Directory the upward walk starts from. Default: process.cwd(). */
118
+ startDir?: string;
119
+ /** Last directory the walk visits (inclusive). Default: the filesystem root. */
120
+ stopDir?: string;
121
+ /** Paths checked after the walk, in order; they rank below every directory match. `~/` is expanded. */
122
+ fallbacks?: readonly string[];
123
+ }
124
+ /** Options for loadLayeredFile(): discovery, plus load options applied to every layer. */
125
+ export interface LayeredLoadOptions extends Omit<LoadOptions, "filePath">, DiscoverOptions {
126
+ }
127
+ export interface LayeredResult<T> {
128
+ /** The merged, validated value. */
129
+ value: T;
130
+ /** The layers that were merged, highest precedence first. */
131
+ layers: FileLayer[];
132
+ }
133
+ export declare const EXTENSIONS: Record<string, FileFormat>;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EXTENSIONS = exports.SchemaFileError = void 0;
4
+ class SchemaFileError extends Error {
5
+ constructor(kind, message, details = {}) {
6
+ super(message, { cause: details.cause });
7
+ this.name = "SchemaFileError";
8
+ this.kind = kind;
9
+ this.filePath = details.filePath;
10
+ this.issues = details.issues;
11
+ }
12
+ }
13
+ exports.SchemaFileError = SchemaFileError;
14
+ exports.EXTENSIONS = {
15
+ ".json": "json",
16
+ ".yaml": "yaml",
17
+ ".yml": "yaml",
18
+ };
@@ -0,0 +1,42 @@
1
+ import * as z from "zod";
2
+ import { FileFormat, LoadOptions, ParseOptions, SafeResult, SaveOptions, SerializeOptions } from "./types";
3
+ declare const MISSING: unique symbol;
4
+ export declare function label(filePath?: string): string;
5
+ export declare function isPlainObject(v: unknown): v is Record<string, unknown>;
6
+ /**
7
+ * Recursively merge plain objects; later sources win. `undefined` values and non-object sources are
8
+ * skipped, arrays and scalars are replaced (not concatenated), and no source is mutated.
9
+ */
10
+ export declare function deepMerge<T extends Record<string, unknown> = Record<string, unknown>>(...sources: readonly unknown[]): T;
11
+ /** Replace a leading `~` with the current user's home directory. */
12
+ export declare function expandHome(filePath: string): string;
13
+ export declare function pathExists(filePath: string): Promise<boolean>;
14
+ /** Run `run`, turning a thrown SchemaFileError into a failed SafeResult. Other errors propagate. */
15
+ export declare function safely<T>(run: () => Promise<T>): Promise<SafeResult<T>>;
16
+ export declare function safelySync<T>(run: () => T): SafeResult<T>;
17
+ export declare function decodeText(text: string, format: FileFormat, opts: ParseOptions): unknown;
18
+ export declare function formatFromExtension(filePath: string): FileFormat | undefined;
19
+ /**
20
+ * Resolve a format from an explicit option, the extension, or (last) the content.
21
+ * Content sniffing falls back to YAML because YAML 1.2 is a superset of JSON.
22
+ */
23
+ export declare function resolveFormat(format: FileFormat | "auto" | undefined, filePath?: string, content?: string): FileFormat;
24
+ export declare function toRaw(text: string | typeof MISSING, opts: LoadOptions): {
25
+ raw: unknown;
26
+ format: FileFormat;
27
+ };
28
+ export declare function readTextAsync(filePath: string, opts: LoadOptions): Promise<string | typeof MISSING>;
29
+ export declare function readTextSync(filePath: string, opts: LoadOptions): string | typeof MISSING;
30
+ /** Read, decode and preprocess a file: everything loadFile does short of validation. */
31
+ export declare function readRawAsync(filePath: string, options: LoadOptions): Promise<unknown>;
32
+ export declare function readRawSync(filePath: string, options: LoadOptions): unknown;
33
+ export declare function runPreprocess(raw: unknown, format: FileFormat, opts: ParseOptions): Promise<unknown>;
34
+ export declare function runPreprocessSync(raw: unknown, format: FileFormat, opts: ParseOptions): unknown;
35
+ export declare function validateAsync<S extends z.ZodType>(schema: S, raw: unknown, opts: ParseOptions): Promise<z.output<S>>;
36
+ export declare function validateSync<S extends z.ZodType>(schema: S, raw: unknown, opts: ParseOptions): z.output<S>;
37
+ export declare function toWireSync<S extends z.ZodType>(schema: S, value: z.output<S>, opts: SerializeOptions): unknown;
38
+ export declare function toWireAsync<S extends z.ZodType>(schema: S, value: z.output<S>, opts: SerializeOptions): Promise<unknown>;
39
+ export declare function render(data: unknown, opts: SerializeOptions): string;
40
+ export declare function writeTextAsync(filePath: string, text: string, opts: SaveOptions): Promise<void>;
41
+ export declare function writeTextSync(filePath: string, text: string, opts: SaveOptions): void;
42
+ export {};