@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.
- package/build/decorators/environment/defaultSystem.d.ts +6 -0
- package/build/decorators/environment/defaultSystem.js +12 -0
- package/build/decorators/environment/dotenv.d.ts +48 -0
- package/build/decorators/environment/dotenv.js +77 -0
- package/build/decorators/environment/errors.d.ts +12 -0
- package/build/decorators/environment/errors.js +13 -0
- package/build/decorators/environment/index.d.ts +7 -164
- package/build/decorators/environment/index.js +19 -221
- package/build/decorators/environment/parse.d.ts +9 -0
- package/build/decorators/environment/parse.js +88 -0
- package/build/decorators/environment/system.d.ts +4 -0
- package/build/decorators/environment/system.js +133 -0
- package/build/decorators/environment/types.d.ts +160 -0
- package/build/decorators/environment/types.js +2 -0
- package/build/files/index.d.ts +11 -0
- package/build/files/index.js +36 -0
- package/build/files/init.d.ts +33 -0
- package/build/files/init.js +62 -0
- package/build/files/layered.d.ts +44 -0
- package/build/files/layered.js +133 -0
- package/build/files/load.d.ts +9 -0
- package/build/files/load.js +33 -0
- package/build/files/parse.d.ts +5 -0
- package/build/files/parse.js +27 -0
- package/build/files/save.d.ts +5 -0
- package/build/files/save.js +30 -0
- package/build/files/serialize.d.ts +6 -0
- package/build/files/serialize.js +24 -0
- package/build/files/types.d.ts +133 -0
- package/build/files/types.js +18 -0
- package/build/files/util.d.ts +42 -0
- package/build/files/util.js +495 -0
- package/package.json +22 -6
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
45
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
46
|
+
};
|
|
47
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
48
|
+
exports.label = label;
|
|
49
|
+
exports.isPlainObject = isPlainObject;
|
|
50
|
+
exports.deepMerge = deepMerge;
|
|
51
|
+
exports.expandHome = expandHome;
|
|
52
|
+
exports.pathExists = pathExists;
|
|
53
|
+
exports.safely = safely;
|
|
54
|
+
exports.safelySync = safelySync;
|
|
55
|
+
exports.decodeText = decodeText;
|
|
56
|
+
exports.formatFromExtension = formatFromExtension;
|
|
57
|
+
exports.resolveFormat = resolveFormat;
|
|
58
|
+
exports.toRaw = toRaw;
|
|
59
|
+
exports.readTextAsync = readTextAsync;
|
|
60
|
+
exports.readTextSync = readTextSync;
|
|
61
|
+
exports.readRawAsync = readRawAsync;
|
|
62
|
+
exports.readRawSync = readRawSync;
|
|
63
|
+
exports.runPreprocess = runPreprocess;
|
|
64
|
+
exports.runPreprocessSync = runPreprocessSync;
|
|
65
|
+
exports.validateAsync = validateAsync;
|
|
66
|
+
exports.validateSync = validateSync;
|
|
67
|
+
exports.toWireSync = toWireSync;
|
|
68
|
+
exports.toWireAsync = toWireAsync;
|
|
69
|
+
exports.render = render;
|
|
70
|
+
exports.writeTextAsync = writeTextAsync;
|
|
71
|
+
exports.writeTextSync = writeTextSync;
|
|
72
|
+
const YAML = __importStar(require("yaml"));
|
|
73
|
+
const z = __importStar(require("zod"));
|
|
74
|
+
const promises_1 = require("node:fs/promises");
|
|
75
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
76
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
77
|
+
const node_fs_1 = require("node:fs");
|
|
78
|
+
const types_1 = require("./types");
|
|
79
|
+
const MISSING = Symbol("missing");
|
|
80
|
+
function label(filePath) {
|
|
81
|
+
return filePath !== null && filePath !== void 0 ? filePath : "input";
|
|
82
|
+
}
|
|
83
|
+
function errMsg(e) {
|
|
84
|
+
return e instanceof Error ? e.message : String(e);
|
|
85
|
+
}
|
|
86
|
+
function isPlainObject(v) {
|
|
87
|
+
if (typeof v !== "object" || v === null)
|
|
88
|
+
return false;
|
|
89
|
+
const proto = Object.getPrototypeOf(v);
|
|
90
|
+
return proto === Object.prototype || proto === null;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Recursively merge plain objects; later sources win. `undefined` values and non-object sources are
|
|
94
|
+
* skipped, arrays and scalars are replaced (not concatenated), and no source is mutated.
|
|
95
|
+
*/
|
|
96
|
+
function deepMerge(...sources) {
|
|
97
|
+
const result = {};
|
|
98
|
+
for (const source of sources) {
|
|
99
|
+
if (!isPlainObject(source))
|
|
100
|
+
continue;
|
|
101
|
+
for (const [key, value] of Object.entries(source)) {
|
|
102
|
+
if (value === undefined)
|
|
103
|
+
continue;
|
|
104
|
+
const existing = result[key];
|
|
105
|
+
// defineProperty, not assignment: a parsed "__proto__" key must stay data, not swap the prototype.
|
|
106
|
+
Object.defineProperty(result, key, {
|
|
107
|
+
value: isPlainObject(existing) && isPlainObject(value) ? deepMerge(existing, value) : value,
|
|
108
|
+
enumerable: true,
|
|
109
|
+
writable: true,
|
|
110
|
+
configurable: true,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
/** Replace a leading `~` with the current user's home directory. */
|
|
117
|
+
function expandHome(filePath) {
|
|
118
|
+
if (filePath === "~")
|
|
119
|
+
return node_os_1.default.homedir();
|
|
120
|
+
return /^~[\\/]/.test(filePath) ? node_path_1.default.join(node_os_1.default.homedir(), filePath.slice(2)) : filePath;
|
|
121
|
+
}
|
|
122
|
+
function pathExists(filePath) {
|
|
123
|
+
return (0, promises_1.access)(filePath).then(() => true, () => false);
|
|
124
|
+
}
|
|
125
|
+
/** Run `run`, turning a thrown SchemaFileError into a failed SafeResult. Other errors propagate. */
|
|
126
|
+
function safely(run) {
|
|
127
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
128
|
+
try {
|
|
129
|
+
return { success: true, data: yield run() };
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
if (error instanceof types_1.SchemaFileError)
|
|
133
|
+
return { success: false, error };
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function safelySync(run) {
|
|
139
|
+
try {
|
|
140
|
+
return { success: true, data: run() };
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
if (error instanceof types_1.SchemaFileError)
|
|
144
|
+
return { success: false, error };
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function isNotFound(e) {
|
|
149
|
+
return (e === null || e === void 0 ? void 0 : e.code) === "ENOENT";
|
|
150
|
+
}
|
|
151
|
+
function decodeText(text, format, opts) {
|
|
152
|
+
var _a;
|
|
153
|
+
const src = opts.stripBom !== false && text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
|
|
154
|
+
if (src.trim() === "")
|
|
155
|
+
return opts.emptyValue;
|
|
156
|
+
try {
|
|
157
|
+
return format === "json" ? JSON.parse(src, (_a = opts.json) === null || _a === void 0 ? void 0 : _a.reviver) : YAML.parse(src, opts.yaml);
|
|
158
|
+
}
|
|
159
|
+
catch (cause) {
|
|
160
|
+
throw new types_1.SchemaFileError("parse", `Failed to parse ${label(opts.filePath)} as ${format.toUpperCase()}: ${errMsg(cause)}`, { filePath: opts.filePath, cause });
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function formatFromExtension(filePath) {
|
|
164
|
+
return types_1.EXTENSIONS[node_path_1.default.extname(filePath).toLowerCase()];
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Resolve a format from an explicit option, the extension, or (last) the content.
|
|
168
|
+
* Content sniffing falls back to YAML because YAML 1.2 is a superset of JSON.
|
|
169
|
+
*/
|
|
170
|
+
function resolveFormat(format, filePath, content) {
|
|
171
|
+
if (format && format !== "auto")
|
|
172
|
+
return format;
|
|
173
|
+
const byExt = filePath ? formatFromExtension(filePath) : undefined;
|
|
174
|
+
if (byExt)
|
|
175
|
+
return byExt;
|
|
176
|
+
if (content !== undefined)
|
|
177
|
+
return "yaml";
|
|
178
|
+
throw new types_1.SchemaFileError("format", `Cannot determine format for ${label(filePath)}; pass { format: "json" | "yaml" }`, { filePath });
|
|
179
|
+
}
|
|
180
|
+
function toRaw(text, opts) {
|
|
181
|
+
if (text === MISSING) {
|
|
182
|
+
return {
|
|
183
|
+
raw: "missingValue" in opts ? opts.missingValue : {},
|
|
184
|
+
format: resolveFormat(opts.format, opts.filePath, ""),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
const format = resolveFormat(opts.format, opts.filePath, text);
|
|
188
|
+
return { raw: decodeText(text, format, opts), format };
|
|
189
|
+
}
|
|
190
|
+
function readTextAsync(filePath, opts) {
|
|
191
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
192
|
+
var _a;
|
|
193
|
+
try {
|
|
194
|
+
return yield (0, promises_1.readFile)(filePath, { encoding: (_a = opts.encoding) !== null && _a !== void 0 ? _a : "utf8" });
|
|
195
|
+
}
|
|
196
|
+
catch (cause) {
|
|
197
|
+
if (opts.allowMissing && isNotFound(cause))
|
|
198
|
+
return MISSING;
|
|
199
|
+
throw new types_1.SchemaFileError("read", `Failed to read ${filePath}: ${errMsg(cause)}`, { filePath, cause });
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
function readTextSync(filePath, opts) {
|
|
204
|
+
var _a;
|
|
205
|
+
try {
|
|
206
|
+
return (0, node_fs_1.readFileSync)(filePath, { encoding: (_a = opts.encoding) !== null && _a !== void 0 ? _a : "utf8" });
|
|
207
|
+
}
|
|
208
|
+
catch (cause) {
|
|
209
|
+
if (opts.allowMissing && isNotFound(cause))
|
|
210
|
+
return MISSING;
|
|
211
|
+
throw new types_1.SchemaFileError("read", `Failed to read ${filePath}: ${errMsg(cause)}`, { filePath, cause });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/** Read, decode and preprocess a file: everything loadFile does short of validation. */
|
|
215
|
+
function readRawAsync(filePath, options) {
|
|
216
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
217
|
+
const opts = Object.assign(Object.assign({}, options), { filePath });
|
|
218
|
+
const { raw, format } = toRaw(yield readTextAsync(filePath, opts), opts);
|
|
219
|
+
return runPreprocess(raw, format, opts);
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
function readRawSync(filePath, options) {
|
|
223
|
+
const opts = Object.assign(Object.assign({}, options), { filePath });
|
|
224
|
+
const { raw, format } = toRaw(readTextSync(filePath, opts), opts);
|
|
225
|
+
return runPreprocessSync(raw, format, opts);
|
|
226
|
+
}
|
|
227
|
+
function runPreprocess(raw, format, opts) {
|
|
228
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
229
|
+
if (!opts.preprocess)
|
|
230
|
+
return raw;
|
|
231
|
+
try {
|
|
232
|
+
return yield opts.preprocess(raw, { format, filePath: opts.filePath });
|
|
233
|
+
}
|
|
234
|
+
catch (cause) {
|
|
235
|
+
throw preprocessError(cause, opts.filePath);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
function runPreprocessSync(raw, format, opts) {
|
|
240
|
+
if (!opts.preprocess)
|
|
241
|
+
return raw;
|
|
242
|
+
let result;
|
|
243
|
+
try {
|
|
244
|
+
result = opts.preprocess(raw, { format, filePath: opts.filePath });
|
|
245
|
+
}
|
|
246
|
+
catch (cause) {
|
|
247
|
+
throw preprocessError(cause, opts.filePath);
|
|
248
|
+
}
|
|
249
|
+
if (result instanceof Promise) {
|
|
250
|
+
// Nobody will await it, so keep a rejection from surfacing as an unhandledRejection.
|
|
251
|
+
result.catch(() => {
|
|
252
|
+
});
|
|
253
|
+
throw new types_1.SchemaFileError("preprocess", "preprocess returned a Promise; use the async API instead", {
|
|
254
|
+
filePath: opts.filePath,
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
return result;
|
|
258
|
+
}
|
|
259
|
+
function preprocessError(cause, filePath) {
|
|
260
|
+
return new types_1.SchemaFileError("preprocess", `Preprocess failed for ${label(filePath)}: ${errMsg(cause)}`, {
|
|
261
|
+
filePath,
|
|
262
|
+
cause,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
function zodError(kind, error, formatError, filePath) {
|
|
266
|
+
const pretty = (formatError !== null && formatError !== void 0 ? formatError : z.prettifyError)(error);
|
|
267
|
+
const verb = kind === "encode" ? "Encoding" : "Validation";
|
|
268
|
+
return new types_1.SchemaFileError(kind, `${verb} failed for ${label(filePath)}:\n${pretty}`, {
|
|
269
|
+
filePath,
|
|
270
|
+
issues: error.issues,
|
|
271
|
+
cause: error,
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
function validateAsync(schema, raw, opts) {
|
|
275
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
276
|
+
const result = yield schema.safeParseAsync(raw, opts.parseParams);
|
|
277
|
+
if (result.success)
|
|
278
|
+
return result.data;
|
|
279
|
+
throw zodError("validate", result.error, opts.formatError, opts.filePath);
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
function validateSync(schema, raw, opts) {
|
|
283
|
+
let result;
|
|
284
|
+
try {
|
|
285
|
+
result = schema.safeParse(raw, opts.parseParams);
|
|
286
|
+
}
|
|
287
|
+
catch (cause) {
|
|
288
|
+
// e.g. "Encountered Promise during synchronous parse" for async refinements
|
|
289
|
+
throw new types_1.SchemaFileError("validate", `Synchronous validation failed for ${label(opts.filePath)}: ${errMsg(cause)} (try the async API)`, { filePath: opts.filePath, cause });
|
|
290
|
+
}
|
|
291
|
+
if (result.success)
|
|
292
|
+
return result.data;
|
|
293
|
+
throw zodError("validate", result.error, opts.formatError, opts.filePath);
|
|
294
|
+
}
|
|
295
|
+
function wireError(cause, strategy, opts) {
|
|
296
|
+
const kind = strategy === "encode" ? "encode" : "validate";
|
|
297
|
+
if (cause instanceof z.core.$ZodError)
|
|
298
|
+
return zodError(kind, cause, opts.formatError, opts.filePath);
|
|
299
|
+
const hint = cause instanceof z.core.$ZodAsyncError
|
|
300
|
+
? " (try the async API)"
|
|
301
|
+
: cause instanceof z.core.$ZodEncodeError
|
|
302
|
+
? ' (one-way .transform() cannot be encoded; use z.codec() or strategy: "parse")'
|
|
303
|
+
: "";
|
|
304
|
+
return new types_1.SchemaFileError(kind, `Could not ${strategy} value for ${label(opts.filePath)}: ${errMsg(cause)}${hint}`, {
|
|
305
|
+
filePath: opts.filePath,
|
|
306
|
+
cause,
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
function toWireSync(schema, value, opts) {
|
|
310
|
+
var _a;
|
|
311
|
+
const strategy = (_a = opts.strategy) !== null && _a !== void 0 ? _a : "encode";
|
|
312
|
+
if (strategy === "none")
|
|
313
|
+
return value;
|
|
314
|
+
try {
|
|
315
|
+
return strategy === "encode" ? z.encode(schema, value) : schema.parse(value);
|
|
316
|
+
}
|
|
317
|
+
catch (cause) {
|
|
318
|
+
throw wireError(cause, strategy, opts);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
function toWireAsync(schema, value, opts) {
|
|
322
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
323
|
+
var _a;
|
|
324
|
+
const strategy = (_a = opts.strategy) !== null && _a !== void 0 ? _a : "encode";
|
|
325
|
+
if (strategy === "none")
|
|
326
|
+
return value;
|
|
327
|
+
try {
|
|
328
|
+
return strategy === "encode" ? yield z.encodeAsync(schema, value) : yield schema.parseAsync(value);
|
|
329
|
+
}
|
|
330
|
+
catch (cause) {
|
|
331
|
+
throw wireError(cause, strategy, opts);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
function sortKeysDeep(v, compare) {
|
|
336
|
+
if (Array.isArray(v))
|
|
337
|
+
return v.map((x) => sortKeysDeep(x, compare));
|
|
338
|
+
if (isPlainObject(v)) {
|
|
339
|
+
return Object.fromEntries(Object.keys(v)
|
|
340
|
+
.sort(compare)
|
|
341
|
+
.map((k) => [k, sortKeysDeep(v[k], compare)]));
|
|
342
|
+
}
|
|
343
|
+
return v;
|
|
344
|
+
}
|
|
345
|
+
function render(data, opts) {
|
|
346
|
+
var _a, _b, _c, _d, _e;
|
|
347
|
+
const input = opts.sortKeys
|
|
348
|
+
? sortKeysDeep(data, typeof opts.sortKeys === "function" ? opts.sortKeys : undefined)
|
|
349
|
+
: data;
|
|
350
|
+
const indent = (_a = opts.indent) !== null && _a !== void 0 ? _a : 2;
|
|
351
|
+
const trailingNewline = opts.trailingNewline !== false;
|
|
352
|
+
try {
|
|
353
|
+
if (opts.format === "json") {
|
|
354
|
+
const out = JSON.stringify(input, (_b = opts.json) === null || _b === void 0 ? void 0 : _b.replacer, indent);
|
|
355
|
+
if (out === undefined)
|
|
356
|
+
throw new Error("value is not JSON-serializable");
|
|
357
|
+
return trailingNewline ? `${out}\n` : out;
|
|
358
|
+
}
|
|
359
|
+
const doc = new YAML.Document(input, (_c = opts.yaml) === null || _c === void 0 ? void 0 : _c.document);
|
|
360
|
+
if ((_d = opts.yaml) === null || _d === void 0 ? void 0 : _d.comment) {
|
|
361
|
+
doc.commentBefore = opts.yaml.comment
|
|
362
|
+
.split("\n")
|
|
363
|
+
.map((line) => (line ? ` ${line}` : line))
|
|
364
|
+
.join("\n");
|
|
365
|
+
}
|
|
366
|
+
const out = doc.toString(Object.assign({ indent }, (_e = opts.yaml) === null || _e === void 0 ? void 0 : _e.stringify));
|
|
367
|
+
return trailingNewline ? out : out.replace(/\n$/, "");
|
|
368
|
+
}
|
|
369
|
+
catch (cause) {
|
|
370
|
+
throw new types_1.SchemaFileError("serialize", `Failed to serialize ${label(opts.filePath)} as ${opts.format.toUpperCase()}: ${errMsg(cause)}`, { filePath: opts.filePath, cause });
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
function tempPathFor(filePath) {
|
|
374
|
+
const rand = Math.random().toString(36).slice(2, 10);
|
|
375
|
+
return node_path_1.default.join(node_path_1.default.dirname(filePath), `.${node_path_1.default.basename(filePath)}.${process.pid}.${rand}.tmp`);
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* The rename in an atomic write replaces whatever sits at the path, so it has to target the file a
|
|
379
|
+
* symlink points at (even one that does not exist yet), or the link itself gets replaced.
|
|
380
|
+
*/
|
|
381
|
+
function atomicTargetAsync(filePath) {
|
|
382
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
383
|
+
try {
|
|
384
|
+
return yield (0, promises_1.realpath)(filePath);
|
|
385
|
+
}
|
|
386
|
+
catch (_a) {
|
|
387
|
+
return (0, promises_1.readlink)(filePath).then((link) => node_path_1.default.resolve(node_path_1.default.dirname(filePath), link), () => filePath);
|
|
388
|
+
}
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
function atomicTargetSync(filePath) {
|
|
392
|
+
try {
|
|
393
|
+
return (0, node_fs_1.realpathSync)(filePath);
|
|
394
|
+
}
|
|
395
|
+
catch (_a) {
|
|
396
|
+
try {
|
|
397
|
+
return node_path_1.default.resolve(node_path_1.default.dirname(filePath), (0, node_fs_1.readlinkSync)(filePath));
|
|
398
|
+
}
|
|
399
|
+
catch (_b) {
|
|
400
|
+
return filePath;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
/** The rename also swaps in a new file, so an explicit `mode` aside, keep the replaced file's permissions. */
|
|
405
|
+
function preservedModeAsync(target, opts) {
|
|
406
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
407
|
+
if (opts.mode !== undefined)
|
|
408
|
+
return undefined;
|
|
409
|
+
return (0, promises_1.stat)(target).then((stats) => stats.mode & 0o777, () => undefined);
|
|
410
|
+
});
|
|
411
|
+
}
|
|
412
|
+
function preservedModeSync(target, opts) {
|
|
413
|
+
if (opts.mode !== undefined)
|
|
414
|
+
return undefined;
|
|
415
|
+
try {
|
|
416
|
+
return (0, node_fs_1.statSync)(target).mode & 0o777;
|
|
417
|
+
}
|
|
418
|
+
catch (_a) {
|
|
419
|
+
return undefined;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function writeTextAsync(filePath, text, opts) {
|
|
423
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
424
|
+
var _a;
|
|
425
|
+
try {
|
|
426
|
+
if (opts.createDirs !== false)
|
|
427
|
+
yield (0, promises_1.mkdir)(node_path_1.default.dirname(filePath), { recursive: true });
|
|
428
|
+
if (opts.overwrite === false && (yield pathExists(filePath))) {
|
|
429
|
+
throw new types_1.SchemaFileError("write", `Refusing to overwrite existing file ${filePath}`, { filePath });
|
|
430
|
+
}
|
|
431
|
+
const base = { encoding: (_a = opts.encoding) !== null && _a !== void 0 ? _a : "utf8", mode: opts.mode };
|
|
432
|
+
if (opts.atomic === false) {
|
|
433
|
+
yield (0, promises_1.writeFile)(filePath, text, Object.assign(Object.assign({}, base), { flag: opts.overwrite === false ? "wx" : "w" }));
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
const target = yield atomicTargetAsync(filePath);
|
|
437
|
+
const preserved = yield preservedModeAsync(target, opts);
|
|
438
|
+
const tmp = tempPathFor(target);
|
|
439
|
+
try {
|
|
440
|
+
yield (0, promises_1.writeFile)(tmp, text, Object.assign(Object.assign({}, base), { flag: "wx" }));
|
|
441
|
+
if (preserved !== undefined)
|
|
442
|
+
yield (0, promises_1.chmod)(tmp, preserved);
|
|
443
|
+
yield (0, promises_1.rename)(tmp, target);
|
|
444
|
+
}
|
|
445
|
+
catch (e) {
|
|
446
|
+
yield (0, promises_1.unlink)(tmp).catch(() => {
|
|
447
|
+
});
|
|
448
|
+
throw e;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
catch (cause) {
|
|
452
|
+
if (cause instanceof types_1.SchemaFileError)
|
|
453
|
+
throw cause;
|
|
454
|
+
throw new types_1.SchemaFileError("write", `Failed to write ${filePath}: ${errMsg(cause)}`, { filePath, cause });
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
function writeTextSync(filePath, text, opts) {
|
|
459
|
+
var _a;
|
|
460
|
+
try {
|
|
461
|
+
if (opts.createDirs !== false)
|
|
462
|
+
(0, node_fs_1.mkdirSync)(node_path_1.default.dirname(filePath), { recursive: true });
|
|
463
|
+
if (opts.overwrite === false && (0, node_fs_1.existsSync)(filePath)) {
|
|
464
|
+
throw new types_1.SchemaFileError("write", `Refusing to overwrite existing file ${filePath}`, { filePath });
|
|
465
|
+
}
|
|
466
|
+
const base = { encoding: (_a = opts.encoding) !== null && _a !== void 0 ? _a : "utf8", mode: opts.mode };
|
|
467
|
+
if (opts.atomic === false) {
|
|
468
|
+
(0, node_fs_1.writeFileSync)(filePath, text, Object.assign(Object.assign({}, base), { flag: opts.overwrite === false ? "wx" : "w" }));
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
const target = atomicTargetSync(filePath);
|
|
472
|
+
const preserved = preservedModeSync(target, opts);
|
|
473
|
+
const tmp = tempPathFor(target);
|
|
474
|
+
try {
|
|
475
|
+
(0, node_fs_1.writeFileSync)(tmp, text, Object.assign(Object.assign({}, base), { flag: "wx" }));
|
|
476
|
+
if (preserved !== undefined)
|
|
477
|
+
(0, node_fs_1.chmodSync)(tmp, preserved);
|
|
478
|
+
(0, node_fs_1.renameSync)(tmp, target);
|
|
479
|
+
}
|
|
480
|
+
catch (e) {
|
|
481
|
+
try {
|
|
482
|
+
(0, node_fs_1.unlinkSync)(tmp);
|
|
483
|
+
}
|
|
484
|
+
catch (_b) {
|
|
485
|
+
/* ignore */
|
|
486
|
+
}
|
|
487
|
+
throw e;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
catch (cause) {
|
|
491
|
+
if (cause instanceof types_1.SchemaFileError)
|
|
492
|
+
throw cause;
|
|
493
|
+
throw new types_1.SchemaFileError("write", `Failed to write ${filePath}: ${errMsg(cause)}`, { filePath, cause });
|
|
494
|
+
}
|
|
495
|
+
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@epsilon-asi/foundation",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "",
|
|
5
5
|
"mainDir": "./",
|
|
6
|
+
"types": "./build/index.d.ts",
|
|
7
|
+
"typesVersions": {
|
|
8
|
+
"*": {
|
|
9
|
+
"files": [
|
|
10
|
+
"./build/files/index.d.ts"
|
|
11
|
+
]
|
|
12
|
+
}
|
|
13
|
+
},
|
|
6
14
|
"scripts": {
|
|
7
15
|
"build": "tsc",
|
|
8
16
|
"build:clean": "rm -rf ./build && npm run build",
|
|
@@ -23,10 +31,10 @@
|
|
|
23
31
|
"testEnvironment": "node",
|
|
24
32
|
"coverageThreshold": {
|
|
25
33
|
"global": {
|
|
26
|
-
"branches":
|
|
27
|
-
"functions":
|
|
28
|
-
"lines":
|
|
29
|
-
"statements":
|
|
34
|
+
"branches": 90,
|
|
35
|
+
"functions": 90,
|
|
36
|
+
"lines": 90,
|
|
37
|
+
"statements": 90
|
|
30
38
|
}
|
|
31
39
|
},
|
|
32
40
|
"testMatch": [
|
|
@@ -50,6 +58,11 @@
|
|
|
50
58
|
"import": "./build/index.js",
|
|
51
59
|
"require": "./build/index.js"
|
|
52
60
|
},
|
|
61
|
+
"./files": {
|
|
62
|
+
"types": "./build/files/index.d.ts",
|
|
63
|
+
"import": "./build/files/index.js",
|
|
64
|
+
"require": "./build/files/index.js"
|
|
65
|
+
},
|
|
53
66
|
"./package.json": "./package.json"
|
|
54
67
|
},
|
|
55
68
|
"files": [
|
|
@@ -59,7 +72,10 @@
|
|
|
59
72
|
],
|
|
60
73
|
"author": "",
|
|
61
74
|
"license": "SEE LICENSE IN LICENSE",
|
|
62
|
-
"dependencies": {
|
|
75
|
+
"dependencies": {
|
|
76
|
+
"dotenv": "^17.4.2",
|
|
77
|
+
"yaml": "^2.9.1"
|
|
78
|
+
},
|
|
63
79
|
"peerDependencies": {
|
|
64
80
|
"zod": "^4.0.0"
|
|
65
81
|
}
|