@amritk/generate-parsers 0.16.3 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generators/assert-supported-keywords.js +45 -72
- package/dist/generators/build-schema.js +56 -168
- package/dist/generators/generate-default-from-pattern.js +24 -31
- package/dist/generators/generate-discriminated-union-validation.js +27 -47
- package/dist/generators/generate-enum-check.js +27 -61
- package/dist/generators/generate-files.js +54 -83
- package/dist/generators/generate-non-discriminated-union-validation.js +24 -26
- package/dist/generators/generate-parser-function.d.ts +12 -0
- package/dist/generators/generate-parser-function.js +1132 -1711
- package/dist/generators/generate-schema-checks.js +216 -250
- package/dist/generators/generate-strict-assertion.js +311 -447
- package/dist/generators/generate-type-checks.js +287 -460
- package/dist/generators/generate-validation-expression.js +300 -439
- package/dist/generators/subschema-match.js +201 -266
- package/dist/helpers/apply-schema-extensions.js +18 -49
- package/dist/helpers/collect-helpers.js +58 -71
- package/dist/helpers/collect-imports.js +161 -237
- package/dist/helpers/find-discriminator.js +23 -29
- package/dist/helpers/get-default-value.js +76 -96
- package/dist/helpers/get-discriminator-value.js +16 -17
- package/dist/index.js +4 -1
- package/package.json +4 -4
|
@@ -1,77 +1,64 @@
|
|
|
1
1
|
const PACKAGE_IMPORTS = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"is-object": "import { isObject } from '@amritk/helpers/is-object';",
|
|
3
|
+
"validate-array": "import { validateArray } from '@amritk/helpers/validate-array';",
|
|
4
|
+
"validate-record": "import { validateRecord } from '@amritk/helpers/validate-record';",
|
|
5
|
+
// hasRef has historically lived in the schema-guards subpath; preserve that for package mode.
|
|
6
|
+
"has-ref": "import { hasRef } from '@amritk/helpers/schema-guards';"
|
|
7
7
|
};
|
|
8
8
|
const EMBEDDED_NAMED_EXPORTS = {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
"is-object": "isObject",
|
|
10
|
+
"validate-array": "validateArray",
|
|
11
|
+
"validate-record": "validateRecord",
|
|
12
|
+
"has-ref": "hasRef"
|
|
13
13
|
};
|
|
14
|
-
const embeddedImport = (helper, prefix, ext) =>
|
|
15
|
-
// An explicit extension so the embedded-helper import resolves under Node ESM, not only Bun.
|
|
16
|
-
`import { ${EMBEDDED_NAMED_EXPORTS[helper]} } from '${prefix}_helpers/${helper}.${ext}'
|
|
17
|
-
|
|
18
|
-
* Detects which runtime helpers a generated parser body references.
|
|
19
|
-
*
|
|
20
|
-
* @param helpersImportPrefix - Relative path prefix to the shared `_helpers/`
|
|
21
|
-
* directory in embedded mode. Defaults to `'./'`. The recursive multi-schema
|
|
22
|
-
* build passes `'../'`, `'../../'`, etc. so nested parsers can reach a single
|
|
23
|
-
* `_helpers/` directory at the output root.
|
|
24
|
-
* @param importExt - Extension used on embedded-helper import specifiers.
|
|
25
|
-
* Defaults to `'js'` (the TS NodeNext form); `'ts'` makes the output runnable
|
|
26
|
-
* under Node's type stripping.
|
|
27
|
-
*/
|
|
28
|
-
// One alternation pass over the generated source instead of four full-text
|
|
29
|
-
// `.includes` scans — an absent helper name used to cost a complete rescan
|
|
30
|
-
// each, which showed up at several percent of total generation time.
|
|
14
|
+
const embeddedImport = (helper, prefix, ext) => (
|
|
15
|
+
// An explicit extension so the embedded-helper import resolves under Node ESM, not only Bun.
|
|
16
|
+
`import { ${EMBEDDED_NAMED_EXPORTS[helper]} } from '${prefix}_helpers/${helper}.${ext}';`
|
|
17
|
+
);
|
|
31
18
|
const HELPER_USAGE = /validateArray|validateRecord|isObject|hasRef\(/g;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
19
|
+
const collectHelpers = (parserFunction, mode, helpersImportPrefix = "./", importExt = "js") => {
|
|
20
|
+
const imports = [];
|
|
21
|
+
const used = /* @__PURE__ */ new Set();
|
|
22
|
+
const importFor = (helper) => mode === "embedded" ? embeddedImport(helper, helpersImportPrefix, importExt) : PACKAGE_IMPORTS[helper];
|
|
23
|
+
let sawValidateArray = false;
|
|
24
|
+
let sawValidateRecord = false;
|
|
25
|
+
let sawIsObject = false;
|
|
26
|
+
let sawHasRef = false;
|
|
27
|
+
HELPER_USAGE.lastIndex = 0;
|
|
28
|
+
let match = HELPER_USAGE.exec(parserFunction);
|
|
29
|
+
while (match !== null) {
|
|
30
|
+
const token = match[0];
|
|
31
|
+
if (token === "validateArray")
|
|
32
|
+
sawValidateArray = true;
|
|
33
|
+
else if (token === "validateRecord")
|
|
34
|
+
sawValidateRecord = true;
|
|
35
|
+
else if (token === "isObject")
|
|
36
|
+
sawIsObject = true;
|
|
37
|
+
else
|
|
38
|
+
sawHasRef = true;
|
|
39
|
+
if (sawValidateArray && sawValidateRecord && sawIsObject && sawHasRef)
|
|
40
|
+
break;
|
|
41
|
+
match = HELPER_USAGE.exec(parserFunction);
|
|
42
|
+
}
|
|
43
|
+
if (sawValidateArray) {
|
|
44
|
+
imports.push(importFor("validate-array"));
|
|
45
|
+
used.add("validate-array");
|
|
46
|
+
}
|
|
47
|
+
if (sawValidateRecord) {
|
|
48
|
+
imports.push(importFor("validate-record"));
|
|
49
|
+
used.add("validate-record");
|
|
50
|
+
used.add("is-object");
|
|
51
|
+
}
|
|
52
|
+
if (sawIsObject) {
|
|
53
|
+
imports.push(importFor("is-object"));
|
|
54
|
+
used.add("is-object");
|
|
55
|
+
}
|
|
56
|
+
if (sawHasRef) {
|
|
57
|
+
imports.push(importFor("has-ref"));
|
|
58
|
+
used.add("has-ref");
|
|
59
|
+
}
|
|
60
|
+
return { imports, used };
|
|
61
|
+
};
|
|
62
|
+
export {
|
|
63
|
+
collectHelpers
|
|
77
64
|
};
|
|
@@ -1,242 +1,166 @@
|
|
|
1
|
-
import { refToFilename } from
|
|
2
|
-
import { refToName } from
|
|
3
|
-
import { resolveRef } from
|
|
4
|
-
import { hasAdditionalProperties, hasAllOf, hasAnyOf, hasItems, hasOneOf, hasRef } from
|
|
5
|
-
// Emit an explicit extension on the relative specifier. Node's ESM resolver
|
|
6
|
-
// requires one (extensionless relative imports only work under a bundler or
|
|
7
|
-
// Bun). `./x.js` pointing at a sibling `x.ts` is the standard TS NodeNext form
|
|
8
|
-
// — accepted by Bun, esbuild, webpack, and tsc alike — while `./x.ts` is the
|
|
9
|
-
// literal on-disk path Node's type stripping needs to run the sources directly.
|
|
1
|
+
import { refToFilename } from "@amritk/helpers/ref-to-filename";
|
|
2
|
+
import { refToName } from "@amritk/helpers/ref-to-name";
|
|
3
|
+
import { resolveRef } from "@amritk/helpers/resolve-ref";
|
|
4
|
+
import { hasAdditionalProperties, hasAllOf, hasAnyOf, hasItems, hasOneOf, hasRef } from "@amritk/helpers/schema-guards";
|
|
10
5
|
const getImportPathForFilename = (filename, ext) => `./${filename}.${ext}`;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
* validateArray) are needed based on the schema structure.
|
|
22
|
-
*
|
|
23
|
-
* @param schema - The JSON Schema to collect imports from
|
|
24
|
-
* @param options - Optional settings to control import generation
|
|
25
|
-
* @returns An array of import statements
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* ```ts
|
|
29
|
-
* const schema = {
|
|
30
|
-
* type: 'object',
|
|
31
|
-
* properties: {
|
|
32
|
-
* contact: { $ref: '#/$defs/contact' },
|
|
33
|
-
* server: { $ref: '#/$defs/server' }
|
|
34
|
-
* }
|
|
35
|
-
* }
|
|
36
|
-
* const imports = collectImports(schema)
|
|
37
|
-
* // imports = [
|
|
38
|
-
* // "import { type Contact, parseContact } from './contact';",
|
|
39
|
-
* // "import { type Server, parseServer } from './server';"
|
|
40
|
-
* // ]
|
|
41
|
-
*
|
|
42
|
-
* // With typesOnly, only type imports are generated:
|
|
43
|
-
* const typeImports = collectImports(schema, { typesOnly: true })
|
|
44
|
-
* // typeImports = [
|
|
45
|
-
* // "import type { Contact } from './contact';",
|
|
46
|
-
* // "import type { Server } from './server';"
|
|
47
|
-
* // ]
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export const collectImports = (schema, options) => {
|
|
51
|
-
const typesOnly = options?.typesOnly === true;
|
|
52
|
-
const importExt = options?.importExt ?? 'js';
|
|
53
|
-
const importMap = new Map();
|
|
54
|
-
for (const [filename, typeName] of collectImportTargets(schema, options)) {
|
|
55
|
-
const importPath = getImportPathForFilename(filename, importExt);
|
|
56
|
-
// In types-only mode, omit the parser function import since there is no parser to call
|
|
57
|
-
const importStatement = typesOnly
|
|
58
|
-
? `import type { ${typeName} } from '${importPath}';`
|
|
59
|
-
: `import { type ${typeName}, parse${typeName}, validate${typeName}Shape } from '${importPath}';`;
|
|
60
|
-
importMap.set(filename, importStatement);
|
|
61
|
-
}
|
|
62
|
-
return Array.from(importMap.values()).sort();
|
|
6
|
+
const collectImports = (schema, options) => {
|
|
7
|
+
const typesOnly = options?.typesOnly === true;
|
|
8
|
+
const importExt = options?.importExt ?? "js";
|
|
9
|
+
const importMap = /* @__PURE__ */ new Map();
|
|
10
|
+
for (const [filename, typeName] of collectImportTargets(schema, options)) {
|
|
11
|
+
const importPath = getImportPathForFilename(filename, importExt);
|
|
12
|
+
const importStatement = typesOnly ? `import type { ${typeName} } from '${importPath}';` : `import { type ${typeName}, parse${typeName}, validate${typeName}Shape } from '${importPath}';`;
|
|
13
|
+
importMap.set(filename, importStatement);
|
|
14
|
+
}
|
|
15
|
+
return Array.from(importMap.values()).sort();
|
|
63
16
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
*/
|
|
70
|
-
export const collectImportTypeNames = (schema, options) => {
|
|
71
|
-
const names = new Set();
|
|
72
|
-
for (const [, typeName] of collectImportTargets(schema, options))
|
|
73
|
-
names.add(typeName);
|
|
74
|
-
return names;
|
|
17
|
+
const collectImportTypeNames = (schema, options) => {
|
|
18
|
+
const names = /* @__PURE__ */ new Set();
|
|
19
|
+
for (const [, typeName] of collectImportTargets(schema, options))
|
|
20
|
+
names.add(typeName);
|
|
21
|
+
return names;
|
|
75
22
|
};
|
|
76
|
-
/** Shared `$ref` walk: filename → derived type name for every import target. */
|
|
77
23
|
const collectImportTargets = (schema, options) => {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
}
|
|
221
|
-
if (typeof schema === 'object' && schema !== null && 'else' in schema) {
|
|
222
|
-
collectRefsFromValue(schema.else);
|
|
223
|
-
}
|
|
224
|
-
// Convert refs to import targets, deduplicating by filename.
|
|
225
|
-
const targets = new Map();
|
|
226
|
-
for (const ref of refs) {
|
|
227
|
-
// For URI refs, skip if the base URI is not resolvable in the root schema.
|
|
228
|
-
// This prevents generating imports for external schemas that were never generated as files.
|
|
229
|
-
if (rootSchema !== undefined && (ref.startsWith('http://') || ref.startsWith('https://'))) {
|
|
230
|
-
if (!resolveRef(ref, rootSchema))
|
|
231
|
-
continue;
|
|
232
|
-
}
|
|
233
|
-
const typeName = refToName(ref, typeSuffix);
|
|
234
|
-
const filename = refToFilename(ref);
|
|
235
|
-
// Skip self-referential imports — a file must not import from itself
|
|
236
|
-
if (selfFilename !== undefined && filename === selfFilename) {
|
|
237
|
-
continue;
|
|
238
|
-
}
|
|
239
|
-
targets.set(filename, typeName);
|
|
240
|
-
}
|
|
241
|
-
return targets;
|
|
24
|
+
const selfFilename = options?.selfRef ? refToFilename(options.selfRef) : void 0;
|
|
25
|
+
const rootSchema = options?.rootSchema;
|
|
26
|
+
const typeSuffix = options?.typeSuffix;
|
|
27
|
+
const refs = /* @__PURE__ */ new Set();
|
|
28
|
+
const collectRefsFromValue = (value) => {
|
|
29
|
+
if (typeof value !== "object" || value === null) {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(value)) {
|
|
33
|
+
for (const item of value) {
|
|
34
|
+
collectRefsFromValue(item);
|
|
35
|
+
}
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const record = value;
|
|
39
|
+
if (hasRef(record)) {
|
|
40
|
+
const ref = record.$ref;
|
|
41
|
+
const isInternal = ref.startsWith("#");
|
|
42
|
+
const isUri = ref.startsWith("http://") || ref.startsWith("https://");
|
|
43
|
+
const isPropertyFragment = isUri && ref.includes("#/properties/");
|
|
44
|
+
if (isInternal || isUri && !isPropertyFragment) {
|
|
45
|
+
refs.add(ref);
|
|
46
|
+
}
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (hasAdditionalProperties(record) && hasRef(record.additionalProperties)) {
|
|
50
|
+
collectRefsFromValue(record.additionalProperties);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (record.type === "array" && hasItems(record) && hasRef(record.items)) {
|
|
54
|
+
collectRefsFromValue(record.items);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if ("properties" in record && typeof record.properties === "object" && record.properties !== null) {
|
|
58
|
+
const props = record.properties;
|
|
59
|
+
for (const key in props) {
|
|
60
|
+
collectRefsFromValue(props[key]);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (hasOneOf(record)) {
|
|
64
|
+
for (const item of record.oneOf) {
|
|
65
|
+
collectRefsFromValue(item);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (hasAnyOf(record)) {
|
|
69
|
+
for (const item of record.anyOf) {
|
|
70
|
+
collectRefsFromValue(item);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (hasAllOf(record)) {
|
|
74
|
+
for (const item of record.allOf) {
|
|
75
|
+
collectRefsFromValue(item);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (hasItems(record)) {
|
|
79
|
+
collectRefsFromValue(record.items);
|
|
80
|
+
}
|
|
81
|
+
if (hasAdditionalProperties(record)) {
|
|
82
|
+
collectRefsFromValue(record.additionalProperties);
|
|
83
|
+
}
|
|
84
|
+
if ("patternProperties" in record && typeof record.patternProperties === "object" && record.patternProperties !== null) {
|
|
85
|
+
const patternProps = record.patternProperties;
|
|
86
|
+
for (const key in patternProps) {
|
|
87
|
+
collectRefsFromValue(patternProps[key]);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if ("then" in record) {
|
|
91
|
+
collectRefsFromValue(record.then);
|
|
92
|
+
}
|
|
93
|
+
if ("else" in record) {
|
|
94
|
+
collectRefsFromValue(record.else);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
if (typeof schema === "object" && schema !== null && hasRef(schema)) {
|
|
98
|
+
const ref = schema.$ref;
|
|
99
|
+
const isInternal = ref.startsWith("#");
|
|
100
|
+
const isUri = ref.startsWith("http://") || ref.startsWith("https://");
|
|
101
|
+
const isPropertyFragment = isUri && ref.includes("#/properties/");
|
|
102
|
+
if (isInternal || isUri && !isPropertyFragment) {
|
|
103
|
+
refs.add(ref);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (typeof schema === "object" && schema !== null && "properties" in schema) {
|
|
107
|
+
const properties = schema.properties;
|
|
108
|
+
for (const key in properties) {
|
|
109
|
+
collectRefsFromValue(properties[key]);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (typeof schema === "object" && schema !== null && "additionalProperties" in schema) {
|
|
113
|
+
collectRefsFromValue(schema.additionalProperties);
|
|
114
|
+
}
|
|
115
|
+
if (typeof schema === "object" && schema !== null && "patternProperties" in schema) {
|
|
116
|
+
const patternProps = schema.patternProperties;
|
|
117
|
+
for (const key in patternProps) {
|
|
118
|
+
collectRefsFromValue(patternProps[key]);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (typeof schema === "object" && schema !== null && hasItems(schema)) {
|
|
122
|
+
collectRefsFromValue(schema.items);
|
|
123
|
+
}
|
|
124
|
+
if (typeof schema === "object" && schema !== null && hasOneOf(schema)) {
|
|
125
|
+
for (const item of schema.oneOf) {
|
|
126
|
+
collectRefsFromValue(item);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (typeof schema === "object" && schema !== null && hasAnyOf(schema)) {
|
|
130
|
+
for (const item of schema.anyOf) {
|
|
131
|
+
collectRefsFromValue(item);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
if (typeof schema === "object" && schema !== null && hasAllOf(schema)) {
|
|
135
|
+
for (const item of schema.allOf) {
|
|
136
|
+
collectRefsFromValue(item);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (typeof schema === "object" && schema !== null && "if" in schema) {
|
|
140
|
+
collectRefsFromValue(schema.if);
|
|
141
|
+
}
|
|
142
|
+
if (typeof schema === "object" && schema !== null && "then" in schema) {
|
|
143
|
+
collectRefsFromValue(schema.then);
|
|
144
|
+
}
|
|
145
|
+
if (typeof schema === "object" && schema !== null && "else" in schema) {
|
|
146
|
+
collectRefsFromValue(schema.else);
|
|
147
|
+
}
|
|
148
|
+
const targets = /* @__PURE__ */ new Map();
|
|
149
|
+
for (const ref of refs) {
|
|
150
|
+
if (rootSchema !== void 0 && (ref.startsWith("http://") || ref.startsWith("https://"))) {
|
|
151
|
+
if (!resolveRef(ref, rootSchema))
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
const typeName = refToName(ref, typeSuffix);
|
|
155
|
+
const filename = refToFilename(ref);
|
|
156
|
+
if (selfFilename !== void 0 && filename === selfFilename) {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
targets.set(filename, typeName);
|
|
160
|
+
}
|
|
161
|
+
return targets;
|
|
162
|
+
};
|
|
163
|
+
export {
|
|
164
|
+
collectImportTypeNames,
|
|
165
|
+
collectImports
|
|
242
166
|
};
|
|
@@ -1,33 +1,27 @@
|
|
|
1
|
-
import { hasConst, hasEnum, hasProperties, isObjectSchema, isSchemaObject } from
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
for (const schema of schemas) {
|
|
10
|
-
if (isObjectSchema(schema) && hasProperties(schema)) {
|
|
11
|
-
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
12
|
-
if (!propertyValues.has(key)) {
|
|
13
|
-
propertyValues.set(key, new Set());
|
|
14
|
-
}
|
|
15
|
-
// Check if property has a const value
|
|
16
|
-
if (isSchemaObject(propSchema) && hasConst(propSchema)) {
|
|
17
|
-
propertyValues.get(key)?.add(propSchema.const);
|
|
18
|
-
}
|
|
19
|
-
// Check if property has a single enum value
|
|
20
|
-
else if (isSchemaObject(propSchema) && hasEnum(propSchema) && propSchema.enum.length === 1) {
|
|
21
|
-
propertyValues.get(key)?.add(propSchema.enum[0]);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
1
|
+
import { hasConst, hasEnum, hasProperties, isObjectSchema, isSchemaObject } from "@amritk/helpers/schema-guards";
|
|
2
|
+
const findDiscriminator = (schemas) => {
|
|
3
|
+
const propertyValues = /* @__PURE__ */ new Map();
|
|
4
|
+
for (const schema of schemas) {
|
|
5
|
+
if (isObjectSchema(schema) && hasProperties(schema)) {
|
|
6
|
+
for (const [key, propSchema] of Object.entries(schema.properties)) {
|
|
7
|
+
if (!propertyValues.has(key)) {
|
|
8
|
+
propertyValues.set(key, /* @__PURE__ */ new Set());
|
|
24
9
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
return key;
|
|
10
|
+
if (isSchemaObject(propSchema) && hasConst(propSchema)) {
|
|
11
|
+
propertyValues.get(key)?.add(propSchema.const);
|
|
12
|
+
} else if (isSchemaObject(propSchema) && hasEnum(propSchema) && propSchema.enum.length === 1) {
|
|
13
|
+
propertyValues.get(key)?.add(propSchema.enum[0]);
|
|
30
14
|
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
for (const [key, values] of propertyValues.entries()) {
|
|
19
|
+
if (values.size === schemas.length) {
|
|
20
|
+
return key;
|
|
31
21
|
}
|
|
32
|
-
|
|
22
|
+
}
|
|
23
|
+
return null;
|
|
24
|
+
};
|
|
25
|
+
export {
|
|
26
|
+
findDiscriminator
|
|
33
27
|
};
|