@ddd-ts-kit/validation 0.0.0-stage → 0.1.0

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.
Files changed (78) hide show
  1. package/README.md +118 -2
  2. package/dist/class-validator/class-schema.d.ts +12 -0
  3. package/dist/class-validator/class-schema.d.ts.map +1 -0
  4. package/dist/class-validator/class-schema.js +35 -0
  5. package/dist/class-validator/class-schema.js.map +1 -0
  6. package/dist/class-validator/dto-class.d.ts +2 -0
  7. package/dist/class-validator/dto-class.d.ts.map +1 -0
  8. package/dist/class-validator/dto-class.js +2 -0
  9. package/dist/class-validator/dto-class.js.map +1 -0
  10. package/dist/class-validator/self-contained-schema.d.ts +4 -0
  11. package/dist/class-validator/self-contained-schema.d.ts.map +1 -0
  12. package/dist/class-validator/self-contained-schema.js +58 -0
  13. package/dist/class-validator/self-contained-schema.js.map +1 -0
  14. package/dist/class-validator.d.ts +3 -0
  15. package/dist/class-validator.d.ts.map +1 -0
  16. package/dist/class-validator.js +2 -0
  17. package/dist/class-validator.js.map +1 -0
  18. package/dist/custom-schema.d.ts +7 -0
  19. package/dist/custom-schema.d.ts.map +1 -0
  20. package/dist/custom-schema.js +5 -0
  21. package/dist/custom-schema.js.map +1 -0
  22. package/dist/format-path.d.ts +3 -0
  23. package/dist/format-path.d.ts.map +1 -0
  24. package/dist/format-path.js +5 -0
  25. package/dist/format-path.js.map +1 -0
  26. package/dist/index.d.ts +9 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +5 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/infer.d.ts +3 -0
  31. package/dist/infer.d.ts.map +1 -0
  32. package/dist/infer.js +2 -0
  33. package/dist/infer.js.map +1 -0
  34. package/dist/json-schema.d.ts +2 -0
  35. package/dist/json-schema.d.ts.map +1 -0
  36. package/dist/json-schema.js +2 -0
  37. package/dist/json-schema.js.map +1 -0
  38. package/dist/parse-or-throw.d.ts +3 -0
  39. package/dist/parse-or-throw.d.ts.map +1 -0
  40. package/dist/parse-or-throw.js +9 -0
  41. package/dist/parse-or-throw.js.map +1 -0
  42. package/dist/schema.d.ts +13 -0
  43. package/dist/schema.d.ts.map +1 -0
  44. package/dist/schema.js +2 -0
  45. package/dist/schema.js.map +1 -0
  46. package/dist/standard-schema/infer-standard-output.d.ts +3 -0
  47. package/dist/standard-schema/infer-standard-output.d.ts.map +1 -0
  48. package/dist/standard-schema/infer-standard-output.js +2 -0
  49. package/dist/standard-schema/infer-standard-output.js.map +1 -0
  50. package/dist/standard-schema/standard-schema-v1.d.ts +25 -0
  51. package/dist/standard-schema/standard-schema-v1.d.ts.map +1 -0
  52. package/dist/standard-schema/standard-schema-v1.js +2 -0
  53. package/dist/standard-schema/standard-schema-v1.js.map +1 -0
  54. package/dist/standard-schema/standard-schema.d.ts +10 -0
  55. package/dist/standard-schema/standard-schema.d.ts.map +1 -0
  56. package/dist/standard-schema/standard-schema.js +32 -0
  57. package/dist/standard-schema/standard-schema.js.map +1 -0
  58. package/dist/standard-schema.d.ts +4 -0
  59. package/dist/standard-schema.d.ts.map +1 -0
  60. package/dist/standard-schema.js +2 -0
  61. package/dist/standard-schema.js.map +1 -0
  62. package/dist/validation-error.d.ts +8 -0
  63. package/dist/validation-error.d.ts.map +1 -0
  64. package/dist/validation-error.js +10 -0
  65. package/dist/validation-error.js.map +1 -0
  66. package/dist/validation-issue.d.ts +7 -0
  67. package/dist/validation-issue.d.ts.map +1 -0
  68. package/dist/validation-issue.js +2 -0
  69. package/dist/validation-issue.js.map +1 -0
  70. package/dist/zod/zod-schema.d.ts +11 -0
  71. package/dist/zod/zod-schema.d.ts.map +1 -0
  72. package/dist/zod/zod-schema.js +27 -0
  73. package/dist/zod/zod-schema.js.map +1 -0
  74. package/dist/zod.d.ts +2 -0
  75. package/dist/zod.d.ts.map +1 -0
  76. package/dist/zod.js +2 -0
  77. package/dist/zod.js.map +1 -0
  78. package/package.json +73 -4
package/README.md CHANGED
@@ -1,3 +1,119 @@
1
- # Temporary Holding Version
1
+ # @ddd-ts-kit/validation
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ One `Schema` contract for input validation at the boundary, with adapters for zod,
4
+ class-validator and any Standard Schema library. Routes, DTOs and the OpenAPI generator depend
5
+ on the contract, so the validation library can change without touching them.
6
+
7
+ Business rules do not belong here: they live in the domain and never import a validation library.
8
+
9
+ ## The contract
10
+
11
+ ```ts
12
+ import { parseOrThrow, type Infer, type Schema } from '@ddd-ts-kit/validation';
13
+
14
+ interface Schema<T> {
15
+ parse(input: unknown): Result<T, ValidationIssue[]>;
16
+ toJsonSchema(): JsonSchema;
17
+ }
18
+
19
+ type ValidationIssue = { path: string; code: string; message: string }; // path: "items.0.sku"
20
+ ```
21
+
22
+ A schema is a value: one per input, handed to the route or the event that validates with it.
23
+ It is never bound in a container, so it is an interface and not an injectable port (an abstract
24
+ class): there is nothing to declare in a composition root.
25
+
26
+ - `parse` never throws for an invalid input: it returns `err(issues)`.
27
+ - `parseOrThrow(schema, input)` returns the value or throws a `ValidationError`, a `DomainError`
28
+ with code `VALIDATION_FAILED` and the `issues`.
29
+ - `Infer<typeof schema>` gives the parsed type.
30
+ - `customSchema(parse, jsonSchema?)` builds a schema from a plain function.
31
+
32
+ The root entry imports no third-party package. Each adapter lives in its own subpath and its
33
+ library is an optional peer dependency: install only the one you use.
34
+
35
+ ## zod
36
+
37
+ ```sh
38
+ npm i zod
39
+ ```
40
+
41
+ ```ts
42
+ import { z } from 'zod';
43
+ import { zodSchema } from '@ddd-ts-kit/validation/zod';
44
+
45
+ const placeOrder = zodSchema(
46
+ z.object({
47
+ customerId: z.string().uuid(),
48
+ items: z.array(z.object({ sku: z.string().min(1), quantity: z.number().int().positive() })).min(1),
49
+ }),
50
+ );
51
+
52
+ const result = placeOrder.parse(input);
53
+ if (!result.ok) {
54
+ console.log(result.error); // [{ path: 'items.0.sku', code: 'too_small', message: '...' }]
55
+ }
56
+ ```
57
+
58
+ The JSON Schema comes from zod 4's `z.toJSONSchema` (draft 2020-12, usable as is in OpenAPI
59
+ 3.1). It describes the input side by default; pass `{ io: 'output' }` for a response body. A
60
+ type JSON Schema cannot represent (a `Date`, a `bigint`) is written as `{}` rather than
61
+ failing the generation.
62
+
63
+ ## class-validator
64
+
65
+ ```sh
66
+ npm i class-validator class-transformer class-validator-jsonschema reflect-metadata
67
+ ```
68
+
69
+ ```ts
70
+ import { Type } from 'class-transformer';
71
+ import { ArrayMinSize, IsInt, IsString, IsUUID, Min, ValidateNested } from 'class-validator';
72
+ import { classSchema } from '@ddd-ts-kit/validation/class-validator';
73
+
74
+ class OrderItemDto {
75
+ @IsString() sku = '';
76
+ @IsInt() @Min(1) quantity = 0;
77
+ }
78
+
79
+ class PlaceOrderDto {
80
+ @IsUUID() customerId = '';
81
+
82
+ @ValidateNested({ each: true })
83
+ @Type(() => OrderItemDto)
84
+ @ArrayMinSize(1)
85
+ items: OrderItemDto[] = [];
86
+ }
87
+
88
+ const placeOrder = classSchema(PlaceOrderDto);
89
+ ```
90
+
91
+ `parse` returns an instance of the class. `whitelist` and `forbidNonWhitelisted` are on by
92
+ default: an undeclared property is an issue. Override with
93
+ `classSchema(Dto, { validator: { forbidNonWhitelisted: false }, transform: { ... } })`.
94
+ Nested errors are flattened (`items.0.quantity`), one issue per failed constraint, the
95
+ constraint name as `code`. The JSON Schema is draft 2020-12 and carries the nested classes
96
+ reachable from the class under `$defs`.
97
+
98
+ Requires `experimentalDecorators` in the project's `tsconfig.json`.
99
+
100
+ ## Standard Schema (valibot, arktype, ...)
101
+
102
+ ```ts
103
+ import * as v from 'valibot';
104
+ import { standardSchema } from '@ddd-ts-kit/validation/standard-schema';
105
+
106
+ const placeOrder = standardSchema(
107
+ v.object({ customerId: v.pipe(v.string(), v.uuid()) }),
108
+ // Optional: the JSON Schema of the contract, which this adapter does not derive.
109
+ { type: 'object', required: ['customerId'], properties: { customerId: { type: 'string', format: 'uuid' } } },
110
+ );
111
+ ```
112
+
113
+ The adapter reads `~standard.validate` of Standard Schema v1 and nothing else: it derives no
114
+ JSON Schema, neither from the library's own exporter nor from the separate Standard JSON
115
+ Schema specification. Give it as the second argument (written by hand, or produced by the
116
+ exporter of your library); without it `toJsonSchema()` returns `{}`, which the OpenAPI
117
+ document shows as "any value". The specification carries no error code, so every issue has
118
+ the code `invalid`. A schema that validates asynchronously makes
119
+ `parse` throw: async schemas are not supported at the boundary.
@@ -0,0 +1,12 @@
1
+ import 'reflect-metadata';
2
+ import { type ClassTransformOptions } from 'class-transformer';
3
+ import { type ValidatorOptions } from 'class-validator';
4
+ import type { Schema } from '../schema.js';
5
+ import type { DtoClass } from './dto-class.js';
6
+ export interface ClassSchemaOptions {
7
+ /** Merged over the defaults `{ whitelist: true, forbidNonWhitelisted: true }`. */
8
+ readonly validator?: ValidatorOptions;
9
+ readonly transform?: ClassTransformOptions;
10
+ }
11
+ export declare function classSchema<T extends object>(dto: DtoClass<T>, options?: ClassSchemaOptions): Schema<T>;
12
+ //# sourceMappingURL=class-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-schema.d.ts","sourceRoot":"","sources":["../../src/class-validator/class-schema.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAmB,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAA6D,KAAK,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAG/C,MAAM,WAAW,kBAAkB;IACjC,kFAAkF;IAClF,QAAQ,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,SAAS,CAAC,EAAE,qBAAqB,CAAC;CAC5C;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,kBAAuB,GAAG,MAAM,CAAC,CAAC,CAAC,CAoB3G"}
@@ -0,0 +1,35 @@
1
+ import 'reflect-metadata';
2
+ import { plainToInstance } from 'class-transformer';
3
+ import { validateSync } from 'class-validator';
4
+ import { err, ok } from '@ddd-ts-kit/kernel';
5
+ import { selfContainedSchema } from './self-contained-schema.js';
6
+ export function classSchema(dto, options = {}) {
7
+ const validatorOptions = {
8
+ whitelist: true,
9
+ forbidNonWhitelisted: true,
10
+ ...options.validator,
11
+ };
12
+ return {
13
+ parse(input) {
14
+ if (typeof input !== 'object' || input === null || Array.isArray(input)) {
15
+ return err([{ path: '', code: 'isObject', message: 'An object is expected.' }]);
16
+ }
17
+ const instance = plainToInstance(dto, input, options.transform);
18
+ const errors = validateSync(instance, validatorOptions);
19
+ return errors.length === 0 ? ok(instance) : err(flatten(errors, ''));
20
+ },
21
+ toJsonSchema: () => selfContainedSchema(dto.name),
22
+ };
23
+ }
24
+ function flatten(errors, parent) {
25
+ return errors.flatMap((error) => {
26
+ const path = parent === '' ? error.property : `${parent}.${error.property}`;
27
+ const own = Object.entries(error.constraints ?? {}).map(([code, message]) => ({
28
+ path,
29
+ code,
30
+ message,
31
+ }));
32
+ return [...own, ...flatten(error.children ?? [], path)];
33
+ });
34
+ }
35
+ //# sourceMappingURL=class-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-schema.js","sourceRoot":"","sources":["../../src/class-validator/class-schema.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAA8B,MAAM,mBAAmB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAsE,MAAM,iBAAiB,CAAC;AACnH,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAI7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAQjE,MAAM,UAAU,WAAW,CAAmB,GAAgB,EAAE,OAAO,GAAuB,EAAE;IAC9F,MAAM,gBAAgB,GAAqB;QACzC,SAAS,EAAE,IAAI;QACf,oBAAoB,EAAE,IAAI;QAC1B,GAAG,OAAO,CAAC,SAAS;KACrB,CAAC;IAEF,OAAO;QACL,KAAK,CAAC,KAAK;YACT,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxE,OAAO,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC,CAAC,CAAC;YAClF,CAAC;YAED,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;YAChE,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;YAExD,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;QACvE,CAAC;QACD,YAAY,EAAE,GAAG,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC;KAClD,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,MAAsC,EAAE,MAAc;IACrE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;QAC9B,MAAM,IAAI,GAAG,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAE5E,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;YAC5E,IAAI;YACJ,IAAI;YACJ,OAAO;SACR,CAAC,CAAC,CAAC;QAEJ,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,2 @@
1
+ export type DtoClass<T extends object> = new () => T;
2
+ //# sourceMappingURL=dto-class.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dto-class.d.ts","sourceRoot":"","sources":["../../src/class-validator/dto-class.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,CAAC,CAAC,SAAS,MAAM,IAAI,UAAU,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dto-class.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dto-class.js","sourceRoot":"","sources":["../../src/class-validator/dto-class.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import type { JsonSchema } from '../json-schema.js';
2
+ /** The JSON Schema of a class, carrying under `$defs` only the classes reachable from it. */
3
+ export declare function selfContainedSchema(className: string): JsonSchema;
4
+ //# sourceMappingURL=self-contained-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-contained-schema.d.ts","sourceRoot":"","sources":["../../src/class-validator/self-contained-schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAMpD,6FAA6F;AAC7F,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAcjE"}
@@ -0,0 +1,58 @@
1
+ import { defaultMetadataStorage } from 'class-transformer/cjs/storage.js';
2
+ import { validationMetadatasToSchemas } from 'class-validator-jsonschema';
3
+ const DEFS_POINTER = '#/$defs/';
4
+ /** The JSON Schema of a class, carrying under `$defs` only the classes reachable from it. */
5
+ export function selfContainedSchema(className) {
6
+ const all = generatedSchemas();
7
+ const own = all[className] ?? { type: 'object' };
8
+ const defs = {};
9
+ collectDefs(own, all, defs);
10
+ const names = Object.keys(defs).sort();
11
+ return {
12
+ $schema: 'https://json-schema.org/draft/2020-12/schema',
13
+ ...own,
14
+ ...(names.length > 0 ? { $defs: Object.fromEntries(names.map((name) => [name, defs[name]])) } : {}),
15
+ };
16
+ }
17
+ function generatedSchemas() {
18
+ const generated = validationMetadatasToSchemas({
19
+ classTransformerMetadataStorage: defaultMetadataStorage,
20
+ refPointerPrefix: DEFS_POINTER,
21
+ });
22
+ return Object.fromEntries(Object.entries(generated).map(([name, schema]) => [name, { ...schema }]));
23
+ }
24
+ function collectDefs(node, all, defs) {
25
+ if (Array.isArray(node)) {
26
+ for (const item of node) {
27
+ collectDefs(item, all, defs);
28
+ }
29
+ return;
30
+ }
31
+ if (typeof node !== 'object' || node === null) {
32
+ return;
33
+ }
34
+ for (const [key, value] of Object.entries(node)) {
35
+ const name = referencedDefinition(key, value);
36
+ if (name === undefined) {
37
+ collectDefs(value, all, defs);
38
+ }
39
+ else {
40
+ collectDefinition(name, all, defs);
41
+ }
42
+ }
43
+ }
44
+ function referencedDefinition(key, value) {
45
+ if (key === '$ref' && typeof value === 'string' && value.startsWith(DEFS_POINTER)) {
46
+ return value.slice(DEFS_POINTER.length);
47
+ }
48
+ return undefined;
49
+ }
50
+ function collectDefinition(name, all, defs) {
51
+ const target = all[name];
52
+ // The root is carried too when a nested class points back at it.
53
+ if (target !== undefined && defs[name] === undefined) {
54
+ defs[name] = target;
55
+ collectDefs(target, all, defs);
56
+ }
57
+ }
58
+ //# sourceMappingURL=self-contained-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"self-contained-schema.js","sourceRoot":"","sources":["../../src/class-validator/self-contained-schema.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { classSchema, type ClassSchemaOptions } from './class-validator/class-schema.js';
2
+ export type { DtoClass } from './class-validator/dto-class.js';
3
+ //# sourceMappingURL=class-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-validator.d.ts","sourceRoot":"","sources":["../src/class-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AACzF,YAAY,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { classSchema } from './class-validator/class-schema.js';
2
+ //# sourceMappingURL=class-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"class-validator.js","sourceRoot":"","sources":["../src/class-validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA2B,MAAM,mCAAmC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { Result } from '@ddd-ts-kit/kernel';
2
+ import type { JsonSchema } from './json-schema.js';
3
+ import type { Schema } from './schema.js';
4
+ import type { ValidationIssue } from './validation-issue.js';
5
+ /** Builds a schema from a plain function, for hand-written checks and for tests. */
6
+ export declare function customSchema<T>(parse: (input: unknown) => Result<T, ValidationIssue[]>, jsonSchema?: JsonSchema): Schema<T>;
7
+ //# sourceMappingURL=custom-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-schema.d.ts","sourceRoot":"","sources":["../src/custom-schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,oFAAoF;AACpF,wBAAgB,YAAY,CAAC,CAAC,EAC5B,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,EACvD,UAAU,GAAE,UAAe,GAC1B,MAAM,CAAC,CAAC,CAAC,CAEX"}
@@ -0,0 +1,5 @@
1
+ /** Builds a schema from a plain function, for hand-written checks and for tests. */
2
+ export function customSchema(parse, jsonSchema = {}) {
3
+ return { parse, toJsonSchema: () => jsonSchema };
4
+ }
5
+ //# sourceMappingURL=custom-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-schema.js","sourceRoot":"","sources":["../src/custom-schema.ts"],"names":[],"mappings":"AAKA,oFAAoF;AACpF,MAAM,UAAU,YAAY,CAC1B,KAAuD,EACvD,UAAU,GAAe,EAAE;IAE3B,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC;AACnD,CAAC"}
@@ -0,0 +1,3 @@
1
+ /** Joins path segments the way every adapter reports them. */
2
+ export declare function formatPath(segments: readonly PropertyKey[]): string;
3
+ //# sourceMappingURL=format-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-path.d.ts","sourceRoot":"","sources":["../src/format-path.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,wBAAgB,UAAU,CAAC,QAAQ,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,CAEnE"}
@@ -0,0 +1,5 @@
1
+ /** Joins path segments the way every adapter reports them. */
2
+ export function formatPath(segments) {
3
+ return segments.map((segment) => String(segment)).join('.');
4
+ }
5
+ //# sourceMappingURL=format-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"format-path.js","sourceRoot":"","sources":["../src/format-path.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,MAAM,UAAU,UAAU,CAAC,QAAgC;IACzD,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { customSchema } from './custom-schema.js';
2
+ export { formatPath } from './format-path.js';
3
+ export type { Infer } from './infer.js';
4
+ export type { JsonSchema } from './json-schema.js';
5
+ export { parseOrThrow } from './parse-or-throw.js';
6
+ export type { Schema } from './schema.js';
7
+ export { ValidationError } from './validation-error.js';
8
+ export type { ValidationIssue } from './validation-issue.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,YAAY,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACxC,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { customSchema } from './custom-schema.js';
2
+ export { formatPath } from './format-path.js';
3
+ export { parseOrThrow } from './parse-or-throw.js';
4
+ export { ValidationError } from './validation-error.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAG9C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Schema } from './schema.js';
2
+ export type Infer<S> = S extends Schema<infer T> ? T : never;
3
+ //# sourceMappingURL=infer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer.d.ts","sourceRoot":"","sources":["../src/infer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,MAAM,KAAK,CAAC,CAAC,IAAI,CAAC,SAAS,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC"}
package/dist/infer.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=infer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer.js","sourceRoot":"","sources":["../src/infer.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ export type JsonSchema = Record<string, unknown>;
2
+ //# sourceMappingURL=json-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema.d.ts","sourceRoot":"","sources":["../src/json-schema.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=json-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json-schema.js","sourceRoot":"","sources":["../src/json-schema.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { Schema } from './schema.js';
2
+ export declare function parseOrThrow<T>(schema: Schema<T>, input: unknown): T;
3
+ //# sourceMappingURL=parse-or-throw.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-or-throw.d.ts","sourceRoot":"","sources":["../src/parse-or-throw.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAG1C,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,GAAG,CAAC,CAQpE"}
@@ -0,0 +1,9 @@
1
+ import { ValidationError } from './validation-error.js';
2
+ export function parseOrThrow(schema, input) {
3
+ const result = schema.parse(input);
4
+ if (result.ok) {
5
+ return result.value;
6
+ }
7
+ throw new ValidationError(result.error);
8
+ }
9
+ //# sourceMappingURL=parse-or-throw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse-or-throw.js","sourceRoot":"","sources":["../src/parse-or-throw.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,MAAM,UAAU,YAAY,CAAI,MAAiB,EAAE,KAAc;IAC/D,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEnC,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,MAAM,CAAC,KAAK,CAAC;IACtB,CAAC;IAED,MAAM,IAAI,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { Result } from '@ddd-ts-kit/kernel';
2
+ import type { JsonSchema } from './json-schema.js';
3
+ import type { ValidationIssue } from './validation-issue.js';
4
+ /**
5
+ * The contract every validation library is adapted to. Presentation code depends on this
6
+ * interface only, so the library can be swapped without touching routes. A schema is a value
7
+ * handed to what validates with it, one per input: it is never bound in a container.
8
+ */
9
+ export interface Schema<T> {
10
+ parse(input: unknown): Result<T, ValidationIssue[]>;
11
+ toJsonSchema(): JsonSchema;
12
+ }
13
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,MAAM,CAAC,CAAC;IACvB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,CAAC;IAEpD,YAAY,IAAI,UAAU,CAAC;CAC5B"}
package/dist/schema.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { StandardSchemaV1 } from './standard-schema-v1.js';
2
+ export type InferStandardOutput<S extends StandardSchemaV1> = NonNullable<S['~standard']['types']>['output'];
3
+ //# sourceMappingURL=infer-standard-output.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer-standard-output.d.ts","sourceRoot":"","sources":["../../src/standard-schema/infer-standard-output.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAEhE,MAAM,MAAM,mBAAmB,CAAC,CAAC,SAAS,gBAAgB,IAAI,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=infer-standard-output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"infer-standard-output.js","sourceRoot":"","sources":["../../src/standard-schema/infer-standard-output.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ /** The subset of the Standard Schema v1 specification this adapter relies on. */
2
+ export interface StandardSchemaV1<Input = unknown, Output = Input> {
3
+ readonly '~standard': {
4
+ readonly version: 1;
5
+ readonly vendor: string;
6
+ readonly validate: (value: unknown) => StandardSchemaResult<Output> | Promise<StandardSchemaResult<Output>>;
7
+ readonly types?: {
8
+ readonly input: Input;
9
+ readonly output: Output;
10
+ } | undefined;
11
+ };
12
+ }
13
+ export type StandardSchemaResult<Output> = {
14
+ readonly value: Output;
15
+ readonly issues?: undefined;
16
+ } | {
17
+ readonly issues: readonly StandardSchemaIssue[];
18
+ };
19
+ export interface StandardSchemaIssue {
20
+ readonly message: string;
21
+ readonly path?: readonly (PropertyKey | {
22
+ readonly key: PropertyKey;
23
+ })[] | undefined;
24
+ }
25
+ //# sourceMappingURL=standard-schema-v1.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-schema-v1.d.ts","sourceRoot":"","sources":["../../src/standard-schema/standard-schema-v1.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,MAAM,WAAW,gBAAgB,CAAC,KAAK,GAAG,OAAO,EAAE,MAAM,GAAG,KAAK;IAC/D,QAAQ,CAAC,WAAW,EAAE;QACpB,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;QACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,oBAAoB,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5G,QAAQ,CAAC,KAAK,CAAC,EAAE;YAAE,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;YAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;SAAE,GAAG,SAAS,CAAC;KACjF,CAAC;CACH;AAED,MAAM,MAAM,oBAAoB,CAAC,MAAM,IACnC;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAA;CAAE,CAAC;AAExD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG;QAAE,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAA;KAAE,CAAC,EAAE,GAAG,SAAS,CAAC;CACtF"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=standard-schema-v1.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-schema-v1.js","sourceRoot":"","sources":["../../src/standard-schema/standard-schema-v1.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import type { JsonSchema } from '../json-schema.js';
2
+ import type { Schema } from '../schema.js';
3
+ import type { InferStandardOutput } from './infer-standard-output.js';
4
+ import type { StandardSchemaV1 } from './standard-schema-v1.js';
5
+ /**
6
+ * Standard Schema has no JSON Schema export, so the contract side is supplied by the caller
7
+ * and defaults to `{}` (any value).
8
+ */
9
+ export declare function standardSchema<S extends StandardSchemaV1>(schema: S, jsonSchema?: JsonSchema): Schema<InferStandardOutput<S>>;
10
+ //# sourceMappingURL=standard-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-schema.d.ts","sourceRoot":"","sources":["../../src/standard-schema/standard-schema.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,KAAK,EAA6C,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAE3G;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,gBAAgB,EACvD,MAAM,EAAE,CAAC,EACT,UAAU,GAAE,UAAe,GAC1B,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAkBhC"}
@@ -0,0 +1,32 @@
1
+ import { err, ok } from '@ddd-ts-kit/kernel';
2
+ import { formatPath } from '../format-path.js';
3
+ /**
4
+ * Standard Schema has no JSON Schema export, so the contract side is supplied by the caller
5
+ * and defaults to `{}` (any value).
6
+ */
7
+ export function standardSchema(schema, jsonSchema = {}) {
8
+ return {
9
+ parse(input) {
10
+ const result = schema['~standard'].validate(input);
11
+ if (result instanceof Promise) {
12
+ // The verdict is discarded, its rejection must not surface as unhandled.
13
+ result.catch(() => undefined);
14
+ throw new Error(`The "${schema['~standard'].vendor}" schema validates asynchronously: async schemas are not supported at the boundary.`);
15
+ }
16
+ return verdictOf(result);
17
+ },
18
+ toJsonSchema: () => jsonSchema,
19
+ };
20
+ }
21
+ function verdictOf(result) {
22
+ if (result.issues === undefined) {
23
+ return ok(result.value);
24
+ }
25
+ return err(result.issues.map(issueOf));
26
+ }
27
+ function issueOf(issue) {
28
+ const segments = (issue.path ?? []).map((segment) => (typeof segment === 'object' ? segment.key : segment));
29
+ // The specification carries no machine-readable code.
30
+ return { path: formatPath(segments), code: 'invalid', message: issue.message };
31
+ }
32
+ //# sourceMappingURL=standard-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-schema.js","sourceRoot":"","sources":["../../src/standard-schema/standard-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAe,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAO/C;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,MAAS,EACT,UAAU,GAAe,EAAE;IAE3B,OAAO;QACL,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YAEnD,IAAI,MAAM,YAAY,OAAO,EAAE,CAAC;gBAC9B,yEAAyE;gBACzE,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;gBAE9B,MAAM,IAAI,KAAK,CACb,QAAQ,MAAM,CAAC,WAAW,CAAC,CAAC,MAAM,qFAAqF,CACxH,CAAC;YACJ,CAAC;YAED,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QACD,YAAY,EAAE,GAAG,EAAE,CAAC,UAAU;KAC/B,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAAS,MAAoC;IAC7D,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC1B,CAAC;IAED,OAAO,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC;AACzC,CAAC;AAED,SAAS,OAAO,CAAC,KAA0B;IACzC,MAAM,QAAQ,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IAE5G,sDAAsD;IACtD,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;AACjF,CAAC"}
@@ -0,0 +1,4 @@
1
+ export type { InferStandardOutput } from './standard-schema/infer-standard-output.js';
2
+ export type { StandardSchemaIssue, StandardSchemaResult, StandardSchemaV1, } from './standard-schema/standard-schema-v1.js';
3
+ export { standardSchema } from './standard-schema/standard-schema.js';
4
+ //# sourceMappingURL=standard-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-schema.d.ts","sourceRoot":"","sources":["../src/standard-schema.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,mBAAmB,EAAE,MAAM,4CAA4C,CAAC;AACtF,YAAY,EACV,mBAAmB,EACnB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { standardSchema } from './standard-schema/standard-schema.js';
2
+ //# sourceMappingURL=standard-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"standard-schema.js","sourceRoot":"","sources":["../src/standard-schema.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,sCAAsC,CAAC"}
@@ -0,0 +1,8 @@
1
+ import { DomainError } from '@ddd-ts-kit/kernel';
2
+ import type { ValidationIssue } from './validation-issue.js';
3
+ export declare class ValidationError extends DomainError {
4
+ readonly code = "VALIDATION_FAILED";
5
+ readonly issues: readonly ValidationIssue[];
6
+ constructor(issues: readonly ValidationIssue[], message?: string);
7
+ }
8
+ //# sourceMappingURL=validation-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-error.d.ts","sourceRoot":"","sources":["../src/validation-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,CAAC,IAAI,uBAAuB;IAEpC,QAAQ,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,CAAC;IAE5C,YAAY,MAAM,EAAE,SAAS,eAAe,EAAE,EAAE,OAAO,SAA4B,EAGlF;CACF"}
@@ -0,0 +1,10 @@
1
+ import { DomainError } from '@ddd-ts-kit/kernel';
2
+ export class ValidationError extends DomainError {
3
+ code = 'VALIDATION_FAILED';
4
+ issues;
5
+ constructor(issues, message = 'The input is not valid.') {
6
+ super(message);
7
+ this.issues = issues;
8
+ }
9
+ }
10
+ //# sourceMappingURL=validation-error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-error.js","sourceRoot":"","sources":["../src/validation-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD,MAAM,OAAO,eAAgB,SAAQ,WAAW;IACrC,IAAI,GAAG,mBAAmB,CAAC;IAE3B,MAAM,CAA6B;IAE5C,YAAY,MAAkC,EAAE,OAAO,GAAG,yBAAyB;QACjF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ /** `path` is dotted (`items.0.sku`); the empty string designates the input itself. */
2
+ export type ValidationIssue = {
3
+ path: string;
4
+ code: string;
5
+ message: string;
6
+ };
7
+ //# sourceMappingURL=validation-issue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-issue.d.ts","sourceRoot":"","sources":["../src/validation-issue.ts"],"names":[],"mappings":"AAAA,sFAAsF;AACtF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validation-issue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-issue.js","sourceRoot":"","sources":["../src/validation-issue.ts"],"names":[],"mappings":""}
@@ -0,0 +1,11 @@
1
+ import { z } from 'zod';
2
+ import type { Schema } from '../schema.js';
3
+ export interface ZodSchemaOptions {
4
+ /**
5
+ * Which side of the schema the JSON Schema describes. `input` (default) documents what a
6
+ * client sends: fields with a default are optional. Use `output` for response bodies.
7
+ */
8
+ readonly io?: 'input' | 'output';
9
+ }
10
+ export declare function zodSchema<Z extends z.ZodType>(type: Z, options?: ZodSchemaOptions): Schema<z.output<Z>>;
11
+ //# sourceMappingURL=zod-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod-schema.d.ts","sourceRoot":"","sources":["../../src/zod/zod-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CAClC;AAED,wBAAgB,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,GAAE,gBAAqB,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CA0B3G"}
@@ -0,0 +1,27 @@
1
+ import { z } from 'zod';
2
+ import { err, ok } from '@ddd-ts-kit/kernel';
3
+ import { formatPath } from '../format-path.js';
4
+ export function zodSchema(type, options = {}) {
5
+ return {
6
+ parse(input) {
7
+ const result = type.safeParse(input);
8
+ if (result.success) {
9
+ return ok(result.data);
10
+ }
11
+ return err(result.error.issues.map((issue) => ({
12
+ path: formatPath(issue.path),
13
+ code: issue.code,
14
+ message: issue.message,
15
+ })));
16
+ },
17
+ toJsonSchema() {
18
+ return z.toJSONSchema(type, {
19
+ target: 'draft-2020-12',
20
+ io: options.io ?? 'input',
21
+ // A contract generator must not crash on a Date or a bigint: they degrade to `{}`.
22
+ unrepresentable: 'any',
23
+ });
24
+ },
25
+ };
26
+ }
27
+ //# sourceMappingURL=zod-schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod-schema.js","sourceRoot":"","sources":["../../src/zod/zod-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAY/C,MAAM,UAAU,SAAS,CAAsB,IAAO,EAAE,OAAO,GAAqB,EAAE;IACpF,OAAO;QACL,KAAK,CAAC,KAAK;YACT,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAErC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACnB,OAAO,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACzB,CAAC;YAED,OAAO,GAAG,CACR,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAClC,IAAI,EAAE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;gBAC5B,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB,CAAC,CAAC,CACJ,CAAC;QACJ,CAAC;QACD,YAAY;YACV,OAAO,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE;gBAC1B,MAAM,EAAE,eAAe;gBACvB,EAAE,EAAE,OAAO,CAAC,EAAE,IAAI,OAAO;gBACzB,mFAAmF;gBACnF,eAAe,EAAE,KAAK;aACvB,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
package/dist/zod.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { zodSchema, type ZodSchemaOptions } from './zod/zod-schema.js';
2
+ //# sourceMappingURL=zod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod.d.ts","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC"}
package/dist/zod.js ADDED
@@ -0,0 +1,2 @@
1
+ export { zodSchema } from './zod/zod-schema.js';
2
+ //# sourceMappingURL=zod.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"zod.js","sourceRoot":"","sources":["../src/zod.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAyB,MAAM,qBAAqB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,75 @@
1
1
  {
2
2
  "name": "@ddd-ts-kit/validation",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "One Schema contract for input validation, with adapters for zod, class-validator and Standard Schema.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/gbourgeat/ddd-ts-kit.git",
9
+ "directory": "packages/validation"
10
+ },
11
+ "homepage": "https://github.com/gbourgeat/ddd-ts-kit/tree/main/packages/validation#readme",
12
+ "bugs": "https://github.com/gbourgeat/ddd-ts-kit/issues",
13
+ "publishConfig": {
14
+ "access": "public",
15
+ "provenance": true
16
+ },
17
+ "type": "module",
18
+ "sideEffects": false,
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "default": "./dist/index.js"
23
+ },
24
+ "./zod": {
25
+ "types": "./dist/zod.d.ts",
26
+ "default": "./dist/zod.js"
27
+ },
28
+ "./class-validator": {
29
+ "types": "./dist/class-validator.d.ts",
30
+ "default": "./dist/class-validator.js"
31
+ },
32
+ "./standard-schema": {
33
+ "types": "./dist/standard-schema.d.ts",
34
+ "default": "./dist/standard-schema.js"
35
+ }
36
+ },
37
+ "files": [
38
+ "dist"
39
+ ],
40
+ "dependencies": {
41
+ "@ddd-ts-kit/kernel": "0.1.0"
42
+ },
43
+ "peerDependencies": {
44
+ "zod": "^4.0.0",
45
+ "class-validator": ">=0.14.0",
46
+ "class-transformer": ">=0.5.0",
47
+ "class-validator-jsonschema": ">=5.0.0",
48
+ "reflect-metadata": ">=0.2.0"
49
+ },
50
+ "peerDependenciesMeta": {
51
+ "zod": {
52
+ "optional": true
53
+ },
54
+ "class-validator": {
55
+ "optional": true
56
+ },
57
+ "class-transformer": {
58
+ "optional": true
59
+ },
60
+ "class-validator-jsonschema": {
61
+ "optional": true
62
+ },
63
+ "reflect-metadata": {
64
+ "optional": true
65
+ }
66
+ },
67
+ "devDependencies": {
68
+ "zod": "^4.6.5",
69
+ "class-validator": "^0.15.1",
70
+ "class-transformer": "^0.5.1",
71
+ "class-validator-jsonschema": "^5.0.0",
72
+ "reflect-metadata": "^0.2.2",
73
+ "valibot": "^1.0.0"
74
+ }
75
+ }