@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 CHANGED
@@ -1,84 +1,6 @@
1
- //#region ../utils/src/json.d.ts
2
- /** Any value representable in a JSON document. */
3
- type JsonValue = string | number | boolean | null | readonly JsonValue[] | JsonObject;
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.0",
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": {