@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/extract.mjs
CHANGED
|
@@ -1,22 +1,91 @@
|
|
|
1
|
-
import { isExtractedSchema,
|
|
2
|
-
import { jsonSchemaToJtd } from "./jtd.mjs";
|
|
1
|
+
import { isExtractedSchema, isJsonSchema, isSchema, isUntypedInput, isUntypedSchema } from "./type-checks.mjs";
|
|
3
2
|
import { getCacheDirectory, writeSchema } from "./persistence.mjs";
|
|
4
3
|
import { reflectionToJsonSchema } from "./reflection.mjs";
|
|
5
4
|
import { resolve } from "./resolve.mjs";
|
|
6
5
|
import defu from "defu";
|
|
7
6
|
import { isSetString } from "@stryke/type-checks";
|
|
7
|
+
import { isSetObject as isSetObject$1 } from "@stryke/type-checks/is-set-object";
|
|
8
|
+
import { isStandardJsonSchema } from "@stryke/json";
|
|
8
9
|
import { isTypeDefinition } from "@powerlines/core";
|
|
9
|
-
import {
|
|
10
|
+
import { rolldownPlugin } from "@powerlines/deepkit/rolldown-plugin";
|
|
10
11
|
import { isType, stringifyType } from "@powerlines/deepkit/vendor/type";
|
|
11
12
|
import { murmurhash } from "@stryke/hash";
|
|
12
|
-
import { isJsonSchemaObjectType, isStandardJsonSchema } from "@stryke/json";
|
|
13
13
|
import { joinPaths } from "@stryke/path/join";
|
|
14
|
-
import { isSetObject as isSetObject$1 } from "@stryke/type-checks/is-set-object";
|
|
15
14
|
import { extractJsonSchema as extractJsonSchema$1, isZod3Type } from "@stryke/zod";
|
|
16
15
|
|
|
17
16
|
//#region src/extract.ts
|
|
17
|
+
function convertNestedUntypedSchema(value) {
|
|
18
|
+
if (isUntypedSchema(value)) return convertUntypedSchemaToJsonSchema(value);
|
|
19
|
+
if (isSetObject$1(value)) {
|
|
20
|
+
if (isUntypedInput(value)) return convertUntypedInputToJsonSchema(value);
|
|
21
|
+
const nested = value;
|
|
22
|
+
if ("$schema" in nested && isUntypedSchema(nested.$schema)) return convertUntypedSchemaToJsonSchema(nested.$schema);
|
|
23
|
+
}
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
function convertNestedUntypedSchemaArray(value) {
|
|
27
|
+
if (!Array.isArray(value)) return value;
|
|
28
|
+
return value.map((item) => convertNestedUntypedSchema(item));
|
|
29
|
+
}
|
|
30
|
+
function convertUntypedSchemaToJsonSchema(schema) {
|
|
31
|
+
const source = schema;
|
|
32
|
+
const jsonSchema = {};
|
|
33
|
+
for (const [key, value] of Object.entries(source)) {
|
|
34
|
+
if (key === "tsType" || key === "markdownType" || key === "tags" || key === "args" || key === "resolve") continue;
|
|
35
|
+
if (key === "id" && isSetString(value)) {
|
|
36
|
+
jsonSchema.$id = value;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (key === "properties" || key === "patternProperties" || key === "dependentSchemas" || key === "$defs" || key === "definitions") {
|
|
40
|
+
if (!isSetObject$1(value)) {
|
|
41
|
+
jsonSchema[key] = value;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
jsonSchema[key] = Object.fromEntries(Object.entries(value).map(([propertyKey, propertyValue]) => [propertyKey, convertNestedUntypedSchema(propertyValue)]));
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (key === "items" || key === "contains" || key === "if" || key === "then" || key === "else" || key === "not" || key === "propertyNames" || key === "additionalProperties" || key === "unevaluatedProperties") {
|
|
48
|
+
jsonSchema[key] = convertNestedUntypedSchema(value);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (key === "oneOf" || key === "anyOf" || key === "allOf") {
|
|
52
|
+
jsonSchema[key] = convertNestedUntypedSchemaArray(value);
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
jsonSchema[key] = value;
|
|
56
|
+
}
|
|
57
|
+
return jsonSchema;
|
|
58
|
+
}
|
|
59
|
+
function convertUntypedInputToJsonSchema(input) {
|
|
60
|
+
const inputObject = input;
|
|
61
|
+
const base = isUntypedSchema(inputObject.$schema) ? convertUntypedSchemaToJsonSchema(inputObject.$schema) : {};
|
|
62
|
+
const properties = {};
|
|
63
|
+
for (const [key, value] of Object.entries(inputObject)) {
|
|
64
|
+
if (key.startsWith("$")) continue;
|
|
65
|
+
if (!isSetObject$1(value)) continue;
|
|
66
|
+
if (isUntypedInput(value)) {
|
|
67
|
+
properties[key] = convertUntypedInputToJsonSchema(value);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const nested = value;
|
|
71
|
+
if ("$schema" in nested && isUntypedSchema(nested.$schema)) {
|
|
72
|
+
properties[key] = convertUntypedSchemaToJsonSchema(nested.$schema);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (isUntypedSchema(value)) properties[key] = convertUntypedSchemaToJsonSchema(value);
|
|
76
|
+
}
|
|
77
|
+
const mergedProperties = {
|
|
78
|
+
...isSetObject$1(base.properties) ? base.properties : {},
|
|
79
|
+
...properties
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
...base,
|
|
83
|
+
type: base.type ?? "object",
|
|
84
|
+
...Object.keys(mergedProperties).length > 0 ? { properties: mergedProperties } : {}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
18
87
|
/**
|
|
19
|
-
* Creates a hash string for a given schema definition input.
|
|
88
|
+
* Creates a hash string for a given schema definition input.
|
|
20
89
|
*/
|
|
21
90
|
function extractHash(variant, input) {
|
|
22
91
|
if (isSetString(input)) return murmurhash({
|
|
@@ -32,10 +101,18 @@ function extractHash(variant, input) {
|
|
|
32
101
|
variant,
|
|
33
102
|
input: input["~standard"]
|
|
34
103
|
});
|
|
35
|
-
else if (
|
|
104
|
+
else if (isJsonSchema(input)) return murmurhash({
|
|
36
105
|
variant,
|
|
37
106
|
input
|
|
38
107
|
});
|
|
108
|
+
else if (isUntypedInput(input)) return murmurhash({
|
|
109
|
+
variant,
|
|
110
|
+
input: convertUntypedInputToJsonSchema(input)
|
|
111
|
+
});
|
|
112
|
+
else if (isUntypedSchema(input)) return murmurhash({
|
|
113
|
+
variant,
|
|
114
|
+
input: convertUntypedSchemaToJsonSchema(input)
|
|
115
|
+
});
|
|
39
116
|
else if (isType(input)) return murmurhash({
|
|
40
117
|
variant,
|
|
41
118
|
input: stringifyType(input)
|
|
@@ -44,95 +121,47 @@ function extractHash(variant, input) {
|
|
|
44
121
|
throw new Error(`Failed to create an input hash for the provided schema definition input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a reflected Deepkit Type object.`);
|
|
45
122
|
}
|
|
46
123
|
/**
|
|
47
|
-
* Converts a reflected Deepkit {@link
|
|
48
|
-
*
|
|
49
|
-
* @remarks
|
|
50
|
-
* This function delegates to an internal recursive walker that handles the full set of Deepkit reflection kinds.
|
|
51
|
-
*
|
|
52
|
-
* @param reflection - The reflected Deepkit Type to convert.
|
|
53
|
-
* @returns A JSON Schema (draft-07) fragment representing the type, or `undefined` when no schema could be produced.
|
|
124
|
+
* Converts a reflected Deepkit {@link Type} into a JSON Schema (draft-07) representation.
|
|
54
125
|
*/
|
|
55
126
|
function extractReflection(reflection) {
|
|
56
127
|
if (!isType(reflection)) return;
|
|
57
128
|
return reflectionToJsonSchema(reflection);
|
|
58
129
|
}
|
|
59
130
|
/**
|
|
60
|
-
* Extracts a JSON
|
|
61
|
-
*
|
|
62
|
-
* @remarks
|
|
63
|
-
* This function checks if the provided input is a Zod schema, a Standard JSON Schema, or already a JSON Schema object, extracts a JSON Schema fragment via the appropriate adapter (Zod and Standard Schema produce draft-07 fragments), and then converts that fragment into a valid JTD form suitable for AJV's JTD validator.
|
|
64
|
-
*
|
|
65
|
-
* @param schema - The schema definition to extract from. This can be a Zod schema, a Standard JSON Schema, or a JSON Schema object.
|
|
66
|
-
* @returns The extracted JTD schema if successful, otherwise undefined.
|
|
131
|
+
* Extracts a JSON Schema from Zod, Standard Schema, untyped, or JSON Schema inputs.
|
|
67
132
|
*/
|
|
68
133
|
function extractJsonSchema(schema) {
|
|
69
|
-
if (isSetObject$1(schema) && (isZod3Type(schema) || isStandardJsonSchema(schema) ||
|
|
70
|
-
|
|
71
|
-
if (
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
const jtd = jsonSchemaToJtd(jsonSchema);
|
|
76
|
-
if (jtd) return jtd;
|
|
134
|
+
if (isSetObject$1(schema) && (isZod3Type(schema) || isStandardJsonSchema(schema) || isJsonSchema(schema) || isUntypedInput(schema) || isUntypedSchema(schema))) {
|
|
135
|
+
if (isZod3Type(schema)) return extractJsonSchema$1(schema);
|
|
136
|
+
if (isStandardJsonSchema(schema)) return schema["~standard"].jsonSchema.input({ target: "draft-2020-12" });
|
|
137
|
+
if (isUntypedInput(schema)) return convertUntypedInputToJsonSchema(schema);
|
|
138
|
+
if (isUntypedSchema(schema)) return convertUntypedSchemaToJsonSchema(schema);
|
|
139
|
+
return schema;
|
|
77
140
|
}
|
|
78
141
|
}
|
|
79
|
-
/**
|
|
80
|
-
* Extracts a schema definition from a given input object, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a reflected Deepkit Type object. The function checks the type of the input and attempts to extract the corresponding schema based on its variant. If the input is a Zod schema, it extracts the JSON Schema using the `extractJsonSchema` function. If the input is a Standard JSON Schema, it retrieves the JSON Schema targeting draft-07. If the input is already a JSON Schema object, it uses it directly. If the input is a reflected Deepkit Type object, it extracts the schema using the `extractReflection` function. The function returns a `Schema` containing the extracted schema and its variant if successful; otherwise, it throws an error.
|
|
81
|
-
*
|
|
82
|
-
* @param input - The input object to extract the schema definition from.
|
|
83
|
-
* @returns A `Schema` containing the extracted schema and its variant if successful.
|
|
84
|
-
* @throws An error if the input does not contain a valid schema definition.
|
|
85
|
-
*/
|
|
86
142
|
function extractResolvedVariant(input) {
|
|
87
143
|
if (isSetObject$1(input)) {
|
|
88
144
|
if (isZod3Type(input)) return "zod3";
|
|
89
145
|
else if (isStandardJsonSchema(input)) return "standard-schema";
|
|
90
|
-
else if (
|
|
91
|
-
else if (isJsonSchemaObjectType(input)) return "json-schema";
|
|
146
|
+
else if (isJsonSchema(input)) return "json-schema";
|
|
92
147
|
else if (isType(input)) return "reflection";
|
|
93
148
|
else if (isUntypedInput(input) || isUntypedSchema(input)) return "untyped";
|
|
94
149
|
}
|
|
95
150
|
throw new Error(`Failed to determine the variant of the provided schema definition input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, a reflected Deepkit Type object, or an Untyped schema.`);
|
|
96
151
|
}
|
|
97
|
-
/**
|
|
98
|
-
* Extracts a schema definition from a given input object, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, a reflected Deepkit Type object, or an Untyped schema. The function checks the type of the input and attempts to extract the corresponding schema based on its variant. If the input is a Zod schema, it extracts the JSON Schema using the `extractJsonSchema` function. If the input is a Standard JSON Schema, it retrieves the JSON Schema targeting draft-07. If the input is already a JSON Schema object, it uses it directly. If the input is a reflected Deepkit Type object, it extracts the schema using the `extractReflection` function. The function returns a `Schema` containing the extracted schema and its variant if successful; otherwise, it throws an error.
|
|
99
|
-
*
|
|
100
|
-
* @param input - The input object to extract the schema definition from.
|
|
101
|
-
* @returns A `Schema` containing the extracted schema and its variant if successful.
|
|
102
|
-
* @throws An error if the input does not contain a valid schema definition.
|
|
103
|
-
*/
|
|
104
152
|
function extractVariant(input) {
|
|
105
153
|
if (isSetString(input) || isTypeDefinition(input)) return "type-definition";
|
|
106
154
|
return extractResolvedVariant(input);
|
|
107
155
|
}
|
|
108
|
-
/**
|
|
109
|
-
* Extracts a JSON Schema object from a given schema definition input. The input can be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a reflected Deepkit Type object. The function checks the type of the input and attempts to extract the corresponding JSON Schema based on its variant. If the input is a Zod schema, it extracts the JSON Schema using the `extractJsonSchema` function. If the input is a Standard JSON Schema, it retrieves the JSON Schema targeting draft-07. If the input is already a JSON Schema object, it uses it directly. If the input is a reflected Deepkit Type object, it extracts the schema using the `extractReflection` function. The function returns the extracted JSON Schema if successful; otherwise, it throws an error.
|
|
110
|
-
*
|
|
111
|
-
* @param input - The schema definition input to extract the JSON Schema from. This can be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a TypeScript type definition.
|
|
112
|
-
* @param variant - The variant of the schema definition to extract.
|
|
113
|
-
* @returns The extracted JSON Schema if successful.
|
|
114
|
-
* @throws An error if the input does not contain a valid schema definition.
|
|
115
|
-
*/
|
|
116
156
|
async function extractSchemaSchema(input, variant) {
|
|
117
157
|
if (isExtractedSchema(input)) return input.schema;
|
|
118
158
|
const resolvedVariant = variant ?? extractResolvedVariant(input);
|
|
119
159
|
let schema;
|
|
120
|
-
if (resolvedVariant === "zod3" || resolvedVariant === "json-schema" || resolvedVariant === "standard-schema" || resolvedVariant === "untyped")
|
|
121
|
-
|
|
122
|
-
if (jsonSchema) schema = jsonSchemaToJtd(jsonSchema);
|
|
123
|
-
} else if (resolvedVariant === "reflection") schema = extractReflection(input);
|
|
124
|
-
else if (resolvedVariant === "jtd-schema") schema = input;
|
|
160
|
+
if (resolvedVariant === "zod3" || resolvedVariant === "json-schema" || resolvedVariant === "standard-schema" || resolvedVariant === "untyped") schema = extractJsonSchema(input);
|
|
161
|
+
else if (resolvedVariant === "reflection") schema = extractReflection(input);
|
|
125
162
|
if (schema) return schema;
|
|
126
|
-
throw new Error(`Failed to extract a valid schema from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object,
|
|
163
|
+
throw new Error(`Failed to extract a valid schema from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object.`);
|
|
127
164
|
}
|
|
128
|
-
/**
|
|
129
|
-
* Extracts a schema definition from a given input object, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, a JTD schema, an untyped schema, or a reflected Deepkit Type object. The function checks the type of the input and attempts to extract the corresponding schema based on its variant. If the input is a Zod schema, it extracts the JSON Schema using the `extractJsonSchema` function. If the input is a Standard JSON Schema, it retrieves the JSON Schema targeting draft-07. If the input is already a JSON Schema object, it uses it directly. If the input is a reflected Deepkit Type object, it extracts the schema using the `extractReflection` function. The function returns a `Schema` containing the extracted schema and its variant if successful; otherwise, it throws an error.
|
|
130
|
-
*
|
|
131
|
-
* @param variant - The variant of the schema definition to extract.
|
|
132
|
-
* @param input - The input object to extract the schema definition from.
|
|
133
|
-
* @returns A `Schema` containing the extracted schema and its variant if successful.
|
|
134
|
-
* @throws An error if the input does not contain a valid schema definition.
|
|
135
|
-
*/
|
|
136
165
|
function extractSource(variant, input) {
|
|
137
166
|
if (variant === "zod3") return {
|
|
138
167
|
hash: extractHash(variant, input),
|
|
@@ -159,40 +188,41 @@ function extractSource(variant, input) {
|
|
|
159
188
|
variant: "reflection",
|
|
160
189
|
schema: input
|
|
161
190
|
};
|
|
162
|
-
|
|
163
|
-
hash: extractHash(variant, input),
|
|
164
|
-
variant: "jtd-schema",
|
|
165
|
-
schema: input
|
|
166
|
-
};
|
|
167
|
-
throw new Error(`Failed to extract source information from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, a JTD schema, an untyped schema, or a reflected Deepkit Type object.`);
|
|
191
|
+
throw new Error(`Failed to extract source information from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object.`);
|
|
168
192
|
}
|
|
169
193
|
/**
|
|
170
|
-
*
|
|
194
|
+
* Extracts a JSON Schema from a given schema definition input, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object. If the input is a type definition reference (e.g. a file path with an export), it will be resolved and bundled using ESBuild to obtain the actual schema definition before extraction.
|
|
171
195
|
*
|
|
172
196
|
* @example
|
|
173
197
|
* ```ts
|
|
174
198
|
* // Resolve a schema definition from a file path
|
|
175
|
-
* const schema1 = await
|
|
199
|
+
* const schema1 = await extract(context, "./schemas.ts#MySchema");
|
|
176
200
|
* // Resolve a schema definition from a JSON Schema object
|
|
177
|
-
* const schema2 = await
|
|
201
|
+
* const schema2 = await extract(context, schemaObject);
|
|
178
202
|
* // Resolve a schema definition from a Zod schema
|
|
179
|
-
* const schema3 = await
|
|
203
|
+
* const schema3 = await extract(context, zodSchema);
|
|
180
204
|
* // Resolve a schema definition from a reflected Deepkit Type object
|
|
181
|
-
* const schema4 = await
|
|
205
|
+
* const schema4 = await extract(context, reflectionType);
|
|
182
206
|
* ```
|
|
183
207
|
*
|
|
184
|
-
* @
|
|
185
|
-
* @
|
|
186
|
-
* @
|
|
187
|
-
* @
|
|
208
|
+
* @see https://github.com/colinhacks/zod
|
|
209
|
+
* @see https://standardschema.dev/json-schema#what-schema-libraries-support-this-spec
|
|
210
|
+
* @see https://json-schema.org/
|
|
211
|
+
* @see https://ajv.js.org/json-type-definition.html
|
|
212
|
+
* @see https://deepkit.io/en/documentation/runtime-types/reflection
|
|
213
|
+
*
|
|
214
|
+
* @param context - The context object providing access to the file system and cache path.
|
|
215
|
+
* @param input - The schema definition input to extract, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object. If the input is a string or a type definition reference, it will be resolved and bundled to obtain the actual schema definition before extraction.
|
|
216
|
+
* @param options - Optional overrides for the ESBuild configuration used during extraction. This can include custom plugins, loaders, or other build options to control how the schema definition is resolved and bundled when the input is a type definition reference.
|
|
217
|
+
* @returns A promise that resolves to the extracted and normalized schema as a JSON Schema object. The function will attempt to extract a valid JSON Schema from the provided input, and if successful, it will return the schema. If the extraction process fails or if the input is not a valid schema definition, it will throw an error indicating the failure.
|
|
188
218
|
*/
|
|
189
219
|
async function extractSchema(context, input, options = {}) {
|
|
190
220
|
if (isExtractedSchema(input)) return input;
|
|
191
221
|
if (isSchema(input)) return {
|
|
192
222
|
...input,
|
|
193
223
|
source: {
|
|
194
|
-
hash: extractHash("
|
|
195
|
-
variant: "
|
|
224
|
+
hash: extractHash("json-schema", input.schema),
|
|
225
|
+
variant: "json-schema",
|
|
196
226
|
schema: input.schema
|
|
197
227
|
}
|
|
198
228
|
};
|
|
@@ -200,20 +230,19 @@ async function extractSchema(context, input, options = {}) {
|
|
|
200
230
|
const variant = extractVariant(input);
|
|
201
231
|
const hash = extractHash(variant, input);
|
|
202
232
|
if (variant === "type-definition") {
|
|
203
|
-
const resolved = await resolve(context, input, defu(options, { plugins: [
|
|
233
|
+
const resolved = await resolve(context, input, defu(options, { plugins: [rolldownPlugin(context, {
|
|
204
234
|
reflection: "default",
|
|
205
235
|
level: "all"
|
|
206
236
|
})] }));
|
|
207
237
|
source = extractSource(extractResolvedVariant(resolved), resolved);
|
|
208
238
|
} else if ([
|
|
209
239
|
"json-schema",
|
|
210
|
-
"jtd-schema",
|
|
211
240
|
"standard-schema",
|
|
212
241
|
"zod3",
|
|
213
242
|
"untyped",
|
|
214
243
|
"reflection"
|
|
215
244
|
].includes(variant)) source = extractSource(variant, input);
|
|
216
|
-
else throw new Error(`Invalid schema definition input "${variant}". The variant must be one of "type-definition", "json-schema", "
|
|
245
|
+
else throw new Error(`Invalid schema definition input "${variant}". The variant must be one of "type-definition", "json-schema", "standard-schema", "zod3", "untyped", or "reflection".`);
|
|
217
246
|
return {
|
|
218
247
|
variant,
|
|
219
248
|
source,
|
|
@@ -222,7 +251,7 @@ async function extractSchema(context, input, options = {}) {
|
|
|
222
251
|
};
|
|
223
252
|
}
|
|
224
253
|
/**
|
|
225
|
-
*
|
|
254
|
+
* Extracts a JSON Schema from a given schema definition input, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object. If the input is a type definition reference (e.g. a file path with an export), it will be resolved and bundled using ESBuild to obtain the actual schema definition before extraction.
|
|
226
255
|
*
|
|
227
256
|
* @example
|
|
228
257
|
* ```ts
|
|
@@ -244,10 +273,11 @@ async function extractSchema(context, input, options = {}) {
|
|
|
244
273
|
* @see https://github.com/unjs/untyped
|
|
245
274
|
* @see https://www.typescriptlang.org/docs/handbook/2/types-from-types.html
|
|
246
275
|
*
|
|
247
|
-
* @param context - The
|
|
248
|
-
* @param input - The
|
|
249
|
-
* @param options - Optional overrides for the
|
|
250
|
-
* @returns A promise that resolves to
|
|
276
|
+
* @param context - The context object providing access to the file system and cache path.
|
|
277
|
+
* @param input - The schema definition input to extract, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object.
|
|
278
|
+
* @param options - Optional overrides for the ESBuild configuration used during extraction.
|
|
279
|
+
* @returns A promise that resolves to the extracted and normalized schema as a JSON Schema object.
|
|
280
|
+
* @throws Will throw an error if the input is not a valid schema definition or if the extraction process fails to produce a valid schema.
|
|
251
281
|
*/
|
|
252
282
|
async function extract(context, input, options = {}) {
|
|
253
283
|
if (isExtractedSchema(input) || isSchema(input)) return input;
|
|
@@ -264,7 +294,7 @@ async function extract(context, input, options = {}) {
|
|
|
264
294
|
};
|
|
265
295
|
}
|
|
266
296
|
result ??= await extractSchema(context, input, options);
|
|
267
|
-
if (!result?.schema) throw new Error(`Failed to extract a valid schema from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object,
|
|
297
|
+
if (!result?.schema) throw new Error(`Failed to extract a valid schema from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object.`);
|
|
268
298
|
if (context.config.skipCache !== true) await writeSchema(context, result);
|
|
269
299
|
return result;
|
|
270
300
|
}
|
package/dist/extract.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extract.mjs","names":["isSetObject","extractJsonSchemaZod"],"sources":["../src/extract.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type { Context } from \"@powerlines/core\";\nimport { isTypeDefinition } from \"@powerlines/core\";\nimport { esbuildPlugin } from \"@powerlines/deepkit/esbuild-plugin\";\nimport { isType, stringifyType, Type } from \"@powerlines/deepkit/vendor/type\";\nimport { StandardJSONSchemaV1 } from \"@standard-schema/spec\";\nimport { murmurhash } from \"@stryke/hash\";\nimport {\n isJsonSchemaObjectType,\n isStandardJsonSchema,\n JsonSchemaType\n} from \"@stryke/json\";\nimport { joinPaths } from \"@stryke/path/join\";\nimport { isSetString } from \"@stryke/type-checks\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport {\n extractJsonSchema as extractJsonSchemaZod,\n isZod3Type\n} from \"@stryke/zod\";\nimport defu from \"defu\";\nimport type { BuildOptions } from \"esbuild\";\nimport * as z3 from \"zod/v3\";\nimport { jsonSchemaToJtd } from \"./jtd\";\nimport { getCacheDirectory, writeSchema } from \"./persistence\";\nimport { reflectionToJsonSchema } from \"./reflection\";\nimport { resolve } from \"./resolve\";\nimport {\n isExtractedSchema,\n isJTDSchema,\n isSchema,\n isUntypedInput,\n isUntypedSchema\n} from \"./type-checks\";\nimport {\n ExtractedSchema,\n JsonSchemaLike,\n JTDSchemaType,\n Schema,\n SchemaInput,\n SchemaInputVariant,\n SchemaMetadata,\n SchemaSource,\n SchemaSourceInput,\n SchemaSourceVariant,\n TypeDefinitionReference,\n UntypedInputObject,\n UntypedSchema\n} from \"./types\";\n\n/**\n * Creates a hash string for a given schema definition input. The function checks the type of the input and generates a hash based on its content. If the input is a Zod schema, it hashes the JSON representation of its internal definition. If the input is a Standard JSON Schema, it hashes the JSON representation of its internal standard schema. If the input is already a JSON Schema object, it hashes its JSON representation directly. If the input is a reflected Deepkit Type object, it hashes its JSON representation. The resulting hash string can be used for caching or comparison purposes.\n */\nexport function extractHash(\n variant: SchemaInputVariant,\n input: SchemaInput\n): string {\n if (isSetString(input)) {\n return murmurhash({ variant, input });\n } else if (isSetObject(input)) {\n if (isZod3Type(input)) {\n return murmurhash({ variant, input: input._def });\n } else if (isStandardJsonSchema(input)) {\n return murmurhash({ variant, input: input[\"~standard\"] });\n } else if (isJsonSchemaObjectType(input)) {\n return murmurhash({ variant, input });\n } else if (isType(input)) {\n return murmurhash({ variant, input: stringifyType(input) });\n }\n }\n\n throw new Error(\n `Failed to create an input hash for the provided schema definition input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a reflected Deepkit Type object.`\n );\n}\n\n/**\n * Converts a reflected Deepkit {@link @powerlines/deepkit/vendor/type#Type} into a JSON Schema (draft-07) representation.\n *\n * @remarks\n * This function delegates to an internal recursive walker that handles the full set of Deepkit reflection kinds.\n *\n * @param reflection - The reflected Deepkit Type to convert.\n * @returns A JSON Schema (draft-07) fragment representing the type, or `undefined` when no schema could be produced.\n */\nexport function extractReflection<\n TMetadata extends Partial<SchemaMetadata> = Partial<SchemaMetadata>\n>(reflection: Type): JTDSchemaType<TMetadata> | undefined {\n if (!isType(reflection)) {\n return undefined;\n }\n\n return reflectionToJsonSchema<TMetadata>(reflection);\n}\n\n/**\n * Extracts a JSON Type Definition (RFC 8927) schema from a given schema definition, if possible.\n *\n * @remarks\n * This function checks if the provided input is a Zod schema, a Standard JSON Schema, or already a JSON Schema object, extracts a JSON Schema fragment via the appropriate adapter (Zod and Standard Schema produce draft-07 fragments), and then converts that fragment into a valid JTD form suitable for AJV's JTD validator.\n *\n * @param schema - The schema definition to extract from. This can be a Zod schema, a Standard JSON Schema, or a JSON Schema object.\n * @returns The extracted JTD schema if successful, otherwise undefined.\n */\nexport function extractJsonSchema<\n TMetadata extends Partial<SchemaMetadata> = Partial<SchemaMetadata>\n>(schema: unknown): JTDSchemaType<TMetadata> | undefined {\n if (\n isSetObject(schema) &&\n (isZod3Type(schema) ||\n isStandardJsonSchema(schema) ||\n isJsonSchemaObjectType(schema) ||\n isUntypedInput(schema) ||\n isUntypedSchema(schema))\n ) {\n let jsonSchema: unknown;\n if (isZod3Type(schema)) {\n jsonSchema = extractJsonSchemaZod(schema);\n } else if (isStandardJsonSchema(schema)) {\n jsonSchema = schema[\"~standard\"].jsonSchema.input({\n target: \"draft-2020-12\"\n });\n } else if (isUntypedInput(schema)) {\n jsonSchema = schema.$schema;\n } else {\n jsonSchema = schema;\n }\n\n const jtd = jsonSchemaToJtd<TMetadata>(jsonSchema as JsonSchemaLike);\n if (jtd) {\n return jtd;\n }\n }\n\n return undefined;\n}\n\n/**\n * Extracts a schema definition from a given input object, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a reflected Deepkit Type object. The function checks the type of the input and attempts to extract the corresponding schema based on its variant. If the input is a Zod schema, it extracts the JSON Schema using the `extractJsonSchema` function. If the input is a Standard JSON Schema, it retrieves the JSON Schema targeting draft-07. If the input is already a JSON Schema object, it uses it directly. If the input is a reflected Deepkit Type object, it extracts the schema using the `extractReflection` function. The function returns a `Schema` containing the extracted schema and its variant if successful; otherwise, it throws an error.\n *\n * @param input - The input object to extract the schema definition from.\n * @returns A `Schema` containing the extracted schema and its variant if successful.\n * @throws An error if the input does not contain a valid schema definition.\n */\nexport function extractResolvedVariant(\n input: SchemaSourceInput\n): SchemaSourceVariant {\n if (isSetObject(input)) {\n if (isZod3Type(input)) {\n return \"zod3\";\n } else if (isStandardJsonSchema(input)) {\n return \"standard-schema\";\n } else if (isJTDSchema(input)) {\n return \"jtd-schema\";\n } else if (isJsonSchemaObjectType(input)) {\n return \"json-schema\";\n } else if (isType(input)) {\n return \"reflection\";\n } else if (isUntypedInput(input) || isUntypedSchema(input)) {\n return \"untyped\";\n }\n }\n\n throw new Error(\n `Failed to determine the variant of the provided schema definition input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, a reflected Deepkit Type object, or an Untyped schema.`\n );\n}\n\n/**\n * Extracts a schema definition from a given input object, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, a reflected Deepkit Type object, or an Untyped schema. The function checks the type of the input and attempts to extract the corresponding schema based on its variant. If the input is a Zod schema, it extracts the JSON Schema using the `extractJsonSchema` function. If the input is a Standard JSON Schema, it retrieves the JSON Schema targeting draft-07. If the input is already a JSON Schema object, it uses it directly. If the input is a reflected Deepkit Type object, it extracts the schema using the `extractReflection` function. The function returns a `Schema` containing the extracted schema and its variant if successful; otherwise, it throws an error.\n *\n * @param input - The input object to extract the schema definition from.\n * @returns A `Schema` containing the extracted schema and its variant if successful.\n * @throws An error if the input does not contain a valid schema definition.\n */\nexport function extractVariant(input: SchemaInput): SchemaInputVariant {\n if (isSetString(input) || isTypeDefinition(input)) {\n return \"type-definition\";\n }\n\n return extractResolvedVariant(input as SchemaSourceInput);\n}\n\n/**\n * Extracts a JSON Schema object from a given schema definition input. The input can be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a reflected Deepkit Type object. The function checks the type of the input and attempts to extract the corresponding JSON Schema based on its variant. If the input is a Zod schema, it extracts the JSON Schema using the `extractJsonSchema` function. If the input is a Standard JSON Schema, it retrieves the JSON Schema targeting draft-07. If the input is already a JSON Schema object, it uses it directly. If the input is a reflected Deepkit Type object, it extracts the schema using the `extractReflection` function. The function returns the extracted JSON Schema if successful; otherwise, it throws an error.\n *\n * @param input - The schema definition input to extract the JSON Schema from. This can be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a TypeScript type definition.\n * @param variant - The variant of the schema definition to extract.\n * @returns The extracted JSON Schema if successful.\n * @throws An error if the input does not contain a valid schema definition.\n */\nexport async function extractSchemaSchema<\n TMetadata extends Partial<SchemaMetadata> = Partial<SchemaMetadata>\n>(\n input: SchemaSourceInput,\n variant?: SchemaInputVariant\n): Promise<JTDSchemaType<TMetadata>> {\n if (isExtractedSchema<TMetadata>(input)) {\n return input.schema;\n }\n\n const resolvedVariant = variant ?? extractResolvedVariant(input);\n\n let schema: JTDSchemaType<TMetadata> | undefined;\n if (\n resolvedVariant === \"zod3\" ||\n resolvedVariant === \"json-schema\" ||\n resolvedVariant === \"standard-schema\" ||\n resolvedVariant === \"untyped\"\n ) {\n const jsonSchema = extractJsonSchema<TMetadata>(input);\n if (jsonSchema) {\n schema = jsonSchemaToJtd<TMetadata>(jsonSchema);\n }\n } else if (resolvedVariant === \"reflection\") {\n schema = extractReflection<TMetadata>(input as Type);\n } else if (resolvedVariant === \"jtd-schema\") {\n schema = input as JTDSchemaType<TMetadata>;\n }\n\n if (schema) {\n return schema;\n }\n\n throw new Error(\n `Failed to extract a valid schema from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, a JTD schema, an untyped schema, or a reflected Deepkit Type object.`\n );\n}\n\n/**\n * Extracts a schema definition from a given input object, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, a JTD schema, an untyped schema, or a reflected Deepkit Type object. The function checks the type of the input and attempts to extract the corresponding schema based on its variant. If the input is a Zod schema, it extracts the JSON Schema using the `extractJsonSchema` function. If the input is a Standard JSON Schema, it retrieves the JSON Schema targeting draft-07. If the input is already a JSON Schema object, it uses it directly. If the input is a reflected Deepkit Type object, it extracts the schema using the `extractReflection` function. The function returns a `Schema` containing the extracted schema and its variant if successful; otherwise, it throws an error.\n *\n * @param variant - The variant of the schema definition to extract.\n * @param input - The input object to extract the schema definition from.\n * @returns A `Schema` containing the extracted schema and its variant if successful.\n * @throws An error if the input does not contain a valid schema definition.\n */\nexport function extractSource<\n TMetadata extends Partial<SchemaMetadata> = Partial<SchemaMetadata>\n>(variant: SchemaSourceVariant, input: SchemaSourceInput): SchemaSource {\n if (variant === \"zod3\") {\n return {\n hash: extractHash(variant, input),\n variant: \"zod3\",\n schema: input as z3.ZodTypeAny\n };\n } else if (variant === \"untyped\") {\n return {\n hash: extractHash(variant, input),\n variant: \"untyped\",\n schema: input as UntypedInputObject | UntypedSchema\n };\n } else if (variant === \"standard-schema\") {\n return {\n hash: extractHash(variant, input),\n variant: \"standard-schema\",\n schema: input as StandardJSONSchemaV1\n };\n } else if (variant === \"json-schema\") {\n return {\n hash: extractHash(variant, input),\n variant: \"json-schema\",\n schema: input as JsonSchemaType\n };\n } else if (variant === \"reflection\") {\n return {\n hash: extractHash(variant, input),\n variant: \"reflection\",\n schema: input as Type\n };\n } else if (variant === \"jtd-schema\") {\n return {\n hash: extractHash(variant, input),\n variant: \"jtd-schema\",\n schema: input as JTDSchemaType<TMetadata>\n };\n }\n\n throw new Error(\n `Failed to extract source information from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, a JTD schema, an untyped schema, or a reflected Deepkit Type object.`\n );\n}\n\n/**\n * Resolves the provided entry points to their corresponding type definitions. The function accepts an array of entry points, which can be strings (file paths) or type definition objects. It processes each entry point, resolving file paths and glob patterns to find matching files. For each resolved file, it creates a type definition object and resolves it using the `resolveInput` function. The function returns an array of resolved entry type definitions.\n *\n * @example\n * ```ts\n * // Resolve a schema definition from a file path\n * const schema1 = await extractSchema(context, \"./schemas.ts#MySchema\");\n * // Resolve a schema definition from a JSON Schema object\n * const schema2 = await extractSchema(context, schemaObject);\n * // Resolve a schema definition from a Zod schema\n * const schema3 = await extractSchema(context, zodSchema);\n * // Resolve a schema definition from a reflected Deepkit Type object\n * const schema4 = await extractSchema(context, reflectionType);\n * ```\n *\n * @param context - The plugin context used for resolving the schema definition input.\n * @param input - The schema definition input to extract the JSON Schema from. This can be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a TypeScript type definition.\n * @param options - Optional overrides for the ESBuild configuration used during resolution.\n * @returns A promise that resolves to a {@link ExtractedSchema} containing the extracted JSON Schema and its variant, or the bytecode if JSON Schema extraction is not possible.\n */\nexport async function extractSchema<\n TMetadata extends Partial<SchemaMetadata> = Partial<SchemaMetadata>,\n TContext extends Context = Context\n>(\n context: TContext,\n input: SchemaInput,\n options: Partial<BuildOptions> = {}\n): Promise<ExtractedSchema<TMetadata>> {\n if (isExtractedSchema<TMetadata>(input)) {\n return input;\n }\n\n if (isSchema<TMetadata>(input)) {\n return {\n ...input,\n source: {\n hash: extractHash(\"jtd-schema\", input.schema),\n variant: \"jtd-schema\",\n schema: input.schema\n }\n };\n }\n\n let source: SchemaSource;\n\n const variant = extractVariant(input);\n const hash = extractHash(variant, input);\n\n if (variant === \"type-definition\") {\n const resolved = await resolve<SchemaSourceInput>(\n context,\n input as TypeDefinitionReference,\n defu(options, {\n plugins: [\n esbuildPlugin(context, {\n reflection: \"default\",\n level: \"all\"\n })\n ]\n })\n );\n\n source = extractSource(extractResolvedVariant(resolved), resolved);\n } else if (\n [\n \"json-schema\",\n \"jtd-schema\",\n \"standard-schema\",\n \"zod3\",\n \"untyped\",\n \"reflection\"\n ].includes(variant)\n ) {\n source = extractSource(variant, input as SchemaSourceInput);\n } else {\n throw new Error(\n `Invalid schema definition input \"${\n variant\n }\". The variant must be one of \"type-definition\", \"json-schema\", \"jtd-schema\", \"standard-schema\", \"zod3\", \"untyped\", or \"reflection\".`\n );\n }\n\n return {\n variant,\n source,\n schema: await extractSchemaSchema<TMetadata>(source.schema, source.variant),\n hash\n };\n}\n\n/**\n * Resolves the provided entry points to their corresponding type definitions. The function accepts an array of entry points, which can be strings (file paths) or type definition objects. It processes each entry point, resolving file paths and glob patterns to find matching files. For each resolved file, it creates a type definition object and resolves it using the `resolveInput` function. The function returns an array of resolved entry type definitions.\n *\n * @example\n * ```ts\n * // Resolve a schema definition from a file path\n * const schema1 = await extract(context, \"./schemas.ts#MySchema\");\n * // Resolve a schema definition from a JSON Schema object\n * const schema2 = await extract(context, schemaObject);\n * // Resolve a schema definition from a Zod schema\n * const schema3 = await extract(context, zodSchema);\n * // Resolve a schema definition from a reflected Deepkit Type object\n * const schema4 = await extract(context, reflectionType);\n * ```\n *\n * @see https://github.com/colinhacks/zod\n * @see https://standardschema.dev/json-schema#what-schema-libraries-support-this-spec\n * @see https://json-schema.org/\n * @see https://ajv.js.org/json-type-definition.html\n * @see https://deepkit.io/en/documentation/runtime-types/reflection\n * @see https://github.com/unjs/untyped\n * @see https://www.typescriptlang.org/docs/handbook/2/types-from-types.html\n *\n * @param context - The {@link Context | context} used for resolving the {@link Schema | schema} definition input.\n * @param input - The input object or string to extract the {@link Schema | schema} from. This can be {@link TypeDefinitionReference | a string that references a Typescript module}, a [Zod v3 schema](https://github.com/colinhacks/zod), any type that adheres to [the Standard JSON Schema specification](https://standardschema.dev/json-schema#what-schema-libraries-support-this-spec), a [JSON Schema object](https://json-schema.org/), a [JTD schema object](https://ajv.js.org/json-type-definition.html), an [untyped schema](https://github.com/unjs/untyped), or a [TypeScript type reflection](https://deepkit.io/en/documentation/runtime-types/reflection).\n * @param options - Optional overrides for the [ESBuild configuration](https://esbuild.github.io/api/#general-options) used during resolution.\n * @returns A promise that resolves to a {@link Schema | schema} object parsed from the input.\n */\nexport async function extract<\n TMetadata extends Partial<SchemaMetadata> = Partial<SchemaMetadata>,\n TContext extends Context = Context\n>(\n context: TContext,\n input: SchemaInput,\n options: Partial<BuildOptions> = {}\n): Promise<Schema<TMetadata>> {\n if (isExtractedSchema<TMetadata>(input) || isSchema<TMetadata>(input)) {\n return input;\n }\n\n let result: Schema<TMetadata> | undefined;\n\n const variant = extractVariant(input);\n const hash = extractHash(variant, input);\n\n const cacheFilePath = joinPaths(getCacheDirectory(context), `${hash}.json`);\n if (\n context.config.skipCache !== true &&\n context.fs.existsSync(cacheFilePath)\n ) {\n const schema = await context.fs.read(cacheFilePath);\n if (schema) {\n result = {\n variant,\n hash,\n schema: JSON.parse(schema) as JTDSchemaType<TMetadata>\n };\n }\n }\n\n result ??= await extractSchema<TMetadata>(context, input, options);\n if (!result?.schema) {\n throw new Error(\n `Failed to extract a valid schema from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, a JTD schema, an untyped schema, or a reflected Deepkit Type object.`\n );\n }\n\n if (context.config.skipCache !== true) {\n await writeSchema(context, result);\n }\n\n return result;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extract.mjs","names":["isSetObject","extractJsonSchemaZod"],"sources":["../src/extract.ts"],"sourcesContent":["/* -------------------------------------------------------------------\n\n ⚡ Storm Software - Powerlines\n\n This code was released as part of the Powerlines project. Powerlines\n is maintained by Storm Software under the Apache-2.0 license, and is\n free for commercial and private use. For more information, please visit\n our licensing page at https://stormsoftware.com/licenses/projects/powerlines.\n\n Website: https://stormsoftware.com\n Repository: https://github.com/storm-software/powerlines\n Documentation: https://docs.stormsoftware.com/projects/powerlines\n Contact: https://stormsoftware.com/contact\n\n SPDX-License-Identifier: Apache-2.0\n\n ------------------------------------------------------------------- */\n\nimport type { Context } from \"@powerlines/core\";\nimport { isTypeDefinition } from \"@powerlines/core\";\nimport { rolldownPlugin } from \"@powerlines/deepkit/rolldown-plugin\";\nimport { isType, stringifyType, Type } from \"@powerlines/deepkit/vendor/type\";\nimport { StandardJSONSchemaV1 } from \"@standard-schema/spec\";\nimport { murmurhash } from \"@stryke/hash\";\nimport { isStandardJsonSchema } from \"@stryke/json\";\nimport { joinPaths } from \"@stryke/path/join\";\nimport { isSetString } from \"@stryke/type-checks\";\nimport { isSetObject } from \"@stryke/type-checks/is-set-object\";\nimport {\n extractJsonSchema as extractJsonSchemaZod,\n isZod3Type\n} from \"@stryke/zod\";\nimport defu from \"defu\";\nimport type { BuildOptions } from \"rolldown\";\nimport * as z3 from \"zod/v3\";\nimport { getCacheDirectory, writeSchema } from \"./persistence\";\nimport { reflectionToJsonSchema } from \"./reflection\";\nimport { resolve } from \"./resolve\";\nimport {\n isExtractedSchema,\n isJsonSchema,\n isSchema,\n isUntypedInput,\n isUntypedSchema\n} from \"./type-checks\";\nimport {\n ExtractedSchema,\n JsonSchema,\n Schema,\n SchemaInput,\n SchemaInputVariant,\n SchemaSource,\n SchemaSourceInput,\n SchemaSourceVariant,\n TypeDefinitionReference,\n UntypedInputObject,\n UntypedSchema\n} from \"./types\";\n\nfunction convertNestedUntypedSchema(value: unknown): unknown {\n if (isUntypedSchema(value)) {\n return convertUntypedSchemaToJsonSchema(value);\n }\n\n if (isSetObject(value)) {\n if (isUntypedInput(value)) {\n return convertUntypedInputToJsonSchema(value);\n }\n\n const nested = value as Record<string, unknown>;\n if (\"$schema\" in nested && isUntypedSchema(nested.$schema)) {\n return convertUntypedSchemaToJsonSchema(nested.$schema);\n }\n }\n\n return value;\n}\n\nfunction convertNestedUntypedSchemaArray(value: unknown): unknown {\n if (!Array.isArray(value)) {\n return value;\n }\n\n return value.map(item => convertNestedUntypedSchema(item));\n}\n\nfunction convertUntypedSchemaToJsonSchema<T = unknown>(\n schema: UntypedSchema | Record<string, unknown>\n): JsonSchema<T> {\n const source = schema as Record<string, unknown>;\n const jsonSchema: Record<string, unknown> = {};\n\n for (const [key, value] of Object.entries(source)) {\n if (\n key === \"tsType\" ||\n key === \"markdownType\" ||\n key === \"tags\" ||\n key === \"args\" ||\n key === \"resolve\"\n ) {\n continue;\n }\n\n if (key === \"id\" && isSetString(value)) {\n jsonSchema.$id = value;\n continue;\n }\n\n if (\n key === \"properties\" ||\n key === \"patternProperties\" ||\n key === \"dependentSchemas\" ||\n key === \"$defs\" ||\n key === \"definitions\"\n ) {\n if (!isSetObject(value)) {\n jsonSchema[key] = value;\n continue;\n }\n\n jsonSchema[key] = Object.fromEntries(\n Object.entries(value).map(([propertyKey, propertyValue]) => [\n propertyKey,\n convertNestedUntypedSchema(propertyValue)\n ])\n );\n continue;\n }\n\n if (\n key === \"items\" ||\n key === \"contains\" ||\n key === \"if\" ||\n key === \"then\" ||\n key === \"else\" ||\n key === \"not\" ||\n key === \"propertyNames\" ||\n key === \"additionalProperties\" ||\n key === \"unevaluatedProperties\"\n ) {\n jsonSchema[key] = convertNestedUntypedSchema(value);\n continue;\n }\n\n if (key === \"oneOf\" || key === \"anyOf\" || key === \"allOf\") {\n jsonSchema[key] = convertNestedUntypedSchemaArray(value);\n continue;\n }\n\n jsonSchema[key] = value;\n }\n\n return jsonSchema as JsonSchema<T>;\n}\n\nfunction convertUntypedInputToJsonSchema<T = unknown>(\n input: UntypedInputObject\n): JsonSchema<T> {\n const inputObject = input as Record<string, unknown>;\n const base = isUntypedSchema(inputObject.$schema)\n ? convertUntypedSchemaToJsonSchema<T>(inputObject.$schema)\n : ({} as JsonSchema<T>);\n const properties: Record<string, JsonSchema<T>> = {};\n\n for (const [key, value] of Object.entries(inputObject)) {\n if (key.startsWith(\"$\")) {\n continue;\n }\n\n if (!isSetObject(value)) {\n continue;\n }\n\n if (isUntypedInput(value)) {\n properties[key] = convertUntypedInputToJsonSchema<T>(value);\n continue;\n }\n\n const nested = value as Record<string, unknown>;\n if (\"$schema\" in nested && isUntypedSchema(nested.$schema)) {\n properties[key] = convertUntypedSchemaToJsonSchema<T>(nested.$schema);\n continue;\n }\n\n if (isUntypedSchema(value)) {\n properties[key] = convertUntypedSchemaToJsonSchema<T>(value);\n }\n }\n\n const baseProperties = isSetObject(base.properties)\n ? (base.properties as Record<string, JsonSchema<T>>)\n : {};\n const mergedProperties = {\n ...baseProperties,\n ...properties\n };\n\n return {\n ...base,\n type: base.type ?? \"object\",\n ...(Object.keys(mergedProperties).length > 0\n ? { properties: mergedProperties }\n : {})\n } as JsonSchema<T>;\n}\n\n/**\n * Creates a hash string for a given schema definition input.\n */\nexport function extractHash<T = unknown>(\n variant: SchemaInputVariant,\n input: SchemaInput<T>\n): string {\n if (isSetString(input)) {\n return murmurhash({ variant, input });\n } else if (isSetObject(input)) {\n if (isZod3Type(input)) {\n return murmurhash({ variant, input: input._def });\n } else if (isStandardJsonSchema(input)) {\n return murmurhash({ variant, input: input[\"~standard\"] });\n } else if (isJsonSchema(input)) {\n return murmurhash({ variant, input });\n } else if (isUntypedInput(input)) {\n return murmurhash({\n variant,\n input: convertUntypedInputToJsonSchema(input)\n });\n } else if (isUntypedSchema(input)) {\n return murmurhash({\n variant,\n input: convertUntypedSchemaToJsonSchema(input)\n });\n } else if (isType(input)) {\n return murmurhash({ variant, input: stringifyType(input) });\n }\n }\n\n throw new Error(\n `Failed to create an input hash for the provided schema definition input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, or a reflected Deepkit Type object.`\n );\n}\n\n/**\n * Converts a reflected Deepkit {@link Type} into a JSON Schema (draft-07) representation.\n */\nexport function extractReflection<T = unknown>(\n reflection: Type\n): JsonSchema<T> | undefined {\n if (!isType(reflection)) {\n return undefined;\n }\n\n return reflectionToJsonSchema<T>(reflection);\n}\n\n/**\n * Extracts a JSON Schema from Zod, Standard Schema, untyped, or JSON Schema inputs.\n */\nexport function extractJsonSchema<T = unknown>(\n schema: unknown\n): JsonSchema<T> | undefined {\n if (\n isSetObject(schema) &&\n (isZod3Type(schema) ||\n isStandardJsonSchema(schema) ||\n isJsonSchema(schema) ||\n isUntypedInput(schema) ||\n isUntypedSchema(schema))\n ) {\n if (isZod3Type(schema)) {\n return extractJsonSchemaZod(schema) as JsonSchema<T>;\n }\n if (isStandardJsonSchema(schema)) {\n return schema[\"~standard\"].jsonSchema.input({\n target: \"draft-2020-12\"\n }) as JsonSchema<T>;\n }\n if (isUntypedInput(schema)) {\n return convertUntypedInputToJsonSchema<T>(schema);\n }\n if (isUntypedSchema(schema)) {\n return convertUntypedSchemaToJsonSchema<T>(schema);\n }\n return schema;\n }\n\n return undefined;\n}\n\nexport function extractResolvedVariant(\n input: SchemaSourceInput\n): SchemaSourceVariant {\n if (isSetObject(input)) {\n if (isZod3Type(input)) {\n return \"zod3\";\n } else if (isStandardJsonSchema(input)) {\n return \"standard-schema\";\n } else if (isJsonSchema(input)) {\n return \"json-schema\";\n } else if (isType(input)) {\n return \"reflection\";\n } else if (isUntypedInput(input) || isUntypedSchema(input)) {\n return \"untyped\";\n }\n }\n\n throw new Error(\n `Failed to determine the variant of the provided schema definition input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, a reflected Deepkit Type object, or an Untyped schema.`\n );\n}\n\nexport function extractVariant<T = unknown>(\n input: SchemaInput<T>\n): SchemaInputVariant {\n if (isSetString(input) || isTypeDefinition(input)) {\n return \"type-definition\";\n }\n\n return extractResolvedVariant(input as SchemaSourceInput);\n}\n\nexport async function extractSchemaSchema<T = unknown>(\n input: SchemaSourceInput,\n variant?: SchemaInputVariant\n): Promise<JsonSchema<T>> {\n if (isExtractedSchema<T>(input)) {\n return input.schema;\n }\n\n const resolvedVariant = variant ?? extractResolvedVariant(input);\n\n let schema: JsonSchema<T> | undefined;\n if (\n resolvedVariant === \"zod3\" ||\n resolvedVariant === \"json-schema\" ||\n resolvedVariant === \"standard-schema\" ||\n resolvedVariant === \"untyped\"\n ) {\n schema = extractJsonSchema<T>(input);\n } else if (resolvedVariant === \"reflection\") {\n schema = extractReflection(input as Type);\n }\n\n if (schema) {\n return schema;\n }\n\n throw new Error(\n `Failed to extract a valid schema from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object.`\n );\n}\n\nexport function extractSource(\n variant: SchemaSourceVariant,\n input: SchemaSourceInput\n): SchemaSource {\n if (variant === \"zod3\") {\n return {\n hash: extractHash(variant, input),\n variant: \"zod3\",\n schema: input as z3.ZodTypeAny\n };\n } else if (variant === \"untyped\") {\n return {\n hash: extractHash(variant, input),\n variant: \"untyped\",\n schema: input as UntypedInputObject | UntypedSchema\n };\n } else if (variant === \"standard-schema\") {\n return {\n hash: extractHash(variant, input),\n variant: \"standard-schema\",\n schema: input as StandardJSONSchemaV1\n };\n } else if (variant === \"json-schema\") {\n return {\n hash: extractHash(variant, input),\n variant: \"json-schema\",\n schema: input as JsonSchema\n };\n } else if (variant === \"reflection\") {\n return {\n hash: extractHash(variant, input),\n variant: \"reflection\",\n schema: input as Type\n };\n }\n\n throw new Error(\n `Failed to extract source information from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object.`\n );\n}\n\n/**\n * Extracts a JSON Schema from a given schema definition input, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object. If the input is a type definition reference (e.g. a file path with an export), it will be resolved and bundled using ESBuild to obtain the actual schema definition before extraction.\n *\n * @example\n * ```ts\n * // Resolve a schema definition from a file path\n * const schema1 = await extract(context, \"./schemas.ts#MySchema\");\n * // Resolve a schema definition from a JSON Schema object\n * const schema2 = await extract(context, schemaObject);\n * // Resolve a schema definition from a Zod schema\n * const schema3 = await extract(context, zodSchema);\n * // Resolve a schema definition from a reflected Deepkit Type object\n * const schema4 = await extract(context, reflectionType);\n * ```\n *\n * @see https://github.com/colinhacks/zod\n * @see https://standardschema.dev/json-schema#what-schema-libraries-support-this-spec\n * @see https://json-schema.org/\n * @see https://ajv.js.org/json-type-definition.html\n * @see https://deepkit.io/en/documentation/runtime-types/reflection\n *\n * @param context - The context object providing access to the file system and cache path.\n * @param input - The schema definition input to extract, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object. If the input is a string or a type definition reference, it will be resolved and bundled to obtain the actual schema definition before extraction.\n * @param options - Optional overrides for the ESBuild configuration used during extraction. This can include custom plugins, loaders, or other build options to control how the schema definition is resolved and bundled when the input is a type definition reference.\n * @returns A promise that resolves to the extracted and normalized schema as a JSON Schema object. The function will attempt to extract a valid JSON Schema from the provided input, and if successful, it will return the schema. If the extraction process fails or if the input is not a valid schema definition, it will throw an error indicating the failure.\n */\nexport async function extractSchema<T = unknown>(\n context: Context,\n input: SchemaInput,\n options: Partial<BuildOptions> = {}\n): Promise<ExtractedSchema<T>> {\n if (isExtractedSchema<T>(input)) {\n return input;\n }\n\n if (isSchema<T>(input)) {\n return {\n ...input,\n source: {\n hash: extractHash(\"json-schema\", input.schema),\n variant: \"json-schema\",\n schema: input.schema\n }\n };\n }\n\n let source: SchemaSource;\n\n const variant = extractVariant(input);\n const hash = extractHash(variant, input);\n\n if (variant === \"type-definition\") {\n const resolved = await resolve<SchemaSourceInput>(\n context,\n input as TypeDefinitionReference,\n defu(options, {\n plugins: [\n rolldownPlugin(context, {\n reflection: \"default\",\n level: \"all\"\n })\n ]\n })\n );\n\n source = extractSource(extractResolvedVariant(resolved), resolved);\n } else if (\n [\n \"json-schema\",\n \"standard-schema\",\n \"zod3\",\n \"untyped\",\n \"reflection\"\n ].includes(variant)\n ) {\n source = extractSource(variant, input as SchemaSourceInput);\n } else {\n throw new Error(\n `Invalid schema definition input \"${\n variant\n }\". The variant must be one of \"type-definition\", \"json-schema\", \"standard-schema\", \"zod3\", \"untyped\", or \"reflection\".`\n );\n }\n\n return {\n variant,\n source,\n schema: await extractSchemaSchema<T>(source.schema, source.variant),\n hash\n };\n}\n\n/**\n * Extracts a JSON Schema from a given schema definition input, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object. If the input is a type definition reference (e.g. a file path with an export), it will be resolved and bundled using ESBuild to obtain the actual schema definition before extraction.\n *\n * @example\n * ```ts\n * // Resolve a schema definition from a file path\n * const schema1 = await extract(context, \"./schemas.ts#MySchema\");\n * // Resolve a schema definition from a JSON Schema object\n * const schema2 = await extract(context, schemaObject);\n * // Resolve a schema definition from a Zod schema\n * const schema3 = await extract(context, zodSchema);\n * // Resolve a schema definition from a reflected Deepkit Type object\n * const schema4 = await extract(context, reflectionType);\n * ```\n *\n * @see https://github.com/colinhacks/zod\n * @see https://standardschema.dev/json-schema#what-schema-libraries-support-this-spec\n * @see https://json-schema.org/\n * @see https://ajv.js.org/json-type-definition.html\n * @see https://deepkit.io/en/documentation/runtime-types/reflection\n * @see https://github.com/unjs/untyped\n * @see https://www.typescriptlang.org/docs/handbook/2/types-from-types.html\n *\n * @param context - The context object providing access to the file system and cache path.\n * @param input - The schema definition input to extract, which can be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object.\n * @param options - Optional overrides for the ESBuild configuration used during extraction.\n * @returns A promise that resolves to the extracted and normalized schema as a JSON Schema object.\n * @throws Will throw an error if the input is not a valid schema definition or if the extraction process fails to produce a valid schema.\n */\nexport async function extract<T = unknown>(\n context: Context,\n input: SchemaInput,\n options: Partial<BuildOptions> = {}\n): Promise<Schema<T>> {\n if (isExtractedSchema<T>(input) || isSchema<T>(input)) {\n return input;\n }\n\n let result: Schema<T> | undefined;\n\n const variant = extractVariant(input);\n const hash = extractHash(variant, input);\n\n const cacheFilePath = joinPaths(getCacheDirectory(context), `${hash}.json`);\n if (\n context.config.skipCache !== true &&\n context.fs.existsSync(cacheFilePath)\n ) {\n const schema = await context.fs.read(cacheFilePath);\n if (schema) {\n result = {\n variant,\n hash,\n schema: JSON.parse(schema) as JsonSchema\n };\n }\n }\n\n result ??= await extractSchema<T>(context, input, options);\n if (!result?.schema) {\n throw new Error(\n `Failed to extract a valid schema from the provided input. The input must be a Zod schema, a Standard JSON Schema, a JSON Schema object, an untyped schema, or a reflected Deepkit Type object.`\n );\n }\n\n if (context.config.skipCache !== true) {\n await writeSchema(context, result);\n }\n\n return result;\n}\n"],"mappings":"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"}
|
package/dist/helpers.cjs
CHANGED
|
@@ -1,90 +1,83 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
-
const
|
|
2
|
+
const require_metadata = require('./metadata.cjs');
|
|
3
3
|
const require_type_checks = require('./type-checks.cjs');
|
|
4
4
|
let defu = require("defu");
|
|
5
5
|
let _stryke_type_checks = require("@stryke/type-checks");
|
|
6
6
|
|
|
7
7
|
//#region src/helpers.ts
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Extracts object properties from a JSON Schema object form.
|
|
10
10
|
*
|
|
11
|
-
* @
|
|
12
|
-
*
|
|
11
|
+
* @remarks
|
|
12
|
+
* This function returns an empty object if the schema is not an object form or if it has no properties.
|
|
13
|
+
*
|
|
14
|
+
* @param obj - The JSON Schema object form or a Schema wrapper to extract properties from.
|
|
15
|
+
* @returns An object mapping property names to their corresponding JSON Schema fragments, including metadata.
|
|
13
16
|
*/
|
|
14
17
|
function getProperties(obj) {
|
|
15
18
|
const properties = {};
|
|
16
|
-
const schema = require_type_checks.
|
|
17
|
-
if (
|
|
18
|
-
|
|
19
|
-
name: key,
|
|
20
|
-
optional: true
|
|
21
|
-
};
|
|
22
|
-
if ("properties" in schema && (0, _stryke_type_checks.isSetObject)(schema.properties)) for (const [key, value] of Object.entries(schema.properties)) properties[key] = {
|
|
19
|
+
const schema = require_type_checks.isSchema(obj) ? obj.schema : obj;
|
|
20
|
+
if (!require_type_checks.isJsonSchemaObject(schema) || !(0, _stryke_type_checks.isSetObject)(schema.properties)) return properties;
|
|
21
|
+
for (const [key, value] of Object.entries(schema.properties)) properties[key] = {
|
|
23
22
|
...value,
|
|
24
23
|
name: key,
|
|
25
|
-
|
|
24
|
+
nullable: require_metadata.isSchemaNullable(value) || require_metadata.isPropertyOptional(schema, key)
|
|
26
25
|
};
|
|
27
26
|
return properties;
|
|
28
27
|
}
|
|
29
28
|
/**
|
|
30
|
-
*
|
|
29
|
+
* Returns object properties as an array.
|
|
30
|
+
*
|
|
31
|
+
* @remarks
|
|
32
|
+
* This is a convenience function that extracts properties using `getProperties` and returns them as an array.
|
|
31
33
|
*
|
|
32
|
-
* @param obj - The
|
|
33
|
-
* @returns An array of
|
|
34
|
+
* @param obj - The JSON Schema object form or a Schema wrapper to extract properties from.
|
|
35
|
+
* @returns An array of JSON Schema fragments representing the properties, each including metadata.
|
|
34
36
|
*/
|
|
35
37
|
function getPropertiesList(obj) {
|
|
36
38
|
return Object.values(getProperties(obj));
|
|
37
39
|
}
|
|
38
40
|
/**
|
|
39
|
-
*
|
|
41
|
+
* Adds a property to a JSON Schema object form.
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* This function modifies the provided schema in place by adding a new property with the specified name and schema. It also updates the `required` array based on the `optional` flag of the property. If the property is marked as optional, it will be removed from the `required` array; otherwise, it will be added to it.
|
|
40
45
|
*
|
|
41
|
-
* @param obj - The
|
|
46
|
+
* @param obj - The JSON Schema object form or a Schema wrapper to which the property should be added.
|
|
42
47
|
* @param name - The name of the property to add.
|
|
43
|
-
* @param property - The
|
|
48
|
+
* @param property - The JSON Schema fragment representing the property's schema, including metadata.
|
|
49
|
+
* @throws Will throw an error if the provided schema is not an object form.
|
|
44
50
|
*/
|
|
45
51
|
function addProperty(obj, name, property) {
|
|
46
|
-
const schema = require_type_checks.
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
schema.properties ??= {};
|
|
58
|
-
schema.properties[name] = {
|
|
59
|
-
...property,
|
|
60
|
-
metadata: {
|
|
61
|
-
...property.metadata,
|
|
62
|
-
name
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
}
|
|
52
|
+
const schema = require_type_checks.isSchema(obj) ? obj.schema : obj;
|
|
53
|
+
if (!require_type_checks.isJsonSchemaObject(schema)) throw new Error("Cannot add property to non-object schema");
|
|
54
|
+
schema.properties ??= {};
|
|
55
|
+
schema.required ??= [];
|
|
56
|
+
schema.properties[name] = {
|
|
57
|
+
...property,
|
|
58
|
+
name
|
|
59
|
+
};
|
|
60
|
+
if (property?.optional) schema.required = schema.required.filter((key) => key !== name);
|
|
61
|
+
else if (!schema.required.includes(name)) schema.required.push(name);
|
|
62
|
+
if (schema.required.length === 0) delete schema.required;
|
|
66
63
|
}
|
|
67
64
|
/**
|
|
68
|
-
* Merges multiple
|
|
65
|
+
* Merges multiple JSON Schema object forms into one.
|
|
69
66
|
*
|
|
70
67
|
* @remarks
|
|
71
|
-
* This function
|
|
68
|
+
* This function takes multiple JSON Schema objects or Schema wrappers and merges them into a single JSON Schema object. The merging process combines properties and metadata from all provided schemas, with later schemas in the arguments list taking precedence over earlier ones in case of conflicts. The resulting schema will include all unique properties and metadata from the input schemas.
|
|
72
69
|
*
|
|
73
|
-
* @param schemas - An array of
|
|
74
|
-
* @returns A
|
|
70
|
+
* @param schemas - An array of JSON Schema objects or Schema wrappers to merge.
|
|
71
|
+
* @returns A new JSON Schema object that is the result of merging all input schemas.
|
|
75
72
|
*/
|
|
76
73
|
function mergeSchemas(...schemas) {
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
for (const schema of schemas.reverse()) {
|
|
83
|
-
const properties = getProperties(schema);
|
|
84
|
-
for (const [key, value] of Object.entries(properties)) if (value.optional) mergedSchema.optionalProperties[key] = mergedSchema.optionalProperties[key] && require_type_checks.isJTDSchemaObject(mergedSchema.optionalProperties[key]) && require_type_checks.isJTDSchemaObject(value) ? (0, defu.defu)(mergedSchema.optionalProperties[key], value) : value;
|
|
85
|
-
else mergedSchema.properties[key] = mergedSchema.properties[key] && require_type_checks.isJTDSchemaObject(mergedSchema.properties[key]) && require_type_checks.isJTDSchemaObject(value) ? (0, defu.defu)(mergedSchema.properties[key], value) : value;
|
|
74
|
+
const result = {};
|
|
75
|
+
for (const schema of schemas) {
|
|
76
|
+
const jsonSchema = require_type_checks.isSchema(schema) ? schema.schema : schema;
|
|
77
|
+
if (!require_type_checks.isJsonSchemaObject(jsonSchema)) continue;
|
|
78
|
+
(0, defu.defu)(result, jsonSchema);
|
|
86
79
|
}
|
|
87
|
-
return
|
|
80
|
+
return result;
|
|
88
81
|
}
|
|
89
82
|
|
|
90
83
|
//#endregion
|