@shirudo/ddd-kit 2.0.0 → 3.0.0-rc.10
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/README.md +191 -53
- package/dist/chunks/kit-errors.d.ts +1081 -0
- package/dist/chunks/kit-errors.js +1165 -0
- package/dist/chunks/kit-errors.js.map +1 -0
- package/dist/chunks/ports.js +1815 -0
- package/dist/chunks/ports.js.map +1 -0
- package/dist/chunks/snapshot-store.d.ts +2397 -0
- package/dist/http.d.ts +64 -52
- package/dist/http.js +54 -20
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +4011 -2367
- package/dist/index.js +7091 -2370
- package/dist/index.js.map +1 -1
- package/dist/money.d.ts +376 -0
- package/dist/money.js +578 -0
- package/dist/money.js.map +1 -0
- package/dist/public-errors.d.ts +102 -0
- package/dist/public-errors.js +215 -0
- package/dist/public-errors.js.map +1 -0
- package/dist/testing.d.ts +631 -252
- package/dist/testing.js +2983 -782
- package/dist/testing.js.map +1 -1
- package/package.json +46 -29
- package/dist/aggregate-CePTINEt.d.ts +0 -722
- package/dist/presentation.d.ts +0 -54
- package/dist/presentation.js +0 -45
- package/dist/presentation.js.map +0 -1
- package/dist/utils.d.ts +0 -105
- package/dist/utils.js +0 -389
- package/dist/utils.js.map +0 -1
package/dist/presentation.d.ts
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { PublicIssue } from '@shirudo/base-error';
|
|
2
|
-
import { PublicErrorView } from '@shirudo/base-error/presentation';
|
|
3
|
-
|
|
4
|
-
/** Details shape carried by the view for a {@link toPublicErrorView} result. */
|
|
5
|
-
interface PublicErrorViewDetails {
|
|
6
|
-
/** Whitelisted field issues, present only for a `ValidationError`. */
|
|
7
|
-
readonly issues: readonly PublicIssue[];
|
|
8
|
-
}
|
|
9
|
-
/** Options for {@link toPublicErrorView}. */
|
|
10
|
-
interface PublicErrorViewOptions {
|
|
11
|
-
/**
|
|
12
|
-
* BCP 47 locale tag stamped on the view. The built-in messages are English;
|
|
13
|
-
* pass a locale only when you supply your own message resolution upstream.
|
|
14
|
-
* Default `"en"`.
|
|
15
|
-
*/
|
|
16
|
-
locale?: string;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Maps a kit error (or any caught value) to a base-error
|
|
20
|
-
* {@link PublicErrorView}: a **transport-neutral**, client-safe representation
|
|
21
|
-
* (`code`, `message`, `locale`, optional `details`). It is deliberately *not* a
|
|
22
|
-
* transport adapter: it carries no HTTP status, header, or exit code, because
|
|
23
|
-
* those are the consumer's concern. Feed the view into base-error's
|
|
24
|
-
* `defineProblemDetailsAdapter` (HTTP / RFC 9457), a gRPC status mapper, or a
|
|
25
|
-
* CLI exit-code table, whichever boundary you are at.
|
|
26
|
-
*
|
|
27
|
-
* Total over `unknown`: an unmapped or non-kit value degrades to a generic
|
|
28
|
-
* `INTERNAL_ERROR` view rather than leaking the technical message or throwing.
|
|
29
|
-
* The kit's class-based errors match by their pinned `error.name`, so it
|
|
30
|
-
* survives minification and duplicate installs (no `instanceof`). A
|
|
31
|
-
* `ValidationError` is detected by its `publicIssues()` whitelist (base-error
|
|
32
|
-
* names it after its code), and those issues ride along in `details.issues`.
|
|
33
|
-
*
|
|
34
|
-
* For richer, multi-locale messages, register the kit's errors in a base-error
|
|
35
|
-
* `PublicErrorRegistry` and use `PublicErrorPresenter` instead; this helper is
|
|
36
|
-
* the lean, single-locale default.
|
|
37
|
-
*
|
|
38
|
-
* @example
|
|
39
|
-
* ```ts
|
|
40
|
-
* import { toPublicErrorView } from "@shirudo/ddd-kit/presentation";
|
|
41
|
-
* import { defineProblemDetailsAdapter } from "@shirudo/base-error/problem-details";
|
|
42
|
-
*
|
|
43
|
-
* const adapter = defineProblemDetailsAdapter({
|
|
44
|
-
* definitions: { AggregateNotFoundError: { type: "about:blank", status: 404 } },
|
|
45
|
-
* fallback: { type: "about:blank", status: 500 },
|
|
46
|
-
* });
|
|
47
|
-
*
|
|
48
|
-
* const { body, status } = adapter.map(toPublicErrorView(error));
|
|
49
|
-
* return Response.json(body, { status });
|
|
50
|
-
* ```
|
|
51
|
-
*/
|
|
52
|
-
declare function toPublicErrorView(error: unknown, options?: PublicErrorViewOptions): PublicErrorView<PublicErrorViewDetails>;
|
|
53
|
-
|
|
54
|
-
export { type PublicErrorViewDetails, type PublicErrorViewOptions, toPublicErrorView };
|
package/dist/presentation.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
|
|
4
|
-
// src/presentation/public-error-view.ts
|
|
5
|
-
var KIT_PUBLIC_MESSAGES = {
|
|
6
|
-
AggregateNotFoundError: "The requested resource could not be found.",
|
|
7
|
-
ConcurrencyConflictError: "The resource was modified by another request. Please reload and try again.",
|
|
8
|
-
DuplicateAggregateError: "The resource already exists."
|
|
9
|
-
};
|
|
10
|
-
var VALIDATION_MESSAGE = "The submitted data is invalid.";
|
|
11
|
-
var FALLBACK_CODE = "INTERNAL_ERROR";
|
|
12
|
-
var FALLBACK_MESSAGE = "An unexpected error occurred.";
|
|
13
|
-
var DEFAULT_LOCALE = "en";
|
|
14
|
-
function toPublicErrorView(error, options = {}) {
|
|
15
|
-
const locale = options.locale ?? DEFAULT_LOCALE;
|
|
16
|
-
const name = errorName(error);
|
|
17
|
-
if (hasPublicIssues(error)) {
|
|
18
|
-
return {
|
|
19
|
-
code: name ?? "VALIDATION_FAILED",
|
|
20
|
-
message: VALIDATION_MESSAGE,
|
|
21
|
-
locale,
|
|
22
|
-
details: { issues: error.publicIssues() }
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
const message = name ? KIT_PUBLIC_MESSAGES[name] : void 0;
|
|
26
|
-
if (message === void 0) {
|
|
27
|
-
return { code: FALLBACK_CODE, message: FALLBACK_MESSAGE, locale };
|
|
28
|
-
}
|
|
29
|
-
return { code: name, message, locale };
|
|
30
|
-
}
|
|
31
|
-
__name(toPublicErrorView, "toPublicErrorView");
|
|
32
|
-
function errorName(error) {
|
|
33
|
-
if (typeof error !== "object" || error === null) return void 0;
|
|
34
|
-
const { name } = error;
|
|
35
|
-
return typeof name === "string" ? name : void 0;
|
|
36
|
-
}
|
|
37
|
-
__name(errorName, "errorName");
|
|
38
|
-
function hasPublicIssues(error) {
|
|
39
|
-
return typeof error.publicIssues === "function";
|
|
40
|
-
}
|
|
41
|
-
__name(hasPublicIssues, "hasPublicIssues");
|
|
42
|
-
|
|
43
|
-
export { toPublicErrorView };
|
|
44
|
-
//# sourceMappingURL=presentation.js.map
|
|
45
|
-
//# sourceMappingURL=presentation.js.map
|
package/dist/presentation.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/presentation/public-error-view.ts"],"names":[],"mappings":";;;;AAaA,IAAM,mBAAA,GAAwD;AAAA,EAC7D,sBAAA,EAAwB,4CAAA;AAAA,EACxB,wBAAA,EACC,4EAAA;AAAA,EACD,uBAAA,EAAyB;AAC1B,CAAA;AAGA,IAAM,kBAAA,GAAqB,gCAAA;AAE3B,IAAM,aAAA,GAAgB,gBAAA;AACtB,IAAM,gBAAA,GAAmB,+BAAA;AAEzB,IAAM,cAAA,GAAiB,IAAA;AAoDhB,SAAS,iBAAA,CACf,KAAA,EACA,OAAA,GAAkC,EAAC,EACO;AAC1C,EAAA,MAAM,MAAA,GAAS,QAAQ,MAAA,IAAU,cAAA;AACjC,EAAA,MAAM,IAAA,GAAO,UAAU,KAAK,CAAA;AAK5B,EAAA,IAAI,eAAA,CAAgB,KAAK,CAAA,EAAG;AAC3B,IAAA,OAAO;AAAA,MACN,MAAM,IAAA,IAAQ,mBAAA;AAAA,MACd,OAAA,EAAS,kBAAA;AAAA,MACT,MAAA;AAAA,MACA,OAAA,EAAS,EAAE,MAAA,EAAQ,KAAA,CAAM,cAAa;AAAE,KACzC;AAAA,EACD;AAEA,EAAA,MAAM,OAAA,GAAU,IAAA,GAAO,mBAAA,CAAoB,IAAI,CAAA,GAAI,MAAA;AACnD,EAAA,IAAI,YAAY,MAAA,EAAW;AAC1B,IAAA,OAAO,EAAE,IAAA,EAAM,aAAA,EAAe,OAAA,EAAS,kBAAkB,MAAA,EAAO;AAAA,EACjE;AAEA,EAAA,OAAO,EAAE,IAAA,EAAM,IAAA,EAAgB,OAAA,EAAS,MAAA,EAAO;AAChD;AAzBgB,MAAA,CAAA,iBAAA,EAAA,mBAAA,CAAA;AA4BhB,SAAS,UAAU,KAAA,EAAoC;AACtD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,KAAA,KAAU,MAAM,OAAO,MAAA;AACxD,EAAA,MAAM,EAAE,MAAK,GAAI,KAAA;AACjB,EAAA,OAAO,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,GAAO,MAAA;AAC1C;AAJS,MAAA,CAAA,SAAA,EAAA,WAAA,CAAA;AAOT,SAAS,gBACR,KAAA,EAC6C;AAC7C,EAAA,OACC,OAAQ,MAAqC,YAAA,KAAiB,UAAA;AAEhE;AANS,MAAA,CAAA,eAAA,EAAA,iBAAA,CAAA","file":"presentation.js","sourcesContent":["import type { PublicIssue } from \"@shirudo/base-error\";\nimport type { PublicErrorView } from \"@shirudo/base-error/presentation\";\n\n/**\n * Safe, client-facing English messages for the kit's known errors. They carry\n * no occurrence data (no id, version, or technical detail), so they never leak\n * across the boundary. This is the transport-neutral *presentation* layer: the\n * technical error classes stay free of these strings (removed from the core in\n * 2.0); here is their opt-in home.\n *\n * Keyed by the kit's pinned `error.name` (stable across minification and\n * duplicate installs), so matching does not depend on `instanceof`.\n */\nconst KIT_PUBLIC_MESSAGES: Readonly<Record<string, string>> = {\n\tAggregateNotFoundError: \"The requested resource could not be found.\",\n\tConcurrencyConflictError:\n\t\t\"The resource was modified by another request. Please reload and try again.\",\n\tDuplicateAggregateError: \"The resource already exists.\",\n};\n\n/** Message for a `ValidationError`, which is detected by capability, not name. */\nconst VALIDATION_MESSAGE = \"The submitted data is invalid.\";\n/** Public code and message used for any unmapped or non-kit error. */\nconst FALLBACK_CODE = \"INTERNAL_ERROR\";\nconst FALLBACK_MESSAGE = \"An unexpected error occurred.\";\n/** BCP 47 locale the built-in messages are written in. */\nconst DEFAULT_LOCALE = \"en\";\n\n/** Details shape carried by the view for a {@link toPublicErrorView} result. */\nexport interface PublicErrorViewDetails {\n\t/** Whitelisted field issues, present only for a `ValidationError`. */\n\treadonly issues: readonly PublicIssue[];\n}\n\n/** Options for {@link toPublicErrorView}. */\nexport interface PublicErrorViewOptions {\n\t/**\n\t * BCP 47 locale tag stamped on the view. The built-in messages are English;\n\t * pass a locale only when you supply your own message resolution upstream.\n\t * Default `\"en\"`.\n\t */\n\tlocale?: string;\n}\n\n/**\n * Maps a kit error (or any caught value) to a base-error\n * {@link PublicErrorView}: a **transport-neutral**, client-safe representation\n * (`code`, `message`, `locale`, optional `details`). It is deliberately *not* a\n * transport adapter: it carries no HTTP status, header, or exit code, because\n * those are the consumer's concern. Feed the view into base-error's\n * `defineProblemDetailsAdapter` (HTTP / RFC 9457), a gRPC status mapper, or a\n * CLI exit-code table, whichever boundary you are at.\n *\n * Total over `unknown`: an unmapped or non-kit value degrades to a generic\n * `INTERNAL_ERROR` view rather than leaking the technical message or throwing.\n * The kit's class-based errors match by their pinned `error.name`, so it\n * survives minification and duplicate installs (no `instanceof`). A\n * `ValidationError` is detected by its `publicIssues()` whitelist (base-error\n * names it after its code), and those issues ride along in `details.issues`.\n *\n * For richer, multi-locale messages, register the kit's errors in a base-error\n * `PublicErrorRegistry` and use `PublicErrorPresenter` instead; this helper is\n * the lean, single-locale default.\n *\n * @example\n * ```ts\n * import { toPublicErrorView } from \"@shirudo/ddd-kit/presentation\";\n * import { defineProblemDetailsAdapter } from \"@shirudo/base-error/problem-details\";\n *\n * const adapter = defineProblemDetailsAdapter({\n * definitions: { AggregateNotFoundError: { type: \"about:blank\", status: 404 } },\n * fallback: { type: \"about:blank\", status: 500 },\n * });\n *\n * const { body, status } = adapter.map(toPublicErrorView(error));\n * return Response.json(body, { status });\n * ```\n */\nexport function toPublicErrorView(\n\terror: unknown,\n\toptions: PublicErrorViewOptions = {},\n): PublicErrorView<PublicErrorViewDetails> {\n\tconst locale = options.locale ?? DEFAULT_LOCALE;\n\tconst name = errorName(error);\n\n\t// ValidationError (and subclasses) are detected by the publicIssues()\n\t// whitelist, not by name: base-error names a ValidationError after its code\n\t// (\"VALIDATION_FAILED\"), so a name match would miss it.\n\tif (hasPublicIssues(error)) {\n\t\treturn {\n\t\t\tcode: name ?? \"VALIDATION_FAILED\",\n\t\t\tmessage: VALIDATION_MESSAGE,\n\t\t\tlocale,\n\t\t\tdetails: { issues: error.publicIssues() },\n\t\t};\n\t}\n\n\tconst message = name ? KIT_PUBLIC_MESSAGES[name] : undefined;\n\tif (message === undefined) {\n\t\treturn { code: FALLBACK_CODE, message: FALLBACK_MESSAGE, locale };\n\t}\n\n\treturn { code: name as string, message, locale };\n}\n\n/** Reads a string `name` off a caught value without assuming it is an Error. */\nfunction errorName(error: unknown): string | undefined {\n\tif (typeof error !== \"object\" || error === null) return undefined;\n\tconst { name } = error as { name?: unknown };\n\treturn typeof name === \"string\" ? name : undefined;\n}\n\n/** Duck-types base-error's `ValidationError.publicIssues()` accessor. */\nfunction hasPublicIssues(\n\terror: unknown,\n): error is { publicIssues(): PublicIssue[] } {\n\treturn (\n\t\ttypeof (error as { publicIssues?: unknown }).publicIssues === \"function\"\n\t);\n}\n"]}
|
package/dist/utils.d.ts
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Performs a deep equality check between two values.
|
|
3
|
-
*
|
|
4
|
-
* This function compares values recursively, handling:
|
|
5
|
-
* - Primitives (with special handling for NaN)
|
|
6
|
-
* - Arrays (nested arrays supported)
|
|
7
|
-
* - Objects (plain objects and class instances)
|
|
8
|
-
* - TypedArrays (Uint8Array, Int32Array, etc.)
|
|
9
|
-
* - DataView
|
|
10
|
-
* - Maps and Sets
|
|
11
|
-
* - Dates and RegExp
|
|
12
|
-
* - Wrapper objects (Boolean, Number, String)
|
|
13
|
-
* - Circular references (detected and handled)
|
|
14
|
-
*
|
|
15
|
-
* @param a - The first value to compare
|
|
16
|
-
* @param b - The second value to compare
|
|
17
|
-
* @returns `true` if the values are deeply equal, `false` otherwise
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```ts
|
|
21
|
-
* deepEqual([1, 2, 3], [1, 2, 3]); // true
|
|
22
|
-
* deepEqual({ a: 1, b: [2, 3] }, { a: 1, b: [2, 3] }); // true
|
|
23
|
-
* deepEqual(NaN, NaN); // true
|
|
24
|
-
* deepEqual([1, 2], [1, 2, 3]); // false
|
|
25
|
-
* ```
|
|
26
|
-
*/
|
|
27
|
-
declare function deepEqual(a: unknown, b: unknown): boolean;
|
|
28
|
-
|
|
29
|
-
type Key = string | symbol;
|
|
30
|
-
type PathSegment = string | number | symbol;
|
|
31
|
-
interface DeepOmitOptions {
|
|
32
|
-
/**
|
|
33
|
-
* Keys to ignore everywhere in the object tree.
|
|
34
|
-
* Only applies to object properties, not Map/Set/TypedArray contents.
|
|
35
|
-
*/
|
|
36
|
-
readonly ignoreKeys?: readonly Key[];
|
|
37
|
-
/**
|
|
38
|
-
* Fine-grained control: Key + path (without current key).
|
|
39
|
-
* Example path: ["user", "meta", 0, "data"]
|
|
40
|
-
*/
|
|
41
|
-
readonly ignoreKeyPredicate?: (key: Key, path: readonly PathSegment[]) => boolean;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Creates a deep copy of `value` with certain keys removed according to the
|
|
45
|
-
* provided rules.
|
|
46
|
-
*
|
|
47
|
-
* Walks the object tree and skips keys that match `ignoreKeys` /
|
|
48
|
-
* `ignoreKeyPredicate`. Built-in atomic types that `deepEqual` compares by
|
|
49
|
-
* value (Date, RegExp, Map, Set, TypedArrays, DataView) are cloned by type
|
|
50
|
-
* rather than walked, since their internal structure has no key filtering to
|
|
51
|
-
* apply. Types that `deepEqual` compares by reference (Error, ArrayBuffer,
|
|
52
|
-
* SharedArrayBuffer, Promise, WeakMap, WeakSet) are passed through by
|
|
53
|
-
* reference, so `deepEqualExcept(x, x)` stays reflexive. Cycles are
|
|
54
|
-
* preserved: a cycle `a → a` clones to `a' → a'`.
|
|
55
|
-
*
|
|
56
|
-
* **Shared references.** Without `ignoreKeyPredicate`, an object reached
|
|
57
|
-
* via several paths dedupes to a single clone. With a predicate, each
|
|
58
|
-
* path gets its own clone, because the predicate may decide differently per
|
|
59
|
-
* path, so memoising the first path's result would be wrong. This is
|
|
60
|
-
* inherently exponential for diamond-shaped sharing (a node reachable
|
|
61
|
-
* via 2^n paths is cloned 2^n times); the walk aborts with a descriptive
|
|
62
|
-
* error after {@link PATH_SENSITIVE_VISIT_BUDGET} node visits instead of
|
|
63
|
-
* hanging the process.
|
|
64
|
-
*
|
|
65
|
-
* **Prototype-pollution safety.** `__proto__` and `constructor` keys
|
|
66
|
-
* encountered as *own* properties of the input (typical of `JSON.parse`
|
|
67
|
-
* output) are copied as inert data properties via `Object.defineProperty`
|
|
68
|
-
* so the clone graph cannot bleed into `Object.prototype`.
|
|
69
|
-
*
|
|
70
|
-
* **Class instances.** When the input is a class instance, the clone is
|
|
71
|
-
* built via `Object.create(proto)` so the prototype is preserved, but the
|
|
72
|
-
* constructor is NOT re-invoked, so class invariants enforced by the
|
|
73
|
-
* constructor are not re-checked. `deepOmit` is therefore best used for
|
|
74
|
-
* comparison/serialisation (`voEqualsExcept`, `deepEqualExcept`), not as
|
|
75
|
-
* a general-purpose clone for behaviour-carrying objects.
|
|
76
|
-
*
|
|
77
|
-
* @param value - The value to create a deep copy from
|
|
78
|
-
* @param options - Options specifying which keys to ignore
|
|
79
|
-
* @returns A deep copy of `value` with specified keys removed
|
|
80
|
-
*/
|
|
81
|
-
declare function deepOmit<T>(value: T, options: DeepOmitOptions): T;
|
|
82
|
-
|
|
83
|
-
type DeepEqualExceptOptions = DeepOmitOptions;
|
|
84
|
-
/**
|
|
85
|
-
* Performs a deep equality comparison between two values after omitting specified keys.
|
|
86
|
-
*
|
|
87
|
-
* This function first removes the specified keys from both values using `deepOmit`,
|
|
88
|
-
* then performs a deep equality check using `deepEqual`.
|
|
89
|
-
*
|
|
90
|
-
* @param a - The first value to compare
|
|
91
|
-
* @param b - The second value to compare
|
|
92
|
-
* @param options - Options specifying which keys to omit before comparison
|
|
93
|
-
* @returns `true` if the values are deeply equal after omitting specified keys, `false` otherwise
|
|
94
|
-
*
|
|
95
|
-
* @example
|
|
96
|
-
* ```ts
|
|
97
|
-
* const obj1 = { id: 1, name: "Alice", updatedAt: "2024-01-01" };
|
|
98
|
-
* const obj2 = { id: 2, name: "Alice", updatedAt: "2024-01-02" };
|
|
99
|
-
*
|
|
100
|
-
* deepEqualExcept(obj1, obj2, { ignoreKeys: ["id", "updatedAt"] }); // true
|
|
101
|
-
* ```
|
|
102
|
-
*/
|
|
103
|
-
declare function deepEqualExcept(a: unknown, b: unknown, options: DeepEqualExceptOptions): boolean;
|
|
104
|
-
|
|
105
|
-
export { type DeepEqualExceptOptions, type DeepOmitOptions, type Key, type PathSegment, deepEqual, deepEqualExcept, deepOmit };
|
package/dist/utils.js
DELETED
|
@@ -1,389 +0,0 @@
|
|
|
1
|
-
var __defProp = Object.defineProperty;
|
|
2
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
|
-
|
|
4
|
-
// src/utils/array/is-built-in.ts
|
|
5
|
-
var BUILT_IN_TAGS = /* @__PURE__ */ new Set([
|
|
6
|
-
"[object Date]",
|
|
7
|
-
"[object RegExp]",
|
|
8
|
-
"[object Map]",
|
|
9
|
-
"[object Set]",
|
|
10
|
-
"[object WeakMap]",
|
|
11
|
-
"[object WeakSet]",
|
|
12
|
-
"[object Promise]",
|
|
13
|
-
"[object Error]",
|
|
14
|
-
"[object Boolean]",
|
|
15
|
-
"[object Number]",
|
|
16
|
-
"[object String]",
|
|
17
|
-
"[object ArrayBuffer]",
|
|
18
|
-
"[object SharedArrayBuffer]",
|
|
19
|
-
"[object DataView]"
|
|
20
|
-
]);
|
|
21
|
-
function intrinsicGetter(proto, prop) {
|
|
22
|
-
const get = Object.getOwnPropertyDescriptor(proto, prop)?.get;
|
|
23
|
-
if (!get) throw new Error(`missing intrinsic getter for ${prop}`);
|
|
24
|
-
return get;
|
|
25
|
-
}
|
|
26
|
-
__name(intrinsicGetter, "intrinsicGetter");
|
|
27
|
-
var dateGetTime = Date.prototype.getTime;
|
|
28
|
-
var mapSizeGet = intrinsicGetter(Map.prototype, "size");
|
|
29
|
-
var setSizeGet = intrinsicGetter(Set.prototype, "size");
|
|
30
|
-
var weakMapHas = WeakMap.prototype.has;
|
|
31
|
-
var weakSetHas = WeakSet.prototype.has;
|
|
32
|
-
var dataViewByteLengthGet = intrinsicGetter(DataView.prototype, "byteLength");
|
|
33
|
-
var arrayBufferByteLengthGet = intrinsicGetter(
|
|
34
|
-
ArrayBuffer.prototype,
|
|
35
|
-
"byteLength"
|
|
36
|
-
);
|
|
37
|
-
var regExpSourceGet = intrinsicGetter(RegExp.prototype, "source");
|
|
38
|
-
var booleanValueOf = Boolean.prototype.valueOf;
|
|
39
|
-
var numberValueOf = Number.prototype.valueOf;
|
|
40
|
-
var stringValueOf = String.prototype.valueOf;
|
|
41
|
-
var PROBE_KEY = {};
|
|
42
|
-
var REFERENCE_COMPARED_TAGS = /* @__PURE__ */ new Set([
|
|
43
|
-
"[object Error]",
|
|
44
|
-
"[object ArrayBuffer]",
|
|
45
|
-
"[object SharedArrayBuffer]",
|
|
46
|
-
"[object Promise]",
|
|
47
|
-
"[object WeakMap]",
|
|
48
|
-
"[object WeakSet]"
|
|
49
|
-
]);
|
|
50
|
-
function hasBrand(obj, tag) {
|
|
51
|
-
try {
|
|
52
|
-
switch (tag) {
|
|
53
|
-
case "[object Date]":
|
|
54
|
-
dateGetTime.call(obj);
|
|
55
|
-
return true;
|
|
56
|
-
case "[object RegExp]":
|
|
57
|
-
regExpSourceGet.call(obj);
|
|
58
|
-
return true;
|
|
59
|
-
case "[object Map]":
|
|
60
|
-
mapSizeGet.call(obj);
|
|
61
|
-
return true;
|
|
62
|
-
case "[object Set]":
|
|
63
|
-
setSizeGet.call(obj);
|
|
64
|
-
return true;
|
|
65
|
-
case "[object WeakMap]":
|
|
66
|
-
weakMapHas.call(obj, PROBE_KEY);
|
|
67
|
-
return true;
|
|
68
|
-
case "[object WeakSet]":
|
|
69
|
-
weakSetHas.call(obj, PROBE_KEY);
|
|
70
|
-
return true;
|
|
71
|
-
case "[object DataView]":
|
|
72
|
-
dataViewByteLengthGet.call(obj);
|
|
73
|
-
return true;
|
|
74
|
-
case "[object ArrayBuffer]":
|
|
75
|
-
arrayBufferByteLengthGet.call(obj);
|
|
76
|
-
return true;
|
|
77
|
-
case "[object Boolean]":
|
|
78
|
-
booleanValueOf.call(obj);
|
|
79
|
-
return true;
|
|
80
|
-
case "[object Number]":
|
|
81
|
-
numberValueOf.call(obj);
|
|
82
|
-
return true;
|
|
83
|
-
case "[object String]":
|
|
84
|
-
stringValueOf.call(obj);
|
|
85
|
-
return true;
|
|
86
|
-
default:
|
|
87
|
-
return true;
|
|
88
|
-
}
|
|
89
|
-
} catch {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
__name(hasBrand, "hasBrand");
|
|
94
|
-
function isBuiltInObject(obj, tag) {
|
|
95
|
-
if (ArrayBuffer.isView(obj)) return true;
|
|
96
|
-
if (tag.endsWith("Array]")) return false;
|
|
97
|
-
return BUILT_IN_TAGS.has(tag) && hasBrand(obj, tag);
|
|
98
|
-
}
|
|
99
|
-
__name(isBuiltInObject, "isBuiltInObject");
|
|
100
|
-
|
|
101
|
-
// src/utils/array/deep-equal.ts
|
|
102
|
-
var objProto = Object.prototype;
|
|
103
|
-
var objToString = objProto.toString;
|
|
104
|
-
var objHasOwn = objProto.hasOwnProperty;
|
|
105
|
-
function sameValueZero(a, b) {
|
|
106
|
-
return a === b || Number.isNaN(a) && Number.isNaN(b);
|
|
107
|
-
}
|
|
108
|
-
__name(sameValueZero, "sameValueZero");
|
|
109
|
-
function deepEqual(a, b) {
|
|
110
|
-
return deepEqualInner(a, b, /* @__PURE__ */ new WeakMap());
|
|
111
|
-
}
|
|
112
|
-
__name(deepEqual, "deepEqual");
|
|
113
|
-
function deepEqualInner(a, b, visited) {
|
|
114
|
-
if (a === b) return true;
|
|
115
|
-
const typeA = typeof a;
|
|
116
|
-
const typeB = typeof b;
|
|
117
|
-
if (typeA !== "object" || a === null || typeB !== "object" || b === null) {
|
|
118
|
-
if (typeA === "number" && typeB === "number") {
|
|
119
|
-
return Number.isNaN(a) && Number.isNaN(b);
|
|
120
|
-
}
|
|
121
|
-
return false;
|
|
122
|
-
}
|
|
123
|
-
const objA = a;
|
|
124
|
-
const objB = b;
|
|
125
|
-
let cachedBs = visited.get(objA);
|
|
126
|
-
if (cachedBs?.has(objB)) {
|
|
127
|
-
return true;
|
|
128
|
-
}
|
|
129
|
-
if (!cachedBs) {
|
|
130
|
-
cachedBs = /* @__PURE__ */ new WeakSet();
|
|
131
|
-
visited.set(objA, cachedBs);
|
|
132
|
-
}
|
|
133
|
-
cachedBs.add(objB);
|
|
134
|
-
if (ArrayBuffer.isView(objA) || ArrayBuffer.isView(objB)) {
|
|
135
|
-
if (!ArrayBuffer.isView(objA) || !ArrayBuffer.isView(objB)) return false;
|
|
136
|
-
const tagA2 = objToString.call(objA);
|
|
137
|
-
const tagB2 = objToString.call(objB);
|
|
138
|
-
if (tagA2 !== tagB2) return false;
|
|
139
|
-
if (tagA2 === "[object DataView]") {
|
|
140
|
-
const viewA = objA;
|
|
141
|
-
const viewB = objB;
|
|
142
|
-
if (viewA.byteLength !== viewB.byteLength) return false;
|
|
143
|
-
const len2 = viewA.byteLength;
|
|
144
|
-
for (let i = 0; i < len2; i++) {
|
|
145
|
-
if (viewA.getUint8(i) !== viewB.getUint8(i)) return false;
|
|
146
|
-
}
|
|
147
|
-
return true;
|
|
148
|
-
}
|
|
149
|
-
const arrA = objA;
|
|
150
|
-
const arrB = objB;
|
|
151
|
-
const len = arrA.length;
|
|
152
|
-
if (len !== arrB.length) return false;
|
|
153
|
-
for (let i = 0; i < len; i++) {
|
|
154
|
-
if (!sameValueZero(arrA[i], arrB[i])) return false;
|
|
155
|
-
}
|
|
156
|
-
return true;
|
|
157
|
-
}
|
|
158
|
-
if (Array.isArray(objA) || Array.isArray(objB)) {
|
|
159
|
-
if (!Array.isArray(objA) || !Array.isArray(objB)) return false;
|
|
160
|
-
const arrA = objA;
|
|
161
|
-
const arrB = objB;
|
|
162
|
-
const len = arrA.length;
|
|
163
|
-
if (len !== arrB.length) return false;
|
|
164
|
-
for (let i = 0; i < len; i++) {
|
|
165
|
-
if (!deepEqualInner(arrA[i], arrB[i], visited)) return false;
|
|
166
|
-
}
|
|
167
|
-
return true;
|
|
168
|
-
}
|
|
169
|
-
const tagA = objToString.call(objA);
|
|
170
|
-
const tagB = objToString.call(objB);
|
|
171
|
-
if (tagA !== tagB) return false;
|
|
172
|
-
const builtInA = isBuiltInObject(objA, tagA);
|
|
173
|
-
const builtInB = isBuiltInObject(objB, tagB);
|
|
174
|
-
if (builtInA !== builtInB) return false;
|
|
175
|
-
if (!builtInA) {
|
|
176
|
-
return comparePlainObjects(objA, objB, visited);
|
|
177
|
-
}
|
|
178
|
-
switch (tagA) {
|
|
179
|
-
case "[object Map]": {
|
|
180
|
-
const mapA = objA;
|
|
181
|
-
const mapB = objB;
|
|
182
|
-
if (mapA.size !== mapB.size) return false;
|
|
183
|
-
for (const [key, valA] of mapA) {
|
|
184
|
-
if (!mapB.has(key)) return false;
|
|
185
|
-
const valB = mapB.get(key);
|
|
186
|
-
if (!deepEqualInner(valA, valB, visited)) return false;
|
|
187
|
-
}
|
|
188
|
-
return true;
|
|
189
|
-
}
|
|
190
|
-
case "[object Set]": {
|
|
191
|
-
const setA = objA;
|
|
192
|
-
const setB = objB;
|
|
193
|
-
if (setA.size !== setB.size) return false;
|
|
194
|
-
for (const value of setA) {
|
|
195
|
-
if (!setB.has(value)) return false;
|
|
196
|
-
}
|
|
197
|
-
return true;
|
|
198
|
-
}
|
|
199
|
-
case "[object Date]": {
|
|
200
|
-
return sameValueZero(objA.getTime(), objB.getTime());
|
|
201
|
-
}
|
|
202
|
-
case "[object RegExp]": {
|
|
203
|
-
const regA = objA;
|
|
204
|
-
const regB = objB;
|
|
205
|
-
return regA.source === regB.source && regA.flags === regB.flags;
|
|
206
|
-
}
|
|
207
|
-
case "[object Boolean]":
|
|
208
|
-
case "[object Number]":
|
|
209
|
-
case "[object String]": {
|
|
210
|
-
return sameValueZero(
|
|
211
|
-
objA.valueOf(),
|
|
212
|
-
objB.valueOf()
|
|
213
|
-
);
|
|
214
|
-
}
|
|
215
|
-
default: {
|
|
216
|
-
return objA === objB;
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
__name(deepEqualInner, "deepEqualInner");
|
|
221
|
-
function comparePlainObjects(objA, objB, visited) {
|
|
222
|
-
const recA = objA;
|
|
223
|
-
const recB = objB;
|
|
224
|
-
const stringKeysA = Object.keys(objA);
|
|
225
|
-
const stringKeysB = Object.keys(objB);
|
|
226
|
-
if (stringKeysA.length !== stringKeysB.length) return false;
|
|
227
|
-
const symbolKeysA = Object.getOwnPropertySymbols(objA);
|
|
228
|
-
const symbolKeysB = Object.getOwnPropertySymbols(objB);
|
|
229
|
-
if (symbolKeysA.length !== symbolKeysB.length) return false;
|
|
230
|
-
const symbolKeysBSet = new Set(symbolKeysB);
|
|
231
|
-
for (const key of stringKeysA) {
|
|
232
|
-
if (!objHasOwn.call(objB, key)) return false;
|
|
233
|
-
}
|
|
234
|
-
for (const key of symbolKeysA) {
|
|
235
|
-
if (!symbolKeysBSet.has(key)) return false;
|
|
236
|
-
}
|
|
237
|
-
for (const key of stringKeysA) {
|
|
238
|
-
if (!deepEqualInner(recA[key], recB[key], visited)) {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
for (const key of symbolKeysA) {
|
|
243
|
-
if (!deepEqualInner(recA[key], recB[key], visited)) {
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
return true;
|
|
248
|
-
}
|
|
249
|
-
__name(comparePlainObjects, "comparePlainObjects");
|
|
250
|
-
|
|
251
|
-
// src/utils/array/deep-omit.ts
|
|
252
|
-
function deepOmit(value, options) {
|
|
253
|
-
const visited = /* @__PURE__ */ new WeakMap();
|
|
254
|
-
const ignoreKeys = options.ignoreKeys ? new Set(options.ignoreKeys) : void 0;
|
|
255
|
-
const budget = options.ignoreKeyPredicate ? { visits: 0 } : void 0;
|
|
256
|
-
return omitInternal(value, options, ignoreKeys, [], visited, budget);
|
|
257
|
-
}
|
|
258
|
-
__name(deepOmit, "deepOmit");
|
|
259
|
-
var PATH_SENSITIVE_VISIT_BUDGET = 1e6;
|
|
260
|
-
function omitInternal(value, options, ignoreKeys, path, visited, budget) {
|
|
261
|
-
if (value === null) return value;
|
|
262
|
-
if (typeof value !== "object") return value;
|
|
263
|
-
const obj = value;
|
|
264
|
-
if (visited.has(obj)) {
|
|
265
|
-
return visited.get(obj);
|
|
266
|
-
}
|
|
267
|
-
if (budget && ++budget.visits > PATH_SENSITIVE_VISIT_BUDGET) {
|
|
268
|
-
throw new Error(
|
|
269
|
-
`deepOmit: exceeded ${PATH_SENSITIVE_VISIT_BUDGET} node visits. With ignoreKeyPredicate, objects reached via shared references are cloned once per path (the predicate may decide differently per path), which expands exponentially on diamond-shaped sharing. Restructure the input to a tree, or use ignoreKeys for path-independent filtering.`
|
|
270
|
-
);
|
|
271
|
-
}
|
|
272
|
-
if (Array.isArray(obj)) {
|
|
273
|
-
const arr = obj;
|
|
274
|
-
const clone2 = new Array(arr.length);
|
|
275
|
-
visited.set(obj, clone2);
|
|
276
|
-
for (let i = 0; i < arr.length; i++) {
|
|
277
|
-
path.push(i);
|
|
278
|
-
clone2[i] = omitInternal(
|
|
279
|
-
arr[i],
|
|
280
|
-
options,
|
|
281
|
-
ignoreKeys,
|
|
282
|
-
path,
|
|
283
|
-
visited,
|
|
284
|
-
budget
|
|
285
|
-
);
|
|
286
|
-
path.pop();
|
|
287
|
-
}
|
|
288
|
-
if (budget) visited.delete(obj);
|
|
289
|
-
return clone2;
|
|
290
|
-
}
|
|
291
|
-
const tag = Object.prototype.toString.call(obj);
|
|
292
|
-
if (isBuiltInObject(obj, tag)) {
|
|
293
|
-
const builtInClone = cloneBuiltIn(obj, tag);
|
|
294
|
-
visited.set(obj, builtInClone);
|
|
295
|
-
return builtInClone;
|
|
296
|
-
}
|
|
297
|
-
const clone = Object.create(Object.getPrototypeOf(obj));
|
|
298
|
-
visited.set(obj, clone);
|
|
299
|
-
const stringKeys = Object.keys(obj);
|
|
300
|
-
const symbolKeys = Object.getOwnPropertySymbols(obj);
|
|
301
|
-
for (const key of stringKeys) {
|
|
302
|
-
if (shouldIgnoreKey(key, path, ignoreKeys, options)) continue;
|
|
303
|
-
path.push(key);
|
|
304
|
-
assignOwn(
|
|
305
|
-
clone,
|
|
306
|
-
key,
|
|
307
|
-
omitInternal(
|
|
308
|
-
obj[key],
|
|
309
|
-
options,
|
|
310
|
-
ignoreKeys,
|
|
311
|
-
path,
|
|
312
|
-
visited,
|
|
313
|
-
budget
|
|
314
|
-
)
|
|
315
|
-
);
|
|
316
|
-
path.pop();
|
|
317
|
-
}
|
|
318
|
-
for (const key of symbolKeys) {
|
|
319
|
-
if (shouldIgnoreKey(key, path, ignoreKeys, options)) continue;
|
|
320
|
-
path.push(key);
|
|
321
|
-
assignOwn(
|
|
322
|
-
clone,
|
|
323
|
-
key,
|
|
324
|
-
omitInternal(
|
|
325
|
-
obj[key],
|
|
326
|
-
options,
|
|
327
|
-
ignoreKeys,
|
|
328
|
-
path,
|
|
329
|
-
visited,
|
|
330
|
-
budget
|
|
331
|
-
)
|
|
332
|
-
);
|
|
333
|
-
path.pop();
|
|
334
|
-
}
|
|
335
|
-
if (budget) visited.delete(obj);
|
|
336
|
-
return clone;
|
|
337
|
-
}
|
|
338
|
-
__name(omitInternal, "omitInternal");
|
|
339
|
-
function assignOwn(target, key, value) {
|
|
340
|
-
Object.defineProperty(target, key, {
|
|
341
|
-
value,
|
|
342
|
-
writable: true,
|
|
343
|
-
enumerable: true,
|
|
344
|
-
configurable: true
|
|
345
|
-
});
|
|
346
|
-
}
|
|
347
|
-
__name(assignOwn, "assignOwn");
|
|
348
|
-
function cloneBuiltIn(obj, tag) {
|
|
349
|
-
if (REFERENCE_COMPARED_TAGS.has(tag)) return obj;
|
|
350
|
-
switch (tag) {
|
|
351
|
-
case "[object Date]":
|
|
352
|
-
return new Date(obj.getTime());
|
|
353
|
-
case "[object RegExp]": {
|
|
354
|
-
const re = obj;
|
|
355
|
-
const copy = new RegExp(re.source, re.flags);
|
|
356
|
-
copy.lastIndex = re.lastIndex;
|
|
357
|
-
return copy;
|
|
358
|
-
}
|
|
359
|
-
case "[object Map]": {
|
|
360
|
-
const m = obj;
|
|
361
|
-
return new Map(m);
|
|
362
|
-
}
|
|
363
|
-
case "[object Set]": {
|
|
364
|
-
const s = obj;
|
|
365
|
-
return new Set(s);
|
|
366
|
-
}
|
|
367
|
-
default:
|
|
368
|
-
return structuredClone(obj);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
__name(cloneBuiltIn, "cloneBuiltIn");
|
|
372
|
-
function shouldIgnoreKey(key, path, ignoreKeys, options) {
|
|
373
|
-
if (ignoreKeys?.has(key)) return true;
|
|
374
|
-
if (options.ignoreKeyPredicate?.(key, path)) return true;
|
|
375
|
-
return false;
|
|
376
|
-
}
|
|
377
|
-
__name(shouldIgnoreKey, "shouldIgnoreKey");
|
|
378
|
-
|
|
379
|
-
// src/utils/array/deep-equal-except.ts
|
|
380
|
-
function deepEqualExcept(a, b, options) {
|
|
381
|
-
const prunedA = deepOmit(a, options);
|
|
382
|
-
const prunedB = deepOmit(b, options);
|
|
383
|
-
return deepEqual(prunedA, prunedB);
|
|
384
|
-
}
|
|
385
|
-
__name(deepEqualExcept, "deepEqualExcept");
|
|
386
|
-
|
|
387
|
-
export { deepEqual, deepEqualExcept, deepOmit };
|
|
388
|
-
//# sourceMappingURL=utils.js.map
|
|
389
|
-
//# sourceMappingURL=utils.js.map
|