@powerlines/schema 0.8.67 → 0.9.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 (55) hide show
  1. package/README.md +36 -22
  2. package/dist/bundle.d.cts +2 -2
  3. package/dist/bundle.d.cts.map +1 -1
  4. package/dist/bundle.d.mts +2 -2
  5. package/dist/bundle.d.mts.map +1 -1
  6. package/dist/bundle.mjs.map +1 -1
  7. package/dist/extract.cjs +200 -51
  8. package/dist/extract.d.cts +82 -16
  9. package/dist/extract.d.cts.map +1 -1
  10. package/dist/extract.d.mts +82 -16
  11. package/dist/extract.d.mts.map +1 -1
  12. package/dist/extract.mjs +198 -54
  13. package/dist/extract.mjs.map +1 -1
  14. package/dist/index.cjs +13 -2
  15. package/dist/index.d.cts +5 -4
  16. package/dist/index.d.mts +5 -4
  17. package/dist/index.mjs +4 -3
  18. package/dist/jtd.cjs +362 -0
  19. package/dist/jtd.d.cts +16 -0
  20. package/dist/jtd.d.cts.map +1 -0
  21. package/dist/jtd.d.mts +16 -0
  22. package/dist/jtd.d.mts.map +1 -0
  23. package/dist/jtd.mjs +361 -0
  24. package/dist/jtd.mjs.map +1 -0
  25. package/dist/reflection.cjs +229 -108
  26. package/dist/reflection.d.cts +17 -7
  27. package/dist/reflection.d.cts.map +1 -1
  28. package/dist/reflection.d.mts +17 -7
  29. package/dist/reflection.d.mts.map +1 -1
  30. package/dist/reflection.mjs +229 -108
  31. package/dist/reflection.mjs.map +1 -1
  32. package/dist/resolve.d.cts +5 -5
  33. package/dist/resolve.d.cts.map +1 -1
  34. package/dist/resolve.d.mts +5 -5
  35. package/dist/resolve.d.mts.map +1 -1
  36. package/dist/resolve.mjs.map +1 -1
  37. package/dist/type-checks.cjs +76 -0
  38. package/dist/type-checks.d.cts +43 -0
  39. package/dist/type-checks.d.cts.map +1 -0
  40. package/dist/type-checks.d.mts +43 -0
  41. package/dist/type-checks.d.mts.map +1 -0
  42. package/dist/type-checks.mjs +71 -0
  43. package/dist/type-checks.mjs.map +1 -0
  44. package/dist/types.d.cts +80 -24
  45. package/dist/types.d.cts.map +1 -1
  46. package/dist/types.d.mts +80 -24
  47. package/dist/types.d.mts.map +1 -1
  48. package/package.json +21 -19
  49. package/dist/is-schema-definition.cjs +0 -18
  50. package/dist/is-schema-definition.d.cts +0 -13
  51. package/dist/is-schema-definition.d.cts.map +0 -1
  52. package/dist/is-schema-definition.d.mts +0 -13
  53. package/dist/is-schema-definition.d.mts.map +0 -1
  54. package/dist/is-schema-definition.mjs +0 -17
  55. package/dist/is-schema-definition.mjs.map +0 -1
@@ -4,120 +4,146 @@ let _powerlines_deepkit_vendor_type = require("@powerlines/deepkit/vendor/type")
4
4
 
5
5
  //#region src/reflection.ts
6
6
  /**
7
- * Converts a Deepkit type reflection into a JSON Schema representation.
7
+ * Maps a Deepkit numeric `brand` to the JTD numeric `type` keyword that best preserves the underlying width and signedness.
8
+ *
9
+ * @param brand - The Deepkit `TypeNumberBrand` of a numeric reflection, or `undefined` when no brand is set.
10
+ * @returns The JTD numeric `type` keyword to use.
11
+ */
12
+ function numberBrandToJtdType(brand) {
13
+ switch (brand) {
14
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.integer: return "int32";
15
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.int8: return "int8";
16
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.uint8: return "uint8";
17
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.int16: return "int16";
18
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.uint16: return "uint16";
19
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.int32: return "int32";
20
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.uint32: return "uint32";
21
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.float:
22
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.float32: return "float32";
23
+ case _powerlines_deepkit_vendor_type.TypeNumberBrand.float64: return "float64";
24
+ case void 0:
25
+ default: return "float64";
26
+ }
27
+ }
28
+ /**
29
+ * Attaches a `description` annotation to a JTD form's `metadata` bag.
30
+ *
31
+ * @param form - The JTD form to decorate.
32
+ * @param description - The description text, or `undefined` to skip.
33
+ * @returns The same JTD form, decorated when a description was provided.
34
+ */
35
+ function attachDescription(form, description) {
36
+ if (!description) return form;
37
+ const metadata = form.metadata ?? {};
38
+ metadata.description = description;
39
+ form.metadata = metadata;
40
+ return form;
41
+ }
42
+ /**
43
+ * Converts a Deepkit type reflection into a JSON Type Definition (RFC 8927) form suitable for AJV's JTD validator.
44
+ *
45
+ * @remarks
46
+ * Some TypeScript constructs have no direct JTD equivalent and are handled with the closest available form:
47
+ *
48
+ * - `null` and `undefined` become the empty JTD form with `nullable: true`.
49
+ * - Unions of primitives that cannot be expressed as a JTD enum collapse to the empty form (which validates any value).
50
+ * - String/number/bigint literal unions are emitted as a JTD enum (non-string members are stringified, as JTD requires string enum members).
51
+ * - Tuples are emitted as a JTD elements form whose element schema is the single tuple member type, or the empty schema for mixed tuples.
52
+ * - `Date` is emitted as `{ type: "timestamp" }`.
53
+ * - Discriminated unions of object literals (a shared string-literal tag property) are emitted as a JTD discriminator form.
8
54
  *
9
55
  * @param reflection - The Deepkit type reflection to convert.
10
- * @returns The corresponding JSON Schema representation, or `undefined` if the type cannot be represented.
56
+ * @returns The corresponding JTD form, or `undefined` if the type cannot be represented.
11
57
  */
12
58
  function reflectionToJsonSchema(reflection) {
59
+ return reflectionToJtd(reflection);
60
+ }
61
+ /**
62
+ * Internal worker that performs the recursive Deepkit reflection → JTD conversion.
63
+ *
64
+ * @param reflection - The Deepkit type reflection to convert.
65
+ * @returns The corresponding JTD form, or `undefined` if the type cannot be represented.
66
+ */
67
+ function reflectionToJtd(reflection) {
13
68
  switch (reflection.kind) {
14
69
  case _powerlines_deepkit_vendor_type.ReflectionKind.any:
15
70
  case _powerlines_deepkit_vendor_type.ReflectionKind.unknown:
16
71
  case _powerlines_deepkit_vendor_type.ReflectionKind.void:
17
72
  case _powerlines_deepkit_vendor_type.ReflectionKind.object: return {};
18
- case _powerlines_deepkit_vendor_type.ReflectionKind.never:
19
- case _powerlines_deepkit_vendor_type.ReflectionKind.undefined: return { not: {} };
20
- case _powerlines_deepkit_vendor_type.ReflectionKind.null: return { type: "null" };
73
+ case _powerlines_deepkit_vendor_type.ReflectionKind.never: return;
74
+ case _powerlines_deepkit_vendor_type.ReflectionKind.undefined:
75
+ case _powerlines_deepkit_vendor_type.ReflectionKind.null: return { nullable: true };
21
76
  case _powerlines_deepkit_vendor_type.ReflectionKind.string: return { type: "string" };
22
77
  case _powerlines_deepkit_vendor_type.ReflectionKind.boolean: return { type: "boolean" };
23
- case _powerlines_deepkit_vendor_type.ReflectionKind.number: {
24
- const brand = reflection.brand;
25
- return { type: brand !== void 0 && brand >= _powerlines_deepkit_vendor_type.TypeNumberBrand.integer && brand <= _powerlines_deepkit_vendor_type.TypeNumberBrand.uint32 ? "integer" : "number" };
26
- }
27
- case _powerlines_deepkit_vendor_type.ReflectionKind.bigint: return {
28
- type: "integer",
29
- format: "int64"
30
- };
78
+ case _powerlines_deepkit_vendor_type.ReflectionKind.number: return { type: numberBrandToJtdType(reflection.brand) };
79
+ case _powerlines_deepkit_vendor_type.ReflectionKind.bigint: return { type: "float64" };
31
80
  case _powerlines_deepkit_vendor_type.ReflectionKind.regexp: return { type: "string" };
32
81
  case _powerlines_deepkit_vendor_type.ReflectionKind.literal: {
33
82
  const { literal } = reflection;
34
- if (typeof literal === "string") return {
35
- type: "string",
36
- const: literal
37
- };
38
- if (typeof literal === "number") return {
39
- type: Number.isInteger(literal) ? "integer" : "number",
40
- const: literal
41
- };
42
- if (typeof literal === "boolean") return {
43
- type: "boolean",
44
- const: literal
45
- };
46
- if (typeof literal === "bigint") return {
47
- type: "integer",
48
- format: "int64"
49
- };
50
- if (literal instanceof RegExp) return {
51
- type: "string",
52
- pattern: literal.source
53
- };
83
+ if (typeof literal === "string") return { enum: [literal] };
84
+ if (typeof literal === "number" || typeof literal === "bigint") return { enum: [String(literal)] };
85
+ if (typeof literal === "boolean") return { type: "boolean" };
86
+ if (literal instanceof RegExp) return { type: "string" };
54
87
  return {};
55
88
  }
56
89
  case _powerlines_deepkit_vendor_type.ReflectionKind.templateLiteral: return { type: "string" };
57
90
  case _powerlines_deepkit_vendor_type.ReflectionKind.enum: {
58
- const values = reflection.values.filter((value) => typeof value === "string" || typeof value === "number");
59
- const allStrings = values.every((value) => typeof value === "string");
60
- const allNumbers = values.every((value) => typeof value === "number");
61
- return {
62
- type: allStrings ? "string" : allNumbers ? "number" : ["string", "number"],
63
- enum: values
64
- };
91
+ const values = reflection.values.filter((value) => typeof value === "string" || typeof value === "number").map((value) => String(value));
92
+ const unique = Array.from(new Set(values));
93
+ if (unique.length === 0) return {};
94
+ return { enum: unique };
65
95
  }
66
- case _powerlines_deepkit_vendor_type.ReflectionKind.array: {
67
- const items = reflectionToJsonSchema(reflection.type);
68
- return items ? {
69
- type: "array",
70
- items
71
- } : { type: "array" };
96
+ case _powerlines_deepkit_vendor_type.ReflectionKind.array: return { elements: reflectionToJtd(reflection.type) ?? {} };
97
+ case _powerlines_deepkit_vendor_type.ReflectionKind.tuple: {
98
+ const items = reflection.types.map((member) => reflectionToJtd(member.type)).filter((item) => item !== void 0);
99
+ if (items.length === 0) return { elements: {} };
100
+ if (items.length === 1) return { elements: items[0] };
101
+ return { elements: {} };
72
102
  }
73
- case _powerlines_deepkit_vendor_type.ReflectionKind.tuple: return {
74
- type: "array",
75
- items: reflection.types.map((member) => reflectionToJsonSchema(member.type)).filter((item) => item !== void 0),
76
- minItems: reflection.types.filter((member) => !member.optional).length,
77
- maxItems: reflection.types.length
78
- };
79
103
  case _powerlines_deepkit_vendor_type.ReflectionKind.union: {
80
- const anyOf = reflection.types.map((inner) => reflectionToJsonSchema(inner)).filter((item) => item !== void 0);
81
- if (anyOf.length === 0) return;
82
- if (anyOf.length === 1) return anyOf[0];
83
- return { anyOf };
104
+ const branches = reflection.types.map((inner) => reflectionToJtd(inner)).filter((item) => item !== void 0);
105
+ const nullable = reflection.types.some((inner) => inner.kind === _powerlines_deepkit_vendor_type.ReflectionKind.null || inner.kind === _powerlines_deepkit_vendor_type.ReflectionKind.undefined);
106
+ const nonNull = branches.filter((b) => !isPureNullable(b));
107
+ if (nonNull.length === 0) return { nullable: true };
108
+ if (nonNull.length === 1) {
109
+ const only = nonNull[0];
110
+ if (nullable) only.nullable = true;
111
+ return only;
112
+ }
113
+ if (nonNull.every(isEnumForm)) {
114
+ const form = { enum: Array.from(new Set(nonNull.flatMap((b) => b.enum))) };
115
+ if (nullable) form.nullable = true;
116
+ return form;
117
+ }
118
+ const discriminator = tryReflectionDiscriminator(reflection.types);
119
+ if (discriminator) {
120
+ if (nullable) discriminator.nullable = true;
121
+ return discriminator;
122
+ }
123
+ const fallback = {};
124
+ if (nullable) fallback.nullable = true;
125
+ return fallback;
84
126
  }
85
127
  case _powerlines_deepkit_vendor_type.ReflectionKind.intersection: {
86
- const allOf = reflection.types.map((inner) => reflectionToJsonSchema(inner)).filter((item) => item !== void 0);
87
- if (allOf.length === 0) return;
88
- if (allOf.length === 1) return allOf[0];
89
- return { allOf };
128
+ const members = reflection.types.map((inner) => reflectionToJtd(inner)).filter((item) => item !== void 0);
129
+ if (members.length === 0) return;
130
+ if (members.length === 1) return members[0];
131
+ if (members.every(isPropertiesForm)) return mergePropertiesForms(members);
132
+ return members[0];
90
133
  }
91
- case _powerlines_deepkit_vendor_type.ReflectionKind.promise: return reflectionToJsonSchema(reflection.type);
92
- case _powerlines_deepkit_vendor_type.ReflectionKind.objectLiteral: return objectReflectionToJsonSchema(reflection);
134
+ case _powerlines_deepkit_vendor_type.ReflectionKind.promise: return reflectionToJtd(reflection.type);
135
+ case _powerlines_deepkit_vendor_type.ReflectionKind.objectLiteral: return objectReflectionToJtd(reflection);
93
136
  case _powerlines_deepkit_vendor_type.ReflectionKind.class: switch (reflection.classType?.name) {
94
- case "Date": return {
95
- type: "string",
96
- format: "date-time"
97
- };
137
+ case "Date": return { type: "timestamp" };
98
138
  case "RegExp": return { type: "string" };
99
- case "URL": return {
100
- type: "string",
101
- format: "uri"
102
- };
139
+ case "URL": return { type: "string" };
103
140
  case "Set": {
104
141
  const itemType = reflection.arguments?.[0];
105
- const items = itemType ? reflectionToJsonSchema(itemType) : void 0;
106
- return items ? {
107
- type: "array",
108
- uniqueItems: true,
109
- items
110
- } : {
111
- type: "array",
112
- uniqueItems: true
113
- };
142
+ return { elements: (itemType ? reflectionToJtd(itemType) : void 0) ?? {} };
114
143
  }
115
144
  case "Map": {
116
145
  const valueType = reflection.arguments?.[1];
117
- const additionalProperties = valueType ? reflectionToJsonSchema(valueType) : void 0;
118
- const schema = { type: "object" };
119
- if (additionalProperties) schema.additionalProperties = additionalProperties;
120
- return schema;
146
+ return { values: (valueType ? reflectionToJtd(valueType) : void 0) ?? {} };
121
147
  }
122
148
  case "Uint8Array":
123
149
  case "Uint8ClampedArray":
@@ -129,12 +155,9 @@ function reflectionToJsonSchema(reflection) {
129
155
  case "Float32Array":
130
156
  case "Float64Array":
131
157
  case "BigInt64Array":
132
- case "BigUint64Array": return {
133
- type: "string",
134
- contentEncoding: "base64"
135
- };
158
+ case "BigUint64Array": return { type: "string" };
136
159
  case void 0:
137
- default: return objectReflectionToJsonSchema(reflection);
160
+ default: return objectReflectionToJtd(reflection);
138
161
  }
139
162
  case _powerlines_deepkit_vendor_type.ReflectionKind.symbol:
140
163
  case _powerlines_deepkit_vendor_type.ReflectionKind.property:
@@ -154,36 +177,134 @@ function reflectionToJsonSchema(reflection) {
154
177
  }
155
178
  }
156
179
  /**
157
- * Builds a JSON Schema object representation from a Deepkit class or object literal type.
180
+ * Tests whether a JTD form is an enum form.
181
+ *
182
+ * @param form - The JTD form to inspect.
183
+ * @returns `true` if the form is a JTD enum form.
184
+ */
185
+ function isEnumForm(form) {
186
+ return Array.isArray(form.enum);
187
+ }
188
+ /**
189
+ * Tests whether a JTD form is a properties form (object).
190
+ *
191
+ * @param form - The JTD form to inspect.
192
+ * @returns `true` if the form is a JTD properties form.
193
+ */
194
+ function isPropertiesForm(form) {
195
+ return "properties" in form || "optionalProperties" in form;
196
+ }
197
+ /**
198
+ * Tests whether a JTD form is the empty `{ nullable: true }` placeholder.
199
+ *
200
+ * @param form - The JTD form to inspect.
201
+ * @returns `true` if the form has no shape constraints beyond `nullable`.
202
+ */
203
+ function isPureNullable(form) {
204
+ return Object.keys(form).filter((k) => k !== "nullable" && k !== "metadata").length === 0 && form.nullable === true;
205
+ }
206
+ /**
207
+ * Shallow-merges two JTD properties forms, unioning their `properties` and `optionalProperties` maps.
208
+ *
209
+ * @param forms - The JTD properties forms to merge.
210
+ * @returns The merged JTD properties form.
211
+ */
212
+ function mergePropertiesForms(forms) {
213
+ const merged = {
214
+ properties: {},
215
+ optionalProperties: {}
216
+ };
217
+ for (const form of forms) {
218
+ const p = form.properties;
219
+ const o = form.optionalProperties;
220
+ if (p) Object.assign(merged.properties, p);
221
+ if (o) Object.assign(merged.optionalProperties, o);
222
+ if (form.additionalProperties) merged.additionalProperties = true;
223
+ }
224
+ const hasProperties = Object.keys(merged.properties).length > 0;
225
+ const hasOptional = Object.keys(merged.optionalProperties).length > 0;
226
+ const result = {};
227
+ if (hasProperties) result.properties = merged.properties;
228
+ else if (!hasOptional) result.properties = {};
229
+ if (hasOptional) result.optionalProperties = merged.optionalProperties;
230
+ if (merged.additionalProperties) result.additionalProperties = true;
231
+ return result;
232
+ }
233
+ /**
234
+ * Detects whether a Deepkit union represents a tagged union and, when so, emits the corresponding JTD discriminator form.
235
+ *
236
+ * @param types - The Deepkit reflection types that make up the union branches.
237
+ * @returns A JTD discriminator form if every non-null branch is an object literal that shares a string-literal tag property, otherwise `undefined`.
238
+ */
239
+ function tryReflectionDiscriminator(types) {
240
+ const nonNullTypes = types.filter((t) => t.kind !== _powerlines_deepkit_vendor_type.ReflectionKind.null && t.kind !== _powerlines_deepkit_vendor_type.ReflectionKind.undefined);
241
+ const objectBranches = nonNullTypes.filter((t) => t.kind === _powerlines_deepkit_vendor_type.ReflectionKind.objectLiteral || t.kind === _powerlines_deepkit_vendor_type.ReflectionKind.class);
242
+ if (objectBranches.length < 2 || objectBranches.length !== nonNullTypes.length) return;
243
+ let tagKey;
244
+ const mapping = {};
245
+ for (const branch of objectBranches) {
246
+ const literalProps = [];
247
+ for (const member of branch.types) if ((member.kind === _powerlines_deepkit_vendor_type.ReflectionKind.property || member.kind === _powerlines_deepkit_vendor_type.ReflectionKind.propertySignature) && typeof member.name === "string" && member.type.kind === _powerlines_deepkit_vendor_type.ReflectionKind.literal && typeof member.type.literal === "string") literalProps.push({
248
+ name: member.name,
249
+ literal: member.type.literal
250
+ });
251
+ if (literalProps.length === 0) return;
252
+ const first = literalProps[0];
253
+ if (!tagKey) tagKey = first.name;
254
+ else if (tagKey !== first.name) return;
255
+ const body = objectReflectionToJtd({
256
+ ...branch,
257
+ types: branch.types.filter((member) => !((member.kind === _powerlines_deepkit_vendor_type.ReflectionKind.property || member.kind === _powerlines_deepkit_vendor_type.ReflectionKind.propertySignature) && member.name === tagKey))
258
+ });
259
+ if (!body || !isPropertiesForm(body)) return;
260
+ mapping[first.literal] = body;
261
+ }
262
+ if (!tagKey) return;
263
+ return {
264
+ discriminator: tagKey,
265
+ mapping
266
+ };
267
+ }
268
+ /**
269
+ * Builds a JTD properties form from a Deepkit class or object literal type.
158
270
  *
159
271
  * @param type - The class or object literal type whose members should be serialized.
160
- * @returns A JSON Schema object describing the type's properties.
272
+ * @returns A JTD properties form describing the type's members.
161
273
  */
162
274
  function objectReflectionToJsonSchema(type) {
275
+ return objectReflectionToJtd(type);
276
+ }
277
+ /**
278
+ * Internal worker that produces a JTD properties form (or `values` form for index signatures alone) from a Deepkit object-like type.
279
+ *
280
+ * @param type - The class or object literal type whose members should be serialized.
281
+ * @returns A JTD properties or values form describing the type's members.
282
+ */
283
+ function objectReflectionToJtd(type) {
163
284
  const properties = {};
164
- const required = [];
165
- let additionalProperties;
285
+ const optionalProperties = {};
286
+ let indexValueSchema;
166
287
  const description = "description" in type && typeof type.description === "string" ? type.description : void 0;
167
288
  for (const member of type.types) if (member.kind === _powerlines_deepkit_vendor_type.ReflectionKind.property || member.kind === _powerlines_deepkit_vendor_type.ReflectionKind.propertySignature) {
168
- const property = member;
169
- if (typeof property.name !== "string") continue;
170
- const propertySchema = reflectionToJsonSchema(property.type);
289
+ if (typeof member.name !== "string") continue;
290
+ const propertySchema = reflectionToJtd(member.type);
171
291
  if (!propertySchema) continue;
172
- if (typeof property.description === "string") propertySchema.description = property.description;
173
- properties[property.name] = propertySchema;
174
- if (!property.optional) required.push(property.name);
292
+ if (typeof member.description === "string") attachDescription(propertySchema, member.description);
293
+ if (member.optional) optionalProperties[member.name] = propertySchema;
294
+ else properties[member.name] = propertySchema;
175
295
  } else if (member.kind === _powerlines_deepkit_vendor_type.ReflectionKind.indexSignature) {
176
- const valueSchema = reflectionToJsonSchema(member.type);
177
- if (valueSchema) additionalProperties = valueSchema;
296
+ const valueSchema = reflectionToJtd(member.type);
297
+ if (valueSchema) indexValueSchema = valueSchema;
178
298
  }
179
- const schema = {
180
- type: "object",
181
- properties
182
- };
183
- if (required.length > 0) schema.required = required;
184
- if (additionalProperties !== void 0) schema.additionalProperties = additionalProperties;
185
- if (description) schema.description = description;
186
- return schema;
299
+ const hasProperties = Object.keys(properties).length > 0;
300
+ const hasOptional = Object.keys(optionalProperties).length > 0;
301
+ if (!hasProperties && !hasOptional && indexValueSchema) return attachDescription({ values: indexValueSchema }, description);
302
+ const form = {};
303
+ if (hasProperties) form.properties = properties;
304
+ else if (!hasOptional) form.properties = {};
305
+ if (hasOptional) form.optionalProperties = optionalProperties;
306
+ if (indexValueSchema) form.additionalProperties = true;
307
+ return attachDescription(form, description);
187
308
  }
188
309
 
189
310
  //#endregion
@@ -1,21 +1,31 @@
1
1
  import { Type, TypeClass, TypeObjectLiteral } from "@powerlines/deepkit/vendor/type";
2
- import { JsonSchema7Type } from "@stryke/json/types";
2
+ import { JTDSchemaType } from "ajv/dist/types/jtd-schema.js";
3
3
 
4
4
  //#region src/reflection.d.ts
5
5
  /**
6
- * Converts a Deepkit type reflection into a JSON Schema representation.
6
+ * Converts a Deepkit type reflection into a JSON Type Definition (RFC 8927) form suitable for AJV's JTD validator.
7
+ *
8
+ * @remarks
9
+ * Some TypeScript constructs have no direct JTD equivalent and are handled with the closest available form:
10
+ *
11
+ * - `null` and `undefined` become the empty JTD form with `nullable: true`.
12
+ * - Unions of primitives that cannot be expressed as a JTD enum collapse to the empty form (which validates any value).
13
+ * - String/number/bigint literal unions are emitted as a JTD enum (non-string members are stringified, as JTD requires string enum members).
14
+ * - Tuples are emitted as a JTD elements form whose element schema is the single tuple member type, or the empty schema for mixed tuples.
15
+ * - `Date` is emitted as `{ type: "timestamp" }`.
16
+ * - Discriminated unions of object literals (a shared string-literal tag property) are emitted as a JTD discriminator form.
7
17
  *
8
18
  * @param reflection - The Deepkit type reflection to convert.
9
- * @returns The corresponding JSON Schema representation, or `undefined` if the type cannot be represented.
19
+ * @returns The corresponding JTD form, or `undefined` if the type cannot be represented.
10
20
  */
11
- declare function reflectionToJsonSchema(reflection: Type): JsonSchema7Type | undefined;
21
+ declare function reflectionToJsonSchema<T = unknown, D extends Record<string, unknown> = Record<string, unknown>>(reflection: Type): JTDSchemaType<T, D> | undefined;
12
22
  /**
13
- * Builds a JSON Schema object representation from a Deepkit class or object literal type.
23
+ * Builds a JTD properties form from a Deepkit class or object literal type.
14
24
  *
15
25
  * @param type - The class or object literal type whose members should be serialized.
16
- * @returns A JSON Schema object describing the type's properties.
26
+ * @returns A JTD properties form describing the type's members.
17
27
  */
18
- declare function objectReflectionToJsonSchema(type: TypeObjectLiteral | TypeClass): JsonSchema7Type;
28
+ declare function objectReflectionToJsonSchema<T = unknown, D extends Record<string, unknown> = Record<string, unknown>>(type: TypeObjectLiteral | TypeClass): JTDSchemaType<T, D>;
19
29
  //#endregion
20
30
  export { objectReflectionToJsonSchema, reflectionToJsonSchema };
21
31
  //# sourceMappingURL=reflection.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reflection.d.cts","names":[],"sources":["../src/reflection.ts"],"mappings":";;;;;AAgCA;;;;;iBAAgB,sBAAA,CACd,UAAA,EAAY,IAAA,GACX,eAAA;;;;AAgMH;;;iBAAgB,4BAAA,CACd,IAAA,EAAM,iBAAA,GAAoB,SAAA,GACzB,eAAA"}
1
+ {"version":3,"file":"reflection.d.cts","names":[],"sources":["../src/reflection.ts"],"mappings":";;;;;AA0GA;;;;;;;;;;;;;;;iBAAgB,sBAAA,wBAEJ,MAAA,oBAA0B,MAAA,kBAAA,CACpC,UAAA,EAAY,IAAA,GAAO,aAAA,CAAc,CAAA,EAAG,CAAA;;;;;;;iBAwYtB,4BAAA,wBAEJ,MAAA,oBAA0B,MAAA,kBAAA,CACpC,IAAA,EAAM,iBAAA,GAAoB,SAAA,GAAY,aAAA,CAAc,CAAA,EAAG,CAAA"}
@@ -1,21 +1,31 @@
1
1
  import { Type, TypeClass, TypeObjectLiteral } from "@powerlines/deepkit/vendor/type";
2
- import { JsonSchema7Type } from "@stryke/json/types";
2
+ import { JTDSchemaType } from "ajv/dist/types/jtd-schema.js";
3
3
 
4
4
  //#region src/reflection.d.ts
5
5
  /**
6
- * Converts a Deepkit type reflection into a JSON Schema representation.
6
+ * Converts a Deepkit type reflection into a JSON Type Definition (RFC 8927) form suitable for AJV's JTD validator.
7
+ *
8
+ * @remarks
9
+ * Some TypeScript constructs have no direct JTD equivalent and are handled with the closest available form:
10
+ *
11
+ * - `null` and `undefined` become the empty JTD form with `nullable: true`.
12
+ * - Unions of primitives that cannot be expressed as a JTD enum collapse to the empty form (which validates any value).
13
+ * - String/number/bigint literal unions are emitted as a JTD enum (non-string members are stringified, as JTD requires string enum members).
14
+ * - Tuples are emitted as a JTD elements form whose element schema is the single tuple member type, or the empty schema for mixed tuples.
15
+ * - `Date` is emitted as `{ type: "timestamp" }`.
16
+ * - Discriminated unions of object literals (a shared string-literal tag property) are emitted as a JTD discriminator form.
7
17
  *
8
18
  * @param reflection - The Deepkit type reflection to convert.
9
- * @returns The corresponding JSON Schema representation, or `undefined` if the type cannot be represented.
19
+ * @returns The corresponding JTD form, or `undefined` if the type cannot be represented.
10
20
  */
11
- declare function reflectionToJsonSchema(reflection: Type): JsonSchema7Type | undefined;
21
+ declare function reflectionToJsonSchema<T = unknown, D extends Record<string, unknown> = Record<string, unknown>>(reflection: Type): JTDSchemaType<T, D> | undefined;
12
22
  /**
13
- * Builds a JSON Schema object representation from a Deepkit class or object literal type.
23
+ * Builds a JTD properties form from a Deepkit class or object literal type.
14
24
  *
15
25
  * @param type - The class or object literal type whose members should be serialized.
16
- * @returns A JSON Schema object describing the type's properties.
26
+ * @returns A JTD properties form describing the type's members.
17
27
  */
18
- declare function objectReflectionToJsonSchema(type: TypeObjectLiteral | TypeClass): JsonSchema7Type;
28
+ declare function objectReflectionToJsonSchema<T = unknown, D extends Record<string, unknown> = Record<string, unknown>>(type: TypeObjectLiteral | TypeClass): JTDSchemaType<T, D>;
19
29
  //#endregion
20
30
  export { objectReflectionToJsonSchema, reflectionToJsonSchema };
21
31
  //# sourceMappingURL=reflection.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reflection.d.mts","names":[],"sources":["../src/reflection.ts"],"mappings":";;;;;AAgCA;;;;;iBAAgB,sBAAA,CACd,UAAA,EAAY,IAAA,GACX,eAAA;;;;AAgMH;;;iBAAgB,4BAAA,CACd,IAAA,EAAM,iBAAA,GAAoB,SAAA,GACzB,eAAA"}
1
+ {"version":3,"file":"reflection.d.mts","names":[],"sources":["../src/reflection.ts"],"mappings":";;;;;AA0GA;;;;;;;;;;;;;;;iBAAgB,sBAAA,wBAEJ,MAAA,oBAA0B,MAAA,kBAAA,CACpC,UAAA,EAAY,IAAA,GAAO,aAAA,CAAc,CAAA,EAAG,CAAA;;;;;;;iBAwYtB,4BAAA,wBAEJ,MAAA,oBAA0B,MAAA,kBAAA,CACpC,IAAA,EAAM,iBAAA,GAAoB,SAAA,GAAY,aAAA,CAAc,CAAA,EAAG,CAAA"}