@crustjs/store 0.4.0 → 0.4.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.ts +3 -81
- package/dist/index.js +4 -103
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,84 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
interface JsonObject {
|
|
5
|
-
[key: string]: JsonValue;
|
|
6
|
-
}
|
|
7
|
-
/** Preserve a type when all of its properties are recursively JSON-compatible. */
|
|
8
|
-
type JsonCompatible<T> = T extends JsonValue ? T : T extends ((...arguments_: never[]) => void) ? never : T extends readonly unknown[] ? { [K in keyof T]: JsonCompatible<T[K]>; } : T extends object ? { [K in keyof T]: JsonCompatible<T[K]>; } : never;
|
|
9
|
-
//#endregion
|
|
10
|
-
//#region ../utils/src/primitive.d.ts
|
|
11
|
-
/** Supported primitive type literals shared by Crust packages. */
|
|
12
|
-
type BaseValueType = "string" | "number" | "boolean";
|
|
13
|
-
/**
|
|
14
|
-
* Resolves a primitive type literal to its corresponding TypeScript type.
|
|
15
|
-
*
|
|
16
|
-
* @example
|
|
17
|
-
* ```ts
|
|
18
|
-
* type Port = ResolvePrimitive<"number">;
|
|
19
|
-
* // ^? number
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
type ResolvePrimitive<T extends BaseValueType> = T extends "string" ? string : T extends "number" ? number : T extends "boolean" ? boolean : never;
|
|
23
|
-
//#endregion
|
|
24
|
-
//#region ../utils/src/schema.d.ts
|
|
25
|
-
/** The Standard Typed types interface. */
|
|
26
|
-
interface StandardSchemaTypes<Input = unknown, Output = Input> {
|
|
27
|
-
/** The input type of the schema. */
|
|
28
|
-
readonly input: Input;
|
|
29
|
-
/** The output type of the schema. */
|
|
30
|
-
readonly output: Output;
|
|
31
|
-
}
|
|
32
|
-
/** The result interface if validation succeeds. */
|
|
33
|
-
interface StandardSchemaSuccessResult<Output> {
|
|
34
|
-
/** The typed output value. */
|
|
35
|
-
readonly value: Output;
|
|
36
|
-
/** A falsy value for `issues` indicates success. */
|
|
37
|
-
readonly issues?: undefined;
|
|
38
|
-
}
|
|
39
|
-
/** The result interface if validation fails. */
|
|
40
|
-
interface StandardSchemaFailureResult {
|
|
41
|
-
/** The issues of failed validation. */
|
|
42
|
-
readonly issues: ReadonlyArray<StandardSchemaIssue>;
|
|
43
|
-
}
|
|
44
|
-
/** The result interface of the validate function. */
|
|
45
|
-
type StandardSchemaResult<Output> = StandardSchemaSuccessResult<Output> | StandardSchemaFailureResult;
|
|
46
|
-
/** The issue interface of the failure output. */
|
|
47
|
-
interface StandardSchemaIssue {
|
|
48
|
-
/** The error message of the issue. */
|
|
49
|
-
readonly message: string;
|
|
50
|
-
/** The path of the issue, if any. */
|
|
51
|
-
readonly path?: ReadonlyArray<PropertyKey | StandardSchemaPathSegment> | undefined;
|
|
52
|
-
}
|
|
53
|
-
/** The path segment interface of the issue. */
|
|
54
|
-
interface StandardSchemaPathSegment {
|
|
55
|
-
/** The key representing a path segment. */
|
|
56
|
-
readonly key: PropertyKey;
|
|
57
|
-
}
|
|
58
|
-
/** The Standard Schema properties interface. */
|
|
59
|
-
interface StandardSchemaProps<Input = unknown, Output = Input> {
|
|
60
|
-
/** The version number of the standard. */
|
|
61
|
-
readonly version: 1;
|
|
62
|
-
/** The vendor name of the schema library. */
|
|
63
|
-
readonly vendor: string;
|
|
64
|
-
/** Inferred types associated with the schema. */
|
|
65
|
-
readonly types?: StandardSchemaTypes<Input, Output> | undefined;
|
|
66
|
-
/** Validates unknown input values. */
|
|
67
|
-
readonly validate: (value: StandardSchemaTypes["input"]) => StandardSchemaResult<Output> | Promise<StandardSchemaResult<Output>>;
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* A Standard Schema-compatible schema object.
|
|
71
|
-
*
|
|
72
|
-
* Any schema library implementing the Standard Schema v1 spec
|
|
73
|
-
* (Zod, Effect, Valibot, ArkType, etc.) produces objects matching this type.
|
|
74
|
-
*/
|
|
75
|
-
type StandardSchema<Input = unknown, Output = Input> = {
|
|
76
|
-
/** The Standard Schema properties. */
|
|
77
|
-
readonly "~standard": StandardSchemaProps<Input, Output>;
|
|
78
|
-
};
|
|
79
|
-
/** Infer the output type produced by a Standard Schema on success. */
|
|
80
|
-
type InferOutput<S extends StandardSchema> = NonNullable<S["~standard"]["types"]>["output"];
|
|
81
|
-
//#endregion
|
|
1
|
+
import { JsonCompatible } from "@crustjs/utils/json";
|
|
2
|
+
import { BaseValueType, ResolvePrimitive } from "@crustjs/utils/primitive";
|
|
3
|
+
import { InferOutput, StandardSchema } from "@crustjs/utils/schema";
|
|
82
4
|
//#region src/types.d.ts
|
|
83
5
|
/** Supported type literals for store fields. */
|
|
84
6
|
type ValueType = BaseValueType;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { homedir } from "node:os";
|
|
2
2
|
import { dirname, join, win32 } from "node:path";
|
|
3
3
|
import { isDeepStrictEqual } from "node:util";
|
|
4
|
+
import { isJsonObject } from "@crustjs/utils/json";
|
|
5
|
+
import { coerceBooleanString, tryCoerceNumber } from "@crustjs/utils/primitive";
|
|
6
|
+
import { normalizeStandardIssues } from "@crustjs/utils/schema";
|
|
4
7
|
import { chmod, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
|
|
8
|
+
import { isErrnoException } from "@crustjs/utils/error";
|
|
5
9
|
//#region src/errors.ts
|
|
6
10
|
/**
|
|
7
11
|
* A typed error thrown by `@crustjs/store` for path, parse, IO, and validation failures.
|
|
@@ -249,103 +253,6 @@ function resolveStorePath(dirPath, name) {
|
|
|
249
253
|
return join(dirPath, `${name}.json`);
|
|
250
254
|
}
|
|
251
255
|
//#endregion
|
|
252
|
-
//#region ../utils/src/json.ts
|
|
253
|
-
/** Narrow a JSON document root to an object (not array/scalar/null). */
|
|
254
|
-
function isJsonObject(value) {
|
|
255
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
256
|
-
}
|
|
257
|
-
//#endregion
|
|
258
|
-
//#region ../utils/src/primitive.ts
|
|
259
|
-
/**
|
|
260
|
-
* Attempts to coerce a string to a number, returning `undefined` only when the
|
|
261
|
-
* result is `NaN`. Callers decide whether `undefined` means throw or fallback.
|
|
262
|
-
*
|
|
263
|
-
* @example
|
|
264
|
-
* ```ts
|
|
265
|
-
* tryCoerceNumber("42"); // 42
|
|
266
|
-
* tryCoerceNumber("abc"); // undefined
|
|
267
|
-
* tryCoerceNumber(""); // 0
|
|
268
|
-
* ```
|
|
269
|
-
*/
|
|
270
|
-
function tryCoerceNumber(raw) {
|
|
271
|
-
const num = Number(raw);
|
|
272
|
-
return Number.isNaN(num) ? void 0 : num;
|
|
273
|
-
}
|
|
274
|
-
/**
|
|
275
|
-
* Coerces Crust boolean strings using the existing strict truthy spellings.
|
|
276
|
-
*
|
|
277
|
-
* @example
|
|
278
|
-
* ```ts
|
|
279
|
-
* coerceBooleanString("true"); // true
|
|
280
|
-
* coerceBooleanString("1"); // true
|
|
281
|
-
* coerceBooleanString("false"); // false
|
|
282
|
-
* ```
|
|
283
|
-
*/
|
|
284
|
-
function coerceBooleanString(raw) {
|
|
285
|
-
return raw === "true" || raw === "1";
|
|
286
|
-
}
|
|
287
|
-
//#endregion
|
|
288
|
-
//#region ../utils/src/schema.ts
|
|
289
|
-
/**
|
|
290
|
-
* Format an issue path into a dot-path string.
|
|
291
|
-
*
|
|
292
|
-
* - Numeric keys (array indexes) are rendered with bracket notation: `items[0]`
|
|
293
|
-
* - String/symbol keys are joined with dots: `flags.verbose`
|
|
294
|
-
* - An empty path array produces an empty string (root-level issue)
|
|
295
|
-
*
|
|
296
|
-
* @example
|
|
297
|
-
* ```ts
|
|
298
|
-
* formatPath(["flags", "verbose"]);
|
|
299
|
-
* // => "flags.verbose"
|
|
300
|
-
*
|
|
301
|
-
* formatPath(["args", 0]);
|
|
302
|
-
* // => "args[0]"
|
|
303
|
-
*
|
|
304
|
-
* formatPath([]);
|
|
305
|
-
* // => ""
|
|
306
|
-
* ```
|
|
307
|
-
*/
|
|
308
|
-
function isNumericPathSegment(segment) {
|
|
309
|
-
return typeof segment === "number";
|
|
310
|
-
}
|
|
311
|
-
function formatPath(path) {
|
|
312
|
-
return path.map((segment, index) => isNumericPathSegment(segment) ? `[${segment}]` : index > 0 ? `.${String(segment)}` : String(segment)).join("");
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Normalize a Standard Schema issue path to an array of `PropertyKey`.
|
|
316
|
-
*
|
|
317
|
-
* Standard Schema paths contain either bare `PropertyKey` values or
|
|
318
|
-
* `{ key: PropertyKey }` segment objects; both forms are flattened to
|
|
319
|
-
* plain `PropertyKey`. Returns an empty array for a root-level issue
|
|
320
|
-
* (`undefined`).
|
|
321
|
-
*/
|
|
322
|
-
function isStandardPathSegment(segment) {
|
|
323
|
-
return typeof segment === "object" && segment !== null && "key" in segment;
|
|
324
|
-
}
|
|
325
|
-
function normalizeStandardPath(path) {
|
|
326
|
-
if (!path) return [];
|
|
327
|
-
return path.map((segment) => isStandardPathSegment(segment) ? segment.key : segment);
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Normalize Standard Schema issues into canonical `ValidationIssue` objects.
|
|
331
|
-
*
|
|
332
|
-
* Applies an optional prefix (e.g. `["flags", "verbose"]`) to each issue
|
|
333
|
-
* path, then formats each path to its canonical dot-path string.
|
|
334
|
-
*
|
|
335
|
-
* @param issues — Raw Standard Schema issues from a failed validation
|
|
336
|
-
* @param prefix — Optional path segments prepended to each issue path
|
|
337
|
-
*/
|
|
338
|
-
function normalizeStandardIssues(issues, prefix = []) {
|
|
339
|
-
return issues.map((issue) => {
|
|
340
|
-
const resolvedPath = normalizeStandardPath(issue.path);
|
|
341
|
-
const fullPath = [...prefix, ...resolvedPath];
|
|
342
|
-
return {
|
|
343
|
-
message: issue.message,
|
|
344
|
-
path: formatPath(fullPath)
|
|
345
|
-
};
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
//#endregion
|
|
349
256
|
//#region src/merge.ts
|
|
350
257
|
/**
|
|
351
258
|
* Applies field defaults to a persisted config object.
|
|
@@ -375,12 +282,6 @@ function applyFieldDefaults(persisted, fields, pruneUnknown = true) {
|
|
|
375
282
|
return result;
|
|
376
283
|
}
|
|
377
284
|
//#endregion
|
|
378
|
-
//#region ../utils/src/error.ts
|
|
379
|
-
/** Narrows a caught Node.js system error to its stable errno contract. */
|
|
380
|
-
function isErrnoException(error) {
|
|
381
|
-
return error instanceof Error && "code" in error && typeof error.code === "string";
|
|
382
|
-
}
|
|
383
|
-
//#endregion
|
|
384
285
|
//#region src/persistence.ts
|
|
385
286
|
/**
|
|
386
287
|
* Reads and parses a JSON config file from disk.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crustjs/store",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "DX-first, typed persistence for CLI apps with config/data/state/cache separation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -47,10 +47,12 @@
|
|
|
47
47
|
"prepack": "cp ../../LICENSE LICENSE",
|
|
48
48
|
"postpack": "rm -f LICENSE"
|
|
49
49
|
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@crustjs/utils": "^0.1.0"
|
|
52
|
+
},
|
|
50
53
|
"devDependencies": {
|
|
51
54
|
"@crustjs/config": "0.0.0",
|
|
52
55
|
"zod": "^4.5.4",
|
|
53
|
-
"@crustjs/utils": "0.0.0",
|
|
54
56
|
"tsdown": "^0.23.0"
|
|
55
57
|
},
|
|
56
58
|
"peerDependencies": {
|