@shirudo/ddd-kit 3.0.0-rc.4 → 3.0.0-rc.6

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.
@@ -1 +0,0 @@
1
- {"version":3,"file":"deep-equal-except.js","names":["m","s"],"sources":["../../src/utils/array/is-built-in.ts","../../src/utils/array/deep-equal.ts","../../src/utils/array/deep-omit.ts","../../src/utils/array/deep-equal-except.ts"],"sourcesContent":["/**\n * Set of `Object.prototype.toString.call(x)` tags that the library treats\n * as built-in atomic types. Members of this set are compared/cloned by\n * reference (or with type-specific logic) rather than walked structurally.\n *\n * Detection is tag-based, since `Object.prototype.toString` gives the same\n * answer across realms (an iframe's `Date` has the same tag as the main\n * window's `Date`), and then brand-verified via internal-slot probes,\n * because `Symbol.toStringTag` lets any plain object claim a built-in tag.\n * The previous strategy also checked `globalThis[name] === constructor`\n * and a `proto !== Object.prototype` heuristic; both broke for cross-realm\n * objects and the latter additionally misclassified ordinary user classes\n * as built-ins.\n */\nconst BUILT_IN_TAGS: ReadonlySet<string> = new Set([\n\t\"[object Date]\",\n\t\"[object RegExp]\",\n\t\"[object Map]\",\n\t\"[object Set]\",\n\t\"[object WeakMap]\",\n\t\"[object WeakSet]\",\n\t\"[object Promise]\",\n\t\"[object Error]\",\n\t\"[object Boolean]\",\n\t\"[object Number]\",\n\t\"[object String]\",\n\t\"[object BigInt]\",\n\t\"[object ArrayBuffer]\",\n\t\"[object SharedArrayBuffer]\",\n\t\"[object DataView]\",\n]);\n\n// Intrinsic probes for brand verification. Each one reads an internal slot\n// and throws a TypeError when `this` is not a genuine instance, the only\n// check a plain object cannot spoof via `Symbol.toStringTag`. Captured once\n// so a tampered prototype cannot redirect the probe later.\nfunction intrinsicGetter(\n\tproto: object,\n\tprop: string,\n): (this: unknown) => unknown {\n\tconst get = Object.getOwnPropertyDescriptor(proto, prop)?.get;\n\t// Spec-guaranteed accessors on intrinsic prototypes: unreachable\n\t// unless the environment itself is broken.\n\tif (!get) throw new Error(`missing intrinsic getter for ${prop}`);\n\treturn get;\n}\n\nconst dateGetTime = Date.prototype.getTime;\nconst mapSizeGet = intrinsicGetter(Map.prototype, \"size\");\nconst setSizeGet = intrinsicGetter(Set.prototype, \"size\");\nconst weakMapHas = WeakMap.prototype.has;\nconst weakSetHas = WeakSet.prototype.has;\nconst dataViewByteLengthGet = intrinsicGetter(DataView.prototype, \"byteLength\");\nconst arrayBufferByteLengthGet = intrinsicGetter(\n\tArrayBuffer.prototype,\n\t\"byteLength\",\n);\nconst sharedArrayBufferByteLengthGet =\n\ttypeof SharedArrayBuffer === \"undefined\"\n\t\t? undefined\n\t\t: intrinsicGetter(SharedArrayBuffer.prototype, \"byteLength\");\nconst regExpSourceGet = intrinsicGetter(RegExp.prototype, \"source\");\nconst booleanValueOf = Boolean.prototype.valueOf;\nconst numberValueOf = Number.prototype.valueOf;\nconst stringValueOf = String.prototype.valueOf;\nconst bigIntValueOf = BigInt.prototype.valueOf;\nconst functionToString = Function.prototype.toString;\nconst PROBE_KEY = {};\n\nconst INTRINSIC_CONSTRUCTOR_NAMES = [\n\t\"Object\",\n\t\"Array\",\n\t\"Date\",\n\t\"RegExp\",\n\t\"Map\",\n\t\"Set\",\n\t\"WeakMap\",\n\t\"WeakSet\",\n\t\"Promise\",\n\t\"Error\",\n\t\"EvalError\",\n\t\"RangeError\",\n\t\"ReferenceError\",\n\t\"SyntaxError\",\n\t\"TypeError\",\n\t\"URIError\",\n\t\"AggregateError\",\n\t\"Boolean\",\n\t\"Number\",\n\t\"String\",\n\t\"BigInt\",\n\t\"ArrayBuffer\",\n\t\"SharedArrayBuffer\",\n\t\"DataView\",\n\t\"Int8Array\",\n\t\"Uint8Array\",\n\t\"Uint8ClampedArray\",\n\t\"Int16Array\",\n\t\"Uint16Array\",\n\t\"Int32Array\",\n\t\"Uint32Array\",\n\t\"Float32Array\",\n\t\"Float64Array\",\n\t\"BigInt64Array\",\n\t\"BigUint64Array\",\n] as const;\n\nconst intrinsicConstructorSources: ReadonlyMap<string, string> = new Map(\n\tINTRINSIC_CONSTRUCTOR_NAMES.flatMap((name) => {\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(globalThis, name);\n\t\tconst intrinsic = descriptor?.value;\n\t\treturn typeof intrinsic === \"function\"\n\t\t\t? [[name, functionToString.call(intrinsic)] as const]\n\t\t\t: [];\n\t}),\n);\nconst intrinsicConstructorSourceSet: ReadonlySet<string> = new Set(\n\tintrinsicConstructorSources.values(),\n);\nconst ERROR_INTRINSIC_NAMES = [\n\t\"Error\",\n\t\"EvalError\",\n\t\"RangeError\",\n\t\"ReferenceError\",\n\t\"SyntaxError\",\n\t\"TypeError\",\n\t\"URIError\",\n\t\"AggregateError\",\n] as const;\n\nexport function isIntrinsicConstructorPrototype(\n\tprototype: object,\n\texpectedName?: string,\n): boolean {\n\tconst constructorDescriptor = Object.getOwnPropertyDescriptor(\n\t\tprototype,\n\t\t\"constructor\",\n\t);\n\tconst candidateConstructor = constructorDescriptor?.value;\n\tif (\n\t\tconstructorDescriptor === undefined ||\n\t\t!(\"value\" in constructorDescriptor) ||\n\t\ttypeof candidateConstructor !== \"function\"\n\t) {\n\t\treturn false;\n\t}\n\n\tlet candidateSource: string;\n\ttry {\n\t\tcandidateSource = functionToString.call(candidateConstructor);\n\t} catch {\n\t\treturn false;\n\t}\n\tconst expectedSource =\n\t\texpectedName === undefined\n\t\t\t? undefined\n\t\t\t: intrinsicConstructorSources.get(expectedName);\n\tif (\n\t\t(expectedSource !== undefined && candidateSource !== expectedSource) ||\n\t\t(expectedSource === undefined &&\n\t\t\t!intrinsicConstructorSourceSet.has(candidateSource))\n\t) {\n\t\treturn false;\n\t}\n\n\tconst nameDescriptor = Object.getOwnPropertyDescriptor(\n\t\tcandidateConstructor,\n\t\t\"name\",\n\t);\n\tconst candidateName =\n\t\tnameDescriptor !== undefined &&\n\t\t\"value\" in nameDescriptor &&\n\t\ttypeof nameDescriptor.value === \"string\"\n\t\t\t? nameDescriptor.value\n\t\t\t: undefined;\n\tconst intrinsicName = expectedName ?? candidateName;\n\tconst intrinsicSource =\n\t\tintrinsicName === undefined\n\t\t\t? undefined\n\t\t\t: intrinsicConstructorSources.get(intrinsicName);\n\treturn (\n\t\tcandidateName === intrinsicName &&\n\t\tintrinsicSource !== undefined &&\n\t\tcandidateSource === intrinsicSource &&\n\t\tObject.getOwnPropertyDescriptor(candidateConstructor, \"prototype\")\n\t\t\t?.value === prototype\n\t);\n}\n\n/**\n * Accepts an intrinsic prototype, optionally behind transparent\n * `Symbol.toStringTag` override layers. A user-defined subclass has its own\n * non-native constructor and is therefore rejected before reaching the\n * intrinsic prototype.\n */\nexport function hasIntrinsicPrototypeChain(\n\tvalue: object,\n\texpectedName?: string,\n): boolean {\n\tconst visited = new WeakSet<object>();\n\tlet prototype = Object.getPrototypeOf(value);\n\n\twhile (prototype !== null && !visited.has(prototype)) {\n\t\tvisited.add(prototype);\n\t\tif (Object.hasOwn(prototype, \"constructor\")) {\n\t\t\treturn isIntrinsicConstructorPrototype(prototype, expectedName);\n\t\t}\n\t\tconst ownKeys = Reflect.ownKeys(prototype);\n\t\tif (ownKeys.length !== 1 || ownKeys[0] !== Symbol.toStringTag) {\n\t\t\treturn false;\n\t\t}\n\t\tprototype = Object.getPrototypeOf(prototype);\n\t}\n\n\treturn false;\n}\n\n/**\n * Tags that `deepEqual` compares BY REFERENCE (its unhandled-built-in\n * fallback) and that `deepOmit` must therefore ALIAS rather than clone:\n * a clone would break `deepEqualExcept(x, x)` reflexivity. Single source\n * of truth so the two modules cannot drift: if `deepEqual` ever learns a\n * by-value comparison for one of these, remove it here and add a clone\n * case in `deepOmit`'s `cloneBuiltIn` in the same change.\n */\nexport const REFERENCE_COMPARED_TAGS: ReadonlySet<string> = new Set([\n\t\"[object Error]\",\n\t\"[object ArrayBuffer]\",\n\t\"[object SharedArrayBuffer]\",\n\t\"[object Promise]\",\n\t\"[object WeakMap]\",\n\t\"[object WeakSet]\",\n]);\n\n/**\n * Intrinsic tags of OPAQUE exotics: objects whose internal state no\n * structural walk can observe (boxed Symbols, generator objects,\n * WeakRefs, FinalizationRegistry handles). `deepEqual` compares them by\n * identity and `deepOmit` passes them through by reference; treating\n * them as (empty) plain objects would make ALL such exotics equal to\n * each other. Deliberately a curated INTRINSIC list, not \"every unknown\n * tag\": a user class exposing its own `Symbol.toStringTag` (e.g.\n * \"Money\") keeps structural comparison, and a plain object spoofing one\n * of these intrinsic tags gets the identity semantics of the thing it\n * claims to be.\n */\nconst OPAQUE_EXOTIC_TAGS: ReadonlySet<string> = new Set([\n\t\"[object Symbol]\",\n\t\"[object Generator]\",\n\t\"[object AsyncGenerator]\",\n\t\"[object WeakRef]\",\n\t\"[object FinalizationRegistry]\",\n]);\n\n/** True when `tag` names an opaque intrinsic; see {@link OPAQUE_EXOTIC_TAGS}. */\nexport function isOpaqueExoticTag(tag: string): boolean {\n\treturn OPAQUE_EXOTIC_TAGS.has(tag);\n}\n\nexport function findPropertyDescriptor(\n\tvalue: object,\n\tkey: PropertyKey,\n): PropertyDescriptor | undefined {\n\tconst visited = new WeakSet<object>();\n\tlet current: object | null = value;\n\n\twhile (current !== null && !visited.has(current)) {\n\t\tvisited.add(current);\n\t\tconst descriptor = Object.getOwnPropertyDescriptor(current, key);\n\t\tif (descriptor !== undefined) return descriptor;\n\t\tcurrent = Object.getPrototypeOf(current);\n\t}\n\n\treturn undefined;\n}\n\nexport type MutableBuiltInTag =\n\t| \"[object Date]\"\n\t| \"[object Map]\"\n\t| \"[object Set]\";\n\nexport function builtInTagWithoutInvokingAccessors(\n\tvalue: object,\n): string | undefined {\n\tif (ArrayBuffer.isView(value)) {\n\t\treturn hasBrand(value, \"[object DataView]\")\n\t\t\t? \"[object DataView]\"\n\t\t\t: \"[object TypedArray]\";\n\t}\n\n\tconst descriptor = findPropertyDescriptor(value, Symbol.toStringTag);\n\tif (descriptor !== undefined && !(\"value\" in descriptor)) {\n\t\treturn builtInTagFromBrand(value);\n\t}\n\n\tconst tag = Object.prototype.toString.call(value);\n\tif (BUILT_IN_TAGS.has(tag) && hasBrand(value, tag)) {\n\t\treturn tag;\n\t}\n\treturn descriptor === undefined ? undefined : builtInTagFromBrand(value);\n}\n\nexport function mutableBuiltInTagWithoutInvokingAccessors(\n\tvalue: object,\n): MutableBuiltInTag | undefined {\n\tconst tag = builtInTagWithoutInvokingAccessors(value);\n\treturn tag === \"[object Date]\" ||\n\t\ttag === \"[object Map]\" ||\n\t\ttag === \"[object Set]\"\n\t\t? tag\n\t\t: undefined;\n}\n\nfunction builtInTagFromBrand(value: object): string | undefined {\n\tif (hasBrand(value, \"[object Date]\")) return \"[object Date]\";\n\tif (hasBrand(value, \"[object RegExp]\")) return \"[object RegExp]\";\n\tif (hasBrand(value, \"[object Map]\")) return \"[object Map]\";\n\tif (hasBrand(value, \"[object Set]\")) return \"[object Set]\";\n\tif (hasBrand(value, \"[object WeakMap]\")) return \"[object WeakMap]\";\n\tif (hasBrand(value, \"[object WeakSet]\")) return \"[object WeakSet]\";\n\tif (hasBrand(value, \"[object DataView]\")) return \"[object DataView]\";\n\tif (hasBrand(value, \"[object ArrayBuffer]\")) return \"[object ArrayBuffer]\";\n\tif (hasBrand(value, \"[object SharedArrayBuffer]\")) {\n\t\treturn \"[object SharedArrayBuffer]\";\n\t}\n\tif (hasBrand(value, \"[object Boolean]\")) return \"[object Boolean]\";\n\tif (hasBrand(value, \"[object Number]\")) return \"[object Number]\";\n\tif (hasBrand(value, \"[object String]\")) return \"[object String]\";\n\tif (hasBrand(value, \"[object BigInt]\")) return \"[object BigInt]\";\n\tif (hasNativePrototype(value, \"Promise\")) return \"[object Promise]\";\n\tif (hasNativePrototype(value, \"Error\")) return \"[object Error]\";\n\treturn undefined;\n}\n\nfunction hasNativePrototype(value: object, expectedName: string): boolean {\n\tconst visited = new WeakSet<object>();\n\tlet prototype = Object.getPrototypeOf(value);\n\n\twhile (prototype !== null && !visited.has(prototype)) {\n\t\tvisited.add(prototype);\n\t\tif (isIntrinsicConstructorPrototype(prototype, expectedName)) {\n\t\t\treturn true;\n\t\t}\n\t\tprototype = Object.getPrototypeOf(prototype);\n\t}\n\treturn false;\n}\n\n/**\n * Verifies that `obj` genuinely is the type its tag claims, via an\n * internal-slot probe. Promise and Error have no side-effect-free standard\n * probe, so their visible tags remain conservative; masked instances are\n * identified separately through their native prototype chain.\n */\nfunction hasBrand(obj: object, tag: string): boolean {\n\ttry {\n\t\tswitch (tag) {\n\t\t\tcase \"[object Date]\":\n\t\t\t\tdateGetTime.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object RegExp]\":\n\t\t\t\tregExpSourceGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object Map]\":\n\t\t\t\tmapSizeGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object Set]\":\n\t\t\t\tsetSizeGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object WeakMap]\":\n\t\t\t\tweakMapHas.call(obj, PROBE_KEY);\n\t\t\t\treturn true;\n\t\t\tcase \"[object WeakSet]\":\n\t\t\t\tweakSetHas.call(obj, PROBE_KEY);\n\t\t\t\treturn true;\n\t\t\tcase \"[object DataView]\":\n\t\t\t\tdataViewByteLengthGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object ArrayBuffer]\":\n\t\t\t\tarrayBufferByteLengthGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object SharedArrayBuffer]\":\n\t\t\t\tif (!sharedArrayBufferByteLengthGet) return false;\n\t\t\t\tsharedArrayBufferByteLengthGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object Boolean]\":\n\t\t\t\tbooleanValueOf.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object Number]\":\n\t\t\t\tnumberValueOf.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object String]\":\n\t\t\t\tstringValueOf.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object BigInt]\":\n\t\t\t\tbigIntValueOf.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object Promise]\":\n\t\t\t\treturn hasNativePrototype(obj, \"Promise\");\n\t\t\tcase \"[object Error]\":\n\t\t\t\treturn ERROR_INTRINSIC_NAMES.some((name) =>\n\t\t\t\t\thasNativePrototype(obj, name),\n\t\t\t\t);\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Returns `true` when `obj` is a built-in JavaScript type that should be\n * treated atomically (compared/cloned as a unit, not walked structurally).\n * Cross-realm safe, and brand-verified: a plain object spoofing a built-in\n * tag via `Symbol.toStringTag` returns `false` and is walked structurally\n * like any other plain object instead of crashing type-specific code.\n *\n * @param obj - The object to classify\n * @param tag - The result of `Object.prototype.toString.call(obj)`, passed\n * in so callers that already computed it don't pay twice\n */\nexport function isBuiltInObject(obj: object, tag: string): boolean {\n\t// ArrayBuffer views (DataView + all TypedArrays, present and future)\n\t// carry an unforgeable internal slot, the strongest brand check.\n\tif (ArrayBuffer.isView(obj)) return true;\n\t// A built-in-looking TypedArray tag WITHOUT the view brand is spoofed.\n\tif (tag.endsWith(\"Array]\")) return false;\n\treturn BUILT_IN_TAGS.has(tag) && hasBrand(obj, tag);\n}\n","import { isBuiltInObject, isOpaqueExoticTag } from \"./is-built-in\";\n\nconst objProto = Object.prototype;\nconst objToString = objProto.toString;\nconst objHasOwn = objProto.hasOwnProperty;\n\n/**\n * SameValueZero: `===` plus NaN-equals-NaN (and `+0 === -0`, unlike\n * `Object.is`). The numeric semantics `deepEqual` documents for primitives,\n * applied consistently inside TypedArrays, Dates and Number wrappers.\n */\nfunction sameValueZero(a: unknown, b: unknown): boolean {\n\treturn a === b || (Number.isNaN(a as number) && Number.isNaN(b as number));\n}\n\n/**\n * Performs a deep equality check between two values.\n *\n * This function compares values recursively, handling:\n * - Primitives (with special handling for NaN)\n * - Arrays (nested arrays supported)\n * - Objects (plain objects and class instances)\n * - TypedArrays (Uint8Array, Int32Array, etc.)\n * - DataView\n * - Maps and Sets\n * - Dates and RegExp\n * - Wrapper objects (Boolean, Number, String)\n * - Circular references (detected and handled)\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are deeply equal, `false` otherwise\n *\n * @example\n * ```ts\n * deepEqual([1, 2, 3], [1, 2, 3]); // true\n * deepEqual({ a: 1, b: [2, 3] }, { a: 1, b: [2, 3] }); // true\n * deepEqual(NaN, NaN); // true\n * deepEqual([1, 2], [1, 2, 3]); // false\n * ```\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n\treturn deepEqualInner(a, b, new WeakMap<object, WeakSet<object>>());\n}\n\n/**\n * Visited pair tracker for cycle detection. The cache is a pair-set:\n * for every left-hand object we keep the set of right-hand objects we\n * have already paired it with. Encountering an already-known pair returns\n * the cycle hypothesis (assume equal); a new (a, b') pair with b' ≠ any\n * previously cached b for that a is walked normally. The previous shape\n * (`WeakMap<object, object>`) could only remember one B per A, which\n * could short-circuit unrelated comparisons that happened to revisit the\n * same A with a different B.\n */\ntype VisitedPairs = WeakMap<object, WeakSet<object>>;\n\n/**\n * Internal recursive function for deep equality comparison.\n *\n * @internal\n */\nfunction deepEqualInner(\n\ta: unknown,\n\tb: unknown,\n\tvisited: VisitedPairs,\n): boolean {\n\t// 1. Fast path: reference equality\n\tif (a === b) return true;\n\n\tconst typeA = typeof a;\n\tconst typeB = typeof b;\n\n\t// 2. If one is not an object → primitive / function\n\tif (typeA !== \"object\" || a === null || typeB !== \"object\" || b === null) {\n\t\t// Special case: NaN should be equal\n\t\tif (typeA === \"number\" && typeB === \"number\") {\n\t\t\treturn Number.isNaN(a as number) && Number.isNaN(b as number);\n\t\t}\n\t\t// Everything else is directly unequal with !== (including functions)\n\t\treturn false;\n\t}\n\n\t// From here on: both are non-null objects\n\n\tconst objA = a as object;\n\tconst objB = b as object;\n\n\t// 3. Cycles: already seen this exact (a, b) pair?\n\tlet cachedBs = visited.get(objA);\n\tif (cachedBs?.has(objB)) {\n\t\t// Cycle hypothesis: pretend equal so the walk can terminate. If the\n\t\t// structure is actually unequal elsewhere, a different recursive\n\t\t// branch will surface the mismatch.\n\t\treturn true;\n\t}\n\tif (!cachedBs) {\n\t\tcachedBs = new WeakSet();\n\t\tvisited.set(objA, cachedBs);\n\t}\n\tcachedBs.add(objB);\n\n\t// 4. Handle Typed Arrays / DataView first\n\tif (ArrayBuffer.isView(objA) || ArrayBuffer.isView(objB)) {\n\t\tif (!ArrayBuffer.isView(objA) || !ArrayBuffer.isView(objB)) return false;\n\n\t\tconst tagA = objToString.call(objA);\n\t\tconst tagB = objToString.call(objB);\n\t\tif (tagA !== tagB) return false;\n\n\t\t// DataView: compare byte by byte\n\t\tif (tagA === \"[object DataView]\") {\n\t\t\tconst viewA = objA as DataView;\n\t\t\tconst viewB = objB as DataView;\n\t\t\tif (viewA.byteLength !== viewB.byteLength) return false;\n\n\t\t\tconst len = viewA.byteLength;\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (viewA.getUint8(i) !== viewB.getUint8(i)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\t// Typed Arrays: element by element (length + numeric index access are\n\t\t// part of the TypedArray contract; the indexed read is sound).\n\t\tconst arrA = objA as unknown as Record<number, unknown> & {\n\t\t\tlength: number;\n\t\t};\n\t\tconst arrB = objB as unknown as Record<number, unknown> & {\n\t\t\tlength: number;\n\t\t};\n\n\t\tconst len = arrA.length;\n\t\tif (len !== arrB.length) return false;\n\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tif (!sameValueZero(arrA[i], arrB[i])) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// 5. Arrays: `Array.isArray` is brand-based and immune to\n\t// `Symbol.toStringTag` spoofing (a spoofed tag would otherwise route a\n\t// real array away from element comparison, or a plain object into it).\n\tif (Array.isArray(objA) || Array.isArray(objB)) {\n\t\tif (!Array.isArray(objA) || !Array.isArray(objB)) return false;\n\t\tif (objA.length !== objB.length) return false;\n\n\t\tconst keysA = Reflect.ownKeys(objA).filter((key) => key !== \"length\");\n\t\tconst keysB = Reflect.ownKeys(objB).filter((key) => key !== \"length\");\n\t\tif (keysA.length !== keysB.length) return false;\n\n\t\tconst arrA = objA as unknown as Record<PropertyKey, unknown>;\n\t\tconst arrB = objB as unknown as Record<PropertyKey, unknown>;\n\t\tfor (const key of keysA) {\n\t\t\tif (!objHasOwn.call(objB, key)) return false;\n\t\t\t// Read the element by access (invoking any getter) rather than\n\t\t\t// comparing accessor descriptors by function identity, so an array\n\t\t\t// index defined as a getter is compared by the value it yields,\n\t\t\t// matching how comparePlainObjects treats accessor properties.\n\t\t\t// Sparse holes stay observable through the key-set comparison above:\n\t\t\t// a hole leaves no own key, so two arrays that differ by a hole vs\n\t\t\t// an explicit undefined have different key sets.\n\t\t\tif (!deepEqualInner(arrA[key], arrB[key], visited)) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\t\treturn true;\n\t}\n\n\t// 6. Tag-based type detection (robust across realms), brand-verified:\n\t// a plain object spoofing a built-in tag is compared as a plain object\n\t// instead of crashing type-specific code below.\n\tconst tagA = objToString.call(objA);\n\tconst tagB = objToString.call(objB);\n\tif (tagA !== tagB) return false;\n\n\tconst builtInA = isBuiltInObject(objA, tagA);\n\tconst builtInB = isBuiltInObject(objB, tagB);\n\t// A genuine built-in never equals a spoofed lookalike.\n\tif (builtInA !== builtInB) return false;\n\n\tif (!builtInA) {\n\t\t// Opaque intrinsics (boxed Symbol, generator, WeakRef, ...):\n\t\t// identity is the only honest comparison; symmetric because\n\t\t// tagA === tagB was already enforced above.\n\t\tif (isOpaqueExoticTag(tagA)) return objA === objB;\n\t\treturn comparePlainObjects(objA, objB, visited);\n\t}\n\n\tswitch (tagA) {\n\t\tcase \"[object Map]\": {\n\t\t\tconst mapA = objA as Map<unknown, unknown>;\n\t\t\tconst mapB = objB as Map<unknown, unknown>;\n\n\t\t\tif (mapA.size !== mapB.size) return false;\n\n\t\t\tfor (const [key, valA] of mapA) {\n\t\t\t\t// Map keys according to JS semantics: reference / SameValueZero\n\t\t\t\tif (!mapB.has(key)) return false;\n\t\t\t\tconst valB = mapB.get(key);\n\t\t\t\tif (!deepEqualInner(valA, valB, visited)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Set]\": {\n\t\t\tconst setA = objA as Set<unknown>;\n\t\t\tconst setB = objB as Set<unknown>;\n\n\t\t\tif (setA.size !== setB.size) return false;\n\n\t\t\t// Set elements: same reference (JS semantics)\n\t\t\tfor (const value of setA) {\n\t\t\t\tif (!setB.has(value)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Date]\": {\n\t\t\t// SameValueZero so two invalid Dates (getTime() === NaN) compare\n\t\t\t// equal, matching the primitive NaN semantics.\n\t\t\treturn sameValueZero((objA as Date).getTime(), (objB as Date).getTime());\n\t\t}\n\n\t\tcase \"[object RegExp]\": {\n\t\t\tconst regA = objA as RegExp;\n\t\t\tconst regB = objB as RegExp;\n\t\t\treturn regA.source === regB.source && regA.flags === regB.flags;\n\t\t}\n\n\t\tcase \"[object Boolean]\":\n\t\tcase \"[object Number]\":\n\t\tcase \"[object String]\":\n\t\tcase \"[object BigInt]\": {\n\t\t\t// Wrapper objects (Boolean/Number/String/BigInt); SameValueZero so\n\t\t\t// two NaN Number wrappers compare equal.\n\t\t\treturn sameValueZero(\n\t\t\t\t(objA as { valueOf(): unknown }).valueOf(),\n\t\t\t\t(objB as { valueOf(): unknown }).valueOf(),\n\t\t\t);\n\t\t}\n\n\t\tdefault: {\n\t\t\t// Unhandled but brand-trusted built-ins: compared by reference.\n\t\t\t// Their internal structure is unknown, and this keeps new\n\t\t\t// built-ins from falling through to plain-object comparison.\n\t\t\t// This branch IS the REFERENCE_COMPARED_TAGS contract exported\n\t\t\t// from is-built-in.ts (and consumed by deepOmit's cloneBuiltIn):\n\t\t\t// adding a by-value case above means removing the tag there.\n\t\t\treturn objA === objB;\n\t\t}\n\t}\n}\n\n/**\n * Plain / custom objects: compare own enumerable string keys + own symbol\n * keys and their values. Used both as the final fallback and for objects\n * whose built-in-looking tag failed brand verification.\n */\nfunction comparePlainObjects(\n\tobjA: object,\n\tobjB: object,\n\tvisited: VisitedPairs,\n): boolean {\n\tconst recA = objA as Record<string | symbol, unknown>;\n\tconst recB = objB as Record<string | symbol, unknown>;\n\n\t// Own string keys including non-enumerable ones: symbols are already\n\t// counted through Object.getOwnPropertySymbols (which ignores\n\t// enumerability), so using Object.keys here would let two objects that\n\t// differ only by a non-enumerable string property compare equal.\n\tconst stringKeysA = Object.getOwnPropertyNames(objA);\n\tconst stringKeysB = Object.getOwnPropertyNames(objB);\n\tif (stringKeysA.length !== stringKeysB.length) return false;\n\n\tconst symbolKeysA = Object.getOwnPropertySymbols(objA);\n\tconst symbolKeysB = Object.getOwnPropertySymbols(objB);\n\tif (symbolKeysA.length !== symbolKeysB.length) return false;\n\n\t// Build the B-side symbol set once; the previous impl rebuilt the\n\t// array and ran .includes per key, which was quadratic.\n\tconst symbolKeysBSet = new Set<symbol>(symbolKeysB);\n\n\tfor (const key of stringKeysA) {\n\t\tif (!objHasOwn.call(objB, key)) return false;\n\t}\n\tfor (const key of symbolKeysA) {\n\t\tif (!symbolKeysBSet.has(key)) return false;\n\t}\n\n\tfor (const key of stringKeysA) {\n\t\tif (!deepEqualInner(recA[key], recB[key], visited)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\tfor (const key of symbolKeysA) {\n\t\tif (!deepEqualInner(recA[key], recB[key], visited)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n","import {\n\tisBuiltInObject,\n\tisOpaqueExoticTag,\n\tREFERENCE_COMPARED_TAGS,\n} from \"./is-built-in\";\n\nexport type DeepOmitKey = string | symbol;\nexport type DeepOmitPathSegment = string | number | symbol;\n\nexport interface DeepOmitOptions {\n\t/**\n\t * Keys to ignore everywhere in the object tree.\n\t * Only applies to object properties, not Map/Set/TypedArray contents.\n\t */\n\treadonly ignoreKeys?: readonly DeepOmitKey[];\n\n\t/**\n\t * Fine-grained control: key + path (without current key).\n\t * Example path: [\"user\", \"meta\", 0, \"data\"]\n\t */\n\treadonly ignoreKeyPredicate?: (\n\t\tkey: DeepOmitKey,\n\t\tpath: readonly DeepOmitPathSegment[],\n\t) => boolean;\n}\n\n/**\n * Creates a deep copy of `value` with certain keys removed according to the\n * provided rules.\n *\n * Walks the object tree and skips keys that match `ignoreKeys` /\n * `ignoreKeyPredicate`. Built-in atomic types that `deepEqual` compares by\n * value (Date, RegExp, Map, Set, TypedArrays, DataView) are cloned by type\n * rather than walked, since their internal structure has no key filtering to\n * apply. Types that `deepEqual` compares by reference (Error, ArrayBuffer,\n * SharedArrayBuffer, Promise, WeakMap, WeakSet) are passed through by\n * reference, so `deepEqualExcept(x, x)` stays reflexive. Cycles are\n * preserved: a cycle `a → a` clones to `a' → a'`. Arrays retain sparse\n * holes and all non-ignored own properties, including symbol keys.\n *\n * **Shared references.** Without `ignoreKeyPredicate`, an object reached\n * via several paths dedupes to a single clone. With a predicate, each\n * path gets its own clone, because the predicate may decide differently per\n * path, so memoising the first path's result would be wrong. This is\n * inherently exponential for diamond-shaped sharing (a node reachable\n * via 2^n paths is cloned 2^n times); the walk aborts with a descriptive\n * error after {@link PATH_SENSITIVE_VISIT_BUDGET} node visits instead of\n * hanging the process.\n *\n * **Prototype-pollution safety.** `__proto__` and `constructor` keys\n * encountered as *own* properties of the input (typical of `JSON.parse`\n * output) are copied as inert data properties via `Object.defineProperty`\n * so the clone graph cannot bleed into `Object.prototype`.\n *\n * **Class instances.** When the input is a class instance, the clone is\n * built via `Object.create(proto)` so the prototype is preserved, but the\n * constructor is NOT re-invoked, so class invariants enforced by the\n * constructor are not re-checked. `deepOmit` is therefore best used for\n * comparison/serialisation (`voEqualsExcept`, `deepEqualExcept`), not as\n * a general-purpose clone for behaviour-carrying objects.\n *\n * @param value - The value to create a deep copy from\n * @param options - Options specifying which keys to ignore\n * @returns A deep copy of `value` with specified keys removed\n */\nexport function deepOmit<T>(value: T, options: DeepOmitOptions): T {\n\tconst visited = new WeakMap<object, unknown>();\n\t// Materialise ignoreKeys as a Set once so the inner loop probes O(1).\n\tconst ignoreKeys = options.ignoreKeys\n\t\t? new Set<DeepOmitKey>(options.ignoreKeys)\n\t\t: undefined;\n\t// With a path-sensitive predicate, a clone computed under one path must\n\t// NOT be reused for the same object reached via another path (the\n\t// predicate may decide differently there). The cache then only tracks\n\t// in-progress ancestors (pure cycle detection) instead of memoising\n\t// completed subtrees. Without a predicate, results are path-independent\n\t// and shared references keep deduplicating to one clone. The budget\n\t// bounds the per-path expansion (exponential on diamond sharing).\n\tconst budget = options.ignoreKeyPredicate ? { visits: 0 } : undefined;\n\treturn omitInternal(value, options, ignoreKeys, [], visited, budget) as T;\n}\n\n/**\n * Maximum object-node visits for a single path-sensitive `deepOmit` walk.\n * Per-path cloning expands exponentially on diamond-shaped sharing; past\n * this bound the walk throws instead of hanging the process. One million\n * visits covers any realistically tree-shaped input.\n */\nconst PATH_SENSITIVE_VISIT_BUDGET = 1_000_000;\n\nfunction omitInternal(\n\tvalue: unknown,\n\toptions: DeepOmitOptions,\n\tignoreKeys: ReadonlySet<DeepOmitKey> | undefined,\n\tpath: DeepOmitPathSegment[],\n\tvisited: WeakMap<object, unknown>,\n\tbudget: { visits: number } | undefined,\n): unknown {\n\tif (value === null) return value;\n\tif (typeof value !== \"object\") return value;\n\n\tconst obj = value as object;\n\n\t// Cycles (and, in the path-independent case, shared references): return\n\t// the cached clone. Use `has` (not `cached !== undefined`) so a\n\t// legitimately-undefined cached clone would not be misclassified as\n\t// \"never seen\".\n\tif (visited.has(obj)) {\n\t\treturn visited.get(obj);\n\t}\n\n\tif (budget && ++budget.visits > PATH_SENSITIVE_VISIT_BUDGET) {\n\t\tthrow new Error(\n\t\t\t`deepOmit: exceeded ${PATH_SENSITIVE_VISIT_BUDGET} node visits. ` +\n\t\t\t\t`With ignoreKeyPredicate, objects reached via shared references ` +\n\t\t\t\t`are cloned once per path (the predicate may decide differently ` +\n\t\t\t\t`per path), which expands exponentially on diamond-shaped ` +\n\t\t\t\t`sharing. Restructure the input to a tree, or use ignoreKeys ` +\n\t\t\t\t`for path-independent filtering.`,\n\t\t);\n\t}\n\n\t// Arrays: recursively process every own property so sparse holes, custom\n\t// properties, symbols, and descriptors remain observable to deepEqual.\n\t// `Array.isArray` is brand-based and immune to `Symbol.toStringTag` spoofing.\n\tif (Array.isArray(obj)) {\n\t\tconst arr = obj as unknown[];\n\t\tconst clone: unknown[] = new Array(arr.length);\n\t\tconst lengthDescriptor = Object.getOwnPropertyDescriptor(arr, \"length\");\n\t\tvisited.set(obj, clone);\n\t\tfor (const key of Reflect.ownKeys(arr)) {\n\t\t\tif (key === \"length\") continue;\n\t\t\tconst segment = arrayPathSegment(key);\n\t\t\t// Key filtering never applies to array elements (numeric indices):\n\t\t\t// dropping an element would leave a hole and make structurally\n\t\t\t// different arrays compare equal through deepEqualExcept. It still\n\t\t\t// applies to custom (non-index) own properties on the array.\n\t\t\tif (\n\t\t\t\ttypeof segment !== \"number\" &&\n\t\t\t\tshouldIgnoreKey(key, path, ignoreKeys, options)\n\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst descriptor = Object.getOwnPropertyDescriptor(arr, key);\n\t\t\tif (descriptor === undefined) continue;\n\n\t\t\tpath.push(segment);\n\t\t\tif (\"value\" in descriptor) {\n\t\t\t\tdescriptor.value = omitInternal(\n\t\t\t\t\tdescriptor.value,\n\t\t\t\t\toptions,\n\t\t\t\t\tignoreKeys,\n\t\t\t\t\tpath,\n\t\t\t\t\tvisited,\n\t\t\t\t\tbudget,\n\t\t\t\t);\n\t\t\t}\n\t\t\tObject.defineProperty(clone, key, descriptor);\n\t\t\tpath.pop();\n\t\t}\n\t\tif (lengthDescriptor !== undefined) {\n\t\t\tObject.defineProperty(clone, \"length\", lengthDescriptor);\n\t\t}\n\t\tif (budget) visited.delete(obj);\n\t\treturn clone;\n\t}\n\n\tconst tag = Object.prototype.toString.call(obj);\n\n\t// Built-in atomic types: clone by type rather than walk. The detection\n\t// is brand-verified: a plain object spoofing a built-in tag falls\n\t// through to the plain-object walk below.\n\tif (isBuiltInObject(obj, tag)) {\n\t\tconst builtInClone = cloneBuiltIn(obj, tag);\n\t\tvisited.set(obj, builtInClone);\n\t\treturn builtInClone;\n\t}\n\n\t// Opaque intrinsics (boxed Symbol, generator, WeakRef, ...): pass\n\t// through by reference, mirroring deepEqual's identity comparison; a\n\t// plain \"clone\" would carry none of their internal state and could\n\t// never compare equal to anything, including itself.\n\tif (isOpaqueExoticTag(tag)) {\n\t\tvisited.set(obj, obj);\n\t\treturn obj;\n\t}\n\n\t// Plain / Custom Objects: filter keys, recursively process values.\n\tconst clone = Object.create(Object.getPrototypeOf(obj));\n\tvisited.set(obj, clone);\n\n\t// Own property NAMES, not Object.keys: deepEqual compares plain objects\n\t// via getOwnPropertyNames (including non-enumerables, test-pinned\n\t// there), so dropping non-enumerable keys here would break the\n\t// deepEqualExcept-equals-deepEqual equivalence. getOwnPropertySymbols\n\t// includes non-enumerable symbols the same way.\n\tconst stringKeys = Object.getOwnPropertyNames(obj);\n\tconst symbolKeys = Object.getOwnPropertySymbols(obj);\n\n\tfor (const key of [...stringKeys, ...symbolKeys]) {\n\t\tif (shouldIgnoreKey(key, path, ignoreKeys, options)) continue;\n\t\tpath.push(key);\n\t\tassignOwn(\n\t\t\tclone,\n\t\t\tkey,\n\t\t\tomitInternal(\n\t\t\t\t(obj as Record<PropertyKey, unknown>)[key],\n\t\t\t\toptions,\n\t\t\t\tignoreKeys,\n\t\t\t\tpath,\n\t\t\t\tvisited,\n\t\t\t\tbudget,\n\t\t\t),\n\t\t\t// Preserve the source's enumerability so the clone stays an\n\t\t\t// exact key-set image (JSON.stringify, for-in, spread behave\n\t\t\t// the same on clone and original).\n\t\t\tObject.getOwnPropertyDescriptor(obj, key)?.enumerable ?? true,\n\t\t);\n\t\tpath.pop();\n\t}\n\n\tif (budget) visited.delete(obj);\n\treturn clone;\n}\n\nfunction arrayPathSegment(key: string | symbol): DeepOmitPathSegment {\n\tif (typeof key === \"symbol\") return key;\n\tconst index = Number(key);\n\treturn Number.isInteger(index) &&\n\t\tindex >= 0 &&\n\t\tindex < 4_294_967_295 &&\n\t\tString(index) === key\n\t\t? index\n\t\t: key;\n}\n\n/**\n * Assigns `value` as an OWN data property on `target` without going through\n * any inherited setter; critically, it never invokes the `__proto__` setter\n * even when `key === \"__proto__\"`. Required to defeat prototype-pollution\n * payloads that ship `__proto__` as a parsed-JSON own key.\n */\nfunction assignOwn(\n\ttarget: object,\n\tkey: PropertyKey,\n\tvalue: unknown,\n\tenumerable = true,\n): void {\n\tObject.defineProperty(target, key, {\n\t\tvalue,\n\t\twritable: true,\n\t\tenumerable,\n\t\tconfigurable: true,\n\t});\n}\n\n/**\n * Clones a built-in atomic type by case. Falls back to `structuredClone`\n * for anything not explicitly enumerated (e.g. DataView, TypedArrays,\n * Boolean/Number/String wrappers, all of which `deepEqual` compares by\n * value). Types that `deepEqual` compares BY REFERENCE (the shared\n * {@link REFERENCE_COMPARED_TAGS} set) are passed through by reference\n * instead; cloning them would make `deepEqualExcept(x, x)` false.\n * Promise/WeakMap/WeakSet additionally cannot be cloned at all\n * (`structuredClone` rejects them).\n */\nfunction cloneBuiltIn(obj: object, tag: string): unknown {\n\tif (REFERENCE_COMPARED_TAGS.has(tag)) return obj;\n\tswitch (tag) {\n\t\tcase \"[object Date]\":\n\t\t\treturn new Date((obj as Date).getTime());\n\t\tcase \"[object RegExp]\": {\n\t\t\tconst re = obj as RegExp;\n\t\t\tconst copy = new RegExp(re.source, re.flags);\n\t\t\tcopy.lastIndex = re.lastIndex;\n\t\t\treturn copy;\n\t\t}\n\t\tcase \"[object Map]\": {\n\t\t\tconst m = obj as Map<unknown, unknown>;\n\t\t\treturn new Map(m);\n\t\t}\n\t\tcase \"[object Set]\": {\n\t\t\tconst s = obj as Set<unknown>;\n\t\t\treturn new Set(s);\n\t\t}\n\t\tdefault:\n\t\t\treturn structuredClone(obj);\n\t}\n}\n\nfunction shouldIgnoreKey(\n\tkey: DeepOmitKey,\n\tpath: readonly DeepOmitPathSegment[],\n\tignoreKeys: ReadonlySet<DeepOmitKey> | undefined,\n\toptions: DeepOmitOptions,\n): boolean {\n\tif (ignoreKeys?.has(key)) return true;\n\t// The walk reuses ONE path array via push/pop; hand the predicate a\n\t// snapshot so paths it captures stay valid after the walk. Paid only\n\t// on the (already path-sensitive, budget-guarded) predicate mode.\n\tif (options.ignoreKeyPredicate?.(key, path.slice())) return true;\n\treturn false;\n}\n","import { deepEqual } from \"./deep-equal\";\nimport { type DeepOmitOptions, deepOmit } from \"./deep-omit\";\n\nexport type DeepEqualExceptOptions = DeepOmitOptions;\n\n/**\n * Performs a deep equality comparison between two values after omitting specified keys.\n *\n * This function first removes the specified keys from both values using `deepOmit`,\n * then performs a deep equality check using `deepEqual`.\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @param options - Options specifying which keys to omit before comparison\n * @returns `true` if the values are deeply equal after omitting specified keys, `false` otherwise\n *\n * @example\n * ```ts\n * const obj1 = { id: 1, name: \"Alice\", updatedAt: \"2024-01-01\" };\n * const obj2 = { id: 2, name: \"Alice\", updatedAt: \"2024-01-02\" };\n *\n * deepEqualExcept(obj1, obj2, { ignoreKeys: [\"id\", \"updatedAt\"] }); // true\n * ```\n */\nexport function deepEqualExcept(\n\ta: unknown,\n\tb: unknown,\n\toptions: DeepEqualExceptOptions,\n): boolean {\n\tconst prunedA = deepOmit(a, options);\n\tconst prunedB = deepOmit(b, options);\n\treturn deepEqual(prunedA, prunedB);\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"errors.js","names":[],"sources":["../../src/core/errors.ts"],"sourcesContent":["import { StructuredError } from \"@shirudo/base-error\";\n\n/**\n * **The kit's error identity model (since v3).** Every kit error is a\n * structured error carrying exactly ONE identifier: `code`, a stable\n * SCREAMING_SNAKE string, and `error.name === error.code` by design, so\n * there is no name/code drift and nothing to keep in sync. `category`\n * follows the class hierarchy mechanically (`\"DOMAIN\"`,\n * `\"INFRASTRUCTURE\"`, or `\"WIRING\"` for the crash-loud family) and\n * `retryable` is a plain boolean field.\n *\n * **No base-error adoption required.** Consumers branch with a plain\n * `switch (error.code)`, catch via `instanceof DomainError` /\n * `instanceof InfrastructureError` (exported from this kit), and read\n * `retryable` / `cause` as ordinary properties. base-error's toolbox\n * (`matchError` exhaustive dispatch, `isStructuredError`, the\n * public-error catalog and `toProblem`) works on every kit error as an\n * OPT-IN benefit on top, never as a prerequisite.\n */\n\n/**\n * Options for consumer subclasses of {@link DomainError} and\n * {@link InfrastructureError}: the `code` (which also becomes\n * `error.name`) and the technical `message` are the only obligations;\n * `retryable` defaults to `false` and the category is fixed by the base.\n */\nexport interface KitErrorOptions<TCode extends string> {\n\t/** Stable SCREAMING_SNAKE identifier; also becomes `error.name`. */\n\tcode: TCode;\n\t/** Technical message for logs and debugging, never for clients. */\n\tmessage: string;\n\t/** Optional underlying error preserved in the cause chain. */\n\tcause?: unknown;\n\t/** Whether retrying the failed operation can succeed. Default `false`. */\n\tretryable?: boolean;\n}\n\n/**\n * Abstract base for **domain-invariant violations**. Domain methods\n * (aggregates, entity validation hooks, value-object constructors)\n * throw `DomainError`-derived exceptions when a business rule is\n * violated. Consumers derive their own concrete errors (e.g.\n * `class OrderAlreadyShippedError extends DomainError<\"ORDER_ALREADY_SHIPPED\">`)\n * for `instanceof`-style catching at the App-Service boundary, where\n * they typically map to HTTP 400 / business-rule responses.\n *\n * The library itself ships no business-rule `DomainError` subclass: the\n * kit can't know your invariants. (The domain-state-machine module's\n * transition errors are the structural exception.)\n *\n * The `category` is fixed to `\"DOMAIN\"` and `retryable` defaults to\n * `false`, so a subclass supplies only its `code` and `message`:\n *\n * ```ts\n * class OrderAlreadyShippedError extends DomainError<\"ORDER_ALREADY_SHIPPED\"> {\n * constructor(orderId: string) {\n * super({\n * code: \"ORDER_ALREADY_SHIPPED\",\n * message: `Order ${orderId} has already been shipped`,\n * });\n * }\n * }\n * ```\n */\nexport abstract class DomainError<\n\tTCode extends string = string,\n> extends StructuredError<TCode, \"DOMAIN\"> {\n\tprotected constructor(options: KitErrorOptions<TCode>) {\n\t\tsuper({\n\t\t\tcode: options.code,\n\t\t\tcategory: \"DOMAIN\",\n\t\t\tretryable: options.retryable ?? false,\n\t\t\tmessage: options.message,\n\t\t\tcause: options.cause,\n\t\t});\n\t}\n}\n\n/**\n * Internal base for the kit's crash-loud **WIRING** family: deterministic\n * programming/configuration bugs that must fail the operation loudly and\n * never be absorbed by generic domain or infrastructure handlers. One\n * implementation of the `{ category: \"WIRING\", retryable: false }` shape\n * so the family cannot drift. Exported for the kit's own modules only;\n * not part of the package entries.\n */\nexport abstract class KitWiringError<\n\tTCode extends string,\n> extends StructuredError<TCode, \"WIRING\"> {\n\tprotected constructor(code: TCode, message: string, cause?: unknown) {\n\t\tsuper({ code, category: \"WIRING\", retryable: false, message, cause });\n\t}\n}\n\n/**\n * Abstract base for **infrastructure / persistence failures** that the\n * App-Service can recover from: typically by retrying, by returning\n * HTTP 404 / 409, or by surfacing a \"please try again\" UX. These are\n * not domain-invariant violations (the business rules were not\n * broken); they describe race conditions and missing rows at the\n * storage boundary.\n *\n * The `category` is fixed to `\"INFRASTRUCTURE\"`; `retryable` defaults\n * to `false` (opt in per subclass, see {@link ConcurrencyConflictError}).\n *\n * Library-internal concrete subclasses: {@link AggregateNotFoundError},\n * {@link ConcurrencyConflictError}, {@link DuplicateAggregateError},\n * plus the unit-of-work lifecycle wrappers `CommitError` and\n * `RollbackError` (in `src/app/unit-of-work.ts`).\n */\nexport abstract class InfrastructureError<\n\tTCode extends string = string,\n> extends StructuredError<TCode, \"INFRASTRUCTURE\"> {\n\tprotected constructor(options: KitErrorOptions<TCode>) {\n\t\tsuper({\n\t\t\tcode: options.code,\n\t\t\tcategory: \"INFRASTRUCTURE\",\n\t\t\tretryable: options.retryable ?? false,\n\t\t\tmessage: options.message,\n\t\t\tcause: options.cause,\n\t\t});\n\t}\n}\n\n/**\n * Copy-safe membership check for the kit's domain-error family.\n *\n * `instanceof` is false for an error constructed by another loaded copy of\n * the kit (a separately installed adapter package, a CJS/ESM dual load), so\n * kit boundaries that route by error family fall back to the structural\n * `category` field, the stable cross-copy contract.\n */\nexport function isDomainErrorLike(value: unknown): value is DomainError {\n\treturn (\n\t\tvalue instanceof DomainError ||\n\t\t(value instanceof Error &&\n\t\t\t(value as { readonly category?: unknown }).category === \"DOMAIN\")\n\t);\n}\n\n/**\n * Copy-safe membership check for the kit's infrastructure-error family.\n * Same rationale as {@link isDomainErrorLike}.\n */\nexport function isInfrastructureErrorLike(\n\tvalue: unknown,\n): value is InfrastructureError {\n\treturn (\n\t\tvalue instanceof InfrastructureError ||\n\t\t(value instanceof Error &&\n\t\t\t(value as { readonly category?: unknown }).category === \"INFRASTRUCTURE\")\n\t);\n}\n\n/** Options bag for {@link InMemoryCapacityExceededError}. */\nexport interface InMemoryCapacityExceededErrorOptions {\n\t/** Concrete reference adapter whose configured capacity was exhausted. */\n\treadonly store: string;\n\t/** Bounded collection or logical resource, such as `events` or `sources`. */\n\treadonly resource: string;\n\t/** Configured maximum number of retained records. */\n\treadonly limit: number;\n\t/** Records retained before the rejected operation. */\n\treadonly current: number;\n\t/** New records the rejected operation would have retained. */\n\treadonly attempted: number;\n}\n\n/**\n * A finite-capacity in-memory reference adapter rejected new state before\n * mutation. Existing records remain usable; callers must release explicit\n * lifecycle state, increase the configured limit, or switch to a durable\n * adapter. The error is not retryable without one of those external changes.\n */\nexport class InMemoryCapacityExceededError extends InfrastructureError<\"IN_MEMORY_CAPACITY_EXCEEDED\"> {\n\treadonly store: string;\n\treadonly resource: string;\n\treadonly limit: number;\n\treadonly current: number;\n\treadonly attempted: number;\n\n\tconstructor(options: InMemoryCapacityExceededErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"IN_MEMORY_CAPACITY_EXCEEDED\",\n\t\t\tmessage:\n\t\t\t\t`${options.store} cannot retain ${options.attempted} new ` +\n\t\t\t\t`${options.resource}: configured limit ${options.limit}, ` +\n\t\t\t\t`currently retained ${options.current}`,\n\t\t});\n\t\tthis.store = options.store;\n\t\tthis.resource = options.resource;\n\t\tthis.limit = options.limit;\n\t\tthis.current = options.current;\n\t\tthis.attempted = options.attempted;\n\t}\n}\n\n/**\n * Thrown when event dispatch reaches a type with no own handler registration.\n * This covers `EventSourcedAggregate.apply()` and the exhaustive\n * `projectionFromHandlers` helper: the declared event union and its handler map\n * disagree at runtime, which is a programming / configuration bug rather than\n * a domain or infrastructure failure.\n *\n * Deliberately **not** on `DomainError` or `InfrastructureError`:\n * a generic `catch (e instanceof DomainError)` handler at the App\n * layer must not mask a forgotten handler; this should crash loud and\n * fail the calling Use Case so the bug surfaces in development. The\n * replay through `loadFromHistory` also lets it propagate uncaught instead\n * of wrapping it in `Result.Err`.\n *\n * Use `isBaseError(e)` from `@shirudo/base-error` to detect\n * \"any structured error from the kit or any other BaseError-using\n * library\" at the App boundary.\n */\nexport class MissingHandlerError extends KitWiringError<\"MISSING_HANDLER\"> {\n\tconstructor(\n\t\tpublic readonly eventType: string,\n\t\tcause?: unknown,\n\t) {\n\t\tsuper(\n\t\t\t\"MISSING_HANDLER\",\n\t\t\t`Missing handler for event type: ${eventType}`,\n\t\t\tcause,\n\t\t);\n\t}\n}\n\n/**\n * Thrown by `Projector.project` when an event cannot be projected\n * safely because its cursor is missing or malformed, or its aggregate\n * address is absent. Applying such an event would break idempotency, so\n * the batch fails. Events written by `withCommit` carry the complete\n * cursor automatically; other sources compose a gap-proof committed-event\n * envelope. A well-formed cursor that does not continue the stored chain\n * instead throws {@link ProjectionGapError}.\n *\n * A wiring error, not a `DomainError`: see {@link MissingHandlerError}\n * for the rationale of crashing loud at the App layer.\n */\nexport class UnprojectableEventError extends KitWiringError<\"UNPROJECTABLE_EVENT\"> {\n\tconstructor(\n\t\tpublic readonly projection: string,\n\t\tpublic readonly eventId: string,\n\t\treason: string,\n\t\tcause?: unknown,\n\t) {\n\t\tsuper(\n\t\t\t\"UNPROJECTABLE_EVENT\",\n\t\t\t`Projector(${projection}): event ${eventId} ${reason}`,\n\t\t\tcause,\n\t\t);\n\t}\n}\n\n/**\n * Thrown when a valid projection cursor does not continue the stored\n * per-aggregate chain. This is an infrastructure/delivery failure: an\n * event or commit is missing, commonly because a partition reordered or\n * dead-lettered it. The projector does not apply the later event and the\n * checkpoint stays put until the missing history is replayed or the\n * projection is rebuilt.\n */\nexport class ProjectionGapError extends InfrastructureError<\"PROJECTION_GAP\"> {\n\tconstructor(\n\t\tpublic readonly projection: string,\n\t\tpublic readonly eventId: string,\n\t\tpublic readonly previousPosition: string,\n\t\tpublic readonly receivedPosition: string,\n\t) {\n\t\tsuper({\n\t\t\tcode: \"PROJECTION_GAP\",\n\t\t\tmessage:\n\t\t\t\t`Projector(${projection}): event ${eventId} creates a projection ` +\n\t\t\t\t`gap after ${previousPosition}; received ${receivedPosition}. ` +\n\t\t\t\t\"Replay the missing commit before advancing the checkpoint.\",\n\t\t});\n\t}\n}\n\n/**\n * Thrown when one batch delivers previously unseen positions of the same\n * aggregate in descending order. Unlike {@link ProjectionGapError}, this is\n * direct proof that the feed violated its per-aggregate ordering contract;\n * no missing-history inference is needed. Positions already covered by the\n * checkpoint at batch start and exact receipts repeated inside the batch\n * remain valid redeliveries and do not trip this diagnostic guard.\n */\nexport class ProjectionOrderViolationError extends InfrastructureError<\"PROJECTION_ORDER_VIOLATION\"> {\n\tconstructor(\n\t\tpublic readonly projection: string,\n\t\tpublic readonly eventId: string,\n\t\tpublic readonly previousReceivedPosition: string,\n\t\tpublic readonly receivedPosition: string,\n\t) {\n\t\tsuper({\n\t\t\tcode: \"PROJECTION_ORDER_VIOLATION\",\n\t\t\tmessage:\n\t\t\t\t`Projector(${projection}): event ${eventId} at ${receivedPosition} ` +\n\t\t\t\t`arrived after the later unprocessed position ${previousReceivedPosition} ` +\n\t\t\t\t\"in the same batch. Partition or serialize the feed by aggregate source.\",\n\t\t});\n\t}\n}\n\n/**\n * Thrown when a source maps different event identities to one position, either\n * inside the current batch or at the position stored as the projection's\n * watermark. The checkpoint retains the identity of that one last-applied\n * event, so the durable collision is provable without keeping an unbounded\n * processed-event ledger. Positions behind the watermark remain governed by\n * the source's one-logical-event-per-position contract.\n */\nexport class ProjectionIdentityViolationError extends InfrastructureError<\"PROJECTION_IDENTITY_VIOLATION\"> {\n\tconstructor(\n\t\tpublic readonly projection: string,\n\t\tpublic readonly eventId: string,\n\t\tpublic readonly recordedEventId: string,\n\t\tpublic readonly position: string,\n\t) {\n\t\tsuper({\n\t\t\tcode: \"PROJECTION_IDENTITY_VIOLATION\",\n\t\t\tmessage:\n\t\t\t\t`Projector(${projection}): position ${position} was already associated ` +\n\t\t\t\t`with event ${recordedEventId}, but the source supplied event ${eventId} ` +\n\t\t\t\t\"at the same position. A source must map exactly one logical event to each position.\",\n\t\t});\n\t}\n}\n\n/**\n * Thrown when one logical projection position keeps its event identity but its\n * commit-boundary receipt changes. `commitSize` and\n * `previousEventfulAggregateVersion` are part of the continuity proof, so a\n * source must keep them immutable just like the eventId. Accepting a\n * contradictory redelivery could hide an incomplete commit or predecessor.\n */\nexport class ProjectionReceiptViolationError extends InfrastructureError<\"PROJECTION_RECEIPT_VIOLATION\"> {\n\tconstructor(\n\t\tpublic readonly projection: string,\n\t\tpublic readonly eventId: string,\n\t\tpublic readonly recordedReceipt: string,\n\t\tpublic readonly receivedReceipt: string,\n\t) {\n\t\tsuper({\n\t\t\tcode: \"PROJECTION_RECEIPT_VIOLATION\",\n\t\t\tmessage:\n\t\t\t\t`Projector(${projection}): event ${eventId} changed its commit receipt ` +\n\t\t\t\t`at one logical position from ${recordedReceipt} to ${receivedReceipt}. ` +\n\t\t\t\t\"A source must keep commitSize and previousEventfulAggregateVersion immutable.\",\n\t\t});\n\t}\n}\n\n/** A malformed or non-JSON-safe message at an integration boundary. */\nexport class InvalidIntegrationMessageError extends InfrastructureError<\"INVALID_INTEGRATION_MESSAGE\"> {\n\tconstructor(\n\t\tpublic readonly path: string,\n\t\tpublic readonly reason: string,\n\t\tcause?: unknown,\n\t) {\n\t\tsuper({\n\t\t\tcode: \"INVALID_INTEGRATION_MESSAGE\",\n\t\t\tmessage: `Invalid integration message at ${path}: ${reason}`,\n\t\t\tcause,\n\t\t});\n\t}\n}\n\n/** A malformed or non-JSON-safe command selected for durable delivery. */\nexport class InvalidCommandMessageError extends InfrastructureError<\"INVALID_COMMAND_MESSAGE\"> {\n\tconstructor(\n\t\tpublic readonly path: string,\n\t\tpublic readonly reason: string,\n\t\tcause?: unknown,\n\t) {\n\t\tsuper({\n\t\t\tcode: \"INVALID_COMMAND_MESSAGE\",\n\t\t\tmessage: `Invalid command message at ${path}: ${reason}`,\n\t\t\tcause,\n\t\t});\n\t}\n}\n\n/**\n * Thrown by `Entity` (constructor and `setState`) and by the event\n * metadata helpers (`createDomainEvent`'s `options.metadata`,\n * `mergeMetadata`, `copyMetadata`) when the value carries an own\n * `\"__proto__\"` data key:\n * the shape `JSON.parse` produces for hostile DB rows or request bodies\n * handed to reconstitute factories. Such a key can never be legitimate\n * domain state; accepting it would hand a prototype-pollution payload to\n * every downstream consumer that copies the state through `[[Set]]`\n * (`Object.assign`, for-in assignment loops), and dropping it would be\n * silent data mutation.\n *\n * Deliberately **not** a `DomainError` or `InfrastructureError` (same\n * posture as {@link MissingHandlerError}): untrusted input reaching the\n * domain layer unvalidated is a boundary bug, and a generic\n * business-rule handler must not absorb it. Validate and strip untrusted\n * input at the application edge; model genuinely arbitrary keys with a\n * `Map`, not a plain object.\n */\nexport class HostileStateKeyError extends KitWiringError<\"HOSTILE_STATE_KEY\"> {\n\tconstructor(\n\t\tpublic readonly key: string,\n\t\tsubject: string = \"Entity state\",\n\t) {\n\t\tsuper(\n\t\t\t\"HOSTILE_STATE_KEY\",\n\t\t\t`${subject} carries a hostile own \"${key}\" key, which can never ` +\n\t\t\t\t\"be legitimate domain data. Validate and strip untrusted input \" +\n\t\t\t\t\"at the boundary, or model arbitrary keys with a Map.\",\n\t\t);\n\t}\n}\n\n/**\n * Thrown by `EventSourcedAggregate.loadFromHistory` when the replay target\n * carries unflushed `pendingEvents`. Replaying persisted facts onto that\n * instance would advance the version underneath decisions made against an\n * older state and could later claim history the stream does not carry.\n *\n * Deliberately **not** a `DomainError` or `InfrastructureError` (same\n * posture as {@link MissingHandlerError}): a deterministic programming\n * bug in how the aggregate was constructed before the restore. It\n * propagates as a throw instead of riding the replay methods' `Result`\n * channel, so a generic corrupted-stream handler cannot absorb it.\n * Reconstitution belongs on a bare instance: construct the aggregate\n * without factory-recorded events or prior mutations, then restore.\n *\n * Each throw site carries the safe remedy in its `reason`. Persistence\n * lifecycle state is intentionally not mutable through the aggregate API:\n * commit an actually saved instance through application orchestration, or\n * discard a dirty instance and replay into a fresh one.\n */\nexport class UnreplayableAggregateError extends KitWiringError<\"UNREPLAYABLE_AGGREGATE\"> {\n\tconstructor(\n\t\tpublic readonly aggregateId: string,\n\t\treason: string,\n\t) {\n\t\tsuper(\n\t\t\t\"UNREPLAYABLE_AGGREGATE\",\n\t\t\t`Cannot replay onto aggregate ${aggregateId}: ${reason}. ` +\n\t\t\t\t\"Reconstitute on a fresh instance (no factory-recorded events, \" +\n\t\t\t\t\"no unpersisted mutations).\",\n\t\t);\n\t}\n}\n\n/**\n * Thrown by `EventSourcedAggregate.apply()` when a NEW event carries an\n * `aggregateId` or `aggregateType` naming a different aggregate: a\n * deterministic programming bug at the call site (a hand-built or\n * copied event addressed elsewhere), caught before the event can be\n * recorded and poison the own stream. Events with MISSING address\n * fields do not trip this: `apply()` stamps them from the aggregate,\n * the same guarantee `createEvent` gives. A wiring error, distinct\n * from {@link ForeignEventError} on purpose: a wrong new event is a\n * bug in today's code, a wrong PERSISTED row is corrupted or miswired\n * infrastructure, and handlers for one must not absorb the other.\n */\nexport class MisaddressedEventError extends KitWiringError<\"MISADDRESSED_EVENT\"> {\n\tconstructor(\n\t\tpublic readonly expectedAggregateId: string,\n\t\tpublic readonly expectedAggregateType: string,\n\t\tpublic readonly eventType: string,\n\t\tpublic readonly actualAggregateId?: string,\n\t\tpublic readonly actualAggregateType?: string,\n\t) {\n\t\tsuper(\n\t\t\t\"MISADDRESSED_EVENT\",\n\t\t\t`New event \"${eventType}\" is addressed to ` +\n\t\t\t\t`${actualAggregateType ?? expectedAggregateType} ${actualAggregateId ?? expectedAggregateId} ` +\n\t\t\t\t`but was applied on ${expectedAggregateType} ${expectedAggregateId}: ` +\n\t\t\t\t\"fix the call site (createEvent stamps the right address).\",\n\t\t);\n\t}\n}\n\n/**\n * The structural-integrity rejection for a stored snapshot. A consumer's\n * adapter-owned `SnapshotModel` may throw it from migration or reconstitution\n * when the blob could not have been produced by any version of the model\n * (missing fields, impossible types, truncated data). An\n * `InfrastructureError`, because corrupted persistence is a storage\n * problem, never a business rejection; it is nevertheless RECOVERABLE\n * by design: the repository catches it, discards the derived snapshot, and\n * refolds from the authoritative event stream.\n */\nexport class SnapshotCorruptedError extends InfrastructureError<\"SNAPSHOT_CORRUPTED\"> {\n\tconstructor(message: string, cause?: unknown) {\n\t\tsuper({ code: \"SNAPSHOT_CORRUPTED\", message, cause });\n\t}\n}\n\n/**\n * Thrown when an event reaches the aggregate's recording paths\n * (`apply`, `commit`, `addDomainEvent`) without having been minted by\n * the kit's constructors: `createDomainEvent`,\n * `createDomainEventFromFacts`, `createUncommittedDomainEvent`, or aggregate\n * event helpers\n * deep-freeze the event and defensively copy payload and metadata,\n * and register the result in an internal, unforgeable mint marker.\n * Anything else (a hand-rolled literal, a shallow-frozen copy with\n * mutable nested data) is rejected: a mutable event recorded next to\n * a state change can silently diverge from it afterwards. A wiring\n * error: deterministic bug at the call site, the remedy is minting\n * through the constructors.\n */\nexport class UnmintedEventError extends KitWiringError<\"UNMINTED_EVENT\"> {\n\tconstructor(eventType: string) {\n\t\tsuper(\n\t\t\t\"UNMINTED_EVENT\",\n\t\t\t`Event \"${eventType}\" was not minted by a domain-event constructor ` +\n\t\t\t\t\"or aggregate createEvent(...) helper. Those \" +\n\t\t\t\t\"constructors deep-freeze the event \" +\n\t\t\t\t\"and defensively copy payload and metadata; a mutable event \" +\n\t\t\t\t\"could diverge from the state change it records.\",\n\t\t);\n\t}\n}\n\n/**\n * Thrown by `recordPendingEvents` when the aggregate's pending-event list\n * changes while its events are being stamped: a stamp provider that\n * directly or transitively triggers a new decision on the same aggregate\n * would otherwise have that decision silently discarded when recording\n * replaces the pending list. Recording is atomic: when this guard fires,\n * every decision (including the re-entrant one) remains unrecorded. A\n * wiring error: deterministic bug at the call site, the remedy is keeping\n * stamp providers free of domain decisions.\n */\nexport class ReentrantEventRecordingError extends KitWiringError<\"REENTRANT_EVENT_RECORDING\"> {\n\tconstructor(aggregateId: string) {\n\t\tsuper(\n\t\t\t\"REENTRANT_EVENT_RECORDING\",\n\t\t\t`Pending events of aggregate ${aggregateId} changed while ` +\n\t\t\t\t\"recordPendingEvents was stamping them. A stamp provider must not \" +\n\t\t\t\t\"trigger new decisions on the aggregate being recorded; make every \" +\n\t\t\t\t\"domain decision first, then record.\",\n\t\t);\n\t}\n}\n\n/**\n * Thrown by `recordPendingEvents` when two events in one aggregate's pending\n * batch carry the same `eventId`: a stamp provider that returns one reused\n * stamp (or repeats an explicit id) would otherwise mint two distinct facts\n * sharing one identity, and downstream idempotent consumers keyed on\n * `eventId` silently drop one of them. A wiring error: deterministic bug in\n * the stamp provider, the remedy is one fresh identity per decision.\n */\nexport class DuplicateEventIdError extends KitWiringError<\"DUPLICATE_EVENT_ID\"> {\n\tconstructor(\n\t\taggregateId: string,\n\t\t/** The identity two pending events would have shared. */\n\t\tpublic readonly eventId: string,\n\t) {\n\t\tsuper(\n\t\t\t\"DUPLICATE_EVENT_ID\",\n\t\t\t`Two pending events of aggregate ${aggregateId} carry the same ` +\n\t\t\t\t`eventId \"${eventId}\". Each decision needs its own identity; ` +\n\t\t\t\t\"return a fresh stamp per event from the stamp provider.\",\n\t\t);\n\t}\n}\n\n/**\n * Thrown by persisted-event consumers (including `loadFromHistory` and\n * `Projector`) when an event carries an\n * `aggregateId` or `aggregateType` that names a different aggregate:\n * the persisted row belongs to someone else (a miswired stream read,\n * ids colliding across aggregate types, a corrupted store). An\n * `InfrastructureError`, NOT a `DomainError` (same posture as\n * {@link SnapshotSchemaMismatchError}): a wrong address is data\n * corruption or wiring, never an expected business rejection, so it\n * must not be absorbed by generic domain error handling or presented\n * as a 4xx. It therefore PROPAGATES as a throw through the replay\n * methods' `Result` contract (which reserves `Err` for `DomainError`),\n * after the usual all-or-nothing rollback. History events without the\n * optional address fields pass unchecked (the fields are optional on\n * the event shape); new events are covered by\n * {@link MisaddressedEventError}.\n */\nexport class ForeignEventError extends InfrastructureError<\"FOREIGN_EVENT\"> {\n\tconstructor(\n\t\tpublic readonly expectedAggregateId: string,\n\t\tpublic readonly expectedAggregateType: string,\n\t\tpublic readonly eventType: string,\n\t\tpublic readonly actualAggregateId?: string,\n\t\tpublic readonly actualAggregateType?: string,\n\t) {\n\t\tsuper({\n\t\t\tcode: \"FOREIGN_EVENT\",\n\t\t\tmessage:\n\t\t\t\t`Persisted event \"${eventType}\" belongs to ` +\n\t\t\t\t`${actualAggregateType ?? expectedAggregateType} ${actualAggregateId ?? expectedAggregateId}, ` +\n\t\t\t\t`not to ${expectedAggregateType} ${expectedAggregateId}: ` +\n\t\t\t\t\"the stream row addresses a different aggregate.\",\n\t\t});\n\t}\n}\n\n/** Constructor options for {@link NonProgressingEventStreamPageError}. */\nexport interface NonProgressingEventStreamPageErrorOptions {\n\treadonly aggregateType: string;\n\treadonly aggregateId: string;\n\t/** Exclusive continuation cursor supplied to `EventStore.readStream`. */\n\treadonly fromVersion: number;\n\t/** Pinned inclusive stream version the replay still has to reach. */\n\treadonly targetVersion: number;\n}\n\n/**\n * Thrown by a paged EventStore consumer when `readStream` returns no events\n * even though its continuation cursor has not reached the pinned target.\n * Such a page cannot advance and violates the EventStore port contract; a\n * replay loop that merely continued would spin forever.\n *\n * This is a non-retryable infrastructure error: the persistence adapter\n * deterministically contradicted its port contract, so retrying the same read\n * is not a recovery policy. Run `createEventStoreContractTests` against the\n * adapter and fix its windowing/continuation implementation.\n */\nexport class NonProgressingEventStreamPageError extends InfrastructureError<\"NON_PROGRESSING_EVENT_STREAM_PAGE\"> {\n\treadonly aggregateType: string;\n\treadonly aggregateId: string;\n\treadonly fromVersion: number;\n\treadonly targetVersion: number;\n\n\tconstructor(options: NonProgressingEventStreamPageErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"NON_PROGRESSING_EVENT_STREAM_PAGE\",\n\t\t\tmessage:\n\t\t\t\t`EventStore returned no events for ${options.aggregateType}(${options.aggregateId}) ` +\n\t\t\t\t`after version ${options.fromVersion}, before pinned target version ` +\n\t\t\t\t`${options.targetVersion}. The page cannot advance; run the EventStore ` +\n\t\t\t\t\"contract suite and fix the adapter's continuation window.\",\n\t\t});\n\t\tthis.aggregateType = options.aggregateType;\n\t\tthis.aggregateId = options.aggregateId;\n\t\tthis.fromVersion = options.fromVersion;\n\t\tthis.targetVersion = options.targetVersion;\n\t}\n}\n\n/**\n * Thrown when an event harvested from an aggregate cannot be safely composed\n * into a commit envelope, or when an outbox can prove that accepting a\n * candidate would violate its event identity/source chain. Harvest failures\n * include missing `aggregateId` / `aggregateType` (downstream routing would\n * break), or an\n * eventful persisted aggregate did not advance its version (two commits\n * would receive the same source position). These programming bugs are\n * deterministic and fail identically on every retry.\n *\n * Deliberately **not** an {@link InfrastructureError} (same reasoning as\n * {@link MissingHandlerError}): this is a deterministic programming error,\n * not a transient storage failure. A `catch (e instanceof InfrastructureError)`\n * retry handler, or a retrying `TransactionScope`, must NOT mask it or loop on\n * it forever; it should crash loud so the caller misuse surfaces in\n * development. This is why `withCommit` throws it directly and\n * `UnitOfWork.run` passes it through unchanged instead of wrapping it in\n * `CommitError`.\n */\nexport class EventHarvestError extends KitWiringError<\"EVENT_HARVEST_FAILED\"> {\n\tconstructor(\n\t\tmessage: string,\n\t\t/** The `type` of the offending event, for programmatic routing. */\n\t\tpublic readonly eventType?: string,\n\t) {\n\t\tsuper(\"EVENT_HARVEST_FAILED\", message);\n\t}\n}\n\n/**\n * Shared guard for the loud-rejection contract on own `__proto__` data\n * keys (the shape `JSON.parse` produces for hostile rows, bodies, or\n * envelopes): used by `Entity` state copies and the event metadata\n * helpers. One implementation so the contract cannot drift.\n * Module-internal export; not part of the package entries.\n */\nexport function assertNoHostileOwnProtoKey(\n\tvalue: object,\n\tsubject: string,\n): void {\n\tif (Object.hasOwn(value, \"__proto__\")) {\n\t\tthrow new HostileStateKeyError(\"__proto__\", subject);\n\t}\n}\n\n/** Constructor options for {@link UnregisteredHandlerError}. */\nexport interface UnregisteredHandlerErrorOptions {\n\t/** Which bus rejected the dispatch. */\n\treadonly busKind: \"command\" | \"query\";\n\t/** The message type no handler was registered for. */\n\treadonly messageType: string;\n}\n\n/**\n * Produced by the in-memory `CommandBus` / `QueryBus` when a message is\n * dispatched for a type no handler was registered under: a wiring bug\n * (typo in the type string, missing `register` call at bootstrap), not\n * a domain or infrastructure failure.\n *\n * Carries the `WIRING` category (same crash-loud family as\n * {@link MissingHandlerError}), and since v3 it is THROWN by `execute`\n * and `executeUnsafe` alike, never delivered through the error channel:\n * the channel carries expected failures a registered handler produced,\n * and a generic err-branch must not absorb a mis-wired bus. Catch it\n * only at a boundary that turns bugs into 500s.\n */\nexport class UnregisteredHandlerError extends KitWiringError<\"UNREGISTERED_HANDLER\"> {\n\treadonly busKind: \"command\" | \"query\";\n\treadonly messageType: string;\n\n\tconstructor(options: UnregisteredHandlerErrorOptions) {\n\t\tsuper(\n\t\t\t\"UNREGISTERED_HANDLER\",\n\t\t\t`No handler registered for ${options.busKind} type: ${options.messageType}`,\n\t\t);\n\t\tthis.busKind = options.busKind;\n\t\tthis.messageType = options.messageType;\n\t}\n}\n\n/** Constructor options for {@link DuplicateHandlerRegistrationError}. */\nexport interface DuplicateHandlerRegistrationErrorOptions {\n\t/** Which bus rejected the registration. */\n\treadonly busKind: \"command\" | \"query\";\n\t/** The message type a handler was already registered for. */\n\treadonly messageType: string;\n}\n\n/**\n * Produced by `CommandBus.register` / `QueryBus.register` when a handler\n * is registered for a type that already has one: silent replacement would\n * turn the first handler into dead code with no signal, so the wiring bug\n * surfaces at registration time. Same crash-loud family as\n * {@link UnregisteredHandlerError}; catch it only at a boundary that\n * turns bugs into 500s.\n */\nexport class DuplicateHandlerRegistrationError extends KitWiringError<\"DUPLICATE_HANDLER_REGISTRATION\"> {\n\treadonly busKind: \"command\" | \"query\";\n\treadonly messageType: string;\n\n\tconstructor(options: DuplicateHandlerRegistrationErrorOptions) {\n\t\tsuper(\n\t\t\t\"DUPLICATE_HANDLER_REGISTRATION\",\n\t\t\t`A handler for ${options.busKind} type \"${options.messageType}\" is ` +\n\t\t\t\t\"already registered; the duplicate would silently shadow the \" +\n\t\t\t\t\"first. Register each type exactly once at bootstrap.\",\n\t\t);\n\t\tthis.busKind = options.busKind;\n\t\tthis.messageType = options.messageType;\n\t}\n}\n\n/** Constructor options for {@link ErrorMapperFailedError}. */\nexport interface ErrorMapperFailedErrorOptions {\n\t/** Which bus was mapping the failure. */\n\treadonly busKind: \"command\" | \"query\";\n\t/** The registered handler's ORIGINAL failure (also set as `cause`). */\n\treadonly handlerError: unknown;\n\t/** The mapper failure or invalid-decision diagnostic. */\n\treadonly mapperError: unknown;\n}\n\n/**\n * Produced by the in-memory `CommandBus` / `QueryBus` when the configured\n * `mapExpectedError` policy fails while classifying a registered handler's\n * failure, either by throwing or by returning an invalid decision. A broken\n * mapper is a wiring bug: letting its failure propagate bare would\n * replace the handler's original failure entirely, and the rest of the\n * kit is fastidious about never letting a secondary failure mask the\n * primary one (`RollbackError.rollbackCause`, the neutralized observers).\n *\n * The handler's original failure is preserved as `cause` (so cause-chain\n * walks, retryability checks, and error-type mapping keep working) and\n * the mapper's own failure rides along as {@link mapperCause}.\n *\n * Carries the `WIRING` category (same crash-loud family as\n * {@link MissingHandlerError} and {@link UnregisteredHandlerError}): it is\n * thrown, never delivered through the error channel.\n */\nexport class ErrorMapperFailedError extends KitWiringError<\"ERROR_MAPPER_FAILED\"> {\n\treadonly busKind: \"command\" | \"query\";\n\t/** The mapper failure or invalid-decision diagnostic. */\n\treadonly mapperCause: unknown;\n\n\tconstructor(options: ErrorMapperFailedErrorOptions) {\n\t\tsuper(\n\t\t\t\"ERROR_MAPPER_FAILED\",\n\t\t\t`The ${options.busKind} bus mapExpectedError policy failed while ` +\n\t\t\t\t\"classifying a \" +\n\t\t\t\t\"handler failure. The original handler error is preserved as \" +\n\t\t\t\t\"cause; the mapper's own failure as mapperCause.\",\n\t\t\toptions.handlerError,\n\t\t);\n\t\tthis.busKind = options.busKind;\n\t\tthis.mapperCause = options.mapperError;\n\t}\n}\n\n/**\n * Thrown at the end of a `UnitOfWork.run` when an aggregate that was\n * loaded into the identity map changed but no `update` intent was registered.\n * Without this guard the changed state or pending events would be silently\n * dropped.\n *\n * Deliberately **not** an `InfrastructureError` (same posture as\n * {@link MissingHandlerError}): a programming bug that must crash loud,\n * not be absorbed by a generic infrastructure-error handler. The throw\n * happens inside the transaction, so the unit of work rolls back and\n * leaves no partial state.\n *\n * **Scope of the guard.** A best-effort runtime safety net, not a proof.\n * It sees aggregates that repository adapters register through\n * `tracking.trackLoaded` and detects ordinary state changes through the version\n * captured at load. The pending-event count remains a second guard for an\n * invalid event-only mutation that did not advance the version. A freshly\n * created aggregate that is never passed to `add` is invisible to the kit.\n */\nexport class UnenrolledChangesError extends KitWiringError<\"UNENROLLED_CHANGES\"> {\n\tconstructor(public readonly aggregateId: string) {\n\t\tsuper(\n\t\t\t\"UNENROLLED_CHANGES\",\n\t\t\t`Aggregate ${aggregateId} was loaded and changed in this unit of work, ` +\n\t\t\t\t\"but no update intent was registered. Call repository.update(aggregate) \" +\n\t\t\t\t\"after the final domain decision so state and events flush together.\",\n\t\t);\n\t}\n}\n\n/**\n * Thrown when an aggregate removed within the current unit of work is added,\n * updated, or tracked again in the same operation. Removal is final within an\n * operation; writing afterwards would resurrect the row, which is always a\n * use-case bug.\n *\n * Carries the `WIRING` category (same reasoning as\n * {@link MissingHandlerError}): a programming bug that should crash\n * loud, not be absorbed by a generic infrastructure-error handler.\n */\nexport class AggregateDeletedError extends KitWiringError<\"AGGREGATE_DELETED\"> {\n\tconstructor(public readonly aggregateId: string) {\n\t\tsuper(\n\t\t\t\"AGGREGATE_DELETED\",\n\t\t\t`Aggregate ${aggregateId} was removed in this unit of work and ` +\n\t\t\t\t\"cannot be added, updated, tracked, or removed through another \" +\n\t\t\t\t\"instance again. Removal is final within an operation. A repeated \" +\n\t\t\t\t\"remove of the SAME instance is an accepted no-op; if the \" +\n\t\t\t\t\"aggregate must remain, do not remove it.\",\n\t\t);\n\t}\n}\n\n/**\n * Thrown by `AggregatePersistence.getById()` when an aggregate with the\n * given id does not exist. `InfrastructureError` because the storage\n * boundary, not a business rule, decided the row is absent. Use the\n * nullable variant `findById()` if \"not found\" is a valid outcome.\n *\n * Accepts an optional `cause` so a repository adapter can wrap a lower-level\n * \"row not found\" or driver-level error without\n * losing context. Cause-chain helpers (`getRootCause`,\n * `findInCauseChain`) from `@shirudo/base-error` traverse the chain.\n *\n * Not retryable: retrying won't make the row appear.\n */\nexport interface AggregateNotFoundErrorOptions {\n\treadonly aggregateType: string;\n\treadonly id: string;\n\t/** Optional lower-level error to preserve in the cause chain. */\n\treadonly cause?: unknown;\n}\n\nexport class AggregateNotFoundError extends InfrastructureError<\"AGGREGATE_NOT_FOUND\"> {\n\treadonly aggregateType: string;\n\treadonly id: string;\n\n\tconstructor(options: AggregateNotFoundErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"AGGREGATE_NOT_FOUND\",\n\t\t\tmessage: `Aggregate not found: ${options.aggregateType}(${options.id})`,\n\t\t\tcause: options.cause,\n\t\t});\n\t\tthis.aggregateType = options.aggregateType;\n\t\tthis.id = options.id;\n\t}\n}\n\n/**\n * Thrown by a repository's `add()` flush when a row with the\n * aggregate's id already exists (unique-constraint violation): two\n * concurrent creators raced on the same business-derived id, or the\n * id generator collided. Same delegation model as\n * {@link ConcurrencyConflictError}: the kit ships the class, the\n * consumer repository maps its driver's unique-violation signal to it\n * instead of letting a raw driver error escape -\n *\n * - Postgres: SQLSTATE `23505` (`unique_violation`)\n * - MySQL/MariaDB: errno `1062` (`ER_DUP_ENTRY`)\n * - SQLite: `SQLITE_CONSTRAINT_UNIQUE` (extended code 2067)\n *\n * `InfrastructureError` because the storage boundary detects the\n * collision. NOT retryable: re-running the same INSERT cannot succeed.\n * The right reactions are domain decisions - map to HTTP 409, or for\n * idempotency-key flows load the existing aggregate and treat the\n * request as already-applied.\n */\nexport interface DuplicateAggregateErrorOptions {\n\treadonly aggregateType: string;\n\treadonly aggregateId: string;\n\t/** Optional driver-level error to preserve in the cause chain. */\n\treadonly cause?: unknown;\n}\n\nexport class DuplicateAggregateError extends InfrastructureError<\"DUPLICATE_AGGREGATE\"> {\n\treadonly aggregateType: string;\n\treadonly aggregateId: string;\n\n\tconstructor(options: DuplicateAggregateErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"DUPLICATE_AGGREGATE\",\n\t\t\tmessage: `Duplicate aggregate: ${options.aggregateType}(${options.aggregateId}) already exists`,\n\t\t\tcause: options.cause,\n\t\t});\n\t\tthis.aggregateType = options.aggregateType;\n\t\tthis.aggregateId = options.aggregateId;\n\t}\n}\n\n/**\n * Thrown by `reconstituteAggregateFromSnapshot` when the stored snapshot\n * carries a different schema version than its adapter-owned `SnapshotModel`\n * and the model declares no `migrate` function. Without the check, a snapshot\n * written against an older DTO shape would surface as an undefined-field crash on\n * the first method call after a much later restore.\n *\n * `InfrastructureError` because the storage boundary served outdated\n * data; the schema evolving past stored snapshots is an expected\n * lifecycle event, not a programming bug. NOT retryable: the recovery\n * is a code path, not a repeat. Add `migrate` to the snapshot model (upgrade\n * old DTOs in place), or catch this error in the repository, discard the\n * snapshot, and refold from the full event stream / reload from the source of\n * truth.\n */\nexport interface SnapshotSchemaMismatchErrorOptions {\n\treadonly aggregateType: string;\n\treadonly aggregateId: string;\n\treadonly expectedSchemaVersion: number;\n\treadonly actualSchemaVersion: number;\n}\n\nexport class SnapshotSchemaMismatchError extends InfrastructureError<\"SNAPSHOT_SCHEMA_MISMATCH\"> {\n\treadonly aggregateType: string;\n\treadonly aggregateId: string;\n\treadonly expectedSchemaVersion: number;\n\treadonly actualSchemaVersion: number;\n\n\tconstructor(options: SnapshotSchemaMismatchErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"SNAPSHOT_SCHEMA_MISMATCH\",\n\t\t\tmessage:\n\t\t\t\t`Snapshot schema mismatch on ${options.aggregateType}(${options.aggregateId}): ` +\n\t\t\t\t`the snapshot model expects schema ${options.expectedSchemaVersion}, ` +\n\t\t\t\t`the stored snapshot carries ${options.actualSchemaVersion}. Override ` +\n\t\t\t\t`the model's migrate function to upgrade old snapshots, or discard the snapshot ` +\n\t\t\t\t`and refold from the full event stream.`,\n\t\t});\n\t\tthis.aggregateType = options.aggregateType;\n\t\tthis.aggregateId = options.aggregateId;\n\t\tthis.expectedSchemaVersion = options.expectedSchemaVersion;\n\t\tthis.actualSchemaVersion = options.actualSchemaVersion;\n\t}\n}\n\n/**\n * Surfaced by a Unit-of-Work flush when the aggregate's expected version does\n * not match the version currently persisted: i.e. another writer\n * updated the aggregate concurrently. The canonical optimistic-\n * concurrency signal; the App-Service typically reloads, re-applies\n * the use case, and retries, or surfaces HTTP 409 to the caller.\n *\n * **Retry means a FRESH unit of work** (a new `UnitOfWork.run()` /\n * `withCommit` invocation): reload, re-apply, and register `update` again. Do NOT catch this\n * inside the same `run()` callback and continue: the failed aggregate\n * is already enrolled (its events would be committed for a write that\n * never happened) and the identity map still serves the same stale\n * instance to any in-place \"reload\".\n *\n * `InfrastructureError` because the persistence layer (not a domain\n * rule) detects the race. Marks itself as `retryable: true` so the\n * `isRetryable` predicate from `@shirudo/base-error` picks it up.\n */\nexport interface ConcurrencyConflictErrorOptions {\n\treadonly aggregateType: string;\n\treadonly aggregateId: string;\n\treadonly expectedVersion: number;\n\treadonly actualVersion: number;\n\t/** Optional driver-level error to preserve in the cause chain. */\n\treadonly cause?: unknown;\n}\n\nexport class ConcurrencyConflictError extends InfrastructureError<\"CONCURRENCY_CONFLICT\"> {\n\treadonly aggregateType: string;\n\treadonly aggregateId: string;\n\treadonly expectedVersion: number;\n\treadonly actualVersion: number;\n\n\tconstructor(options: ConcurrencyConflictErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"CONCURRENCY_CONFLICT\",\n\t\t\tmessage: `Concurrency conflict on ${options.aggregateType}(${options.aggregateId}): expected version ${options.expectedVersion}, actual ${options.actualVersion}`,\n\t\t\tcause: options.cause,\n\t\t\t// The canonical OCC pattern: reload the aggregate, re-apply the\n\t\t\t// use case, retry in a FRESH unit of work. The structured field\n\t\t\t// is what the retry classifier (someChainRetryable) reads.\n\t\t\tretryable: true,\n\t\t});\n\t\tthis.aggregateType = options.aggregateType;\n\t\tthis.aggregateId = options.aggregateId;\n\t\tthis.expectedVersion = options.expectedVersion;\n\t\tthis.actualVersion = options.actualVersion;\n\t}\n}\n\n/**\n * Options bag for {@link IdempotencyKeyReuseError}.\n */\nexport interface IdempotencyKeyReuseErrorOptions {\n\treadonly key: string;\n\treadonly storedFingerprint: string;\n\treadonly receivedFingerprint: string;\n\t/** Optional driver-level error to preserve in the cause chain. */\n\treadonly cause?: unknown;\n}\n\n/**\n * Thrown by `IdempotencyStore.claim()` when the same idempotency key\n * arrives with a DIFFERENT command fingerprint than the one it was\n * first claimed with: the caller is reusing a key for a different\n * command. Replaying the stored outcome would answer a question that\n * was never asked; rejecting is the only safe reaction.\n *\n * `InfrastructureError` because the store detects the collision, same\n * delegation model as {@link DuplicateAggregateError}. NOT retryable:\n * re-sending the same mismatched pair cannot succeed. Map it to an\n * unprocessable/conflict application outcome.\n */\nexport class IdempotencyKeyReuseError extends InfrastructureError<\"IDEMPOTENCY_KEY_REUSE\"> {\n\treadonly key: string;\n\treadonly storedFingerprint: string;\n\treadonly receivedFingerprint: string;\n\n\tconstructor(options: IdempotencyKeyReuseErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"IDEMPOTENCY_KEY_REUSE\",\n\t\t\tmessage:\n\t\t\t\t`Idempotency key reuse on \"${options.key}\": stored fingerprint ` +\n\t\t\t\t`${options.storedFingerprint}, received ${options.receivedFingerprint}`,\n\t\t\tcause: options.cause,\n\t\t});\n\t\tthis.key = options.key;\n\t\tthis.storedFingerprint = options.storedFingerprint;\n\t\tthis.receivedFingerprint = options.receivedFingerprint;\n\t}\n}\n\n/** Options bag for {@link IdempotencyClaimLostError}. */\nexport interface IdempotencyClaimLostErrorOptions {\n\treadonly key: string;\n\treadonly token: string;\n\t/** Optional driver-level error to preserve in the cause chain. */\n\treadonly cause?: unknown;\n}\n\n/**\n * Thrown when a leased idempotency owner tries to renew, complete, or\n * reconcile through a claim token that no longer owns the key. The usual\n * cause is lease expiry followed by a successful takeover. The stale\n * execution must abort before its transaction commits; retrying starts from\n * a fresh claim or replays the winner.\n */\nexport class IdempotencyClaimLostError extends InfrastructureError<\"IDEMPOTENCY_CLAIM_LOST\"> {\n\treadonly key: string;\n\treadonly token: string;\n\n\tconstructor(options: IdempotencyClaimLostErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"IDEMPOTENCY_CLAIM_LOST\",\n\t\t\tmessage:\n\t\t\t\t`Idempotency claim for key \"${options.key}\" no longer belongs to ` +\n\t\t\t\t`token \"${options.token}\"`,\n\t\t\tcause: options.cause,\n\t\t\tretryable: true,\n\t\t});\n\t\tthis.key = options.key;\n\t\tthis.token = options.token;\n\t}\n}\n\n/**\n * Options bag for {@link IdempotencyInFlightError}.\n */\nexport interface IdempotencyInFlightErrorOptions {\n\treadonly key: string;\n\t/** Optional driver-level error to preserve in the cause chain. */\n\treadonly cause?: unknown;\n}\n\n/**\n * Thrown by `IdempotencyStore.claim()` when the key is already claimed\n * by an execution that has not completed yet: the first delivery of the\n * command is still running (or crashed mid-flight on a\n * non-transactional store). Retryable by design: a later retry either\n * finds the completed outcome and replays it, or finds the claim\n * released (rolled back) and executes fresh. `RetryingTransactionScope`\n * picks this up through the `retryable` flag without extra wiring.\n */\nexport class IdempotencyInFlightError extends InfrastructureError<\"IDEMPOTENCY_IN_FLIGHT\"> {\n\treadonly key: string;\n\n\tconstructor(options: IdempotencyInFlightErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"IDEMPOTENCY_IN_FLIGHT\",\n\t\t\tmessage:\n\t\t\t\t`Idempotency key \"${options.key}\" is claimed by an execution ` +\n\t\t\t\t`that has not completed yet`,\n\t\t\tcause: options.cause,\n\t\t\tretryable: true,\n\t\t});\n\t\tthis.key = options.key;\n\t}\n}\n\n/** Options bag for {@link IdempotencyReconciliationRequiredError}. */\nexport interface IdempotencyReconciliationRequiredErrorOptions {\n\treadonly key: string;\n\treadonly fingerprint: string;\n\treadonly token: string;\n\treadonly expiredAt: string;\n}\n\n/**\n * An expired staged outcome cannot be replayed or discarded until the\n * application checks the authoritative write model. Immediate retry without\n * that evidence cannot make progress, so this error is deliberately not\n * marked retryable.\n */\nexport class IdempotencyReconciliationRequiredError extends InfrastructureError<\"IDEMPOTENCY_RECONCILIATION_REQUIRED\"> {\n\treadonly key: string;\n\treadonly fingerprint: string;\n\treadonly token: string;\n\treadonly expiredAt: string;\n\n\tconstructor(options: IdempotencyReconciliationRequiredErrorOptions) {\n\t\tsuper({\n\t\t\tcode: \"IDEMPOTENCY_RECONCILIATION_REQUIRED\",\n\t\t\tmessage:\n\t\t\t\t`Idempotency key \"${options.key}\" has an expired staged outcome; ` +\n\t\t\t\t\"consult the authoritative write model before confirming or releasing it\",\n\t\t});\n\t\tthis.key = options.key;\n\t\tthis.fingerprint = options.fingerprint;\n\t\tthis.token = options.token;\n\t\tthis.expiredAt = options.expiredAt;\n\t}\n}\n\n/**\n * Thrown by `IdempotencyStore.complete()` when no pending claim exists\n * for the key: `complete` ran without a preceding successful `claim`\n * in the same execution, or against a key whose claim was already\n * completed or abandoned. Always a wiring bug in hand-rolled\n * orchestration (`withIdempotentCommit` cannot produce it), hence the\n * crash-loud category.\n */\nexport class IdempotencyCompletionWithoutClaimError extends KitWiringError<\"IDEMPOTENCY_COMPLETED_WITHOUT_CLAIM\"> {\n\tconstructor(public readonly key: string) {\n\t\tsuper(\n\t\t\t\"IDEMPOTENCY_COMPLETED_WITHOUT_CLAIM\",\n\t\t\t`IdempotencyStore.complete() called for key \"${key}\" without a ` +\n\t\t\t\t\"pending claim; call claim() first (or use withIdempotentCommit)\",\n\t\t);\n\t}\n}\n\n/**\n * The closed union of every error code the kit itself can produce\n * (consumer subclasses of {@link DomainError} / {@link InfrastructureError}\n * add their own on top). Useful for building `switch` tables or\n * base-error `matchError` cases that cover kit and consumer codes\n * together, without importing anything from base-error.\n */\nexport type KitErrorCode =\n\t| \"AGGREGATE_DELETED\"\n\t| \"AGGREGATE_NOT_FOUND\"\n\t| \"AGGREGATE_TRACKING\"\n\t| \"COMMIT_FAILED\"\n\t| \"CONCURRENCY_CONFLICT\"\n\t| \"DOMAIN_TRANSITION_GUARD_REJECTED\"\n\t| \"DUPLICATE_AGGREGATE\"\n\t| \"DUPLICATE_EVENT_ID\"\n\t| \"DUPLICATE_HANDLER_REGISTRATION\"\n\t| \"ERROR_MAPPER_FAILED\"\n\t| \"EVENT_ADDRESS_INVALID\"\n\t| \"EVENT_HARVEST_FAILED\"\n\t| \"EVENT_ID_INVALID\"\n\t| \"EVENT_ID_REQUIRED\"\n\t| \"EVENT_OCCURRED_AT_INVALID\"\n\t| \"EVENT_OCCURRED_AT_REQUIRED\"\n\t| \"EVENT_SCHEMA_VERSION_INVALID\"\n\t| \"EVENT_TYPE_INVALID\"\n\t| \"FOREIGN_EVENT\"\n\t| \"HOSTILE_STATE_KEY\"\n\t| \"IDEMPOTENCY_CLAIM_LOST\"\n\t| \"IDEMPOTENCY_COMPLETED_WITHOUT_CLAIM\"\n\t| \"IDEMPOTENCY_IN_FLIGHT\"\n\t| \"IDEMPOTENCY_KEY_REUSE\"\n\t| \"IDEMPOTENCY_RECONCILIATION_REQUIRED\"\n\t| \"IN_MEMORY_CAPACITY_EXCEEDED\"\n\t| \"INVALID_DOMAIN_MACHINE_CONTEXT\"\n\t| \"INVALID_DOMAIN_MACHINE_DEFINITION\"\n\t| \"INVALID_DOMAIN_MACHINE_INPUT\"\n\t| \"INVALID_DOMAIN_MACHINE_SNAPSHOT\"\n\t| \"INVALID_DOMAIN_TRANSITION\"\n\t| \"INVALID_DOMAIN_TRANSITION_GUARD_RESULT\"\n\t| \"INVALID_DOMAIN_TRANSITION_RESULT\"\n\t| \"INVALID_COMMAND_MESSAGE\"\n\t| \"INVALID_INTEGRATION_MESSAGE\"\n\t| \"INVALID_MONEY\"\n\t| \"INVALID_REPOSITORY_ADAPTER\"\n\t| \"INVALID_REPOSITORY_DEFINITION\"\n\t| \"MISADDRESSED_EVENT\"\n\t| \"MISSING_HANDLER\"\n\t| \"MONEY_CURRENCY_MISMATCH\"\n\t| \"MONEY_PRECISION_LOSS\"\n\t| \"MONEY_SCALE_MISMATCH\"\n\t| \"NESTED_UNIT_OF_WORK\"\n\t| \"NON_PROGRESSING_EVENT_STREAM_PAGE\"\n\t| \"PROJECTION_GAP\"\n\t| \"PROJECTION_IDENTITY_VIOLATION\"\n\t| \"PROJECTION_ORDER_VIOLATION\"\n\t| \"PROJECTION_RECEIPT_VIOLATION\"\n\t| \"REENTRANT_DOMAIN_STATE_MACHINE_EVALUATION\"\n\t| \"REENTRANT_EVENT_RECORDING\"\n\t| \"REPOSITORY_ERROR_MAPPING_FAILED\"\n\t| \"ROLLBACK_FAILED\"\n\t| \"SNAPSHOT_CORRUPTED\"\n\t| \"SNAPSHOT_SCHEMA_MISMATCH\"\n\t| \"SNAPSHOT_TIME_INVALID\"\n\t| \"TRANSACTION_CLOSED\"\n\t| \"UNENROLLED_CHANGES\"\n\t| \"UNKNOWN_CURRENCY\"\n\t| \"UNMINTED_EVENT\"\n\t| \"UNPROJECTABLE_EVENT\"\n\t| \"UNREGISTERED_HANDLER\"\n\t| \"UNREPLAYABLE_AGGREGATE\";\n"],"mappings":"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"}
@@ -1,110 +0,0 @@
1
- //#region src/utils/array/deep-equal.d.ts
2
- /**
3
- * Performs a deep equality check between two values.
4
- *
5
- * This function compares values recursively, handling:
6
- * - Primitives (with special handling for NaN)
7
- * - Arrays (nested arrays supported)
8
- * - Objects (plain objects and class instances)
9
- * - TypedArrays (Uint8Array, Int32Array, etc.)
10
- * - DataView
11
- * - Maps and Sets
12
- * - Dates and RegExp
13
- * - Wrapper objects (Boolean, Number, String)
14
- * - Circular references (detected and handled)
15
- *
16
- * @param a - The first value to compare
17
- * @param b - The second value to compare
18
- * @returns `true` if the values are deeply equal, `false` otherwise
19
- *
20
- * @example
21
- * ```ts
22
- * deepEqual([1, 2, 3], [1, 2, 3]); // true
23
- * deepEqual({ a: 1, b: [2, 3] }, { a: 1, b: [2, 3] }); // true
24
- * deepEqual(NaN, NaN); // true
25
- * deepEqual([1, 2], [1, 2, 3]); // false
26
- * ```
27
- */
28
- declare function deepEqual(a: unknown, b: unknown): boolean;
29
- //#endregion
30
- //#region src/utils/array/deep-omit.d.ts
31
- type DeepOmitKey = string | symbol;
32
- type DeepOmitPathSegment = string | number | symbol;
33
- interface DeepOmitOptions {
34
- /**
35
- * Keys to ignore everywhere in the object tree.
36
- * Only applies to object properties, not Map/Set/TypedArray contents.
37
- */
38
- readonly ignoreKeys?: readonly DeepOmitKey[];
39
- /**
40
- * Fine-grained control: key + path (without current key).
41
- * Example path: ["user", "meta", 0, "data"]
42
- */
43
- readonly ignoreKeyPredicate?: (key: DeepOmitKey, path: readonly DeepOmitPathSegment[]) => boolean;
44
- }
45
- /**
46
- * Creates a deep copy of `value` with certain keys removed according to the
47
- * provided rules.
48
- *
49
- * Walks the object tree and skips keys that match `ignoreKeys` /
50
- * `ignoreKeyPredicate`. Built-in atomic types that `deepEqual` compares by
51
- * value (Date, RegExp, Map, Set, TypedArrays, DataView) are cloned by type
52
- * rather than walked, since their internal structure has no key filtering to
53
- * apply. Types that `deepEqual` compares by reference (Error, ArrayBuffer,
54
- * SharedArrayBuffer, Promise, WeakMap, WeakSet) are passed through by
55
- * reference, so `deepEqualExcept(x, x)` stays reflexive. Cycles are
56
- * preserved: a cycle `a → a` clones to `a' → a'`. Arrays retain sparse
57
- * holes and all non-ignored own properties, including symbol keys.
58
- *
59
- * **Shared references.** Without `ignoreKeyPredicate`, an object reached
60
- * via several paths dedupes to a single clone. With a predicate, each
61
- * path gets its own clone, because the predicate may decide differently per
62
- * path, so memoising the first path's result would be wrong. This is
63
- * inherently exponential for diamond-shaped sharing (a node reachable
64
- * via 2^n paths is cloned 2^n times); the walk aborts with a descriptive
65
- * error after {@link PATH_SENSITIVE_VISIT_BUDGET} node visits instead of
66
- * hanging the process.
67
- *
68
- * **Prototype-pollution safety.** `__proto__` and `constructor` keys
69
- * encountered as *own* properties of the input (typical of `JSON.parse`
70
- * output) are copied as inert data properties via `Object.defineProperty`
71
- * so the clone graph cannot bleed into `Object.prototype`.
72
- *
73
- * **Class instances.** When the input is a class instance, the clone is
74
- * built via `Object.create(proto)` so the prototype is preserved, but the
75
- * constructor is NOT re-invoked, so class invariants enforced by the
76
- * constructor are not re-checked. `deepOmit` is therefore best used for
77
- * comparison/serialisation (`voEqualsExcept`, `deepEqualExcept`), not as
78
- * a general-purpose clone for behaviour-carrying objects.
79
- *
80
- * @param value - The value to create a deep copy from
81
- * @param options - Options specifying which keys to ignore
82
- * @returns A deep copy of `value` with specified keys removed
83
- */
84
- declare function deepOmit<T>(value: T, options: DeepOmitOptions): T;
85
- //#endregion
86
- //#region src/utils/array/deep-equal-except.d.ts
87
- type DeepEqualExceptOptions = DeepOmitOptions;
88
- /**
89
- * Performs a deep equality comparison between two values after omitting specified keys.
90
- *
91
- * This function first removes the specified keys from both values using `deepOmit`,
92
- * then performs a deep equality check using `deepEqual`.
93
- *
94
- * @param a - The first value to compare
95
- * @param b - The second value to compare
96
- * @param options - Options specifying which keys to omit before comparison
97
- * @returns `true` if the values are deeply equal after omitting specified keys, `false` otherwise
98
- *
99
- * @example
100
- * ```ts
101
- * const obj1 = { id: 1, name: "Alice", updatedAt: "2024-01-01" };
102
- * const obj2 = { id: 2, name: "Alice", updatedAt: "2024-01-02" };
103
- *
104
- * deepEqualExcept(obj1, obj2, { ignoreKeys: ["id", "updatedAt"] }); // true
105
- * ```
106
- */
107
- declare function deepEqualExcept(a: unknown, b: unknown, options: DeepEqualExceptOptions): boolean;
108
- //#endregion
109
- export { DeepOmitPathSegment as a, DeepOmitOptions as i, deepEqualExcept as n, deepOmit as o, DeepOmitKey as r, deepEqual as s, DeepEqualExceptOptions as t };
110
- //# sourceMappingURL=utils.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"presentation.js","names":[],"sources":["../src/presentation/kit-public-errors.ts","../src/presentation/public-error-view.ts"],"sourcesContent":["import type { PublicIssue } from \"@shirudo/base-error\";\nimport {\n\tdefinePublicErrors,\n\tLocalizedMessageSet,\n} from \"@shirudo/base-error/public-error\";\n\n/** Details shape carried by the validation views this catalog projects. */\nexport interface PublicErrorViewDetails {\n\t/** Whitelisted field issues, present only for a validation error. */\n\treadonly issues: readonly PublicIssue[];\n}\n\n/** Single-locale message set for the kit's built-in English texts. */\nfunction english(message: string): LocalizedMessageSet {\n\treturn new LocalizedMessageSet({\n\t\tbaseLocale: \"en\",\n\t\tmessages: { en: message },\n\t});\n}\n\n/**\n * Duck-types the base-error validation family by capability, not\n * `instanceof` (duplicate installs), and not by a name whitelist (custom\n * codes): a SCREAMING_SNAKE `name` (base-error names a `ValidationError`\n * after its code), `category === \"VALIDATION\"` (kit and\n * convention-following consumer errors carry DOMAIN / INFRASTRUCTURE /\n * WIRING, so a structured infrastructure error exposing a\n * `publicIssues()` method is NOT mistaken for one), and a `publicIssues()`\n * that actually returns an array. Reads and the probe call may throw on\n * hostile inputs; `project` contains a throwing matcher as a miss, which\n * keeps the projection total.\n */\nfunction isValidationErrorLike(\n\terror: unknown,\n): error is { publicIssues(): unknown[] } {\n\tif (typeof error !== \"object\" || error === null) return false;\n\tconst { name, category, publicIssues } = error as {\n\t\tname?: unknown;\n\t\tcategory?: unknown;\n\t\tpublicIssues?: unknown;\n\t};\n\treturn (\n\t\ttypeof name === \"string\" &&\n\t\t/^[A-Z][A-Z0-9_]*$/.test(name) &&\n\t\tcategory === \"VALIDATION\" &&\n\t\ttypeof publicIssues === \"function\" &&\n\t\tArray.isArray((error as { publicIssues(): unknown }).publicIssues())\n\t);\n}\n\n/**\n * Re-emits a `publicIssues()` result through the {@link PublicIssue}\n * whitelist so only the documented wire fields (`message`, `path`, `code`,\n * `pointer`) can reach a client: a duck-typed implementation must not be\n * able to smuggle arbitrary payloads into the view. Drops entries without\n * a string `message`.\n */\nfunction sanitizePublicIssues(result: unknown[]): readonly PublicIssue[] {\n\tconst issues: PublicIssue[] = [];\n\tfor (const entry of result) {\n\t\tif (typeof entry !== \"object\" || entry === null) continue;\n\t\tconst { message, path, code, pointer } = entry as Record<string, unknown>;\n\t\tif (typeof message !== \"string\") continue;\n\t\tconst issue: PublicIssue = { message };\n\t\tconst safePath = sanitizeIssuePath(path);\n\t\tif (safePath !== undefined) issue.path = safePath;\n\t\tif (typeof code === \"string\") issue.code = code;\n\t\tif (typeof pointer === \"string\") issue.pointer = pointer;\n\t\tissues.push(issue);\n\t}\n\treturn issues;\n}\n\n/** Keeps only the documented path segments: property keys or `{ key }`. */\nfunction sanitizeIssuePath(path: unknown): PublicIssue[\"path\"] | undefined {\n\tif (!Array.isArray(path)) return undefined;\n\tconst segments: Array<PropertyKey | { readonly key: PropertyKey }> = [];\n\tfor (const segment of path) {\n\t\tif (\n\t\t\ttypeof segment === \"string\" ||\n\t\t\ttypeof segment === \"number\" ||\n\t\t\ttypeof segment === \"symbol\"\n\t\t) {\n\t\t\tsegments.push(segment);\n\t\t\tcontinue;\n\t\t}\n\t\tif (typeof segment === \"object\" && segment !== null) {\n\t\t\tconst { key } = segment as { key?: unknown };\n\t\t\tif (\n\t\t\t\ttypeof key === \"string\" ||\n\t\t\t\ttypeof key === \"number\" ||\n\t\t\t\ttypeof key === \"symbol\"\n\t\t\t) {\n\t\t\t\tsegments.push({ key });\n\t\t\t}\n\t\t}\n\t}\n\treturn segments;\n}\n\n/**\n * Builds the kit's public-error catalog: one descriptor per public code\n * the kit itself can emit, ready for base-error's `project` / `localize`\n * / `toProblem` pipeline, and the single source of truth behind\n * `toPublicErrorView`. Messages are client-safe and carry no occurrence\n * data (no id, version, or technical detail).\n *\n * A FACTORY, deliberately not a shared instance: base-error's\n * `registerByCode` / `register` widen the TYPE but register into the\n * same underlying catalog, so a shared export would let one consumer's\n * extension leak into every other (and a second registration of the\n * same code throws). Each caller builds its own catalog at its\n * composition root and extends that:\n *\n * ```ts\n * import { createKitPublicErrors } from \"@shirudo/ddd-kit/presentation\";\n *\n * const catalog = createKitPublicErrors().registerByCode(\n * \"ORDER_ALREADY_SHIPPED\",\n * {\n * publicCode: \"ORDER_ALREADY_SHIPPED\",\n * status: 409,\n * userMessages: new LocalizedMessageSet({\n * baseLocale: \"en\",\n * messages: { en: \"This order has already been shipped.\" },\n * }),\n * },\n * );\n * ```\n *\n * Kit errors resolve by their stable `code` (since v3,\n * `error.name === error.code`); the base-error validation family resolves\n * by capability (see the matcher), with its whitelisted issues projected\n * under `details.issues`. Everything else degrades to the\n * `INTERNAL_ERROR` fallback.\n */\nexport function createKitPublicErrors() {\n\treturn definePublicErrors({\n\t\tfallback: {\n\t\t\tpublicCode: \"INTERNAL_ERROR\",\n\t\t\tstatus: 500,\n\t\t\tuserMessages: english(\"An unexpected error occurred.\"),\n\t\t},\n\t})\n\t\t.registerByCode(\"AGGREGATE_NOT_FOUND\", {\n\t\t\tpublicCode: \"AGGREGATE_NOT_FOUND\",\n\t\t\tstatus: 404,\n\t\t\tuserMessages: english(\"The requested resource could not be found.\"),\n\t\t})\n\t\t.registerByCode(\"CONCURRENCY_CONFLICT\", {\n\t\t\tpublicCode: \"CONCURRENCY_CONFLICT\",\n\t\t\tstatus: 409,\n\t\t\tretryable: true,\n\t\t\tuserMessages: english(\n\t\t\t\t\"The resource was modified by another request. Please reload and try again.\",\n\t\t\t),\n\t\t})\n\t\t.registerByCode(\"DUPLICATE_AGGREGATE\", {\n\t\t\tpublicCode: \"DUPLICATE_AGGREGATE\",\n\t\t\tstatus: 409,\n\t\t\tuserMessages: english(\"The resource already exists.\"),\n\t\t})\n\t\t.registerByCode(\"INVALID_MONEY\", {\n\t\t\tpublicCode: \"INVALID_MONEY\",\n\t\t\tstatus: 422,\n\t\t\tuserMessages: english(\n\t\t\t\t\"The submitted amount is not a valid monetary value.\",\n\t\t\t),\n\t\t})\n\t\t.registerByCode(\"MONEY_CURRENCY_MISMATCH\", {\n\t\t\tpublicCode: \"MONEY_CURRENCY_MISMATCH\",\n\t\t\tstatus: 422,\n\t\t\tuserMessages: english(\"The amounts involved use different currencies.\"),\n\t\t})\n\t\t.registerByCode(\"MONEY_SCALE_MISMATCH\", {\n\t\t\tpublicCode: \"MONEY_SCALE_MISMATCH\",\n\t\t\tstatus: 422,\n\t\t\tuserMessages: english(\n\t\t\t\t\"The amounts involved use different decimal precisions.\",\n\t\t\t),\n\t\t})\n\t\t.registerByCode(\"MONEY_PRECISION_LOSS\", {\n\t\t\tpublicCode: \"MONEY_PRECISION_LOSS\",\n\t\t\tstatus: 422,\n\t\t\tuserMessages: english(\n\t\t\t\t\"The submitted amount has more decimal places than the currency allows.\",\n\t\t\t),\n\t\t})\n\t\t.registerByCode(\"UNKNOWN_CURRENCY\", {\n\t\t\tpublicCode: \"UNKNOWN_CURRENCY\",\n\t\t\tstatus: 422,\n\t\t\tuserMessages: english(\"The currency is not supported.\"),\n\t\t})\n\t\t.register({\n\t\t\tmatch: isValidationErrorLike,\n\t\t\tdescriptor: {\n\t\t\t\tpublicCode: \"VALIDATION_FAILED\",\n\t\t\t\tstatus: 422,\n\t\t\t\tuserMessages: english(\"The submitted data is invalid.\"),\n\t\t\t\tprojectDetails: (error): PublicErrorViewDetails => ({\n\t\t\t\t\tissues: sanitizePublicIssues(error.publicIssues()),\n\t\t\t\t}),\n\t\t\t},\n\t\t});\n}\n","import {\n\tlocalize,\n\ttype LocalizedPublicError,\n\tproject,\n\ttype PublicError,\n\ttype PublicErrorCatalog,\n} from \"@shirudo/base-error/public-error\";\nimport {\n\tcreateKitPublicErrors,\n\ttype PublicErrorViewDetails,\n} from \"./kit-public-errors\";\n\nexport type { PublicErrorViewDetails } from \"./kit-public-errors\";\n\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// Private default instance: never exported and never handed out, so no\n// consumer can register into it (extensions go through options.catalog\n// on a consumer-built createKitPublicErrors() instance).\nconst defaultCatalog = createKitPublicErrors();\n\n/** Options for {@link toPublicErrorView}. */\nexport interface PublicErrorViewOptions {\n\t/**\n\t * PREFERRED BCP 47 locale tag. Resolution follows base-error's\n\t * `localize` (RFC 4647 lookup with base-locale fallback), and the view\n\t * carries the locale that actually RESOLVED, never a claimed one: with\n\t * the kit's built-in English messages a `\"de-DE\"` preference still\n\t * yields `locale: \"en\"` unless the catalog carries German. Default\n\t * `\"en\"`.\n\t */\n\tlocale?: string;\n\t/**\n\t * The public-error catalog to resolve against. Defaults to a private\n\t * {@link createKitPublicErrors} instance; pass your own extended\n\t * catalog (`createKitPublicErrors().registerByCode(...)`) so your own\n\t * codes and locales resolve through the same pipeline.\n\t */\n\tcatalog?: PublicErrorCatalog<string>;\n}\n\n/**\n * Maps a kit error (or any caught value) to a base-error\n * {@link LocalizedPublicError} by delegating to the public-error pipeline:\n * `project` against a catalog (default {@link createKitPublicErrors}), then\n * `localize` with the catalog's messages. A **transport-neutral**,\n * client-safe representation (`code`, `message`, `locale`, optional\n * `details`); feed it into base-error's `toProblem` (HTTP / RFC 9457), a\n * gRPC status mapper, or a CLI exit-code table, whichever boundary you\n * are at.\n *\n * Total over `unknown`: an unmatched or hostile value (throwing\n * accessors, a throwing or lying `publicIssues()`) degrades to the\n * catalog's fallback view rather than leaking the technical message or\n * crashing the 500 path. Kit errors resolve by their stable `code`\n * (`error.name === error.code`, minification- and duplicate-install-\n * stable); the base-error validation family resolves by capability with\n * its whitelisted issues sanitized under `details.issues` (see the\n * catalog). No base-error adoption is required to consume the view: it\n * is a plain object read with plain property access.\n *\n * @example\n * ```ts\n * import { toPublicErrorView } from \"@shirudo/ddd-kit/presentation\";\n * import { toProblem } from \"@shirudo/base-error/public-error\";\n *\n * const { body, status } = toProblem(\n * { status: 500 }, // or the catalog, for per-code type/status\n * toPublicErrorView(error),\n * );\n * return Response.json(body, { status });\n * ```\n */\nexport function toPublicErrorView(\n\terror: unknown,\n\toptions: PublicErrorViewOptions = {},\n): LocalizedPublicError<PublicErrorViewDetails> {\n\tconst locale = options.locale ?? DEFAULT_LOCALE;\n\tconst catalog = options.catalog ?? defaultCatalog;\n\t// The catch is the totality guarantee's last line: `project` is total\n\t// by contract, but a hostile catalog or message set handed in via\n\t// options must still degrade to the fallback view, never crash the\n\t// 500 path.\n\ttry {\n\t\tconst view = project(catalog, error) as PublicError<\n\t\t\tPublicErrorViewDetails,\n\t\t\tstring\n\t\t>;\n\t\tconst messages = catalog.messagesFor(view.code);\n\t\tif (messages !== undefined) {\n\t\t\treturn localize(view, messages, { locales: [locale] });\n\t\t}\n\t\t// A consumer descriptor without userMessages: keep the view, attach\n\t\t// the generic fallback text so the type stays LocalizedPublicError.\n\t\treturn { ...view, message: FALLBACK_MESSAGE, locale: DEFAULT_LOCALE };\n\t} catch {\n\t\treturn {\n\t\t\tcode: FALLBACK_CODE,\n\t\t\tmessage: FALLBACK_MESSAGE,\n\t\t\tlocale: DEFAULT_LOCALE,\n\t\t};\n\t}\n}\n"],"mappings":"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"}
package/dist/utils.d.ts DELETED
@@ -1,2 +0,0 @@
1
- import { a as DeepOmitPathSegment, i as DeepOmitOptions, n as deepEqualExcept, o as deepOmit, r as DeepOmitKey, s as deepEqual, t as DeepEqualExceptOptions } from "./chunks/utils.js";
2
- export { type DeepEqualExceptOptions, type DeepOmitKey, type DeepOmitOptions, type DeepOmitPathSegment, deepEqual, deepEqualExcept, deepOmit };
package/dist/utils.js DELETED
@@ -1,3 +0,0 @@
1
- import { n as deepOmit, r as deepEqual, t as deepEqualExcept } from "./chunks/deep-equal-except.js";
2
-
3
- export { deepEqual, deepEqualExcept, deepOmit };