@shirudo/ddd-kit 2.2.0 → 3.0.0-rc.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +204 -55
- package/dist/chunks/deep-equal-except.js +639 -0
- package/dist/chunks/deep-equal-except.js.map +1 -0
- package/dist/chunks/errors.d.ts +785 -0
- package/dist/chunks/errors.js +822 -0
- package/dist/chunks/errors.js.map +1 -0
- package/dist/chunks/ports.js +891 -0
- package/dist/chunks/ports.js.map +1 -0
- package/dist/chunks/snapshot-store.d.ts +2808 -0
- package/dist/chunks/utils.d.ts +110 -0
- package/dist/http.d.ts +64 -51
- package/dist/http.js +54 -20
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +2341 -2640
- package/dist/index.js +6073 -3915
- package/dist/index.js.map +1 -1
- package/dist/money.d.ts +376 -0
- package/dist/money.js +578 -0
- package/dist/money.js.map +1 -0
- package/dist/presentation.d.ts +86 -37
- package/dist/presentation.js +208 -39
- package/dist/presentation.js.map +1 -1
- package/dist/testing.d.ts +517 -335
- package/dist/testing.js +2396 -1184
- package/dist/testing.js.map +1 -1
- package/dist/utils.d.ts +2 -106
- package/dist/utils.js +2 -530
- package/package.json +35 -18
- package/dist/aggregate-DFi6HlEh.d.ts +0 -771
- package/dist/utils.js.map +0 -1
|
@@ -0,0 +1,110 @@
|
|
|
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
|
package/dist/http.d.ts
CHANGED
|
@@ -1,69 +1,82 @@
|
|
|
1
|
-
import { ValidationError } from
|
|
2
|
-
import {
|
|
1
|
+
import { PublicIssue, ValidationError } from "@shirudo/base-error";
|
|
2
|
+
import { ProblemDetailsResult, ToProblemContext } from "@shirudo/base-error/public-error";
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
//#region src/http/problem-details.d.ts
|
|
5
|
+
/** Details member carried by a {@link toProblemDetails} body. */
|
|
6
|
+
interface ValidationProblemDetails {
|
|
7
|
+
/** The whitelisted field issues, straight from `publicIssues()`. */
|
|
8
|
+
readonly issues: readonly PublicIssue[];
|
|
9
|
+
}
|
|
6
10
|
/**
|
|
7
|
-
* Options for {@link toProblemDetails}: the
|
|
8
|
-
*
|
|
9
|
-
* and {@link extensions} for extra public members merged alongside them.
|
|
11
|
+
* Options for {@link toProblemDetails}: the transport members the boundary
|
|
12
|
+
* may set, plus {@link extensions} for extra public body members.
|
|
10
13
|
*/
|
|
11
|
-
interface ValidationProblemOptions {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
* by contract (RFC 9457 bodies must serialize); a trace id, for example,
|
|
31
|
-
* is passed here, not as a recognized top-level field.
|
|
32
|
-
*/
|
|
33
|
-
extensions?: ProblemDetailsExtensions;
|
|
14
|
+
interface ValidationProblemOptions<TExtensions extends object = Record<never, never>> {
|
|
15
|
+
/** URI reference identifying the problem type. Defaults to `"about:blank"`. */
|
|
16
|
+
type?: string;
|
|
17
|
+
/** Short, human-readable summary. Default `"Validation Failed"`. */
|
|
18
|
+
title?: string;
|
|
19
|
+
/** HTTP status code. Default `422`. */
|
|
20
|
+
status?: number;
|
|
21
|
+
/** Human-readable explanation specific to this occurrence. */
|
|
22
|
+
detail?: string;
|
|
23
|
+
/** URI reference identifying this specific occurrence. */
|
|
24
|
+
instance?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Extra public extension members merged alongside the documented body
|
|
27
|
+
* members. Constrained by base-error's `toProblem` contract: JSON-safe,
|
|
28
|
+
* string-keyed, and free of the reserved member names, checked at
|
|
29
|
+
* compile time and re-validated at runtime (a colliding or
|
|
30
|
+
* non-JSON-safe set is dropped and recorded in `outcome.omitted`).
|
|
31
|
+
*/
|
|
32
|
+
extensions?: ToProblemContext<TExtensions>["extensions"];
|
|
34
33
|
}
|
|
35
34
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* issues
|
|
35
|
+
* The kit-named result of {@link toProblemDetails}: base-error's
|
|
36
|
+
* `ProblemDetailsResult` specialized to the validation shortcut. Exists so
|
|
37
|
+
* consumers can annotate boundaries from the kit entry alone; importing
|
|
38
|
+
* base-error stays an opt-in, never a prerequisite.
|
|
39
|
+
*/
|
|
40
|
+
type ValidationProblemResult<TExtensions extends object = Record<never, never>> = ProblemDetailsResult<ValidationProblemDetails, string, TExtensions>;
|
|
41
|
+
/**
|
|
42
|
+
* Projects a base-error {@link ValidationError} to an RFC 9457 Problem
|
|
43
|
+
* Details result by delegating to base-error's `toProblem` transport stage:
|
|
44
|
+
* one pipeline, one wire profile, one hardening implementation. The body
|
|
45
|
+
* carries the error's public `code`, and the whitelisted issues ride under
|
|
46
|
+
* `details.issues` (`{ message, path, code?, pointer? }`, never raw
|
|
47
|
+
* validator extras), the same shape `toPublicErrorView` uses.
|
|
48
48
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
49
|
+
* All of `toProblem`'s wire-safety guarantees apply: the body is deeply
|
|
50
|
+
* frozen with a null prototype (cannot carry or receive prototype
|
|
51
|
+
* pollution), every member is JSON-safe (a non-serializable value drops
|
|
52
|
+
* that member and records it in `result.outcome.omitted` instead of
|
|
53
|
+
* corrupting the wire), and extensions cannot collide with the reserved
|
|
54
|
+
* members. The result also carries the HTTP `status` and ready-made
|
|
55
|
+
* `headers`, so the boundary does not restate them.
|
|
52
56
|
*
|
|
53
57
|
* This is a presentation/transport concern and ships from the opt-in
|
|
54
58
|
* `@shirudo/ddd-kit/http` entry point: the core kit stays transport-free.
|
|
59
|
+
* For catalog-driven mapping across ALL your public errors use
|
|
60
|
+
* base-error's `definePublicErrors` + `project` + `toProblem` directly;
|
|
61
|
+
* this helper is the narrow validation shortcut.
|
|
55
62
|
*
|
|
56
63
|
* @example
|
|
57
64
|
* ```ts
|
|
58
65
|
* import { toProblemDetails } from "@shirudo/ddd-kit/http";
|
|
59
66
|
*
|
|
60
67
|
* if (result.isErr()) {
|
|
61
|
-
*
|
|
68
|
+
* const problem = toProblemDetails(result.error);
|
|
69
|
+
* return Response.json(problem.body, {
|
|
70
|
+
* status: problem.status,
|
|
71
|
+
* headers: problem.headers,
|
|
72
|
+
* });
|
|
62
73
|
* }
|
|
63
|
-
* // → { type: "about:blank", title: "Validation Failed", status: 422,
|
|
64
|
-
* //
|
|
74
|
+
* // body → { type: "about:blank", title: "Validation Failed", status: 422,
|
|
75
|
+
* // code: "VALIDATION_FAILED",
|
|
76
|
+
* // details: { issues: [{ message: "must be a valid email", ... }] } }
|
|
65
77
|
* ```
|
|
66
78
|
*/
|
|
67
|
-
declare function toProblemDetails(error: ValidationError, options?: ValidationProblemOptions):
|
|
68
|
-
|
|
69
|
-
export { type
|
|
79
|
+
declare function toProblemDetails<TExtensions extends object = Record<never, never>>(error: ValidationError, options?: ValidationProblemOptions<TExtensions>): ValidationProblemResult<TExtensions>;
|
|
80
|
+
//#endregion
|
|
81
|
+
export { type ValidationProblemDetails, type ValidationProblemOptions, type ValidationProblemResult, toProblemDetails };
|
|
82
|
+
//# sourceMappingURL=http.d.ts.map
|
package/dist/http.js
CHANGED
|
@@ -1,26 +1,60 @@
|
|
|
1
|
-
|
|
2
|
-
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
1
|
+
import { toProblem } from "@shirudo/base-error/public-error";
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
//#region src/http/problem-details.ts
|
|
4
|
+
/**
|
|
5
|
+
* Projects a base-error {@link ValidationError} to an RFC 9457 Problem
|
|
6
|
+
* Details result by delegating to base-error's `toProblem` transport stage:
|
|
7
|
+
* one pipeline, one wire profile, one hardening implementation. The body
|
|
8
|
+
* carries the error's public `code`, and the whitelisted issues ride under
|
|
9
|
+
* `details.issues` (`{ message, path, code?, pointer? }`, never raw
|
|
10
|
+
* validator extras), the same shape `toPublicErrorView` uses.
|
|
11
|
+
*
|
|
12
|
+
* All of `toProblem`'s wire-safety guarantees apply: the body is deeply
|
|
13
|
+
* frozen with a null prototype (cannot carry or receive prototype
|
|
14
|
+
* pollution), every member is JSON-safe (a non-serializable value drops
|
|
15
|
+
* that member and records it in `result.outcome.omitted` instead of
|
|
16
|
+
* corrupting the wire), and extensions cannot collide with the reserved
|
|
17
|
+
* members. The result also carries the HTTP `status` and ready-made
|
|
18
|
+
* `headers`, so the boundary does not restate them.
|
|
19
|
+
*
|
|
20
|
+
* This is a presentation/transport concern and ships from the opt-in
|
|
21
|
+
* `@shirudo/ddd-kit/http` entry point: the core kit stays transport-free.
|
|
22
|
+
* For catalog-driven mapping across ALL your public errors use
|
|
23
|
+
* base-error's `definePublicErrors` + `project` + `toProblem` directly;
|
|
24
|
+
* this helper is the narrow validation shortcut.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { toProblemDetails } from "@shirudo/ddd-kit/http";
|
|
29
|
+
*
|
|
30
|
+
* if (result.isErr()) {
|
|
31
|
+
* const problem = toProblemDetails(result.error);
|
|
32
|
+
* return Response.json(problem.body, {
|
|
33
|
+
* status: problem.status,
|
|
34
|
+
* headers: problem.headers,
|
|
35
|
+
* });
|
|
36
|
+
* }
|
|
37
|
+
* // body → { type: "about:blank", title: "Validation Failed", status: 422,
|
|
38
|
+
* // code: "VALIDATION_FAILED",
|
|
39
|
+
* // details: { issues: [{ message: "must be a valid email", ... }] } }
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
5
42
|
function toProblemDetails(error, options = {}) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
problem[member] = error.publicIssues();
|
|
20
|
-
return problem;
|
|
43
|
+
const { type = "about:blank", title = "Validation Failed", status = 422, detail, instance, extensions } = options;
|
|
44
|
+
return toProblem({
|
|
45
|
+
status,
|
|
46
|
+
type,
|
|
47
|
+
title
|
|
48
|
+
}, {
|
|
49
|
+
code: error.code,
|
|
50
|
+
details: { issues: error.publicIssues() }
|
|
51
|
+
}, {
|
|
52
|
+
detail,
|
|
53
|
+
instance,
|
|
54
|
+
extensions
|
|
55
|
+
});
|
|
21
56
|
}
|
|
22
|
-
__name(toProblemDetails, "toProblemDetails");
|
|
23
57
|
|
|
58
|
+
//#endregion
|
|
24
59
|
export { toProblemDetails };
|
|
25
|
-
//# sourceMappingURL=http.js.map
|
|
26
60
|
//# sourceMappingURL=http.js.map
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"http.js","names":[],"sources":["../src/http/problem-details.ts"],"sourcesContent":["import type { PublicIssue, ValidationError } from \"@shirudo/base-error\";\nimport {\n\ttype ProblemDetailsResult,\n\ttype ToProblemContext,\n\ttoProblem,\n} from \"@shirudo/base-error/public-error\";\n\n/** Details member carried by a {@link toProblemDetails} body. */\nexport interface ValidationProblemDetails {\n\t/** The whitelisted field issues, straight from `publicIssues()`. */\n\treadonly issues: readonly PublicIssue[];\n}\n\n/**\n * Options for {@link toProblemDetails}: the transport members the boundary\n * may set, plus {@link extensions} for extra public body members.\n */\nexport interface ValidationProblemOptions<\n\tTExtensions extends object = Record<never, never>,\n> {\n\t/** URI reference identifying the problem type. Defaults to `\"about:blank\"`. */\n\ttype?: string;\n\t/** Short, human-readable summary. Default `\"Validation Failed\"`. */\n\ttitle?: string;\n\t/** HTTP status code. Default `422`. */\n\tstatus?: number;\n\t/** Human-readable explanation specific to this occurrence. */\n\tdetail?: string;\n\t/** URI reference identifying this specific occurrence. */\n\tinstance?: string;\n\t/**\n\t * Extra public extension members merged alongside the documented body\n\t * members. Constrained by base-error's `toProblem` contract: JSON-safe,\n\t * string-keyed, and free of the reserved member names, checked at\n\t * compile time and re-validated at runtime (a colliding or\n\t * non-JSON-safe set is dropped and recorded in `outcome.omitted`).\n\t */\n\textensions?: ToProblemContext<TExtensions>[\"extensions\"];\n}\n\n/**\n * The kit-named result of {@link toProblemDetails}: base-error's\n * `ProblemDetailsResult` specialized to the validation shortcut. Exists so\n * consumers can annotate boundaries from the kit entry alone; importing\n * base-error stays an opt-in, never a prerequisite.\n */\nexport type ValidationProblemResult<\n\tTExtensions extends object = Record<never, never>,\n> = ProblemDetailsResult<ValidationProblemDetails, string, TExtensions>;\n\n/**\n * Projects a base-error {@link ValidationError} to an RFC 9457 Problem\n * Details result by delegating to base-error's `toProblem` transport stage:\n * one pipeline, one wire profile, one hardening implementation. The body\n * carries the error's public `code`, and the whitelisted issues ride under\n * `details.issues` (`{ message, path, code?, pointer? }`, never raw\n * validator extras), the same shape `toPublicErrorView` uses.\n *\n * All of `toProblem`'s wire-safety guarantees apply: the body is deeply\n * frozen with a null prototype (cannot carry or receive prototype\n * pollution), every member is JSON-safe (a non-serializable value drops\n * that member and records it in `result.outcome.omitted` instead of\n * corrupting the wire), and extensions cannot collide with the reserved\n * members. The result also carries the HTTP `status` and ready-made\n * `headers`, so the boundary does not restate them.\n *\n * This is a presentation/transport concern and ships from the opt-in\n * `@shirudo/ddd-kit/http` entry point: the core kit stays transport-free.\n * For catalog-driven mapping across ALL your public errors use\n * base-error's `definePublicErrors` + `project` + `toProblem` directly;\n * this helper is the narrow validation shortcut.\n *\n * @example\n * ```ts\n * import { toProblemDetails } from \"@shirudo/ddd-kit/http\";\n *\n * if (result.isErr()) {\n * const problem = toProblemDetails(result.error);\n * return Response.json(problem.body, {\n * status: problem.status,\n * headers: problem.headers,\n * });\n * }\n * // body → { type: \"about:blank\", title: \"Validation Failed\", status: 422,\n * // code: \"VALIDATION_FAILED\",\n * // details: { issues: [{ message: \"must be a valid email\", ... }] } }\n * ```\n */\nexport function toProblemDetails<\n\tTExtensions extends object = Record<never, never>,\n>(\n\terror: ValidationError,\n\toptions: ValidationProblemOptions<TExtensions> = {},\n): ValidationProblemResult<TExtensions> {\n\tconst {\n\t\ttype = \"about:blank\",\n\t\ttitle = \"Validation Failed\",\n\t\tstatus = 422,\n\t\tdetail,\n\t\tinstance,\n\t\textensions,\n\t} = options;\n\n\treturn toProblem<ValidationProblemDetails, string, TExtensions>(\n\t\t{ status, type, title },\n\t\t{ code: error.code, details: { issues: error.publicIssues() } },\n\t\t{ detail, instance, extensions },\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwFA,SAAgB,iBAGf,OACA,UAAiD,CAAC,GACX;CACvC,MAAM,EACL,OAAO,eACP,QAAQ,qBACR,SAAS,KACT,QACA,UACA,eACG;CAEJ,OAAO,UACN;EAAE;EAAQ;EAAM;CAAM,GACtB;EAAE,MAAM,MAAM;EAAM,SAAS,EAAE,QAAQ,MAAM,aAAa,EAAE;CAAE,GAC9D;EAAE;EAAQ;EAAU;CAAW,CAChC;AACD"}
|