@kubb/ast 5.0.0-alpha.2 → 5.0.0-alpha.20
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/index.cjs +1031 -128
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +273 -9
- package/dist/index.js +1008 -129
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/visitor-DCQyoFvH.d.ts +1976 -0
- package/package.json +3 -2
- package/src/constants.ts +97 -4
- package/src/factory.ts +276 -18
- package/src/guards.ts +63 -8
- package/src/index.ts +32 -6
- package/src/infer.ts +130 -0
- package/src/mocks.ts +12 -5
- package/src/nodes/base.ts +31 -4
- package/src/nodes/function.ts +131 -0
- package/src/nodes/http.ts +17 -5
- package/src/nodes/index.ts +18 -5
- package/src/nodes/operation.ts +61 -4
- package/src/nodes/parameter.ts +27 -1
- package/src/nodes/property.ts +23 -1
- package/src/nodes/response.ts +29 -3
- package/src/nodes/root.ts +41 -10
- package/src/nodes/schema.ts +328 -38
- package/src/printers/functionPrinter.ts +196 -0
- package/src/printers/index.ts +3 -0
- package/src/printers/printer.ts +204 -0
- package/src/refs.ts +36 -4
- package/src/resolvers.ts +45 -0
- package/src/transformers.ts +196 -0
- package/src/types.ts +9 -2
- package/src/utils.ts +77 -0
- package/src/visitor.ts +376 -81
- package/dist/visitor-CmsfJzro.d.ts +0 -649
- package/src/printer.ts +0 -129
package/dist/index.cjs
CHANGED
|
@@ -12,8 +12,22 @@ const nodeKinds = {
|
|
|
12
12
|
schema: "Schema",
|
|
13
13
|
property: "Property",
|
|
14
14
|
parameter: "Parameter",
|
|
15
|
-
response: "Response"
|
|
15
|
+
response: "Response",
|
|
16
|
+
functionParameter: "FunctionParameter",
|
|
17
|
+
objectBindingParameter: "ObjectBindingParameter",
|
|
18
|
+
functionParameters: "FunctionParameters"
|
|
16
19
|
};
|
|
20
|
+
/**
|
|
21
|
+
* Canonical schema type strings used by AST schema nodes.
|
|
22
|
+
*
|
|
23
|
+
* These values are used across the AST as stable discriminators
|
|
24
|
+
* (for example `schema.type === schemaTypes.object`).
|
|
25
|
+
*
|
|
26
|
+
* The map is grouped by intent:
|
|
27
|
+
* - primitives (`string`, `number`, `boolean`, ...)
|
|
28
|
+
* - structural/composite (`object`, `array`, `union`, ...)
|
|
29
|
+
* - special OpenAPI-oriented types (`ref`, `datetime`, `uuid`, ...)
|
|
30
|
+
*/
|
|
17
31
|
const schemaTypes = {
|
|
18
32
|
string: "string",
|
|
19
33
|
number: "number",
|
|
@@ -37,8 +51,19 @@ const schemaTypes = {
|
|
|
37
51
|
uuid: "uuid",
|
|
38
52
|
email: "email",
|
|
39
53
|
url: "url",
|
|
40
|
-
blob: "blob"
|
|
54
|
+
blob: "blob",
|
|
55
|
+
never: "never"
|
|
41
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* Primitive scalar schema types used when simplifying union members.
|
|
59
|
+
*/
|
|
60
|
+
const SCALAR_PRIMITIVE_TYPES = new Set([
|
|
61
|
+
"string",
|
|
62
|
+
"number",
|
|
63
|
+
"integer",
|
|
64
|
+
"bigint",
|
|
65
|
+
"boolean"
|
|
66
|
+
]);
|
|
42
67
|
const httpMethods = {
|
|
43
68
|
get: "GET",
|
|
44
69
|
post: "POST",
|
|
@@ -71,9 +96,241 @@ const mediaTypes = {
|
|
|
71
96
|
videoMp4: "video/mp4"
|
|
72
97
|
};
|
|
73
98
|
//#endregion
|
|
99
|
+
//#region ../../internals/utils/src/casing.ts
|
|
100
|
+
/**
|
|
101
|
+
* Shared implementation for camelCase and PascalCase conversion.
|
|
102
|
+
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
103
|
+
* and capitalizes each word according to `pascal`.
|
|
104
|
+
*
|
|
105
|
+
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
106
|
+
*/
|
|
107
|
+
function toCamelOrPascal(text, pascal) {
|
|
108
|
+
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
109
|
+
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
110
|
+
if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
|
|
111
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
112
|
+
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
116
|
+
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
117
|
+
* Segments are joined with `/` to form a file path.
|
|
118
|
+
*
|
|
119
|
+
* Only splits on dots followed by a letter so that version numbers
|
|
120
|
+
* embedded in operationIds (e.g. `v2025.0`) are kept intact.
|
|
121
|
+
*/
|
|
122
|
+
function applyToFileParts(text, transformPart) {
|
|
123
|
+
const parts = text.split(/\.(?=[a-zA-Z])/);
|
|
124
|
+
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Converts `text` to camelCase.
|
|
128
|
+
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* camelCase('hello-world') // 'helloWorld'
|
|
132
|
+
* camelCase('pet.petId', { isFile: true }) // 'pet/petId'
|
|
133
|
+
*/
|
|
134
|
+
function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
135
|
+
if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
|
|
136
|
+
prefix,
|
|
137
|
+
suffix
|
|
138
|
+
} : {}));
|
|
139
|
+
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Converts `text` to PascalCase.
|
|
143
|
+
* When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* pascalCase('hello-world') // 'HelloWorld'
|
|
147
|
+
* pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'
|
|
148
|
+
*/
|
|
149
|
+
function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
150
|
+
if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
|
|
151
|
+
prefix,
|
|
152
|
+
suffix
|
|
153
|
+
}) : camelCase(part));
|
|
154
|
+
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
//#region ../../internals/utils/src/reserved.ts
|
|
158
|
+
/**
|
|
159
|
+
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* ```ts
|
|
163
|
+
* isValidVarName('status') // true
|
|
164
|
+
* isValidVarName('class') // false (reserved word)
|
|
165
|
+
* isValidVarName('42foo') // false (starts with digit)
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
function isValidVarName(name) {
|
|
169
|
+
try {
|
|
170
|
+
new Function(`var ${name}`);
|
|
171
|
+
} catch {
|
|
172
|
+
return false;
|
|
173
|
+
}
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/guards.ts
|
|
178
|
+
/**
|
|
179
|
+
* Narrows a `SchemaNode` to the variant that matches `type`.
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* ```ts
|
|
183
|
+
* const schema = createSchema({ type: 'string' })
|
|
184
|
+
* const stringNode = narrowSchema(schema, 'string') // StringSchemaNode | undefined
|
|
185
|
+
* ```
|
|
186
|
+
*/
|
|
187
|
+
function narrowSchema(node, type) {
|
|
188
|
+
return node?.type === type ? node : void 0;
|
|
189
|
+
}
|
|
190
|
+
function isKind(kind) {
|
|
191
|
+
return (node) => node.kind === kind;
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Returns `true` when the input is a `RootNode`.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* if (isRootNode(node)) {
|
|
199
|
+
* console.log(node.schemas.length)
|
|
200
|
+
* }
|
|
201
|
+
* ```
|
|
202
|
+
*/
|
|
203
|
+
const isRootNode = isKind("Root");
|
|
204
|
+
/**
|
|
205
|
+
* Returns `true` when the input is an `OperationNode`.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
* ```ts
|
|
209
|
+
* if (isOperationNode(node)) {
|
|
210
|
+
* console.log(node.operationId)
|
|
211
|
+
* }
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
const isOperationNode = isKind("Operation");
|
|
215
|
+
/**
|
|
216
|
+
* Returns `true` when the input is a `SchemaNode`.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* if (isSchemaNode(node)) {
|
|
221
|
+
* console.log(node.type)
|
|
222
|
+
* }
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
const isSchemaNode = isKind("Schema");
|
|
226
|
+
/**
|
|
227
|
+
* Returns `true` when the input is a `PropertyNode`.
|
|
228
|
+
*/
|
|
229
|
+
const isPropertyNode = isKind("Property");
|
|
230
|
+
/**
|
|
231
|
+
* Returns `true` when the input is a `ParameterNode`.
|
|
232
|
+
*/
|
|
233
|
+
const isParameterNode = isKind("Parameter");
|
|
234
|
+
/**
|
|
235
|
+
* Returns `true` when the input is a `ResponseNode`.
|
|
236
|
+
*/
|
|
237
|
+
const isResponseNode = isKind("Response");
|
|
238
|
+
/**
|
|
239
|
+
* Returns `true` when the input is a `FunctionParameterNode`.
|
|
240
|
+
*/
|
|
241
|
+
const isFunctionParameterNode = isKind("FunctionParameter");
|
|
242
|
+
/**
|
|
243
|
+
* Returns `true` when the input is an `ObjectBindingParameterNode`.
|
|
244
|
+
*/
|
|
245
|
+
const isObjectBindingParameterNode = isKind("ObjectBindingParameter");
|
|
246
|
+
/**
|
|
247
|
+
* Returns `true` when the input is a `FunctionParametersNode`.
|
|
248
|
+
*/
|
|
249
|
+
const isFunctionParametersNode = isKind("FunctionParameters");
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/utils.ts
|
|
252
|
+
const plainStringTypes = new Set([
|
|
253
|
+
"string",
|
|
254
|
+
"uuid",
|
|
255
|
+
"email",
|
|
256
|
+
"url",
|
|
257
|
+
"datetime"
|
|
258
|
+
]);
|
|
259
|
+
/**
|
|
260
|
+
* Returns `true` when a schema is emitted as a plain TypeScript `string`.
|
|
261
|
+
*
|
|
262
|
+
* - `string`, `uuid`, `email`, `url`, `datetime` are always plain strings.
|
|
263
|
+
* - `date` and `time` are plain strings when their `representation` is `'string'` rather than `'date'`.
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* isStringType(createSchema({ type: 'uuid' })) // true
|
|
268
|
+
* isStringType(createSchema({ type: 'date', representation: 'date' })) // false
|
|
269
|
+
* ```
|
|
270
|
+
*/
|
|
271
|
+
function isStringType(node) {
|
|
272
|
+
if (plainStringTypes.has(node.type)) return true;
|
|
273
|
+
const temporal = narrowSchema(node, "date") ?? narrowSchema(node, "time");
|
|
274
|
+
if (temporal) return temporal.representation !== "date";
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Applies casing rules to parameter names and returns a new parameter array.
|
|
279
|
+
*
|
|
280
|
+
* The input array is not mutated.
|
|
281
|
+
* If `casing` is not set, the original array is returned unchanged.
|
|
282
|
+
*
|
|
283
|
+
* Use this before passing parameters to schema builders so that property keys
|
|
284
|
+
* in generated output match the desired casing while preserving
|
|
285
|
+
* `OperationNode.parameters` for other consumers.
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* ```ts
|
|
289
|
+
* const params = [createParameter({ name: 'pet_id', in: 'query', schema: createSchema({ type: 'string' }) })]
|
|
290
|
+
* const cased = caseParams(params, 'camelcase')
|
|
291
|
+
* // cased[0].name === 'petId'
|
|
292
|
+
* ```
|
|
293
|
+
*/
|
|
294
|
+
function caseParams(params, casing) {
|
|
295
|
+
if (!casing) return params;
|
|
296
|
+
return params.map((param) => {
|
|
297
|
+
const transformed = casing === "camelcase" || !isValidVarName(param.name) ? camelCase(param.name) : param.name;
|
|
298
|
+
return {
|
|
299
|
+
...param,
|
|
300
|
+
name: transformed
|
|
301
|
+
};
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Syncs property/parameter schema optionality flags from `required` and `schema.nullable`.
|
|
306
|
+
*
|
|
307
|
+
* - `optional` is set for non-required, non-nullable schemas.
|
|
308
|
+
* - `nullish` is set for non-required, nullable schemas.
|
|
309
|
+
*/
|
|
310
|
+
function syncOptionality(required, schema) {
|
|
311
|
+
const nullable = schema.nullable ?? false;
|
|
312
|
+
return {
|
|
313
|
+
...schema,
|
|
314
|
+
optional: !required && !nullable ? true : void 0,
|
|
315
|
+
nullish: !required && nullable ? true : void 0
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
//#endregion
|
|
74
319
|
//#region src/factory.ts
|
|
75
320
|
/**
|
|
76
|
-
* Creates a `RootNode`.
|
|
321
|
+
* Creates a `RootNode` with stable defaults for `schemas` and `operations`.
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* ```ts
|
|
325
|
+
* const root = createRoot()
|
|
326
|
+
* // { kind: 'Root', schemas: [], operations: [] }
|
|
327
|
+
* ```
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* ```ts
|
|
331
|
+
* const root = createRoot({ schemas: [petSchema] })
|
|
332
|
+
* // keeps default operations: []
|
|
333
|
+
* ```
|
|
77
334
|
*/
|
|
78
335
|
function createRoot(overrides = {}) {
|
|
79
336
|
return {
|
|
@@ -84,7 +341,27 @@ function createRoot(overrides = {}) {
|
|
|
84
341
|
};
|
|
85
342
|
}
|
|
86
343
|
/**
|
|
87
|
-
* Creates an `OperationNode`.
|
|
344
|
+
* Creates an `OperationNode` with default empty arrays for `tags`, `parameters`, and `responses`.
|
|
345
|
+
*
|
|
346
|
+
* @example
|
|
347
|
+
* ```ts
|
|
348
|
+
* const operation = createOperation({
|
|
349
|
+
* operationId: 'getPetById',
|
|
350
|
+
* method: 'GET',
|
|
351
|
+
* path: '/pet/{petId}',
|
|
352
|
+
* })
|
|
353
|
+
* // tags, parameters, and responses are []
|
|
354
|
+
* ```
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```ts
|
|
358
|
+
* const operation = createOperation({
|
|
359
|
+
* operationId: 'findPets',
|
|
360
|
+
* method: 'GET',
|
|
361
|
+
* path: '/pet/findByStatus',
|
|
362
|
+
* tags: ['pet'],
|
|
363
|
+
* })
|
|
364
|
+
* ```
|
|
88
365
|
*/
|
|
89
366
|
function createOperation(props) {
|
|
90
367
|
return {
|
|
@@ -107,27 +384,85 @@ function createSchema(props) {
|
|
|
107
384
|
};
|
|
108
385
|
}
|
|
109
386
|
/**
|
|
110
|
-
* Creates a `PropertyNode`.
|
|
387
|
+
* Creates a `PropertyNode`.
|
|
388
|
+
*
|
|
389
|
+
* `required` defaults to `false`.
|
|
390
|
+
* `schema.optional` and `schema.nullish` are derived from `required` and `schema.nullable`.
|
|
391
|
+
*
|
|
392
|
+
* @example
|
|
393
|
+
* ```ts
|
|
394
|
+
* const property = createProperty({
|
|
395
|
+
* name: 'status',
|
|
396
|
+
* schema: createSchema({ type: 'string' }),
|
|
397
|
+
* })
|
|
398
|
+
* // required=false, schema.optional=true
|
|
399
|
+
* ```
|
|
400
|
+
*
|
|
401
|
+
* @example
|
|
402
|
+
* ```ts
|
|
403
|
+
* const property = createProperty({
|
|
404
|
+
* name: 'status',
|
|
405
|
+
* required: true,
|
|
406
|
+
* schema: createSchema({ type: 'string', nullable: true }),
|
|
407
|
+
* })
|
|
408
|
+
* // required=true, no optional/nullish
|
|
409
|
+
* ```
|
|
111
410
|
*/
|
|
112
411
|
function createProperty(props) {
|
|
412
|
+
const required = props.required ?? false;
|
|
113
413
|
return {
|
|
114
|
-
required: false,
|
|
115
414
|
...props,
|
|
116
|
-
kind: "Property"
|
|
415
|
+
kind: "Property",
|
|
416
|
+
required,
|
|
417
|
+
schema: syncOptionality(required, props.schema)
|
|
117
418
|
};
|
|
118
419
|
}
|
|
119
420
|
/**
|
|
120
|
-
* Creates a `ParameterNode`.
|
|
421
|
+
* Creates a `ParameterNode`.
|
|
422
|
+
*
|
|
423
|
+
* `required` defaults to `false`.
|
|
424
|
+
* Nested schema flags are set from `required` and `schema.nullable`.
|
|
425
|
+
*
|
|
426
|
+
* @example
|
|
427
|
+
* ```ts
|
|
428
|
+
* const param = createParameter({
|
|
429
|
+
* name: 'petId',
|
|
430
|
+
* in: 'path',
|
|
431
|
+
* required: true,
|
|
432
|
+
* schema: createSchema({ type: 'string' }),
|
|
433
|
+
* })
|
|
434
|
+
* ```
|
|
435
|
+
*
|
|
436
|
+
* @example
|
|
437
|
+
* ```ts
|
|
438
|
+
* const param = createParameter({
|
|
439
|
+
* name: 'status',
|
|
440
|
+
* in: 'query',
|
|
441
|
+
* schema: createSchema({ type: 'string', nullable: true }),
|
|
442
|
+
* })
|
|
443
|
+
* // required=false, schema.nullish=true
|
|
444
|
+
* ```
|
|
121
445
|
*/
|
|
122
446
|
function createParameter(props) {
|
|
447
|
+
const required = props.required ?? false;
|
|
123
448
|
return {
|
|
124
|
-
required: false,
|
|
125
449
|
...props,
|
|
126
|
-
kind: "Parameter"
|
|
450
|
+
kind: "Parameter",
|
|
451
|
+
required,
|
|
452
|
+
schema: syncOptionality(required, props.schema)
|
|
127
453
|
};
|
|
128
454
|
}
|
|
129
455
|
/**
|
|
130
456
|
* Creates a `ResponseNode`.
|
|
457
|
+
*
|
|
458
|
+
* @example
|
|
459
|
+
* ```ts
|
|
460
|
+
* const response = createResponse({
|
|
461
|
+
* statusCode: '200',
|
|
462
|
+
* description: 'Success',
|
|
463
|
+
* schema: createSchema({ type: 'object', properties: [] }),
|
|
464
|
+
* })
|
|
465
|
+
* ```
|
|
131
466
|
*/
|
|
132
467
|
function createResponse(props) {
|
|
133
468
|
return {
|
|
@@ -135,99 +470,329 @@ function createResponse(props) {
|
|
|
135
470
|
kind: "Response"
|
|
136
471
|
};
|
|
137
472
|
}
|
|
138
|
-
//#endregion
|
|
139
|
-
//#region src/guards.ts
|
|
140
473
|
/**
|
|
141
|
-
*
|
|
474
|
+
* Creates a single-property object schema used as a discriminator literal.
|
|
475
|
+
*
|
|
476
|
+
* @example
|
|
477
|
+
* ```ts
|
|
478
|
+
* createDiscriminantNode({ propertyName: 'type', value: 'dog' })
|
|
479
|
+
* // -> { type: 'object', properties: [{ name: 'type', required: true, schema: enum('dog') }] }
|
|
480
|
+
* ```
|
|
142
481
|
*/
|
|
143
|
-
function
|
|
144
|
-
return
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
482
|
+
function createDiscriminantNode({ propertyName, value }) {
|
|
483
|
+
return createSchema({
|
|
484
|
+
type: "object",
|
|
485
|
+
primitive: "object",
|
|
486
|
+
properties: [createProperty({
|
|
487
|
+
name: propertyName,
|
|
488
|
+
schema: createSchema({
|
|
489
|
+
type: "enum",
|
|
490
|
+
primitive: "string",
|
|
491
|
+
enumValues: [value]
|
|
492
|
+
}),
|
|
493
|
+
required: true
|
|
494
|
+
})]
|
|
495
|
+
});
|
|
148
496
|
}
|
|
149
497
|
/**
|
|
150
|
-
*
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
*
|
|
498
|
+
* Creates a `FunctionParameterNode`.
|
|
499
|
+
*
|
|
500
|
+
* `optional` defaults to `false`.
|
|
501
|
+
*
|
|
502
|
+
* @example Required typed param
|
|
503
|
+
* ```ts
|
|
504
|
+
* createFunctionParameter({ name: 'petId', type: 'string' })
|
|
505
|
+
* // → petId: string
|
|
506
|
+
* ```
|
|
507
|
+
*
|
|
508
|
+
* @example Optional param
|
|
509
|
+
* ```ts
|
|
510
|
+
* createFunctionParameter({ name: 'params', type: 'QueryParams', optional: true })
|
|
511
|
+
* // → params?: QueryParams
|
|
512
|
+
* ```
|
|
513
|
+
*
|
|
514
|
+
* @example Param with default (implicitly optional; cannot combine with `optional: true`)
|
|
515
|
+
* ```ts
|
|
516
|
+
* createFunctionParameter({ name: 'config', type: 'RequestConfig', default: '{}' })
|
|
517
|
+
* // → config: RequestConfig = {}
|
|
518
|
+
* ```
|
|
155
519
|
*/
|
|
156
|
-
|
|
520
|
+
function createFunctionParameter(props) {
|
|
521
|
+
return {
|
|
522
|
+
optional: false,
|
|
523
|
+
...props,
|
|
524
|
+
kind: "FunctionParameter"
|
|
525
|
+
};
|
|
526
|
+
}
|
|
157
527
|
/**
|
|
158
|
-
*
|
|
528
|
+
* Creates an `ObjectBindingParameterNode` for object-destructured parameter groups.
|
|
529
|
+
*
|
|
530
|
+
* @example Destructured object param
|
|
531
|
+
* ```ts
|
|
532
|
+
* createObjectBindingParameter({
|
|
533
|
+
* properties: [
|
|
534
|
+
* createFunctionParameter({ name: 'id', type: 'string', optional: false }),
|
|
535
|
+
* createFunctionParameter({ name: 'name', type: 'string', optional: true }),
|
|
536
|
+
* ],
|
|
537
|
+
* default: '{}',
|
|
538
|
+
* })
|
|
539
|
+
* // declaration → { id, name? }: { id: string; name?: string } = {}
|
|
540
|
+
* // call → { id, name }
|
|
541
|
+
* ```
|
|
542
|
+
*
|
|
543
|
+
* @example Inline mode — children emitted as individual top-level parameters
|
|
544
|
+
* ```ts
|
|
545
|
+
* createObjectBindingParameter({
|
|
546
|
+
* properties: [createFunctionParameter({ name: 'petId', type: 'string', optional: false })],
|
|
547
|
+
* inline: true,
|
|
548
|
+
* })
|
|
549
|
+
* // declaration → petId: string
|
|
550
|
+
* // call → petId
|
|
551
|
+
* ```
|
|
159
552
|
*/
|
|
160
|
-
|
|
553
|
+
function createObjectBindingParameter(props) {
|
|
554
|
+
return {
|
|
555
|
+
...props,
|
|
556
|
+
kind: "ObjectBindingParameter"
|
|
557
|
+
};
|
|
558
|
+
}
|
|
161
559
|
/**
|
|
162
|
-
*
|
|
560
|
+
* Creates a `FunctionParametersNode` from an ordered list of parameters.
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* ```ts
|
|
564
|
+
* createFunctionParameters({
|
|
565
|
+
* params: [
|
|
566
|
+
* createFunctionParameter({ name: 'petId', type: 'string', optional: false }),
|
|
567
|
+
* createFunctionParameter({ name: 'config', type: 'RequestConfig', optional: false, default: '{}' }),
|
|
568
|
+
* ],
|
|
569
|
+
* })
|
|
570
|
+
* ```
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* ```ts
|
|
574
|
+
* const empty = createFunctionParameters()
|
|
575
|
+
* // { kind: 'FunctionParameters', params: [] }
|
|
576
|
+
* ```
|
|
163
577
|
*/
|
|
164
|
-
|
|
578
|
+
function createFunctionParameters(props = {}) {
|
|
579
|
+
return {
|
|
580
|
+
params: [],
|
|
581
|
+
...props,
|
|
582
|
+
kind: "FunctionParameters"
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
//#endregion
|
|
586
|
+
//#region src/printers/printer.ts
|
|
165
587
|
/**
|
|
166
|
-
*
|
|
588
|
+
* Creates a schema printer factory.
|
|
589
|
+
*
|
|
590
|
+
* This function wraps a builder and makes options optional at call sites.
|
|
591
|
+
*
|
|
592
|
+
* The builder receives resolved options and returns:
|
|
593
|
+
* - `name` — a unique identifier for the printer
|
|
594
|
+
* - `options` — options stored on the returned printer instance
|
|
595
|
+
* - `nodes` — a map of `SchemaType` → handler functions that convert a `SchemaNode` to `TOutput`
|
|
596
|
+
* - `print` _(optional)_ — top-level override exposed as `printer.print`
|
|
597
|
+
* - Inside this function, `this.print(node)` still dispatches to the `nodes` map
|
|
598
|
+
* - This keeps recursion safe and avoids self-calls
|
|
599
|
+
*
|
|
600
|
+
* When no `print` override is provided, `printer.print` is the node-level dispatcher directly.
|
|
601
|
+
*
|
|
602
|
+
* @example Basic usage — Zod schema printer
|
|
603
|
+
* ```ts
|
|
604
|
+
* type ZodPrinter = PrinterFactoryOptions<'zod', { strict?: boolean }, string>
|
|
605
|
+
*
|
|
606
|
+
* export const zodPrinter = definePrinter<ZodPrinter>((options) => ({
|
|
607
|
+
* name: 'zod',
|
|
608
|
+
* options: { strict: options.strict ?? true },
|
|
609
|
+
* nodes: {
|
|
610
|
+
* string: () => 'z.string()',
|
|
611
|
+
* object(node) {
|
|
612
|
+
* const props = node.properties.map(p => `${p.name}: ${this.print(p.schema)}`).join(', ')
|
|
613
|
+
* return `z.object({ ${props} })`
|
|
614
|
+
* },
|
|
615
|
+
* },
|
|
616
|
+
* }))
|
|
617
|
+
* ```
|
|
167
618
|
*/
|
|
168
|
-
|
|
619
|
+
function definePrinter(build) {
|
|
620
|
+
return createPrinterFactory((node) => node.type)(build);
|
|
621
|
+
}
|
|
169
622
|
/**
|
|
170
|
-
*
|
|
623
|
+
* Generic printer-factory function used by `definePrinter` and `defineFunctionPrinter`.
|
|
624
|
+
**
|
|
625
|
+
* @example
|
|
626
|
+
* ```ts
|
|
627
|
+
* export const defineFunctionPrinter = createPrinterFactory<FunctionNode, FunctionNodeType, FunctionNodeByType>(
|
|
628
|
+
* (node) => kindToHandlerKey[node.kind],
|
|
629
|
+
* )
|
|
630
|
+
* ```
|
|
171
631
|
*/
|
|
172
|
-
|
|
632
|
+
function createPrinterFactory(getKey) {
|
|
633
|
+
return function(build) {
|
|
634
|
+
return (options) => {
|
|
635
|
+
const { name, options: resolvedOptions, nodes, print: printOverride } = build(options ?? {});
|
|
636
|
+
const context = {
|
|
637
|
+
options: resolvedOptions,
|
|
638
|
+
print: (node) => {
|
|
639
|
+
const key = getKey(node);
|
|
640
|
+
if (key === void 0) return null;
|
|
641
|
+
const handler = nodes[key];
|
|
642
|
+
if (!handler) return null;
|
|
643
|
+
return handler.call(context, node);
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
return {
|
|
647
|
+
name,
|
|
648
|
+
options: resolvedOptions,
|
|
649
|
+
print: printOverride ? printOverride.bind(context) : context.print
|
|
650
|
+
};
|
|
651
|
+
};
|
|
652
|
+
};
|
|
653
|
+
}
|
|
173
654
|
//#endregion
|
|
174
|
-
//#region src/
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
655
|
+
//#region src/printers/functionPrinter.ts
|
|
656
|
+
const kindToHandlerKey = {
|
|
657
|
+
FunctionParameter: "functionParameter",
|
|
658
|
+
ObjectBindingParameter: "objectBindingParameter",
|
|
659
|
+
FunctionParameters: "functionParameters"
|
|
660
|
+
};
|
|
661
|
+
/**
|
|
662
|
+
* Creates a function-parameter printer factory.
|
|
663
|
+
*
|
|
664
|
+
* This wrapper uses `createPrinterFactory` and dispatches handlers by `node.kind`
|
|
665
|
+
* (for function nodes) rather than by `node.type` (for schema nodes).
|
|
666
|
+
*
|
|
667
|
+
* @example
|
|
668
|
+
* ```ts
|
|
669
|
+
* type MyPrinter = PrinterFactoryOptions<'my', { mode: 'declaration' | 'call' }, string>
|
|
670
|
+
*
|
|
671
|
+
* export const myPrinter = defineFunctionPrinter<MyPrinter>((options) => ({
|
|
672
|
+
* name: 'my',
|
|
673
|
+
* options,
|
|
674
|
+
* nodes: {
|
|
675
|
+
* functionParameter(node) {
|
|
676
|
+
* return options.mode === 'declaration' && node.type ? `${node.name}: ${node.type}` : node.name
|
|
677
|
+
* },
|
|
678
|
+
* objectBindingParameter(node) {
|
|
679
|
+
* const inner = node.properties.map(p => this.print(p)).filter(Boolean).join(', ')
|
|
680
|
+
* return `{ ${inner} }`
|
|
681
|
+
* },
|
|
682
|
+
* functionParameters(node) {
|
|
683
|
+
* return node.params.map(p => this.print(p)).filter(Boolean).join(', ')
|
|
199
684
|
* },
|
|
200
|
-
* }
|
|
685
|
+
* },
|
|
686
|
+
* }))
|
|
687
|
+
* ```
|
|
688
|
+
*/
|
|
689
|
+
const defineFunctionPrinter = createPrinterFactory((node) => kindToHandlerKey[node.kind]);
|
|
690
|
+
function rank(param) {
|
|
691
|
+
if (param.kind === "ObjectBindingParameter") {
|
|
692
|
+
if (param.default) return 2;
|
|
693
|
+
return param.optional ?? param.properties.every((p) => p.optional || p.default !== void 0) ? 1 : 0;
|
|
694
|
+
}
|
|
695
|
+
if (param.rest) return 3;
|
|
696
|
+
if (param.default) return 2;
|
|
697
|
+
return param.optional ? 1 : 0;
|
|
698
|
+
}
|
|
699
|
+
function sortParams(params) {
|
|
700
|
+
return [...params].sort((a, b) => rank(a) - rank(b));
|
|
701
|
+
}
|
|
702
|
+
function sortChildParams(params) {
|
|
703
|
+
return [...params].sort((a, b) => rank(a) - rank(b));
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Default function-signature printer.
|
|
707
|
+
* Covers the four standard output modes used across Kubb plugins.
|
|
708
|
+
*
|
|
709
|
+
* @example
|
|
710
|
+
* ```ts
|
|
711
|
+
* const printer = functionPrinter({ mode: 'declaration' })
|
|
712
|
+
*
|
|
713
|
+
* const sig = createFunctionParameters({
|
|
714
|
+
* params: [
|
|
715
|
+
* createFunctionParameter({ name: 'petId', type: 'string', optional: false }),
|
|
716
|
+
* createFunctionParameter({ name: 'config', type: 'Config', optional: false, default: '{}' }),
|
|
717
|
+
* ],
|
|
201
718
|
* })
|
|
202
719
|
*
|
|
203
|
-
*
|
|
204
|
-
* printer.name // 'zod'
|
|
205
|
-
* printer.options // { strict: false }
|
|
206
|
-
* printer.print(node) // 'z.string()'
|
|
720
|
+
* printer.print(sig) // → "petId: string, config: Config = {}"
|
|
207
721
|
* ```
|
|
208
722
|
*/
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
723
|
+
const functionPrinter = defineFunctionPrinter((options) => ({
|
|
724
|
+
name: "functionParameters",
|
|
725
|
+
options,
|
|
726
|
+
nodes: {
|
|
727
|
+
functionParameter(node) {
|
|
728
|
+
const { mode, transformName, transformType } = this.options;
|
|
729
|
+
const name = transformName ? transformName(node.name) : node.name;
|
|
730
|
+
const type = node.type && transformType ? transformType(node.type) : node.type;
|
|
731
|
+
if (mode === "keys" || mode === "values") return node.rest ? `...${name}` : name;
|
|
732
|
+
if (mode === "call") return node.rest ? `...${name}` : name;
|
|
733
|
+
if (node.rest) return type ? `...${name}: ${type}` : `...${name}`;
|
|
734
|
+
if (type) {
|
|
735
|
+
if (node.optional) return `${name}?: ${type}`;
|
|
736
|
+
return node.default ? `${name}: ${type} = ${node.default}` : `${name}: ${type}`;
|
|
217
737
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
738
|
+
return node.default ? `${name} = ${node.default}` : name;
|
|
739
|
+
},
|
|
740
|
+
objectBindingParameter(node) {
|
|
741
|
+
const { mode, transformName, transformType } = this.options;
|
|
742
|
+
const sorted = sortChildParams(node.properties);
|
|
743
|
+
const isOptional = node.optional ?? sorted.every((p) => p.optional || p.default !== void 0);
|
|
744
|
+
if (node.inline) return sorted.map((p) => this.print(p)).filter(Boolean).join(", ");
|
|
745
|
+
if (mode === "keys" || mode === "values") return `{ ${sorted.map((p) => p.name).join(", ")} }`;
|
|
746
|
+
if (mode === "call") return `{ ${sorted.map((p) => p.name).join(", ")} }`;
|
|
747
|
+
const names = sorted.map((p) => {
|
|
748
|
+
return transformName ? transformName(p.name) : p.name;
|
|
749
|
+
});
|
|
750
|
+
const nameStr = names.length ? `{ ${names.join(", ")} }` : void 0;
|
|
751
|
+
if (!nameStr) return null;
|
|
752
|
+
let typeAnnotation = node.type;
|
|
753
|
+
if (!typeAnnotation) {
|
|
754
|
+
const typeParts = sorted.filter((p) => p.type).map((p) => {
|
|
755
|
+
const t = transformType && p.type ? transformType(p.type) : p.type;
|
|
756
|
+
return p.optional || p.default !== void 0 ? `${p.name}?: ${t}` : `${p.name}: ${t}`;
|
|
757
|
+
});
|
|
758
|
+
typeAnnotation = typeParts.length ? `{ ${typeParts.join("; ")} }` : void 0;
|
|
759
|
+
}
|
|
760
|
+
if (typeAnnotation) {
|
|
761
|
+
if (isOptional) return `${nameStr}: ${typeAnnotation} = ${node.default ?? "{}"}`;
|
|
762
|
+
return node.default ? `${nameStr}: ${typeAnnotation} = ${node.default}` : `${nameStr}: ${typeAnnotation}`;
|
|
763
|
+
}
|
|
764
|
+
return node.default ? `${nameStr} = ${node.default}` : nameStr;
|
|
765
|
+
},
|
|
766
|
+
functionParameters(node) {
|
|
767
|
+
return sortParams(node.params).map((p) => this.print(p)).filter(Boolean).join(", ");
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}));
|
|
227
771
|
//#endregion
|
|
228
772
|
//#region src/refs.ts
|
|
229
773
|
/**
|
|
230
|
-
*
|
|
774
|
+
* Returns the last path segment of a reference string.
|
|
775
|
+
*
|
|
776
|
+
* Example: `#/components/schemas/Pet` becomes `Pet`.
|
|
777
|
+
*
|
|
778
|
+
* @example
|
|
779
|
+
* ```ts
|
|
780
|
+
* extractRefName('#/components/schemas/Pet') // 'Pet'
|
|
781
|
+
* ```
|
|
782
|
+
*/
|
|
783
|
+
function extractRefName(ref) {
|
|
784
|
+
return ref.split("/").at(-1) ?? ref;
|
|
785
|
+
}
|
|
786
|
+
/**
|
|
787
|
+
* Builds a `RefMap` from `root.schemas` using each schema's `name`.
|
|
788
|
+
*
|
|
789
|
+
* Unnamed schemas are skipped.
|
|
790
|
+
*
|
|
791
|
+
* @example
|
|
792
|
+
* ```ts
|
|
793
|
+
* const refMap = buildRefMap(root)
|
|
794
|
+
* const pet = refMap.get('Pet')
|
|
795
|
+
* ```
|
|
231
796
|
*/
|
|
232
797
|
function buildRefMap(root) {
|
|
233
798
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -235,19 +800,45 @@ function buildRefMap(root) {
|
|
|
235
800
|
return map;
|
|
236
801
|
}
|
|
237
802
|
/**
|
|
238
|
-
*
|
|
803
|
+
* Resolves a schema by name from a `RefMap`.
|
|
804
|
+
*
|
|
805
|
+
* @example
|
|
806
|
+
* ```ts
|
|
807
|
+
* const petSchema = resolveRef(refMap, 'Pet')
|
|
808
|
+
* ```
|
|
239
809
|
*/
|
|
240
810
|
function resolveRef(refMap, ref) {
|
|
241
811
|
return refMap.get(ref);
|
|
242
812
|
}
|
|
243
813
|
/**
|
|
244
|
-
* Converts a `RefMap`
|
|
814
|
+
* Converts a `RefMap` into a plain object.
|
|
815
|
+
*
|
|
816
|
+
* @example
|
|
817
|
+
* ```ts
|
|
818
|
+
* const refsObject = refMapToObject(refMap)
|
|
819
|
+
* ```
|
|
245
820
|
*/
|
|
246
821
|
function refMapToObject(refMap) {
|
|
247
822
|
return Object.fromEntries(refMap);
|
|
248
823
|
}
|
|
249
824
|
//#endregion
|
|
250
825
|
//#region src/visitor.ts
|
|
826
|
+
/**
|
|
827
|
+
* Creates a small async concurrency limiter.
|
|
828
|
+
*
|
|
829
|
+
* At most `concurrency` tasks are in flight at once. Extra tasks are queued.
|
|
830
|
+
*
|
|
831
|
+
* @example
|
|
832
|
+
* ```ts
|
|
833
|
+
* const limit = createLimit(2)
|
|
834
|
+
* await Promise.all([
|
|
835
|
+
* limit(() => taskA()),
|
|
836
|
+
* limit(() => taskB()),
|
|
837
|
+
* limit(() => taskC()),
|
|
838
|
+
* ])
|
|
839
|
+
* // only 2 tasks run at the same time
|
|
840
|
+
* ```
|
|
841
|
+
*/
|
|
251
842
|
function createLimit(concurrency) {
|
|
252
843
|
let active = 0;
|
|
253
844
|
const queue = [];
|
|
@@ -270,14 +861,24 @@ function createLimit(concurrency) {
|
|
|
270
861
|
};
|
|
271
862
|
}
|
|
272
863
|
/**
|
|
273
|
-
*
|
|
864
|
+
* Returns the immediate traversable children of `node`.
|
|
865
|
+
*
|
|
866
|
+
* For `Schema` nodes, children (`properties`, `items`, `members`, and non-boolean
|
|
867
|
+
* `additionalProperties`) are only included
|
|
868
|
+
* when `recurse` is `true`; shallow mode skips them.
|
|
869
|
+
*
|
|
870
|
+
* @example
|
|
871
|
+
* ```ts
|
|
872
|
+
* const children = getChildren(operationNode, true)
|
|
873
|
+
* // returns parameters, requestBody schema (if present), and responses
|
|
874
|
+
* ```
|
|
274
875
|
*/
|
|
275
876
|
function getChildren(node, recurse) {
|
|
276
877
|
switch (node.kind) {
|
|
277
878
|
case "Root": return [...node.schemas, ...node.operations];
|
|
278
879
|
case "Operation": return [
|
|
279
880
|
...node.parameters,
|
|
280
|
-
...node.requestBody ? [node.requestBody] : [],
|
|
881
|
+
...node.requestBody?.schema ? [node.requestBody.schema] : [],
|
|
281
882
|
...node.responses
|
|
282
883
|
];
|
|
283
884
|
case "Schema": {
|
|
@@ -286,162 +887,464 @@ function getChildren(node, recurse) {
|
|
|
286
887
|
if ("properties" in node && node.properties.length > 0) children.push(...node.properties);
|
|
287
888
|
if ("items" in node && node.items) children.push(...node.items);
|
|
288
889
|
if ("members" in node && node.members) children.push(...node.members);
|
|
890
|
+
if ("additionalProperties" in node && node.additionalProperties && node.additionalProperties !== true) children.push(node.additionalProperties);
|
|
289
891
|
return children;
|
|
290
892
|
}
|
|
291
893
|
case "Property": return [node.schema];
|
|
292
894
|
case "Parameter": return [node.schema];
|
|
293
895
|
case "Response": return node.schema ? [node.schema] : [];
|
|
896
|
+
case "FunctionParameter":
|
|
897
|
+
case "ObjectBindingParameter":
|
|
898
|
+
case "FunctionParameters": return [];
|
|
294
899
|
}
|
|
295
900
|
}
|
|
296
901
|
/**
|
|
297
902
|
* Depth-first traversal for side effects. Visitor return values are ignored.
|
|
298
|
-
* Sibling nodes at each level are visited concurrently up to `options.concurrency`
|
|
903
|
+
* Sibling nodes at each level are visited concurrently up to `options.concurrency`
|
|
904
|
+
* (default: `WALK_CONCURRENCY`).
|
|
905
|
+
*
|
|
906
|
+
* @example
|
|
907
|
+
* ```ts
|
|
908
|
+
* await walk(root, {
|
|
909
|
+
* operation(node) {
|
|
910
|
+
* console.log(node.operationId)
|
|
911
|
+
* },
|
|
912
|
+
* })
|
|
913
|
+
* ```
|
|
914
|
+
*
|
|
915
|
+
* @example
|
|
916
|
+
* ```ts
|
|
917
|
+
* // Visit only the current node
|
|
918
|
+
* await walk(root, { depth: 'shallow', root: () => {} })
|
|
919
|
+
* ```
|
|
299
920
|
*/
|
|
300
|
-
async function walk(node,
|
|
301
|
-
return _walk(node,
|
|
921
|
+
async function walk(node, options) {
|
|
922
|
+
return _walk(node, options, (options.depth ?? visitorDepths.deep) === visitorDepths.deep, createLimit(options.concurrency ?? 30), void 0);
|
|
302
923
|
}
|
|
303
|
-
async function _walk(node, visitor, recurse, limit) {
|
|
924
|
+
async function _walk(node, visitor, recurse, limit, parent) {
|
|
304
925
|
switch (node.kind) {
|
|
305
926
|
case "Root":
|
|
306
|
-
await limit(() => visitor.root?.(node));
|
|
927
|
+
await limit(() => visitor.root?.(node, { parent }));
|
|
307
928
|
break;
|
|
308
929
|
case "Operation":
|
|
309
|
-
await limit(() => visitor.operation?.(node));
|
|
930
|
+
await limit(() => visitor.operation?.(node, { parent }));
|
|
310
931
|
break;
|
|
311
932
|
case "Schema":
|
|
312
|
-
await limit(() => visitor.schema?.(node));
|
|
933
|
+
await limit(() => visitor.schema?.(node, { parent }));
|
|
313
934
|
break;
|
|
314
935
|
case "Property":
|
|
315
|
-
await limit(() => visitor.property?.(node));
|
|
936
|
+
await limit(() => visitor.property?.(node, { parent }));
|
|
316
937
|
break;
|
|
317
938
|
case "Parameter":
|
|
318
|
-
await limit(() => visitor.parameter?.(node));
|
|
939
|
+
await limit(() => visitor.parameter?.(node, { parent }));
|
|
319
940
|
break;
|
|
320
941
|
case "Response":
|
|
321
|
-
await limit(() => visitor.response?.(node));
|
|
942
|
+
await limit(() => visitor.response?.(node, { parent }));
|
|
322
943
|
break;
|
|
944
|
+
case "FunctionParameter":
|
|
945
|
+
case "ObjectBindingParameter":
|
|
946
|
+
case "FunctionParameters": break;
|
|
323
947
|
}
|
|
324
948
|
const children = getChildren(node, recurse);
|
|
325
|
-
await Promise.all(children.map((child) => _walk(child, visitor, recurse, limit)));
|
|
949
|
+
await Promise.all(children.map((child) => _walk(child, visitor, recurse, limit, node)));
|
|
326
950
|
}
|
|
327
|
-
function transform(node,
|
|
328
|
-
const
|
|
951
|
+
function transform(node, options) {
|
|
952
|
+
const { depth, parent, ...visitor } = options;
|
|
953
|
+
const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep;
|
|
329
954
|
switch (node.kind) {
|
|
330
955
|
case "Root": {
|
|
331
956
|
let root = node;
|
|
332
|
-
const replaced = visitor.root?.(root);
|
|
957
|
+
const replaced = visitor.root?.(root, { parent });
|
|
333
958
|
if (replaced) root = replaced;
|
|
334
959
|
return {
|
|
335
960
|
...root,
|
|
336
|
-
schemas: root.schemas.map((s) => transform(s,
|
|
337
|
-
|
|
961
|
+
schemas: root.schemas.map((s) => transform(s, {
|
|
962
|
+
...options,
|
|
963
|
+
parent: root
|
|
964
|
+
})),
|
|
965
|
+
operations: root.operations.map((op) => transform(op, {
|
|
966
|
+
...options,
|
|
967
|
+
parent: root
|
|
968
|
+
}))
|
|
338
969
|
};
|
|
339
970
|
}
|
|
340
971
|
case "Operation": {
|
|
341
972
|
let op = node;
|
|
342
|
-
const replaced = visitor.operation?.(op);
|
|
973
|
+
const replaced = visitor.operation?.(op, { parent });
|
|
343
974
|
if (replaced) op = replaced;
|
|
344
975
|
return {
|
|
345
976
|
...op,
|
|
346
|
-
parameters: op.parameters.map((p) => transform(p,
|
|
347
|
-
|
|
348
|
-
|
|
977
|
+
parameters: op.parameters.map((p) => transform(p, {
|
|
978
|
+
...options,
|
|
979
|
+
parent: op
|
|
980
|
+
})),
|
|
981
|
+
requestBody: op.requestBody ? {
|
|
982
|
+
...op.requestBody,
|
|
983
|
+
schema: op.requestBody.schema ? transform(op.requestBody.schema, {
|
|
984
|
+
...options,
|
|
985
|
+
parent: op
|
|
986
|
+
}) : void 0
|
|
987
|
+
} : void 0,
|
|
988
|
+
responses: op.responses.map((r) => transform(r, {
|
|
989
|
+
...options,
|
|
990
|
+
parent: op
|
|
991
|
+
}))
|
|
349
992
|
};
|
|
350
993
|
}
|
|
351
994
|
case "Schema": {
|
|
352
995
|
let schema = node;
|
|
353
|
-
const replaced = visitor.schema?.(schema);
|
|
996
|
+
const replaced = visitor.schema?.(schema, { parent });
|
|
354
997
|
if (replaced) schema = replaced;
|
|
998
|
+
const childOptions = {
|
|
999
|
+
...options,
|
|
1000
|
+
parent: schema
|
|
1001
|
+
};
|
|
355
1002
|
return {
|
|
356
1003
|
...schema,
|
|
357
|
-
..."properties" in schema && recurse ? { properties: schema.properties.map((p) => transform(p,
|
|
358
|
-
..."items" in schema && recurse ? { items: schema.items?.map((i) => transform(i,
|
|
359
|
-
..."members" in schema && recurse ? { members: schema.members?.map((m) => transform(m,
|
|
1004
|
+
..."properties" in schema && recurse ? { properties: schema.properties.map((p) => transform(p, childOptions)) } : {},
|
|
1005
|
+
..."items" in schema && recurse ? { items: schema.items?.map((i) => transform(i, childOptions)) } : {},
|
|
1006
|
+
..."members" in schema && recurse ? { members: schema.members?.map((m) => transform(m, childOptions)) } : {},
|
|
1007
|
+
..."additionalProperties" in schema && recurse && schema.additionalProperties && schema.additionalProperties !== true ? { additionalProperties: transform(schema.additionalProperties, childOptions) } : {}
|
|
360
1008
|
};
|
|
361
1009
|
}
|
|
362
1010
|
case "Property": {
|
|
363
1011
|
let prop = node;
|
|
364
|
-
const replaced = visitor.property?.(prop);
|
|
1012
|
+
const replaced = visitor.property?.(prop, { parent });
|
|
365
1013
|
if (replaced) prop = replaced;
|
|
366
|
-
return {
|
|
1014
|
+
return createProperty({
|
|
367
1015
|
...prop,
|
|
368
|
-
schema: transform(prop.schema,
|
|
369
|
-
|
|
1016
|
+
schema: transform(prop.schema, {
|
|
1017
|
+
...options,
|
|
1018
|
+
parent: prop
|
|
1019
|
+
})
|
|
1020
|
+
});
|
|
370
1021
|
}
|
|
371
1022
|
case "Parameter": {
|
|
372
1023
|
let param = node;
|
|
373
|
-
const replaced = visitor.parameter?.(param);
|
|
1024
|
+
const replaced = visitor.parameter?.(param, { parent });
|
|
374
1025
|
if (replaced) param = replaced;
|
|
375
|
-
return {
|
|
1026
|
+
return createParameter({
|
|
376
1027
|
...param,
|
|
377
|
-
schema: transform(param.schema,
|
|
378
|
-
|
|
1028
|
+
schema: transform(param.schema, {
|
|
1029
|
+
...options,
|
|
1030
|
+
parent: param
|
|
1031
|
+
})
|
|
1032
|
+
});
|
|
379
1033
|
}
|
|
380
1034
|
case "Response": {
|
|
381
1035
|
let response = node;
|
|
382
|
-
const replaced = visitor.response?.(response);
|
|
1036
|
+
const replaced = visitor.response?.(response, { parent });
|
|
383
1037
|
if (replaced) response = replaced;
|
|
384
1038
|
return {
|
|
385
1039
|
...response,
|
|
386
|
-
schema:
|
|
1040
|
+
schema: transform(response.schema, {
|
|
1041
|
+
...options,
|
|
1042
|
+
parent: response
|
|
1043
|
+
})
|
|
387
1044
|
};
|
|
388
1045
|
}
|
|
1046
|
+
case "FunctionParameter":
|
|
1047
|
+
case "ObjectBindingParameter":
|
|
1048
|
+
case "FunctionParameters": return node;
|
|
389
1049
|
}
|
|
390
1050
|
}
|
|
391
1051
|
/**
|
|
392
|
-
*
|
|
1052
|
+
* Composes multiple visitors into one visitor, applied left to right.
|
|
1053
|
+
*
|
|
1054
|
+
* For each node kind, output from one visitor is input to the next.
|
|
1055
|
+
* If a visitor returns `undefined`, the previous node value is kept.
|
|
1056
|
+
*
|
|
1057
|
+
* @example
|
|
1058
|
+
* ```ts
|
|
1059
|
+
* const visitor = composeTransformers(
|
|
1060
|
+
* { operation: (node) => ({ ...node, operationId: `a_${node.operationId}` }) },
|
|
1061
|
+
* { operation: (node) => ({ ...node, operationId: `b_${node.operationId}` }) },
|
|
1062
|
+
* )
|
|
1063
|
+
* ```
|
|
393
1064
|
*/
|
|
394
|
-
function
|
|
395
|
-
|
|
1065
|
+
function composeTransformers(...visitors) {
|
|
1066
|
+
return {
|
|
1067
|
+
root(node, context) {
|
|
1068
|
+
return visitors.reduce((acc, v) => v.root?.(acc, context) ?? acc, node);
|
|
1069
|
+
},
|
|
1070
|
+
operation(node, context) {
|
|
1071
|
+
return visitors.reduce((acc, v) => v.operation?.(acc, context) ?? acc, node);
|
|
1072
|
+
},
|
|
1073
|
+
schema(node, context) {
|
|
1074
|
+
return visitors.reduce((acc, v) => v.schema?.(acc, context) ?? acc, node);
|
|
1075
|
+
},
|
|
1076
|
+
property(node, context) {
|
|
1077
|
+
return visitors.reduce((acc, v) => v.property?.(acc, context) ?? acc, node);
|
|
1078
|
+
},
|
|
1079
|
+
parameter(node, context) {
|
|
1080
|
+
return visitors.reduce((acc, v) => v.parameter?.(acc, context) ?? acc, node);
|
|
1081
|
+
},
|
|
1082
|
+
response(node, context) {
|
|
1083
|
+
return visitors.reduce((acc, v) => v.response?.(acc, context) ?? acc, node);
|
|
1084
|
+
}
|
|
1085
|
+
};
|
|
1086
|
+
}
|
|
1087
|
+
/**
|
|
1088
|
+
* Runs a depth-first synchronous collection pass.
|
|
1089
|
+
*
|
|
1090
|
+
* Non-`undefined` values returned by visitor callbacks are appended to the result.
|
|
1091
|
+
*
|
|
1092
|
+
* @example
|
|
1093
|
+
* ```ts
|
|
1094
|
+
* const ids = collect(root, {
|
|
1095
|
+
* operation(node) {
|
|
1096
|
+
* return node.operationId
|
|
1097
|
+
* },
|
|
1098
|
+
* })
|
|
1099
|
+
* ```
|
|
1100
|
+
*
|
|
1101
|
+
* @example
|
|
1102
|
+
* ```ts
|
|
1103
|
+
* // Collect from only the current node
|
|
1104
|
+
* const values = collect(root, { depth: 'shallow', root: () => 'root' })
|
|
1105
|
+
* ```
|
|
1106
|
+
*/
|
|
1107
|
+
function collect(node, options) {
|
|
1108
|
+
const { depth, parent, ...visitor } = options;
|
|
1109
|
+
const recurse = (depth ?? visitorDepths.deep) === visitorDepths.deep;
|
|
396
1110
|
const results = [];
|
|
397
1111
|
let v;
|
|
398
1112
|
switch (node.kind) {
|
|
399
1113
|
case "Root":
|
|
400
|
-
v = visitor.root?.(node);
|
|
1114
|
+
v = visitor.root?.(node, { parent });
|
|
401
1115
|
break;
|
|
402
1116
|
case "Operation":
|
|
403
|
-
v = visitor.operation?.(node);
|
|
1117
|
+
v = visitor.operation?.(node, { parent });
|
|
404
1118
|
break;
|
|
405
1119
|
case "Schema":
|
|
406
|
-
v = visitor.schema?.(node);
|
|
1120
|
+
v = visitor.schema?.(node, { parent });
|
|
407
1121
|
break;
|
|
408
1122
|
case "Property":
|
|
409
|
-
v = visitor.property?.(node);
|
|
1123
|
+
v = visitor.property?.(node, { parent });
|
|
410
1124
|
break;
|
|
411
1125
|
case "Parameter":
|
|
412
|
-
v = visitor.parameter?.(node);
|
|
1126
|
+
v = visitor.parameter?.(node, { parent });
|
|
413
1127
|
break;
|
|
414
1128
|
case "Response":
|
|
415
|
-
v = visitor.response?.(node);
|
|
1129
|
+
v = visitor.response?.(node, { parent });
|
|
416
1130
|
break;
|
|
1131
|
+
case "FunctionParameter":
|
|
1132
|
+
case "ObjectBindingParameter":
|
|
1133
|
+
case "FunctionParameters": break;
|
|
417
1134
|
}
|
|
418
1135
|
if (v !== void 0) results.push(v);
|
|
419
|
-
for (const child of getChildren(node, recurse)) for (const item of collect(child,
|
|
1136
|
+
for (const child of getChildren(node, recurse)) for (const item of collect(child, {
|
|
1137
|
+
...options,
|
|
1138
|
+
parent: node
|
|
1139
|
+
})) results.push(item);
|
|
420
1140
|
return results;
|
|
421
1141
|
}
|
|
422
1142
|
//#endregion
|
|
1143
|
+
//#region src/resolvers.ts
|
|
1144
|
+
function findDiscriminator(mapping, ref) {
|
|
1145
|
+
if (!mapping || !ref) return null;
|
|
1146
|
+
return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null;
|
|
1147
|
+
}
|
|
1148
|
+
function childName(parentName, propName) {
|
|
1149
|
+
return parentName ? pascalCase([parentName, propName].join(" ")) : null;
|
|
1150
|
+
}
|
|
1151
|
+
function enumPropName(parentName, propName, enumSuffix) {
|
|
1152
|
+
return pascalCase([
|
|
1153
|
+
parentName,
|
|
1154
|
+
propName,
|
|
1155
|
+
enumSuffix
|
|
1156
|
+
].filter(Boolean).join(" "));
|
|
1157
|
+
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Collects import entries for all `ref` schema nodes in `node`.
|
|
1160
|
+
*/
|
|
1161
|
+
function collectImports({ node, nameMapping, resolve }) {
|
|
1162
|
+
return collect(node, { schema(schemaNode) {
|
|
1163
|
+
const schemaRef = narrowSchema(schemaNode, "ref");
|
|
1164
|
+
if (!schemaRef?.ref) return;
|
|
1165
|
+
const rawName = extractRefName(schemaRef.ref);
|
|
1166
|
+
const result = resolve(nameMapping.get(rawName) ?? rawName);
|
|
1167
|
+
if (!result) return;
|
|
1168
|
+
return result;
|
|
1169
|
+
} });
|
|
1170
|
+
}
|
|
1171
|
+
//#endregion
|
|
1172
|
+
//#region src/transformers.ts
|
|
1173
|
+
/**
|
|
1174
|
+
* Replaces a discriminator property's schema with a string enum of allowed values.
|
|
1175
|
+
*
|
|
1176
|
+
* If `node` is not an object schema, or if the property does not exist, the input
|
|
1177
|
+
* node is returned as-is.
|
|
1178
|
+
*
|
|
1179
|
+
* @example
|
|
1180
|
+
* ```ts
|
|
1181
|
+
* const schema = createSchema({
|
|
1182
|
+
* type: 'object',
|
|
1183
|
+
* properties: [createProperty({ name: 'type', required: true, schema: createSchema({ type: 'string' }) })],
|
|
1184
|
+
* })
|
|
1185
|
+
* const result = setDiscriminatorEnum({ node: schema, propertyName: 'type', values: ['dog', 'cat'] })
|
|
1186
|
+
* ```
|
|
1187
|
+
*/
|
|
1188
|
+
function setDiscriminatorEnum({ node, propertyName, values, enumName }) {
|
|
1189
|
+
const objectNode = narrowSchema(node, "object");
|
|
1190
|
+
if (!objectNode?.properties?.length) return node;
|
|
1191
|
+
if (!objectNode.properties.some((prop) => prop.name === propertyName)) return node;
|
|
1192
|
+
return createSchema({
|
|
1193
|
+
...objectNode,
|
|
1194
|
+
properties: objectNode.properties.map((prop) => {
|
|
1195
|
+
if (prop.name !== propertyName) return prop;
|
|
1196
|
+
return createProperty({
|
|
1197
|
+
...prop,
|
|
1198
|
+
schema: createSchema({
|
|
1199
|
+
type: "enum",
|
|
1200
|
+
primitive: "string",
|
|
1201
|
+
enumValues: values,
|
|
1202
|
+
name: enumName,
|
|
1203
|
+
readOnly: prop.schema.readOnly,
|
|
1204
|
+
writeOnly: prop.schema.writeOnly
|
|
1205
|
+
})
|
|
1206
|
+
});
|
|
1207
|
+
})
|
|
1208
|
+
});
|
|
1209
|
+
}
|
|
1210
|
+
/**
|
|
1211
|
+
* Merges adjacent anonymous object members into a single anonymous object member.
|
|
1212
|
+
*
|
|
1213
|
+
* @example
|
|
1214
|
+
* ```ts
|
|
1215
|
+
* const merged = mergeAdjacentObjects([
|
|
1216
|
+
* createSchema({ type: 'object', properties: [createProperty({ name: 'a', schema: createSchema({ type: 'string' }) })] }),
|
|
1217
|
+
* createSchema({ type: 'object', properties: [createProperty({ name: 'b', schema: createSchema({ type: 'number' }) })] }),
|
|
1218
|
+
* ])
|
|
1219
|
+
* ```
|
|
1220
|
+
*/
|
|
1221
|
+
function mergeAdjacentObjects(members) {
|
|
1222
|
+
return members.reduce((acc, member) => {
|
|
1223
|
+
const objectMember = narrowSchema(member, "object");
|
|
1224
|
+
if (objectMember && !objectMember.name) {
|
|
1225
|
+
const previous = acc.at(-1);
|
|
1226
|
+
const previousObject = previous ? narrowSchema(previous, "object") : void 0;
|
|
1227
|
+
if (previousObject && !previousObject.name) {
|
|
1228
|
+
acc[acc.length - 1] = createSchema({
|
|
1229
|
+
...previousObject,
|
|
1230
|
+
properties: [...previousObject.properties ?? [], ...objectMember.properties ?? []]
|
|
1231
|
+
});
|
|
1232
|
+
return acc;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
acc.push(member);
|
|
1236
|
+
return acc;
|
|
1237
|
+
}, []);
|
|
1238
|
+
}
|
|
1239
|
+
/**
|
|
1240
|
+
* Removes enum members that are covered by broader scalar primitives in the same union.
|
|
1241
|
+
*
|
|
1242
|
+
* @example
|
|
1243
|
+
* ```ts
|
|
1244
|
+
* const simplified = simplifyUnion([
|
|
1245
|
+
* createSchema({ type: 'enum', primitive: 'string', enumValues: ['active'] }),
|
|
1246
|
+
* createSchema({ type: 'string' }),
|
|
1247
|
+
* ])
|
|
1248
|
+
* // keeps only string member
|
|
1249
|
+
* ```
|
|
1250
|
+
*/
|
|
1251
|
+
function simplifyUnion(members) {
|
|
1252
|
+
const scalarPrimitives = new Set(members.filter((member) => SCALAR_PRIMITIVE_TYPES.has(member.type)).map((m) => m.type));
|
|
1253
|
+
if (!scalarPrimitives.size) return members;
|
|
1254
|
+
return members.filter((member) => {
|
|
1255
|
+
const enumNode = narrowSchema(member, "enum");
|
|
1256
|
+
if (!enumNode) return true;
|
|
1257
|
+
const primitive = enumNode.primitive;
|
|
1258
|
+
if (!primitive) return true;
|
|
1259
|
+
if ((enumNode.namedEnumValues?.length ?? enumNode.enumValues?.length ?? 0) <= 1) return true;
|
|
1260
|
+
if (scalarPrimitives.has(primitive)) return false;
|
|
1261
|
+
if ((primitive === "integer" || primitive === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
|
|
1262
|
+
return true;
|
|
1263
|
+
});
|
|
1264
|
+
}
|
|
1265
|
+
function setEnumName(propNode, parentName, propName, enumSuffix) {
|
|
1266
|
+
const enumNode = narrowSchema(propNode, "enum");
|
|
1267
|
+
if (enumNode?.primitive === "boolean") return {
|
|
1268
|
+
...propNode,
|
|
1269
|
+
name: void 0
|
|
1270
|
+
};
|
|
1271
|
+
if (enumNode) return {
|
|
1272
|
+
...propNode,
|
|
1273
|
+
name: enumPropName(parentName, propName, enumSuffix)
|
|
1274
|
+
};
|
|
1275
|
+
return propNode;
|
|
1276
|
+
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Walks a schema tree and resolves `ref`/`enum` names through callbacks.
|
|
1279
|
+
*/
|
|
1280
|
+
function resolveNames({ node, nameMapping, resolveName, resolveEnumName }) {
|
|
1281
|
+
return transform(node, { schema(schemaNode) {
|
|
1282
|
+
const schemaRef = narrowSchema(schemaNode, "ref");
|
|
1283
|
+
if (schemaRef && (schemaRef.ref || schemaRef.name)) {
|
|
1284
|
+
const rawRef = schemaRef.ref ?? schemaRef.name;
|
|
1285
|
+
const resolved = resolveName(nameMapping.get(rawRef) ?? rawRef);
|
|
1286
|
+
if (resolved) return {
|
|
1287
|
+
...schemaNode,
|
|
1288
|
+
name: resolved
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
const schemaEnum = narrowSchema(schemaNode, "enum");
|
|
1292
|
+
if (schemaEnum?.name) {
|
|
1293
|
+
const resolved = (resolveEnumName ?? resolveName)(schemaEnum.name);
|
|
1294
|
+
if (resolved) return {
|
|
1295
|
+
...schemaNode,
|
|
1296
|
+
name: resolved
|
|
1297
|
+
};
|
|
1298
|
+
}
|
|
1299
|
+
} });
|
|
1300
|
+
}
|
|
1301
|
+
//#endregion
|
|
1302
|
+
exports.SCALAR_PRIMITIVE_TYPES = SCALAR_PRIMITIVE_TYPES;
|
|
423
1303
|
exports.buildRefMap = buildRefMap;
|
|
1304
|
+
exports.caseParams = caseParams;
|
|
1305
|
+
exports.childName = childName;
|
|
424
1306
|
exports.collect = collect;
|
|
1307
|
+
exports.collectImports = collectImports;
|
|
1308
|
+
exports.composeTransformers = composeTransformers;
|
|
1309
|
+
exports.createDiscriminantNode = createDiscriminantNode;
|
|
1310
|
+
exports.createFunctionParameter = createFunctionParameter;
|
|
1311
|
+
exports.createFunctionParameters = createFunctionParameters;
|
|
1312
|
+
exports.createObjectBindingParameter = createObjectBindingParameter;
|
|
425
1313
|
exports.createOperation = createOperation;
|
|
426
1314
|
exports.createParameter = createParameter;
|
|
427
1315
|
exports.createProperty = createProperty;
|
|
428
1316
|
exports.createResponse = createResponse;
|
|
429
1317
|
exports.createRoot = createRoot;
|
|
430
1318
|
exports.createSchema = createSchema;
|
|
1319
|
+
exports.defineFunctionPrinter = defineFunctionPrinter;
|
|
431
1320
|
exports.definePrinter = definePrinter;
|
|
1321
|
+
exports.enumPropName = enumPropName;
|
|
1322
|
+
exports.extractRefName = extractRefName;
|
|
1323
|
+
exports.findDiscriminator = findDiscriminator;
|
|
1324
|
+
exports.functionPrinter = functionPrinter;
|
|
432
1325
|
exports.httpMethods = httpMethods;
|
|
1326
|
+
exports.isFunctionParameterNode = isFunctionParameterNode;
|
|
1327
|
+
exports.isFunctionParametersNode = isFunctionParametersNode;
|
|
1328
|
+
exports.isObjectBindingParameterNode = isObjectBindingParameterNode;
|
|
433
1329
|
exports.isOperationNode = isOperationNode;
|
|
434
1330
|
exports.isParameterNode = isParameterNode;
|
|
435
1331
|
exports.isPropertyNode = isPropertyNode;
|
|
436
1332
|
exports.isResponseNode = isResponseNode;
|
|
437
1333
|
exports.isRootNode = isRootNode;
|
|
438
1334
|
exports.isSchemaNode = isSchemaNode;
|
|
1335
|
+
exports.isStringType = isStringType;
|
|
439
1336
|
exports.mediaTypes = mediaTypes;
|
|
1337
|
+
exports.mergeAdjacentObjects = mergeAdjacentObjects;
|
|
440
1338
|
exports.narrowSchema = narrowSchema;
|
|
441
1339
|
exports.nodeKinds = nodeKinds;
|
|
442
1340
|
exports.refMapToObject = refMapToObject;
|
|
1341
|
+
exports.resolveNames = resolveNames;
|
|
443
1342
|
exports.resolveRef = resolveRef;
|
|
444
1343
|
exports.schemaTypes = schemaTypes;
|
|
1344
|
+
exports.setDiscriminatorEnum = setDiscriminatorEnum;
|
|
1345
|
+
exports.setEnumName = setEnumName;
|
|
1346
|
+
exports.simplifyUnion = simplifyUnion;
|
|
1347
|
+
exports.syncOptionality = syncOptionality;
|
|
445
1348
|
exports.transform = transform;
|
|
446
1349
|
exports.walk = walk;
|
|
447
1350
|
|