@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.
Files changed (82) hide show
  1. package/dist/bundle.cjs +34 -20
  2. package/dist/bundle.d.cts +3 -3
  3. package/dist/bundle.d.cts.map +1 -1
  4. package/dist/bundle.d.mts +3 -3
  5. package/dist/bundle.d.mts.map +1 -1
  6. package/dist/bundle.mjs +35 -21
  7. package/dist/bundle.mjs.map +1 -1
  8. package/dist/codegen.cjs +40 -36
  9. package/dist/codegen.d.cts +10 -22
  10. package/dist/codegen.d.cts.map +1 -1
  11. package/dist/codegen.d.mts +10 -22
  12. package/dist/codegen.d.mts.map +1 -1
  13. package/dist/codegen.mjs +39 -36
  14. package/dist/codegen.mjs.map +1 -1
  15. package/dist/constants.cjs +34 -11
  16. package/dist/constants.d.cts +9 -11
  17. package/dist/constants.d.cts.map +1 -1
  18. package/dist/constants.d.mts +9 -11
  19. package/dist/constants.d.mts.map +1 -1
  20. package/dist/constants.mjs +32 -11
  21. package/dist/constants.mjs.map +1 -1
  22. package/dist/extract.cjs +122 -92
  23. package/dist/extract.d.cts +34 -69
  24. package/dist/extract.d.cts.map +1 -1
  25. package/dist/extract.d.mts +34 -69
  26. package/dist/extract.d.mts.map +1 -1
  27. package/dist/extract.mjs +123 -93
  28. package/dist/extract.mjs.map +1 -1
  29. package/dist/helpers.cjs +45 -52
  30. package/dist/helpers.d.cts +28 -24
  31. package/dist/helpers.d.cts.map +1 -1
  32. package/dist/helpers.d.mts +28 -24
  33. package/dist/helpers.d.mts.map +1 -1
  34. package/dist/helpers.mjs +46 -52
  35. package/dist/helpers.mjs.map +1 -1
  36. package/dist/index.cjs +14 -7
  37. package/dist/index.d.cts +6 -6
  38. package/dist/index.d.mts +6 -6
  39. package/dist/index.mjs +5 -5
  40. package/dist/metadata.cjs +80 -0
  41. package/dist/metadata.d.cts +52 -0
  42. package/dist/metadata.d.cts.map +1 -0
  43. package/dist/metadata.d.mts +52 -0
  44. package/dist/metadata.d.mts.map +1 -0
  45. package/dist/metadata.mjs +76 -0
  46. package/dist/metadata.mjs.map +1 -0
  47. package/dist/persistence.cjs +1 -2
  48. package/dist/persistence.d.cts +5 -5
  49. package/dist/persistence.d.cts.map +1 -1
  50. package/dist/persistence.d.mts +5 -5
  51. package/dist/persistence.d.mts.map +1 -1
  52. package/dist/persistence.mjs +1 -1
  53. package/dist/persistence.mjs.map +1 -1
  54. package/dist/reflection.cjs +289 -303
  55. package/dist/reflection.d.cts +3 -16
  56. package/dist/reflection.d.cts.map +1 -1
  57. package/dist/reflection.d.mts +3 -16
  58. package/dist/reflection.d.mts.map +1 -1
  59. package/dist/reflection.mjs +290 -304
  60. package/dist/reflection.mjs.map +1 -1
  61. package/dist/resolve.cjs +7 -7
  62. package/dist/resolve.mjs +7 -7
  63. package/dist/resolve.mjs.map +1 -1
  64. package/dist/type-checks.cjs +122 -40
  65. package/dist/type-checks.d.cts +41 -33
  66. package/dist/type-checks.d.cts.map +1 -1
  67. package/dist/type-checks.d.mts +41 -33
  68. package/dist/type-checks.d.mts.map +1 -1
  69. package/dist/type-checks.mjs +120 -37
  70. package/dist/type-checks.mjs.map +1 -1
  71. package/dist/types.d.cts +225 -113
  72. package/dist/types.d.cts.map +1 -1
  73. package/dist/types.d.mts +225 -113
  74. package/dist/types.d.mts.map +1 -1
  75. package/package.json +11 -7
  76. package/dist/jtd.cjs +0 -385
  77. package/dist/jtd.d.cts +0 -15
  78. package/dist/jtd.d.cts.map +0 -1
  79. package/dist/jtd.d.mts +0 -15
  80. package/dist/jtd.d.mts.map +0 -1
  81. package/dist/jtd.mjs +0 -384
  82. package/dist/jtd.mjs.map +0 -1
package/dist/extract.mjs CHANGED
@@ -1,22 +1,91 @@
1
- import { isExtractedSchema, isJTDSchema, isSchema, isUntypedInput, isUntypedSchema } from "./type-checks.mjs";
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 { esbuildPlugin } from "@powerlines/deepkit/esbuild-plugin";
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. 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.
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 (isJsonSchemaObjectType(input)) return murmurhash({
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 @powerlines/deepkit/vendor/type#Type} into a JSON Schema (draft-07) representation.
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 Type Definition (RFC 8927) schema from a given schema definition, if possible.
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) || isJsonSchemaObjectType(schema) || isUntypedInput(schema) || isUntypedSchema(schema))) {
70
- let jsonSchema;
71
- if (isZod3Type(schema)) jsonSchema = extractJsonSchema$1(schema);
72
- else if (isStandardJsonSchema(schema)) jsonSchema = schema["~standard"].jsonSchema.input({ target: "draft-2020-12" });
73
- else if (isUntypedInput(schema)) jsonSchema = schema.$schema;
74
- else jsonSchema = schema;
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 (isJTDSchema(input)) return "jtd-schema";
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
- const jsonSchema = extractJsonSchema(input);
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, a JTD schema, an untyped schema, or a reflected Deepkit Type 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
- else if (variant === "jtd-schema") return {
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
- * 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.
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 extractSchema(context, "./schemas.ts#MySchema");
199
+ * const schema1 = await extract(context, "./schemas.ts#MySchema");
176
200
  * // Resolve a schema definition from a JSON Schema object
177
- * const schema2 = await extractSchema(context, schemaObject);
201
+ * const schema2 = await extract(context, schemaObject);
178
202
  * // Resolve a schema definition from a Zod schema
179
- * const schema3 = await extractSchema(context, zodSchema);
203
+ * const schema3 = await extract(context, zodSchema);
180
204
  * // Resolve a schema definition from a reflected Deepkit Type object
181
- * const schema4 = await extractSchema(context, reflectionType);
205
+ * const schema4 = await extract(context, reflectionType);
182
206
  * ```
183
207
  *
184
- * @param context - The plugin context used for resolving the schema definition input.
185
- * @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.
186
- * @param options - Optional overrides for the ESBuild configuration used during resolution.
187
- * @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.
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("jtd-schema", input.schema),
195
- variant: "jtd-schema",
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: [esbuildPlugin(context, {
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", "jtd-schema", "standard-schema", "zod3", "untyped", or "reflection".`);
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
- * 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.
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 {@link Context | context} used for resolving the {@link Schema | schema} definition input.
248
- * @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).
249
- * @param options - Optional overrides for the [ESBuild configuration](https://esbuild.github.io/api/#general-options) used during resolution.
250
- * @returns A promise that resolves to a {@link Schema | schema} object parsed from the input.
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, a JTD schema, an untyped schema, or a reflected Deepkit Type 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
  }
@@ -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 require_runtime = require('./_virtual/_rolldown/runtime.cjs');
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
- * A helper function to extract the properties from a JTD object schema. This function takes an {@link ObjectSchema} as input and returns a record of its properties, where each key is the property name and the value is the corresponding JTD schema type along with an `optional` flag indicating whether the property is optional (i.e., defined in `optionalProperties`) or required (i.e., defined in `properties`). The function checks both `properties` and `optionalProperties` of the JTD schema to construct the resulting record.
9
+ * Extracts object properties from a JSON Schema object form.
10
10
  *
11
- * @param obj - The {@link ObjectSchema} from which to extract the properties.
12
- * @returns A record of the properties defined in the JTD object schema, where each key is the property name and the value is an object containing the JTD schema type and an `optional` flag.
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.isObjectSchema(obj) ? obj.schema : obj;
17
- if ("optionalProperties" in schema && (0, _stryke_type_checks.isSetObject)(schema.optionalProperties)) for (const [key, value] of Object.entries(schema.optionalProperties)) properties[key] = {
18
- ...value,
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
- optional: false
24
+ nullable: require_metadata.isSchemaNullable(value) || require_metadata.isPropertyOptional(schema, key)
26
25
  };
27
26
  return properties;
28
27
  }
29
28
  /**
30
- * A helper function to get a list of properties from a JTD object schema. This function takes an {@link ObjectSchema} as input and returns an array of its properties, where each element is an object containing the property name, the corresponding JTD schema type, and an `optional` flag indicating whether the property is optional (i.e., defined in `optionalProperties`) or required (i.e., defined in `properties`). The function utilizes the `getProperties` helper function to first retrieve the properties as a record and then converts that record into an array format for easier iteration and access.
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 {@link ObjectSchema} from which to extract the properties.
33
- * @returns An array of properties defined in the JTD object schema, where each element is an object containing the property name, the corresponding JTD schema type, and an `optional` flag.
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
- * A helper function to add a property to a JTD object schema. This function takes a JTD object schema (either {@link JTDSchemaObjectType} or {@link ObjectSchema}), a property name, and a JTD schema type as input. It adds the specified property to the appropriate section of the JTD schema based on whether the property is optional or required. If the property is optional (i.e., has `nullable: true`), it is added to the `optionalProperties` section of the schema; otherwise, it is added to the `properties` section. The function also ensures that the property's metadata includes its name for easier identification and access in future operations.
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 JTD object schema to which the property should be added.
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 JTD schema type of the property to add, which may include a `nullable` flag indicating whether the property is optional.
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.isObjectSchema(obj) ? obj.schema : obj;
47
- if (property.nullable) {
48
- schema.optionalProperties ??= {};
49
- schema.optionalProperties[name] = {
50
- ...property,
51
- metadata: {
52
- ...property.metadata,
53
- name
54
- }
55
- };
56
- } else {
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 JTD object schemas into a single schema. This function takes an array of JTD object schemas (either {@link JTDSchemaObjectType} or {@link ObjectSchema}) and combines their properties into a single JTD object schema. The resulting schema will contain all properties from the input schemas, with optional properties marked accordingly. If there are overlapping properties between the input schemas, the function will merge them using a deep merge strategy (via `defu`) if they are both JTD object schemas; otherwise, the property from the first schema in the input array will take precedence.
65
+ * Merges multiple JSON Schema object forms into one.
69
66
  *
70
67
  * @remarks
71
- * This function attempts to mimic {@link defu}'s behavior for merging objects, but with special handling for JTD schemas. When merging properties, if a property exists in multiple input schemas and is defined as a JTD object schema in all of them, the function will perform a deep merge of those schemas. If the property is not a JTD object schema in any of the input schemas, the function will simply take the first definition it encounters.
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 JTD object schemas to merge.
74
- * @returns A single JTD object schema that combines the properties of all input schemas.
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 mergedSchema = {
78
- properties: {},
79
- optionalProperties: {},
80
- additionalProperties: false
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 mergedSchema;
80
+ return result;
88
81
  }
89
82
 
90
83
  //#endregion