@powerlines/schema 0.11.27 → 0.11.37
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/dist/bundle.cjs +34 -20
- package/dist/bundle.d.cts +3 -3
- package/dist/bundle.d.cts.map +1 -1
- package/dist/bundle.d.mts +3 -3
- package/dist/bundle.d.mts.map +1 -1
- package/dist/bundle.mjs +35 -21
- package/dist/bundle.mjs.map +1 -1
- package/dist/codegen.cjs +40 -36
- package/dist/codegen.d.cts +10 -22
- package/dist/codegen.d.cts.map +1 -1
- package/dist/codegen.d.mts +10 -22
- package/dist/codegen.d.mts.map +1 -1
- package/dist/codegen.mjs +39 -36
- package/dist/codegen.mjs.map +1 -1
- package/dist/constants.cjs +34 -11
- package/dist/constants.d.cts +9 -11
- package/dist/constants.d.cts.map +1 -1
- package/dist/constants.d.mts +9 -11
- package/dist/constants.d.mts.map +1 -1
- package/dist/constants.mjs +32 -11
- package/dist/constants.mjs.map +1 -1
- package/dist/extract.cjs +122 -92
- package/dist/extract.d.cts +34 -69
- package/dist/extract.d.cts.map +1 -1
- package/dist/extract.d.mts +34 -69
- package/dist/extract.d.mts.map +1 -1
- package/dist/extract.mjs +123 -93
- package/dist/extract.mjs.map +1 -1
- package/dist/helpers.cjs +45 -52
- package/dist/helpers.d.cts +28 -24
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.mts +28 -24
- package/dist/helpers.d.mts.map +1 -1
- package/dist/helpers.mjs +46 -52
- package/dist/helpers.mjs.map +1 -1
- package/dist/index.cjs +14 -7
- package/dist/index.d.cts +6 -6
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +5 -5
- package/dist/metadata.cjs +80 -0
- package/dist/metadata.d.cts +52 -0
- package/dist/metadata.d.cts.map +1 -0
- package/dist/metadata.d.mts +52 -0
- package/dist/metadata.d.mts.map +1 -0
- package/dist/metadata.mjs +76 -0
- package/dist/metadata.mjs.map +1 -0
- package/dist/persistence.cjs +1 -2
- package/dist/persistence.d.cts +5 -5
- package/dist/persistence.d.cts.map +1 -1
- package/dist/persistence.d.mts +5 -5
- package/dist/persistence.d.mts.map +1 -1
- package/dist/persistence.mjs +1 -1
- package/dist/persistence.mjs.map +1 -1
- package/dist/reflection.cjs +289 -303
- package/dist/reflection.d.cts +3 -16
- package/dist/reflection.d.cts.map +1 -1
- package/dist/reflection.d.mts +3 -16
- package/dist/reflection.d.mts.map +1 -1
- package/dist/reflection.mjs +290 -304
- package/dist/reflection.mjs.map +1 -1
- package/dist/resolve.cjs +7 -7
- package/dist/resolve.mjs +7 -7
- package/dist/resolve.mjs.map +1 -1
- package/dist/type-checks.cjs +122 -40
- package/dist/type-checks.d.cts +41 -33
- package/dist/type-checks.d.cts.map +1 -1
- package/dist/type-checks.d.mts +41 -33
- package/dist/type-checks.d.mts.map +1 -1
- package/dist/type-checks.mjs +120 -37
- package/dist/type-checks.mjs.map +1 -1
- package/dist/types.d.cts +225 -113
- package/dist/types.d.cts.map +1 -1
- package/dist/types.d.mts +225 -113
- package/dist/types.d.mts.map +1 -1
- package/package.json +11 -7
- package/dist/jtd.cjs +0 -385
- package/dist/jtd.d.cts +0 -15
- package/dist/jtd.d.cts.map +0 -1
- package/dist/jtd.d.mts +0 -15
- package/dist/jtd.d.mts.map +0 -1
- package/dist/jtd.mjs +0 -384
- package/dist/jtd.mjs.map +0 -1
package/dist/reflection.cjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
2
|
const require_runtime = require('./_virtual/_rolldown/runtime.cjs');
|
|
3
|
+
const require_type_checks = require('./type-checks.cjs');
|
|
3
4
|
let defu = require("defu");
|
|
4
5
|
defu = require_runtime.__toESM(defu, 1);
|
|
5
6
|
let _stryke_type_checks = require("@stryke/type-checks");
|
|
@@ -7,234 +8,255 @@ let _powerlines_deepkit_vendor_type = require("@powerlines/deepkit/vendor/type")
|
|
|
7
8
|
|
|
8
9
|
//#region src/reflection.ts
|
|
9
10
|
/**
|
|
10
|
-
* Maps a Deepkit numeric `brand` to
|
|
11
|
+
* Maps a Deepkit numeric `brand` to JSON Schema `type` and `format`.
|
|
11
12
|
*
|
|
12
|
-
* @
|
|
13
|
-
*
|
|
13
|
+
* @remarks
|
|
14
|
+
* This function takes a `TypeNumberBrand` (which represents specific numeric types in Deepkit, such as `integer`, `float`, `int8`, etc.) and returns a corresponding JSON Schema fragment that includes the appropriate `type`, `format`, and any relevant keywords (like `multipleOf` for integers). If the brand is not recognized, it defaults to a generic JSON Schema for numbers.
|
|
15
|
+
*
|
|
16
|
+
* @param brand - The Deepkit numeric brand to convert.
|
|
17
|
+
* @return A JSON Schema fragment representing the numeric type corresponding to the provided brand.
|
|
14
18
|
*/
|
|
15
|
-
function
|
|
19
|
+
function numberBrandToJsonSchema(brand) {
|
|
16
20
|
switch (brand) {
|
|
17
|
-
case _powerlines_deepkit_vendor_type.TypeNumberBrand.integer: return
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
case _powerlines_deepkit_vendor_type.TypeNumberBrand.
|
|
23
|
-
|
|
21
|
+
case _powerlines_deepkit_vendor_type.TypeNumberBrand.integer: return {
|
|
22
|
+
type: "integer",
|
|
23
|
+
format: "int32",
|
|
24
|
+
multipleOf: 1
|
|
25
|
+
};
|
|
26
|
+
case _powerlines_deepkit_vendor_type.TypeNumberBrand.int8: return {
|
|
27
|
+
type: "integer",
|
|
28
|
+
format: "int8",
|
|
29
|
+
multipleOf: 1
|
|
30
|
+
};
|
|
31
|
+
case _powerlines_deepkit_vendor_type.TypeNumberBrand.uint8: return {
|
|
32
|
+
type: "integer",
|
|
33
|
+
format: "uint8",
|
|
34
|
+
multipleOf: 1
|
|
35
|
+
};
|
|
36
|
+
case _powerlines_deepkit_vendor_type.TypeNumberBrand.int16: return {
|
|
37
|
+
type: "integer",
|
|
38
|
+
format: "int16",
|
|
39
|
+
multipleOf: 1
|
|
40
|
+
};
|
|
41
|
+
case _powerlines_deepkit_vendor_type.TypeNumberBrand.uint16: return {
|
|
42
|
+
type: "integer",
|
|
43
|
+
format: "uint16",
|
|
44
|
+
multipleOf: 1
|
|
45
|
+
};
|
|
46
|
+
case _powerlines_deepkit_vendor_type.TypeNumberBrand.int32: return {
|
|
47
|
+
type: "integer",
|
|
48
|
+
format: "int32",
|
|
49
|
+
multipleOf: 1
|
|
50
|
+
};
|
|
51
|
+
case _powerlines_deepkit_vendor_type.TypeNumberBrand.uint32: return {
|
|
52
|
+
type: "integer",
|
|
53
|
+
format: "uint32",
|
|
54
|
+
multipleOf: 1
|
|
55
|
+
};
|
|
24
56
|
case _powerlines_deepkit_vendor_type.TypeNumberBrand.float:
|
|
25
|
-
case _powerlines_deepkit_vendor_type.TypeNumberBrand.float32: return
|
|
26
|
-
|
|
57
|
+
case _powerlines_deepkit_vendor_type.TypeNumberBrand.float32: return {
|
|
58
|
+
type: "number",
|
|
59
|
+
format: "float"
|
|
60
|
+
};
|
|
61
|
+
case _powerlines_deepkit_vendor_type.TypeNumberBrand.float64: return {
|
|
62
|
+
type: "number",
|
|
63
|
+
format: "double"
|
|
64
|
+
};
|
|
27
65
|
case void 0:
|
|
28
|
-
default: return "
|
|
66
|
+
default: return { type: "number" };
|
|
29
67
|
}
|
|
30
68
|
}
|
|
69
|
+
function withReflectionTags(reflection, schema) {
|
|
70
|
+
if (!(0, _stryke_type_checks.isSetObject)(reflection?.tags)) return schema;
|
|
71
|
+
const tags = reflection.tags;
|
|
72
|
+
if ((0, _stryke_type_checks.isSetString)(tags.title)) schema.title = tags.title;
|
|
73
|
+
if ((0, _stryke_type_checks.isSetArray)(tags.alias)) schema.alias = tags.alias;
|
|
74
|
+
if (!(0, _stryke_type_checks.isUndefined)(tags.hidden)) schema.hidden = tags.hidden;
|
|
75
|
+
if (!(0, _stryke_type_checks.isUndefined)(tags.ignore)) schema.ignore = tags.ignore;
|
|
76
|
+
if (!(0, _stryke_type_checks.isUndefined)(tags.internal)) schema.internal = tags.internal;
|
|
77
|
+
if (!(0, _stryke_type_checks.isUndefined)(tags.runtime)) schema.runtime = tags.runtime;
|
|
78
|
+
if (!(0, _stryke_type_checks.isUndefined)(tags.readonly)) schema.readOnly = tags.readonly;
|
|
79
|
+
return schema;
|
|
80
|
+
}
|
|
81
|
+
function withNullable(schema, nullable) {
|
|
82
|
+
if (!nullable) return schema;
|
|
83
|
+
const types = Array.isArray(schema.type) ? [...schema.type] : schema.type ? [schema.type] : [];
|
|
84
|
+
if (!types.includes("null")) types.push("null");
|
|
85
|
+
return {
|
|
86
|
+
...schema,
|
|
87
|
+
type: types.length === 1 ? types[0] : types
|
|
88
|
+
};
|
|
89
|
+
}
|
|
31
90
|
/**
|
|
32
|
-
* Converts a Deepkit type reflection into a JSON
|
|
33
|
-
*
|
|
34
|
-
* @remarks
|
|
35
|
-
* Some TypeScript constructs have no direct JTD equivalent and are handled with the closest available form:
|
|
36
|
-
*
|
|
37
|
-
* - `null` and `undefined` become the empty JTD form with `nullable: true`.
|
|
38
|
-
* - Unions of primitives that cannot be expressed as a JTD enum collapse to the empty form (which validates any value).
|
|
39
|
-
* - String/number/bigint literal unions are emitted as a JTD enum (non-string members are stringified, as JTD requires string enum members).
|
|
40
|
-
* - Tuples are emitted as a JTD elements form whose element schema is the single tuple member type, or the empty schema for mixed tuples.
|
|
41
|
-
* - `Date` is emitted as `{ type: "timestamp" }`.
|
|
42
|
-
* - Discriminated unions of object literals (a shared string-literal tag property) are emitted as a JTD discriminator form.
|
|
43
|
-
*
|
|
44
|
-
* @param reflection - The Deepkit type reflection to convert.
|
|
45
|
-
* @returns The corresponding JTD form, or `undefined` if the type cannot be represented.
|
|
91
|
+
* Converts a Deepkit type reflection into a JSON Schema (draft-07) fragment.
|
|
46
92
|
*/
|
|
47
93
|
function reflectionToJsonSchema(reflection) {
|
|
48
|
-
return
|
|
94
|
+
return reflectionToJsonSchemaInner(reflection);
|
|
49
95
|
}
|
|
50
|
-
|
|
51
|
-
* Internal worker that performs the recursive Deepkit reflection → JTD conversion.
|
|
52
|
-
*
|
|
53
|
-
* @param reflection - The Deepkit type reflection to convert.
|
|
54
|
-
* @returns The corresponding JTD form, or `undefined` if the type cannot be represented.
|
|
55
|
-
*/
|
|
56
|
-
function reflectionToJtd(reflection) {
|
|
57
|
-
const schema = {};
|
|
58
|
-
if ((0, _stryke_type_checks.isSetObject)(reflection?.tags)) {
|
|
59
|
-
const tags = reflection.tags;
|
|
60
|
-
schema.metadata = schema.metadata ?? {};
|
|
61
|
-
if (tags.readonly === true) schema.metadata.isReadonly = true;
|
|
62
|
-
if (tags.ignore === true) schema.metadata.isIgnored = true;
|
|
63
|
-
if (tags.internal === true) schema.metadata.isInternal = true;
|
|
64
|
-
if (tags.runtime === true) schema.metadata.isRuntime = true;
|
|
65
|
-
if (tags.hidden === true) schema.metadata.isHidden = true;
|
|
66
|
-
if ((0, _stryke_type_checks.isSetArray)(tags.alias)) schema.metadata.alias = tags.alias;
|
|
67
|
-
if ((0, _stryke_type_checks.isSetString)(tags.title)) schema.metadata.title = tags.title;
|
|
68
|
-
}
|
|
96
|
+
function reflectionToJsonSchemaInner(reflection) {
|
|
69
97
|
switch (reflection.kind) {
|
|
70
98
|
case _powerlines_deepkit_vendor_type.ReflectionKind.any:
|
|
71
99
|
case _powerlines_deepkit_vendor_type.ReflectionKind.unknown:
|
|
72
100
|
case _powerlines_deepkit_vendor_type.ReflectionKind.void:
|
|
73
|
-
case _powerlines_deepkit_vendor_type.ReflectionKind.object: return {};
|
|
101
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.object: return withReflectionTags(reflection, { name: reflection.typeName });
|
|
74
102
|
case _powerlines_deepkit_vendor_type.ReflectionKind.never: return;
|
|
75
103
|
case _powerlines_deepkit_vendor_type.ReflectionKind.undefined:
|
|
76
|
-
case _powerlines_deepkit_vendor_type.ReflectionKind.null: return {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
};
|
|
81
|
-
case _powerlines_deepkit_vendor_type.ReflectionKind.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
};
|
|
85
|
-
case _powerlines_deepkit_vendor_type.ReflectionKind.
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
};
|
|
89
|
-
case _powerlines_deepkit_vendor_type.ReflectionKind.
|
|
90
|
-
|
|
91
|
-
type: "
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
104
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.null: return withReflectionTags(reflection, {
|
|
105
|
+
type: "null",
|
|
106
|
+
name: reflection.typeName,
|
|
107
|
+
nullable: true
|
|
108
|
+
});
|
|
109
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.string: return withReflectionTags(reflection, {
|
|
110
|
+
type: "string",
|
|
111
|
+
name: reflection.typeName
|
|
112
|
+
});
|
|
113
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.boolean: return withReflectionTags(reflection, {
|
|
114
|
+
type: "boolean",
|
|
115
|
+
name: reflection.typeName
|
|
116
|
+
});
|
|
117
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.number: return withReflectionTags(reflection, numberBrandToJsonSchema(reflection.brand));
|
|
118
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.bigint: return withReflectionTags(reflection, {
|
|
119
|
+
type: "integer",
|
|
120
|
+
name: reflection.typeName,
|
|
121
|
+
format: "int64",
|
|
122
|
+
multipleOf: 1
|
|
123
|
+
});
|
|
124
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.regexp: return withReflectionTags(reflection, {
|
|
125
|
+
type: "string",
|
|
126
|
+
name: reflection.typeName,
|
|
127
|
+
format: "regex",
|
|
128
|
+
contentMediaType: "text/regex"
|
|
129
|
+
});
|
|
97
130
|
case _powerlines_deepkit_vendor_type.ReflectionKind.literal: {
|
|
98
131
|
const { literal } = reflection;
|
|
99
|
-
if (typeof literal === "string") return {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
};
|
|
111
|
-
if (literal instanceof RegExp) return {
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
132
|
+
if (typeof literal === "string" || typeof literal === "number" || typeof literal === "boolean") return withReflectionTags(reflection, {
|
|
133
|
+
type: typeof literal,
|
|
134
|
+
name: reflection.typeName,
|
|
135
|
+
const: literal
|
|
136
|
+
});
|
|
137
|
+
if (typeof literal === "bigint") return withReflectionTags(reflection, {
|
|
138
|
+
type: "integer",
|
|
139
|
+
name: reflection.typeName,
|
|
140
|
+
format: "int64",
|
|
141
|
+
multipleOf: 1,
|
|
142
|
+
const: String(literal)
|
|
143
|
+
});
|
|
144
|
+
if (literal instanceof RegExp) return withReflectionTags(reflection, {
|
|
145
|
+
type: "string",
|
|
146
|
+
name: reflection.typeName,
|
|
147
|
+
format: "regex",
|
|
148
|
+
const: literal.source
|
|
149
|
+
});
|
|
150
|
+
return withReflectionTags(reflection, { name: reflection.typeName });
|
|
116
151
|
}
|
|
117
|
-
case _powerlines_deepkit_vendor_type.ReflectionKind.templateLiteral: return {
|
|
118
|
-
...schema,
|
|
119
|
-
type: "string"
|
|
120
|
-
};
|
|
152
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.templateLiteral: return withReflectionTags(reflection, { type: "string" });
|
|
121
153
|
case _powerlines_deepkit_vendor_type.ReflectionKind.enum: {
|
|
122
|
-
const values = reflection.values.filter((value) => typeof value === "string" || typeof value === "number"
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
154
|
+
const values = reflection.values.filter((value) => typeof value === "string" || typeof value === "number" || typeof value === "boolean");
|
|
155
|
+
if (values.length === 0) return withReflectionTags(reflection, {
|
|
156
|
+
name: reflection.typeName,
|
|
157
|
+
description: reflection.description
|
|
158
|
+
});
|
|
159
|
+
return withReflectionTags(reflection, {
|
|
160
|
+
name: reflection.typeName,
|
|
161
|
+
description: reflection.description,
|
|
162
|
+
enum: values
|
|
163
|
+
});
|
|
129
164
|
}
|
|
130
165
|
case _powerlines_deepkit_vendor_type.ReflectionKind.array: {
|
|
131
|
-
const items =
|
|
132
|
-
return {
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
166
|
+
const items = reflectionToJsonSchemaInner(reflection.type);
|
|
167
|
+
return withReflectionTags(reflection, {
|
|
168
|
+
type: "array",
|
|
169
|
+
name: reflection.typeName,
|
|
170
|
+
items: items ?? {}
|
|
171
|
+
});
|
|
136
172
|
}
|
|
137
173
|
case _powerlines_deepkit_vendor_type.ReflectionKind.tuple: {
|
|
138
|
-
const items = reflection.types.map((member) =>
|
|
139
|
-
if (items.length
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
};
|
|
174
|
+
const items = reflection.types.map((member) => reflectionToJsonSchemaInner(member.type)).filter((item) => item !== void 0);
|
|
175
|
+
if (items.length <= 1) return withReflectionTags(reflection, {
|
|
176
|
+
type: "array",
|
|
177
|
+
name: reflection.typeName,
|
|
178
|
+
items: items[0] ?? {}
|
|
179
|
+
});
|
|
180
|
+
return withReflectionTags(reflection, {
|
|
181
|
+
type: "array",
|
|
182
|
+
name: reflection.typeName,
|
|
183
|
+
items,
|
|
184
|
+
minItems: items.length,
|
|
185
|
+
maxItems: items.length
|
|
186
|
+
});
|
|
151
187
|
}
|
|
152
188
|
case _powerlines_deepkit_vendor_type.ReflectionKind.union: {
|
|
153
|
-
const branches = reflection.types.map((inner) =>
|
|
189
|
+
const branches = reflection.types.map((inner) => reflectionToJsonSchemaInner(inner)).filter(require_type_checks.isJsonSchema);
|
|
154
190
|
const nullable = reflection.types.some((inner) => inner.kind === _powerlines_deepkit_vendor_type.ReflectionKind.null || inner.kind === _powerlines_deepkit_vendor_type.ReflectionKind.undefined);
|
|
155
|
-
const nonNull = branches.filter((
|
|
156
|
-
if (nonNull.length === 0) return {
|
|
157
|
-
|
|
191
|
+
const nonNull = branches.filter((branch) => branch.type !== "null" && !require_type_checks.isNullOnlyJsonSchema(branch));
|
|
192
|
+
if (nonNull.length === 0) return withReflectionTags(reflection, {
|
|
193
|
+
type: "null",
|
|
158
194
|
nullable: true
|
|
159
|
-
};
|
|
160
|
-
if (nonNull.length === 1) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const merged = Array.from(new Set(nonNull.flatMap((b) => b.enum)));
|
|
170
|
-
const form = {
|
|
171
|
-
...schema,
|
|
172
|
-
enum: merged
|
|
173
|
-
};
|
|
174
|
-
if (nullable) form.nullable = true;
|
|
175
|
-
return {
|
|
176
|
-
...schema,
|
|
177
|
-
...form
|
|
178
|
-
};
|
|
179
|
-
}
|
|
195
|
+
});
|
|
196
|
+
if (nonNull.length === 1) return withNullable(withReflectionTags(reflection, {
|
|
197
|
+
name: reflection.typeName,
|
|
198
|
+
...nonNull[0]
|
|
199
|
+
}), nullable);
|
|
200
|
+
const enumValues = nonNull.map((branch) => branch.const).filter((value) => value !== void 0);
|
|
201
|
+
if (enumValues.length === nonNull.length) return withNullable(withReflectionTags(reflection, {
|
|
202
|
+
name: reflection.typeName,
|
|
203
|
+
enum: enumValues
|
|
204
|
+
}), nullable);
|
|
180
205
|
const discriminator = tryReflectionDiscriminator(reflection.types);
|
|
181
|
-
if (discriminator) {
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (nullable) fallback.nullable = true;
|
|
190
|
-
return {
|
|
191
|
-
...schema,
|
|
192
|
-
...fallback
|
|
193
|
-
};
|
|
206
|
+
if (discriminator) return withNullable(withReflectionTags(reflection, {
|
|
207
|
+
name: reflection.typeName,
|
|
208
|
+
...discriminator
|
|
209
|
+
}), nullable);
|
|
210
|
+
return withNullable(withReflectionTags(reflection, {
|
|
211
|
+
name: reflection.typeName,
|
|
212
|
+
anyOf: nonNull
|
|
213
|
+
}), nullable);
|
|
194
214
|
}
|
|
195
215
|
case _powerlines_deepkit_vendor_type.ReflectionKind.intersection: {
|
|
196
|
-
const members = reflection.types.map((inner) =>
|
|
216
|
+
const members = reflection.types.map((inner) => reflectionToJsonSchemaInner(inner)).filter((item) => item !== void 0);
|
|
197
217
|
if (members.length === 0) return;
|
|
198
|
-
if (members.length === 1) return {
|
|
199
|
-
|
|
200
|
-
...members[0]
|
|
201
|
-
};
|
|
202
|
-
if (members.every((member) => member && isPropertiesForm(member))) return mergePropertiesForms(members);
|
|
203
|
-
return {
|
|
204
|
-
...schema,
|
|
218
|
+
if (members.length === 1) return withReflectionTags(reflection, {
|
|
219
|
+
name: reflection.typeName,
|
|
205
220
|
...members[0]
|
|
206
|
-
};
|
|
221
|
+
});
|
|
222
|
+
if (members.every(require_type_checks.isJsonSchemaObject)) return withReflectionTags(reflection, {
|
|
223
|
+
name: reflection.typeName,
|
|
224
|
+
...mergeObjectSchemas(members)
|
|
225
|
+
});
|
|
226
|
+
return withReflectionTags(reflection, {
|
|
227
|
+
name: reflection.typeName,
|
|
228
|
+
allOf: members
|
|
229
|
+
});
|
|
207
230
|
}
|
|
208
|
-
case _powerlines_deepkit_vendor_type.ReflectionKind.promise: return
|
|
209
|
-
case _powerlines_deepkit_vendor_type.ReflectionKind.objectLiteral: return
|
|
231
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.promise: return reflectionToJsonSchemaInner(reflection.type);
|
|
232
|
+
case _powerlines_deepkit_vendor_type.ReflectionKind.objectLiteral: return objectReflectionToJsonSchema(reflection);
|
|
210
233
|
case _powerlines_deepkit_vendor_type.ReflectionKind.class: switch (reflection.classType?.name) {
|
|
211
|
-
case "Date": return {
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
};
|
|
215
|
-
case "RegExp": return {
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
};
|
|
219
|
-
case "URL": return {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
};
|
|
234
|
+
case "Date": return withReflectionTags(reflection, {
|
|
235
|
+
type: "string",
|
|
236
|
+
format: "date-time"
|
|
237
|
+
});
|
|
238
|
+
case "RegExp": return withReflectionTags(reflection, {
|
|
239
|
+
type: "string",
|
|
240
|
+
format: "regex"
|
|
241
|
+
});
|
|
242
|
+
case "URL": return withReflectionTags(reflection, {
|
|
243
|
+
type: "string",
|
|
244
|
+
format: "uri"
|
|
245
|
+
});
|
|
223
246
|
case "Set": {
|
|
224
247
|
const itemType = reflection.arguments?.[0];
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
};
|
|
248
|
+
return withReflectionTags(reflection, {
|
|
249
|
+
type: "array",
|
|
250
|
+
items: (itemType ? reflectionToJsonSchemaInner(itemType) : void 0) ?? {},
|
|
251
|
+
uniqueItems: true
|
|
252
|
+
});
|
|
230
253
|
}
|
|
231
254
|
case "Map": {
|
|
232
255
|
const valueType = reflection.arguments?.[1];
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
};
|
|
256
|
+
return withReflectionTags(reflection, {
|
|
257
|
+
type: "object",
|
|
258
|
+
additionalProperties: (valueType ? reflectionToJsonSchemaInner(valueType) : void 0) ?? true
|
|
259
|
+
});
|
|
238
260
|
}
|
|
239
261
|
case "Uint8Array":
|
|
240
262
|
case "Uint8ClampedArray":
|
|
@@ -246,12 +268,17 @@ function reflectionToJtd(reflection) {
|
|
|
246
268
|
case "Float32Array":
|
|
247
269
|
case "Float64Array":
|
|
248
270
|
case "BigInt64Array":
|
|
249
|
-
case "BigUint64Array": return {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
271
|
+
case "BigUint64Array": return withReflectionTags(reflection, {
|
|
272
|
+
type: "string",
|
|
273
|
+
format: "byte",
|
|
274
|
+
contentEncoding: "base64"
|
|
275
|
+
});
|
|
253
276
|
case void 0:
|
|
254
|
-
default: return
|
|
277
|
+
default: return withReflectionTags(reflection, {
|
|
278
|
+
name: reflection.typeName,
|
|
279
|
+
description: reflection.description,
|
|
280
|
+
...objectReflectionToJsonSchema(reflection)
|
|
281
|
+
});
|
|
255
282
|
}
|
|
256
283
|
case _powerlines_deepkit_vendor_type.ReflectionKind.symbol:
|
|
257
284
|
case _powerlines_deepkit_vendor_type.ReflectionKind.property:
|
|
@@ -270,72 +297,26 @@ function reflectionToJtd(reflection) {
|
|
|
270
297
|
default: return;
|
|
271
298
|
}
|
|
272
299
|
}
|
|
273
|
-
|
|
274
|
-
* Tests whether a JTD form is an enum form.
|
|
275
|
-
*
|
|
276
|
-
* @param form - The JTD form to inspect.
|
|
277
|
-
* @returns `true` if the form is a JTD enum form.
|
|
278
|
-
*/
|
|
279
|
-
function isEnumForm(form) {
|
|
280
|
-
return Array.isArray(form.enum);
|
|
281
|
-
}
|
|
282
|
-
/**
|
|
283
|
-
* Tests whether a JTD form is a properties form (object).
|
|
284
|
-
*
|
|
285
|
-
* @param form - The JTD form to inspect.
|
|
286
|
-
* @returns `true` if the form is a JTD properties form.
|
|
287
|
-
*/
|
|
288
|
-
function isPropertiesForm(form) {
|
|
289
|
-
return "properties" in form || "optionalProperties" in form;
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Tests whether a JTD form is the empty `{ nullable: true }` placeholder.
|
|
293
|
-
*
|
|
294
|
-
* @param form - The JTD form to inspect.
|
|
295
|
-
* @returns `true` if the form has no shape constraints beyond `nullable`.
|
|
296
|
-
*/
|
|
297
|
-
function isPureNullable(form) {
|
|
298
|
-
return Object.keys(form).filter((k) => k !== "nullable" && k !== "metadata").length === 0 && form.nullable === true;
|
|
299
|
-
}
|
|
300
|
-
/**
|
|
301
|
-
* Shallow-merges two JTD properties forms, unioning their `properties` and `optionalProperties` maps.
|
|
302
|
-
*
|
|
303
|
-
* @param forms - The JTD properties forms to merge.
|
|
304
|
-
* @returns The merged JTD properties form.
|
|
305
|
-
*/
|
|
306
|
-
function mergePropertiesForms(forms) {
|
|
300
|
+
function mergeObjectSchemas(schemas) {
|
|
307
301
|
const merged = {
|
|
302
|
+
type: "object",
|
|
308
303
|
properties: {},
|
|
309
|
-
|
|
304
|
+
required: []
|
|
310
305
|
};
|
|
311
|
-
for (const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (
|
|
315
|
-
if (optionalProperties) (0, defu.default)(merged.optionalProperties, optionalProperties);
|
|
316
|
-
if (form.additionalProperties) merged.additionalProperties = true;
|
|
306
|
+
for (const schema of schemas) {
|
|
307
|
+
if (schema.properties) merged.properties = (0, defu.default)(merged.properties, schema.properties);
|
|
308
|
+
if (schema.required) merged.required = Array.from(new Set([...merged.required ?? [], ...schema.required]));
|
|
309
|
+
if (schema.additionalProperties !== void 0) merged.additionalProperties = schema.additionalProperties;
|
|
317
310
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
const result = {};
|
|
321
|
-
if (hasProperties) result.properties = merged.properties;
|
|
322
|
-
else if (!hasOptional) result.properties = {};
|
|
323
|
-
if (hasOptional) result.optionalProperties = merged.optionalProperties;
|
|
324
|
-
if (merged.additionalProperties) result.additionalProperties = true;
|
|
325
|
-
return result;
|
|
311
|
+
if ((merged.required?.length ?? 0) === 0) delete merged.required;
|
|
312
|
+
return merged;
|
|
326
313
|
}
|
|
327
|
-
/**
|
|
328
|
-
* Detects whether a Deepkit union represents a tagged union and, when so, emits the corresponding JTD discriminator form.
|
|
329
|
-
*
|
|
330
|
-
* @param types - The Deepkit reflection types that make up the union branches.
|
|
331
|
-
* @returns A JTD discriminator form if every non-null branch is an object literal that shares a string-literal tag property, otherwise `undefined`.
|
|
332
|
-
*/
|
|
333
314
|
function tryReflectionDiscriminator(types) {
|
|
334
315
|
const nonNullTypes = types.filter((t) => t.kind !== _powerlines_deepkit_vendor_type.ReflectionKind.null && t.kind !== _powerlines_deepkit_vendor_type.ReflectionKind.undefined);
|
|
335
316
|
const objectBranches = nonNullTypes.filter((t) => t.kind === _powerlines_deepkit_vendor_type.ReflectionKind.objectLiteral || t.kind === _powerlines_deepkit_vendor_type.ReflectionKind.class);
|
|
336
317
|
if (objectBranches.length < 2 || objectBranches.length !== nonNullTypes.length) return;
|
|
337
318
|
let tagKey;
|
|
338
|
-
const
|
|
319
|
+
const branches = [];
|
|
339
320
|
for (const branch of objectBranches) {
|
|
340
321
|
const literalProps = [];
|
|
341
322
|
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({
|
|
@@ -346,72 +327,77 @@ function tryReflectionDiscriminator(types) {
|
|
|
346
327
|
const first = literalProps[0];
|
|
347
328
|
if (!tagKey) tagKey = first.name;
|
|
348
329
|
else if (tagKey !== first.name) return;
|
|
349
|
-
const body =
|
|
330
|
+
const body = objectReflectionToJsonSchema({
|
|
350
331
|
...branch,
|
|
351
332
|
types: branch.types.filter((member) => !((member.kind === _powerlines_deepkit_vendor_type.ReflectionKind.property || member.kind === _powerlines_deepkit_vendor_type.ReflectionKind.propertySignature) && member.name === tagKey))
|
|
352
333
|
});
|
|
353
|
-
if (!body || !
|
|
354
|
-
|
|
334
|
+
if (!body || !require_type_checks.isJsonSchemaObject(body)) return;
|
|
335
|
+
branches.push({
|
|
336
|
+
type: "object",
|
|
337
|
+
properties: {
|
|
338
|
+
[tagKey]: { const: first.literal },
|
|
339
|
+
...body.properties ?? {}
|
|
340
|
+
},
|
|
341
|
+
required: [tagKey, ...body.required ?? []],
|
|
342
|
+
additionalProperties: body.additionalProperties ?? false
|
|
343
|
+
});
|
|
355
344
|
}
|
|
356
345
|
if (!tagKey) return;
|
|
357
346
|
return {
|
|
358
|
-
|
|
359
|
-
|
|
347
|
+
oneOf: branches,
|
|
348
|
+
discriminator: { propertyName: tagKey }
|
|
360
349
|
};
|
|
361
350
|
}
|
|
362
|
-
|
|
363
|
-
* Internal worker that produces a JTD properties form (or `values` form for index signatures alone) from a Deepkit object-like type.
|
|
364
|
-
*
|
|
365
|
-
* @param type - The class or object literal type whose members should be serialized.
|
|
366
|
-
* @returns A JTD properties or values form describing the type's members.
|
|
367
|
-
*/
|
|
368
|
-
function objectReflectionToJtd(type) {
|
|
351
|
+
function objectReflectionToJsonSchema(type) {
|
|
369
352
|
const reflection = _powerlines_deepkit_vendor_type.ReflectionClass.from(type);
|
|
370
|
-
const schema = {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
353
|
+
const schema = {
|
|
354
|
+
type: "object",
|
|
355
|
+
name: reflection.getName(),
|
|
356
|
+
description: reflection.getDescription(),
|
|
357
|
+
properties: {},
|
|
358
|
+
required: [],
|
|
359
|
+
readOnly: reflection.isReadonly(),
|
|
360
|
+
ignore: reflection.isIgnored(),
|
|
361
|
+
internal: reflection.isInternal(),
|
|
362
|
+
runtime: reflection.isRuntime(),
|
|
363
|
+
hidden: reflection.isHidden(),
|
|
364
|
+
primaryKey: reflection.getPrimaries().map((primary) => primary.getNameAsString()),
|
|
365
|
+
...(0, _stryke_type_checks.isSetString)(reflection.databaseSchemaName) ? { databaseSchemaName: reflection.databaseSchemaName } : {},
|
|
366
|
+
...(0, _stryke_type_checks.isSetString)(reflection.getName()) ? { name: reflection.getName() } : {},
|
|
367
|
+
...(0, _stryke_type_checks.isSetString)(reflection.getDescription()) ? { description: reflection.getDescription() } : {},
|
|
368
|
+
...(0, _stryke_type_checks.isSetArray)(reflection.getAlias()) ? { alias: reflection.getAlias() } : {},
|
|
369
|
+
...(0, _stryke_type_checks.isSetString)(reflection.getTitle()) ? { title: reflection.getTitle() } : {}
|
|
370
|
+
};
|
|
371
|
+
for (const propertyReflection of reflection.getProperties()) {
|
|
372
|
+
if (propertyReflection.getKind() === _powerlines_deepkit_vendor_type.ReflectionKind.indexSignature) {
|
|
373
|
+
schema.additionalProperties = reflectionToJsonSchemaInner(propertyReflection.type) ?? true;
|
|
374
|
+
continue;
|
|
375
|
+
}
|
|
376
|
+
let property = reflectionToJsonSchemaInner(propertyReflection.type);
|
|
393
377
|
if (!property) continue;
|
|
394
|
-
property
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
if (propertyReflection.
|
|
410
|
-
|
|
378
|
+
property = {
|
|
379
|
+
...property,
|
|
380
|
+
name: propertyReflection.getNameAsString(),
|
|
381
|
+
description: propertyReflection.getDescription(),
|
|
382
|
+
readOnly: propertyReflection.isReadonly(),
|
|
383
|
+
ignore: propertyReflection.isIgnored(),
|
|
384
|
+
internal: propertyReflection.isInternal(),
|
|
385
|
+
runtime: propertyReflection.isRuntime(),
|
|
386
|
+
hidden: propertyReflection.isHidden(),
|
|
387
|
+
visibility: propertyReflection.isPublic() ? "public" : propertyReflection.isProtected() ? "protected" : propertyReflection.isPrivate() ? "private" : void 0,
|
|
388
|
+
...propertyReflection.hasDefault() ? { default: propertyReflection.getDefaultValue() } : {},
|
|
389
|
+
...(0, _stryke_type_checks.isSetArray)(propertyReflection.getGroups()) ? { tags: propertyReflection.getGroups() } : {},
|
|
390
|
+
...(0, _stryke_type_checks.isSetArray)(propertyReflection.getAlias()) ? { alias: propertyReflection.getAlias() } : {},
|
|
391
|
+
...(0, _stryke_type_checks.isSetString)(propertyReflection.getTitle()) ? { title: propertyReflection.getTitle() } : {}
|
|
392
|
+
};
|
|
393
|
+
if (propertyReflection.isNullable()) property = withNullable(property, true);
|
|
394
|
+
schema.properties ??= {};
|
|
395
|
+
schema.properties[propertyReflection.name] = property;
|
|
396
|
+
if (!propertyReflection.isOptional()) {
|
|
397
|
+
schema.required ??= [];
|
|
398
|
+
schema.required.push(propertyReflection.name);
|
|
399
|
+
}
|
|
411
400
|
}
|
|
412
|
-
if (Object.keys(properties).length > 0) schema.properties = properties;
|
|
413
|
-
else if (Object.keys(optionalProperties).length > 0) schema.optionalProperties = optionalProperties;
|
|
414
|
-
else schema.properties = {};
|
|
415
401
|
return schema;
|
|
416
402
|
}
|
|
417
403
|
|