@kubb/ast 5.0.0-alpha.16 → 5.0.0-alpha.18
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 +651 -494
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +229 -68
- package/dist/index.js +638 -489
- 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 +1 -1
- package/src/constants.ts +88 -4
- package/src/factory.ts +174 -37
- package/src/guards.ts +37 -10
- package/src/index.ts +6 -5
- package/src/infer.ts +130 -0
- package/src/mocks.ts +4 -3
- package/src/nodes/base.ts +21 -3
- package/src/nodes/function.ts +34 -22
- package/src/nodes/http.ts +17 -5
- package/src/nodes/index.ts +14 -4
- package/src/nodes/operation.ts +47 -9
- package/src/nodes/parameter.ts +27 -1
- package/src/nodes/property.ts +23 -1
- package/src/nodes/response.ts +24 -4
- package/src/nodes/root.ts +29 -8
- package/src/nodes/schema.ts +301 -37
- package/src/{functionPrinter.ts → printers/functionPrinter.ts} +20 -19
- package/src/printers/index.ts +3 -0
- package/src/{printer.ts → printers/printer.ts} +60 -44
- package/src/refs.ts +30 -6
- package/src/resolvers.ts +45 -0
- package/src/transformers.ts +196 -0
- package/src/types.ts +2 -1
- package/src/utils.ts +37 -8
- package/src/visitor.ts +204 -18
- package/dist/visitor-YMltBj6w.d.ts +0 -970
- package/src/transforms.ts +0 -114
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import "./chunk--u3MIqq1.js";
|
|
2
|
-
import { parseArgs, styleText } from "node:util";
|
|
3
2
|
//#region src/constants.ts
|
|
4
3
|
const visitorDepths = {
|
|
5
4
|
shallow: "shallow",
|
|
@@ -16,6 +15,17 @@ const nodeKinds = {
|
|
|
16
15
|
objectBindingParameter: "ObjectBindingParameter",
|
|
17
16
|
functionParameters: "FunctionParameters"
|
|
18
17
|
};
|
|
18
|
+
/**
|
|
19
|
+
* Canonical schema type strings used by AST schema nodes.
|
|
20
|
+
*
|
|
21
|
+
* These values are used across the AST as stable discriminators
|
|
22
|
+
* (for example `schema.type === schemaTypes.object`).
|
|
23
|
+
*
|
|
24
|
+
* The map is grouped by intent:
|
|
25
|
+
* - primitives (`string`, `number`, `boolean`, ...)
|
|
26
|
+
* - structural/composite (`object`, `array`, `union`, ...)
|
|
27
|
+
* - special OpenAPI-oriented types (`ref`, `datetime`, `uuid`, ...)
|
|
28
|
+
*/
|
|
19
29
|
const schemaTypes = {
|
|
20
30
|
string: "string",
|
|
21
31
|
number: "number",
|
|
@@ -43,7 +53,7 @@ const schemaTypes = {
|
|
|
43
53
|
never: "never"
|
|
44
54
|
};
|
|
45
55
|
/**
|
|
46
|
-
*
|
|
56
|
+
* Primitive scalar schema types used when simplifying union members.
|
|
47
57
|
*/
|
|
48
58
|
const SCALAR_PRIMITIVE_TYPES = new Set([
|
|
49
59
|
"string",
|
|
@@ -84,9 +94,241 @@ const mediaTypes = {
|
|
|
84
94
|
videoMp4: "video/mp4"
|
|
85
95
|
};
|
|
86
96
|
//#endregion
|
|
97
|
+
//#region ../../internals/utils/src/casing.ts
|
|
98
|
+
/**
|
|
99
|
+
* Shared implementation for camelCase and PascalCase conversion.
|
|
100
|
+
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
101
|
+
* and capitalizes each word according to `pascal`.
|
|
102
|
+
*
|
|
103
|
+
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
104
|
+
*/
|
|
105
|
+
function toCamelOrPascal(text, pascal) {
|
|
106
|
+
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) => {
|
|
107
|
+
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
108
|
+
if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
|
|
109
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
110
|
+
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
114
|
+
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
115
|
+
* Segments are joined with `/` to form a file path.
|
|
116
|
+
*
|
|
117
|
+
* Only splits on dots followed by a letter so that version numbers
|
|
118
|
+
* embedded in operationIds (e.g. `v2025.0`) are kept intact.
|
|
119
|
+
*/
|
|
120
|
+
function applyToFileParts(text, transformPart) {
|
|
121
|
+
const parts = text.split(/\.(?=[a-zA-Z])/);
|
|
122
|
+
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Converts `text` to camelCase.
|
|
126
|
+
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* camelCase('hello-world') // 'helloWorld'
|
|
130
|
+
* camelCase('pet.petId', { isFile: true }) // 'pet/petId'
|
|
131
|
+
*/
|
|
132
|
+
function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
133
|
+
if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
|
|
134
|
+
prefix,
|
|
135
|
+
suffix
|
|
136
|
+
} : {}));
|
|
137
|
+
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Converts `text` to PascalCase.
|
|
141
|
+
* When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* pascalCase('hello-world') // 'HelloWorld'
|
|
145
|
+
* pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'
|
|
146
|
+
*/
|
|
147
|
+
function pascalCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
148
|
+
if (isFile) return applyToFileParts(text, (part, isLast) => isLast ? pascalCase(part, {
|
|
149
|
+
prefix,
|
|
150
|
+
suffix
|
|
151
|
+
}) : camelCase(part));
|
|
152
|
+
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true);
|
|
153
|
+
}
|
|
154
|
+
//#endregion
|
|
155
|
+
//#region ../../internals/utils/src/reserved.ts
|
|
156
|
+
/**
|
|
157
|
+
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* isValidVarName('status') // true
|
|
162
|
+
* isValidVarName('class') // false (reserved word)
|
|
163
|
+
* isValidVarName('42foo') // false (starts with digit)
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
function isValidVarName(name) {
|
|
167
|
+
try {
|
|
168
|
+
new Function(`var ${name}`);
|
|
169
|
+
} catch {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
//#region src/guards.ts
|
|
176
|
+
/**
|
|
177
|
+
* Narrows a `SchemaNode` to the variant that matches `type`.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* const schema = createSchema({ type: 'string' })
|
|
182
|
+
* const stringNode = narrowSchema(schema, 'string') // StringSchemaNode | undefined
|
|
183
|
+
* ```
|
|
184
|
+
*/
|
|
185
|
+
function narrowSchema(node, type) {
|
|
186
|
+
return node?.type === type ? node : void 0;
|
|
187
|
+
}
|
|
188
|
+
function isKind(kind) {
|
|
189
|
+
return (node) => node.kind === kind;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Returns `true` when the input is a `RootNode`.
|
|
193
|
+
*
|
|
194
|
+
* @example
|
|
195
|
+
* ```ts
|
|
196
|
+
* if (isRootNode(node)) {
|
|
197
|
+
* console.log(node.schemas.length)
|
|
198
|
+
* }
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
201
|
+
const isRootNode = isKind("Root");
|
|
202
|
+
/**
|
|
203
|
+
* Returns `true` when the input is an `OperationNode`.
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```ts
|
|
207
|
+
* if (isOperationNode(node)) {
|
|
208
|
+
* console.log(node.operationId)
|
|
209
|
+
* }
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
212
|
+
const isOperationNode = isKind("Operation");
|
|
213
|
+
/**
|
|
214
|
+
* Returns `true` when the input is a `SchemaNode`.
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```ts
|
|
218
|
+
* if (isSchemaNode(node)) {
|
|
219
|
+
* console.log(node.type)
|
|
220
|
+
* }
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
const isSchemaNode = isKind("Schema");
|
|
224
|
+
/**
|
|
225
|
+
* Returns `true` when the input is a `PropertyNode`.
|
|
226
|
+
*/
|
|
227
|
+
const isPropertyNode = isKind("Property");
|
|
228
|
+
/**
|
|
229
|
+
* Returns `true` when the input is a `ParameterNode`.
|
|
230
|
+
*/
|
|
231
|
+
const isParameterNode = isKind("Parameter");
|
|
232
|
+
/**
|
|
233
|
+
* Returns `true` when the input is a `ResponseNode`.
|
|
234
|
+
*/
|
|
235
|
+
const isResponseNode = isKind("Response");
|
|
236
|
+
/**
|
|
237
|
+
* Returns `true` when the input is a `FunctionParameterNode`.
|
|
238
|
+
*/
|
|
239
|
+
const isFunctionParameterNode = isKind("FunctionParameter");
|
|
240
|
+
/**
|
|
241
|
+
* Returns `true` when the input is an `ObjectBindingParameterNode`.
|
|
242
|
+
*/
|
|
243
|
+
const isObjectBindingParameterNode = isKind("ObjectBindingParameter");
|
|
244
|
+
/**
|
|
245
|
+
* Returns `true` when the input is a `FunctionParametersNode`.
|
|
246
|
+
*/
|
|
247
|
+
const isFunctionParametersNode = isKind("FunctionParameters");
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region src/utils.ts
|
|
250
|
+
const plainStringTypes = new Set([
|
|
251
|
+
"string",
|
|
252
|
+
"uuid",
|
|
253
|
+
"email",
|
|
254
|
+
"url",
|
|
255
|
+
"datetime"
|
|
256
|
+
]);
|
|
257
|
+
/**
|
|
258
|
+
* Returns `true` when a schema is emitted as a plain TypeScript `string`.
|
|
259
|
+
*
|
|
260
|
+
* - `string`, `uuid`, `email`, `url`, `datetime` are always plain strings.
|
|
261
|
+
* - `date` and `time` are plain strings when their `representation` is `'string'` rather than `'date'`.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```ts
|
|
265
|
+
* isStringType(createSchema({ type: 'uuid' })) // true
|
|
266
|
+
* isStringType(createSchema({ type: 'date', representation: 'date' })) // false
|
|
267
|
+
* ```
|
|
268
|
+
*/
|
|
269
|
+
function isStringType(node) {
|
|
270
|
+
if (plainStringTypes.has(node.type)) return true;
|
|
271
|
+
const temporal = narrowSchema(node, "date") ?? narrowSchema(node, "time");
|
|
272
|
+
if (temporal) return temporal.representation !== "date";
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Applies casing rules to parameter names and returns a new parameter array.
|
|
277
|
+
*
|
|
278
|
+
* The input array is not mutated.
|
|
279
|
+
* If `casing` is not set, the original array is returned unchanged.
|
|
280
|
+
*
|
|
281
|
+
* Use this before passing parameters to schema builders so that property keys
|
|
282
|
+
* in generated output match the desired casing while preserving
|
|
283
|
+
* `OperationNode.parameters` for other consumers.
|
|
284
|
+
*
|
|
285
|
+
* @example
|
|
286
|
+
* ```ts
|
|
287
|
+
* const params = [createParameter({ name: 'pet_id', in: 'query', schema: createSchema({ type: 'string' }) })]
|
|
288
|
+
* const cased = caseParams(params, 'camelcase')
|
|
289
|
+
* // cased[0].name === 'petId'
|
|
290
|
+
* ```
|
|
291
|
+
*/
|
|
292
|
+
function caseParams(params, casing) {
|
|
293
|
+
if (!casing) return params;
|
|
294
|
+
return params.map((param) => {
|
|
295
|
+
const transformed = casing === "camelcase" || !isValidVarName(param.name) ? camelCase(param.name) : param.name;
|
|
296
|
+
return {
|
|
297
|
+
...param,
|
|
298
|
+
name: transformed
|
|
299
|
+
};
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* Syncs property/parameter schema optionality flags from `required` and `schema.nullable`.
|
|
304
|
+
*
|
|
305
|
+
* - `optional` is set for non-required, non-nullable schemas.
|
|
306
|
+
* - `nullish` is set for non-required, nullable schemas.
|
|
307
|
+
*/
|
|
308
|
+
function syncOptionality(required, schema) {
|
|
309
|
+
const nullable = schema.nullable ?? false;
|
|
310
|
+
return {
|
|
311
|
+
...schema,
|
|
312
|
+
optional: !required && !nullable ? true : void 0,
|
|
313
|
+
nullish: !required && nullable ? true : void 0
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
//#endregion
|
|
87
317
|
//#region src/factory.ts
|
|
88
318
|
/**
|
|
89
|
-
* Creates a `RootNode`.
|
|
319
|
+
* Creates a `RootNode` with stable defaults for `schemas` and `operations`.
|
|
320
|
+
*
|
|
321
|
+
* @example
|
|
322
|
+
* ```ts
|
|
323
|
+
* const root = createRoot()
|
|
324
|
+
* // { kind: 'Root', schemas: [], operations: [] }
|
|
325
|
+
* ```
|
|
326
|
+
*
|
|
327
|
+
* @example
|
|
328
|
+
* ```ts
|
|
329
|
+
* const root = createRoot({ schemas: [petSchema] })
|
|
330
|
+
* // keeps default operations: []
|
|
331
|
+
* ```
|
|
90
332
|
*/
|
|
91
333
|
function createRoot(overrides = {}) {
|
|
92
334
|
return {
|
|
@@ -97,7 +339,27 @@ function createRoot(overrides = {}) {
|
|
|
97
339
|
};
|
|
98
340
|
}
|
|
99
341
|
/**
|
|
100
|
-
* Creates an `OperationNode`.
|
|
342
|
+
* Creates an `OperationNode` with default empty arrays for `tags`, `parameters`, and `responses`.
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```ts
|
|
346
|
+
* const operation = createOperation({
|
|
347
|
+
* operationId: 'getPetById',
|
|
348
|
+
* method: 'GET',
|
|
349
|
+
* path: '/pet/{petId}',
|
|
350
|
+
* })
|
|
351
|
+
* // tags, parameters, and responses are []
|
|
352
|
+
* ```
|
|
353
|
+
*
|
|
354
|
+
* @example
|
|
355
|
+
* ```ts
|
|
356
|
+
* const operation = createOperation({
|
|
357
|
+
* operationId: 'findPets',
|
|
358
|
+
* method: 'GET',
|
|
359
|
+
* path: '/pet/findByStatus',
|
|
360
|
+
* tags: ['pet'],
|
|
361
|
+
* })
|
|
362
|
+
* ```
|
|
101
363
|
*/
|
|
102
364
|
function createOperation(props) {
|
|
103
365
|
return {
|
|
@@ -120,20 +382,29 @@ function createSchema(props) {
|
|
|
120
382
|
};
|
|
121
383
|
}
|
|
122
384
|
/**
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
*
|
|
136
|
-
*
|
|
385
|
+
* Creates a `PropertyNode`.
|
|
386
|
+
*
|
|
387
|
+
* `required` defaults to `false`.
|
|
388
|
+
* `schema.optional` and `schema.nullish` are derived from `required` and `schema.nullable`.
|
|
389
|
+
*
|
|
390
|
+
* @example
|
|
391
|
+
* ```ts
|
|
392
|
+
* const property = createProperty({
|
|
393
|
+
* name: 'status',
|
|
394
|
+
* schema: createSchema({ type: 'string' }),
|
|
395
|
+
* })
|
|
396
|
+
* // required=false, schema.optional=true
|
|
397
|
+
* ```
|
|
398
|
+
*
|
|
399
|
+
* @example
|
|
400
|
+
* ```ts
|
|
401
|
+
* const property = createProperty({
|
|
402
|
+
* name: 'status',
|
|
403
|
+
* required: true,
|
|
404
|
+
* schema: createSchema({ type: 'string', nullable: true }),
|
|
405
|
+
* })
|
|
406
|
+
* // required=true, no optional/nullish
|
|
407
|
+
* ```
|
|
137
408
|
*/
|
|
138
409
|
function createProperty(props) {
|
|
139
410
|
const required = props.required ?? false;
|
|
@@ -141,12 +412,34 @@ function createProperty(props) {
|
|
|
141
412
|
...props,
|
|
142
413
|
kind: "Property",
|
|
143
414
|
required,
|
|
144
|
-
schema:
|
|
415
|
+
schema: syncOptionality(required, props.schema)
|
|
145
416
|
};
|
|
146
417
|
}
|
|
147
418
|
/**
|
|
148
|
-
* Creates a `ParameterNode`.
|
|
149
|
-
*
|
|
419
|
+
* Creates a `ParameterNode`.
|
|
420
|
+
*
|
|
421
|
+
* `required` defaults to `false`.
|
|
422
|
+
* Nested schema flags are set from `required` and `schema.nullable`.
|
|
423
|
+
*
|
|
424
|
+
* @example
|
|
425
|
+
* ```ts
|
|
426
|
+
* const param = createParameter({
|
|
427
|
+
* name: 'petId',
|
|
428
|
+
* in: 'path',
|
|
429
|
+
* required: true,
|
|
430
|
+
* schema: createSchema({ type: 'string' }),
|
|
431
|
+
* })
|
|
432
|
+
* ```
|
|
433
|
+
*
|
|
434
|
+
* @example
|
|
435
|
+
* ```ts
|
|
436
|
+
* const param = createParameter({
|
|
437
|
+
* name: 'status',
|
|
438
|
+
* in: 'query',
|
|
439
|
+
* schema: createSchema({ type: 'string', nullable: true }),
|
|
440
|
+
* })
|
|
441
|
+
* // required=false, schema.nullish=true
|
|
442
|
+
* ```
|
|
150
443
|
*/
|
|
151
444
|
function createParameter(props) {
|
|
152
445
|
const required = props.required ?? false;
|
|
@@ -154,11 +447,20 @@ function createParameter(props) {
|
|
|
154
447
|
...props,
|
|
155
448
|
kind: "Parameter",
|
|
156
449
|
required,
|
|
157
|
-
schema:
|
|
450
|
+
schema: syncOptionality(required, props.schema)
|
|
158
451
|
};
|
|
159
452
|
}
|
|
160
453
|
/**
|
|
161
454
|
* Creates a `ResponseNode`.
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* ```ts
|
|
458
|
+
* const response = createResponse({
|
|
459
|
+
* statusCode: '200',
|
|
460
|
+
* description: 'Success',
|
|
461
|
+
* schema: createSchema({ type: 'object', properties: [] }),
|
|
462
|
+
* })
|
|
463
|
+
* ```
|
|
162
464
|
*/
|
|
163
465
|
function createResponse(props) {
|
|
164
466
|
return {
|
|
@@ -167,7 +469,33 @@ function createResponse(props) {
|
|
|
167
469
|
};
|
|
168
470
|
}
|
|
169
471
|
/**
|
|
170
|
-
* Creates a
|
|
472
|
+
* Creates a single-property object schema used as a discriminator literal.
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
* ```ts
|
|
476
|
+
* createDiscriminantNode({ propertyName: 'type', value: 'dog' })
|
|
477
|
+
* // -> { type: 'object', properties: [{ name: 'type', required: true, schema: enum('dog') }] }
|
|
478
|
+
* ```
|
|
479
|
+
*/
|
|
480
|
+
function createDiscriminantNode({ propertyName, value }) {
|
|
481
|
+
return createSchema({
|
|
482
|
+
type: "object",
|
|
483
|
+
primitive: "object",
|
|
484
|
+
properties: [createProperty({
|
|
485
|
+
name: propertyName,
|
|
486
|
+
schema: createSchema({
|
|
487
|
+
type: "enum",
|
|
488
|
+
primitive: "string",
|
|
489
|
+
enumValues: [value]
|
|
490
|
+
}),
|
|
491
|
+
required: true
|
|
492
|
+
})]
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
/**
|
|
496
|
+
* Creates a `FunctionParameterNode`.
|
|
497
|
+
*
|
|
498
|
+
* `optional` defaults to `false`.
|
|
171
499
|
*
|
|
172
500
|
* @example Required typed param
|
|
173
501
|
* ```ts
|
|
@@ -181,7 +509,7 @@ function createResponse(props) {
|
|
|
181
509
|
* // → params?: QueryParams
|
|
182
510
|
* ```
|
|
183
511
|
*
|
|
184
|
-
* @example Param with default (implicitly optional
|
|
512
|
+
* @example Param with default (implicitly optional; cannot combine with `optional: true`)
|
|
185
513
|
* ```ts
|
|
186
514
|
* createFunctionParameter({ name: 'config', type: 'RequestConfig', default: '{}' })
|
|
187
515
|
* // → config: RequestConfig = {}
|
|
@@ -195,7 +523,7 @@ function createFunctionParameter(props) {
|
|
|
195
523
|
};
|
|
196
524
|
}
|
|
197
525
|
/**
|
|
198
|
-
* Creates an `ObjectBindingParameterNode`
|
|
526
|
+
* Creates an `ObjectBindingParameterNode` for object-destructured parameter groups.
|
|
199
527
|
*
|
|
200
528
|
* @example Destructured object param
|
|
201
529
|
* ```ts
|
|
@@ -210,7 +538,7 @@ function createFunctionParameter(props) {
|
|
|
210
538
|
* // call → { id, name }
|
|
211
539
|
* ```
|
|
212
540
|
*
|
|
213
|
-
* @example Inline — children emitted as individual top-level
|
|
541
|
+
* @example Inline mode — children emitted as individual top-level parameters
|
|
214
542
|
* ```ts
|
|
215
543
|
* createObjectBindingParameter({
|
|
216
544
|
* properties: [createFunctionParameter({ name: 'petId', type: 'string', optional: false })],
|
|
@@ -227,7 +555,7 @@ function createObjectBindingParameter(props) {
|
|
|
227
555
|
};
|
|
228
556
|
}
|
|
229
557
|
/**
|
|
230
|
-
* Creates a `FunctionParametersNode` from an ordered list of
|
|
558
|
+
* Creates a `FunctionParametersNode` from an ordered list of parameters.
|
|
231
559
|
*
|
|
232
560
|
* @example
|
|
233
561
|
* ```ts
|
|
@@ -238,6 +566,12 @@ function createObjectBindingParameter(props) {
|
|
|
238
566
|
* ],
|
|
239
567
|
* })
|
|
240
568
|
* ```
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* ```ts
|
|
572
|
+
* const empty = createFunctionParameters()
|
|
573
|
+
* // { kind: 'FunctionParameters', params: [] }
|
|
574
|
+
* ```
|
|
241
575
|
*/
|
|
242
576
|
function createFunctionParameters(props = {}) {
|
|
243
577
|
return {
|
|
@@ -247,18 +581,19 @@ function createFunctionParameters(props = {}) {
|
|
|
247
581
|
};
|
|
248
582
|
}
|
|
249
583
|
//#endregion
|
|
250
|
-
//#region src/printer.ts
|
|
584
|
+
//#region src/printers/printer.ts
|
|
251
585
|
/**
|
|
252
|
-
* Creates a
|
|
253
|
-
*
|
|
254
|
-
*
|
|
586
|
+
* Creates a schema printer factory.
|
|
587
|
+
*
|
|
588
|
+
* This function wraps a builder and makes options optional at call sites.
|
|
255
589
|
*
|
|
256
590
|
* The builder receives resolved options and returns:
|
|
257
591
|
* - `name` — a unique identifier for the printer
|
|
258
592
|
* - `options` — options stored on the returned printer instance
|
|
259
593
|
* - `nodes` — a map of `SchemaType` → handler functions that convert a `SchemaNode` to `TOutput`
|
|
260
|
-
* - `print` _(optional)_ —
|
|
261
|
-
* Inside
|
|
594
|
+
* - `print` _(optional)_ — top-level override exposed as `printer.print`
|
|
595
|
+
* - Inside this function, `this.print(node)` still dispatches to the `nodes` map
|
|
596
|
+
* - This keeps recursion safe and avoids self-calls
|
|
262
597
|
*
|
|
263
598
|
* When no `print` override is provided, `printer.print` is the node-level dispatcher directly.
|
|
264
599
|
*
|
|
@@ -278,32 +613,13 @@ function createFunctionParameters(props = {}) {
|
|
|
278
613
|
* },
|
|
279
614
|
* }))
|
|
280
615
|
* ```
|
|
281
|
-
*
|
|
282
|
-
* @example With a root-level `print` override to wrap output in a full declaration
|
|
283
|
-
* ```ts
|
|
284
|
-
* type TsPrinter = PrinterFactoryOptions<'ts', { typeName?: string }, ts.TypeNode, ts.Node>
|
|
285
|
-
*
|
|
286
|
-
* export const printerTs = definePrinter<TsPrinter>((options) => ({
|
|
287
|
-
* name: 'ts',
|
|
288
|
-
* options,
|
|
289
|
-
* nodes: { string: () => factory.keywordTypeNodes.string },
|
|
290
|
-
* print(node) {
|
|
291
|
-
* const type = this.print(node) // calls the node-level dispatcher
|
|
292
|
-
* if (!type || !this.options.typeName) return type
|
|
293
|
-
* return factory.createTypeAliasDeclaration(this.options.typeName, type)
|
|
294
|
-
* },
|
|
295
|
-
* }))
|
|
296
|
-
* ```
|
|
297
616
|
*/
|
|
298
617
|
function definePrinter(build) {
|
|
299
618
|
return createPrinterFactory((node) => node.type)(build);
|
|
300
619
|
}
|
|
301
620
|
/**
|
|
302
|
-
* Generic printer
|
|
303
|
-
|
|
304
|
-
*
|
|
305
|
-
* @param getKey — derives the handler-map key from a node. Return `undefined` to skip.
|
|
306
|
-
*
|
|
621
|
+
* Generic printer-factory function used by `definePrinter` and `defineFunctionPrinter`.
|
|
622
|
+
**
|
|
307
623
|
* @example
|
|
308
624
|
* ```ts
|
|
309
625
|
* export const defineFunctionPrinter = createPrinterFactory<FunctionNode, FunctionNodeType, FunctionNodeByType>(
|
|
@@ -319,9 +635,9 @@ function createPrinterFactory(getKey) {
|
|
|
319
635
|
options: resolvedOptions,
|
|
320
636
|
print: (node) => {
|
|
321
637
|
const key = getKey(node);
|
|
322
|
-
if (key === void 0) return
|
|
638
|
+
if (key === void 0) return null;
|
|
323
639
|
const handler = nodes[key];
|
|
324
|
-
if (!handler) return
|
|
640
|
+
if (!handler) return null;
|
|
325
641
|
return handler.call(context, node);
|
|
326
642
|
}
|
|
327
643
|
};
|
|
@@ -334,15 +650,17 @@ function createPrinterFactory(getKey) {
|
|
|
334
650
|
};
|
|
335
651
|
}
|
|
336
652
|
//#endregion
|
|
337
|
-
//#region src/functionPrinter.ts
|
|
653
|
+
//#region src/printers/functionPrinter.ts
|
|
338
654
|
const kindToHandlerKey = {
|
|
339
655
|
FunctionParameter: "functionParameter",
|
|
340
656
|
ObjectBindingParameter: "objectBindingParameter",
|
|
341
657
|
FunctionParameters: "functionParameters"
|
|
342
658
|
};
|
|
343
659
|
/**
|
|
344
|
-
* Creates a
|
|
345
|
-
*
|
|
660
|
+
* Creates a function-parameter printer factory.
|
|
661
|
+
*
|
|
662
|
+
* This wrapper uses `createPrinterFactory` and dispatches handlers by `node.kind`
|
|
663
|
+
* (for function nodes) rather than by `node.type` (for schema nodes).
|
|
346
664
|
*
|
|
347
665
|
* @example
|
|
348
666
|
* ```ts
|
|
@@ -383,12 +701,12 @@ function sortChildParams(params) {
|
|
|
383
701
|
return [...params].sort((a, b) => rank(a) - rank(b));
|
|
384
702
|
}
|
|
385
703
|
/**
|
|
386
|
-
* Default function-signature printer.
|
|
387
|
-
* used
|
|
704
|
+
* Default function-signature printer.
|
|
705
|
+
* Covers the four standard output modes used across Kubb plugins.
|
|
388
706
|
*
|
|
389
707
|
* @example
|
|
390
708
|
* ```ts
|
|
391
|
-
* const printer =
|
|
709
|
+
* const printer = functionPrinter({ mode: 'declaration' })
|
|
392
710
|
*
|
|
393
711
|
* const sig = createFunctionParameters({
|
|
394
712
|
* params: [
|
|
@@ -449,63 +767,30 @@ const functionPrinter = defineFunctionPrinter((options) => ({
|
|
|
449
767
|
}
|
|
450
768
|
}));
|
|
451
769
|
//#endregion
|
|
452
|
-
//#region src/
|
|
770
|
+
//#region src/refs.ts
|
|
453
771
|
/**
|
|
454
|
-
*
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Type guard for `RootNode`.
|
|
464
|
-
*/
|
|
465
|
-
const isRootNode = isKind("Root");
|
|
466
|
-
/**
|
|
467
|
-
* Type guard for `OperationNode`.
|
|
468
|
-
*/
|
|
469
|
-
const isOperationNode = isKind("Operation");
|
|
470
|
-
/**
|
|
471
|
-
* Type guard for `SchemaNode`.
|
|
472
|
-
*/
|
|
473
|
-
const isSchemaNode = isKind("Schema");
|
|
474
|
-
/**
|
|
475
|
-
* Type guard for `PropertyNode`.
|
|
476
|
-
*/
|
|
477
|
-
const isPropertyNode = isKind("Property");
|
|
478
|
-
/**
|
|
479
|
-
* Type guard for `ParameterNode`.
|
|
480
|
-
*/
|
|
481
|
-
const isParameterNode = isKind("Parameter");
|
|
482
|
-
/**
|
|
483
|
-
* Type guard for `ResponseNode`.
|
|
484
|
-
*/
|
|
485
|
-
const isResponseNode = isKind("Response");
|
|
486
|
-
/**
|
|
487
|
-
* Type guard for `FunctionParameterNode`.
|
|
488
|
-
*/
|
|
489
|
-
const isFunctionParameterNode = isKind("FunctionParameter");
|
|
490
|
-
/**
|
|
491
|
-
* Type guard for `ObjectBindingParameterNode`.
|
|
492
|
-
*/
|
|
493
|
-
const isObjectBindingParameterNode = isKind("ObjectBindingParameter");
|
|
494
|
-
/**
|
|
495
|
-
* Type guard for `FunctionParametersNode`.
|
|
496
|
-
*/
|
|
497
|
-
const isFunctionParametersNode = isKind("FunctionParameters");
|
|
498
|
-
//#endregion
|
|
499
|
-
//#region src/refs.ts
|
|
500
|
-
/**
|
|
501
|
-
* Extracts the final segment from a reference string.
|
|
502
|
-
* Falls back to the original string when no slash exists.
|
|
772
|
+
* Returns the last path segment of a reference string.
|
|
773
|
+
*
|
|
774
|
+
* Example: `#/components/schemas/Pet` becomes `Pet`.
|
|
775
|
+
*
|
|
776
|
+
* @example
|
|
777
|
+
* ```ts
|
|
778
|
+
* extractRefName('#/components/schemas/Pet') // 'Pet'
|
|
779
|
+
* ```
|
|
503
780
|
*/
|
|
504
781
|
function extractRefName(ref) {
|
|
505
782
|
return ref.split("/").at(-1) ?? ref;
|
|
506
783
|
}
|
|
507
784
|
/**
|
|
508
|
-
*
|
|
785
|
+
* Builds a `RefMap` from `root.schemas` using each schema's `name`.
|
|
786
|
+
*
|
|
787
|
+
* Unnamed schemas are skipped.
|
|
788
|
+
*
|
|
789
|
+
* @example
|
|
790
|
+
* ```ts
|
|
791
|
+
* const refMap = buildRefMap(root)
|
|
792
|
+
* const pet = refMap.get('Pet')
|
|
793
|
+
* ```
|
|
509
794
|
*/
|
|
510
795
|
function buildRefMap(root) {
|
|
511
796
|
const map = /* @__PURE__ */ new Map();
|
|
@@ -513,389 +798,44 @@ function buildRefMap(root) {
|
|
|
513
798
|
return map;
|
|
514
799
|
}
|
|
515
800
|
/**
|
|
516
|
-
*
|
|
801
|
+
* Resolves a schema by name from a `RefMap`.
|
|
802
|
+
*
|
|
803
|
+
* @example
|
|
804
|
+
* ```ts
|
|
805
|
+
* const petSchema = resolveRef(refMap, 'Pet')
|
|
806
|
+
* ```
|
|
517
807
|
*/
|
|
518
808
|
function resolveRef(refMap, ref) {
|
|
519
809
|
return refMap.get(ref);
|
|
520
810
|
}
|
|
521
811
|
/**
|
|
522
|
-
* Converts a `RefMap`
|
|
812
|
+
* Converts a `RefMap` into a plain object.
|
|
813
|
+
*
|
|
814
|
+
* @example
|
|
815
|
+
* ```ts
|
|
816
|
+
* const refsObject = refMapToObject(refMap)
|
|
817
|
+
* ```
|
|
523
818
|
*/
|
|
524
819
|
function refMapToObject(refMap) {
|
|
525
820
|
return Object.fromEntries(refMap);
|
|
526
821
|
}
|
|
527
822
|
//#endregion
|
|
528
|
-
//#region src/
|
|
529
|
-
/**
|
|
530
|
-
* Replaces the discriminator property's schema inside an object node with
|
|
531
|
-
* an enum of the provided values.
|
|
532
|
-
*/
|
|
533
|
-
function applyDiscriminatorEnum({ node, propertyName, values, enumName }) {
|
|
534
|
-
const objectNode = narrowSchema(node, "object");
|
|
535
|
-
if (!objectNode?.properties?.length) return node;
|
|
536
|
-
if (!objectNode.properties.some((prop) => prop.name === propertyName)) return node;
|
|
537
|
-
return createSchema({
|
|
538
|
-
...objectNode,
|
|
539
|
-
properties: objectNode.properties.map((prop) => {
|
|
540
|
-
if (prop.name !== propertyName) return prop;
|
|
541
|
-
return createProperty({
|
|
542
|
-
...prop,
|
|
543
|
-
schema: createSchema({
|
|
544
|
-
type: "enum",
|
|
545
|
-
primitive: "string",
|
|
546
|
-
enumValues: values,
|
|
547
|
-
name: enumName,
|
|
548
|
-
readOnly: prop.schema.readOnly,
|
|
549
|
-
writeOnly: prop.schema.writeOnly
|
|
550
|
-
})
|
|
551
|
-
});
|
|
552
|
-
})
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
/**
|
|
556
|
-
* Merges adjacent anonymous object members into a single anonymous object.
|
|
557
|
-
*/
|
|
558
|
-
function mergeAdjacentAnonymousObjects(members) {
|
|
559
|
-
return members.reduce((acc, member) => {
|
|
560
|
-
const objectMember = narrowSchema(member, "object");
|
|
561
|
-
if (objectMember && !objectMember.name) {
|
|
562
|
-
const previous = acc.at(-1);
|
|
563
|
-
const previousObject = previous ? narrowSchema(previous, "object") : void 0;
|
|
564
|
-
if (previousObject && !previousObject.name) {
|
|
565
|
-
acc[acc.length - 1] = createSchema({
|
|
566
|
-
...previousObject,
|
|
567
|
-
properties: [...previousObject.properties ?? [], ...objectMember.properties ?? []]
|
|
568
|
-
});
|
|
569
|
-
return acc;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
acc.push(member);
|
|
573
|
-
return acc;
|
|
574
|
-
}, []);
|
|
575
|
-
}
|
|
576
|
-
/**
|
|
577
|
-
* Removes enum members subsumed by broader scalar members in the same union.
|
|
578
|
-
*/
|
|
579
|
-
function simplifyUnionMembers(members) {
|
|
580
|
-
const scalarPrimitives = new Set(members.filter((member) => SCALAR_PRIMITIVE_TYPES.has(member.type)).map((m) => m.type));
|
|
581
|
-
if (!scalarPrimitives.size) return members;
|
|
582
|
-
return members.filter((member) => {
|
|
583
|
-
const enumNode = narrowSchema(member, "enum");
|
|
584
|
-
if (!enumNode) return true;
|
|
585
|
-
const primitive = enumNode.primitive;
|
|
586
|
-
if (!primitive) return true;
|
|
587
|
-
if (!enumNode.enumType) return true;
|
|
588
|
-
if (scalarPrimitives.has(primitive)) return false;
|
|
589
|
-
if ((primitive === "integer" || primitive === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
|
|
590
|
-
return true;
|
|
591
|
-
});
|
|
592
|
-
}
|
|
593
|
-
//#endregion
|
|
594
|
-
//#region ../../internals/utils/dist/index.js
|
|
595
|
-
/**
|
|
596
|
-
* Shared implementation for camelCase and PascalCase conversion.
|
|
597
|
-
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
598
|
-
* and capitalizes each word according to `pascal`.
|
|
599
|
-
*
|
|
600
|
-
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
601
|
-
*/
|
|
602
|
-
function toCamelOrPascal(text, pascal) {
|
|
603
|
-
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) => {
|
|
604
|
-
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
605
|
-
if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
|
|
606
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
607
|
-
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
608
|
-
}
|
|
823
|
+
//#region src/visitor.ts
|
|
609
824
|
/**
|
|
610
|
-
*
|
|
611
|
-
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
612
|
-
* Segments are joined with `/` to form a file path.
|
|
825
|
+
* Creates a small async concurrency limiter.
|
|
613
826
|
*
|
|
614
|
-
*
|
|
615
|
-
* embedded in operationIds (e.g. `v2025.0`) are kept intact.
|
|
616
|
-
*/
|
|
617
|
-
function applyToFileParts(text, transformPart) {
|
|
618
|
-
const parts = text.split(/\.(?=[a-zA-Z])/);
|
|
619
|
-
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
|
|
620
|
-
}
|
|
621
|
-
/**
|
|
622
|
-
* Converts `text` to camelCase.
|
|
623
|
-
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
827
|
+
* At most `concurrency` tasks are in flight at once. Extra tasks are queued.
|
|
624
828
|
*
|
|
625
829
|
* @example
|
|
626
|
-
*
|
|
627
|
-
*
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
}
|
|
636
|
-
/** Returns a `CLIAdapter` with type inference. Pass a different adapter to `createCLI` to swap the CLI engine. */
|
|
637
|
-
function defineCLIAdapter(adapter) {
|
|
638
|
-
return adapter;
|
|
639
|
-
}
|
|
640
|
-
/**
|
|
641
|
-
* Serializes `CommandDefinition[]` to a plain, JSON-serializable structure.
|
|
642
|
-
* Use to expose CLI capabilities to AI agents or MCP tools.
|
|
643
|
-
*/
|
|
644
|
-
function getCommandSchema(defs) {
|
|
645
|
-
return defs.map(serializeCommand);
|
|
646
|
-
}
|
|
647
|
-
function serializeCommand(def) {
|
|
648
|
-
return {
|
|
649
|
-
name: def.name,
|
|
650
|
-
description: def.description,
|
|
651
|
-
arguments: def.arguments,
|
|
652
|
-
options: serializeOptions(def.options ?? {}),
|
|
653
|
-
subCommands: def.subCommands ? def.subCommands.map(serializeCommand) : []
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
function serializeOptions(options) {
|
|
657
|
-
return Object.entries(options).map(([name, opt]) => {
|
|
658
|
-
return {
|
|
659
|
-
name,
|
|
660
|
-
flags: `${opt.short ? `-${opt.short}, ` : ""}--${name}${opt.type === "string" ? ` <${opt.hint ?? name}>` : ""}`,
|
|
661
|
-
type: opt.type,
|
|
662
|
-
description: opt.description,
|
|
663
|
-
...opt.default !== void 0 ? { default: opt.default } : {},
|
|
664
|
-
...opt.hint ? { hint: opt.hint } : {},
|
|
665
|
-
...opt.enum ? { enum: opt.enum } : {},
|
|
666
|
-
...opt.required ? { required: opt.required } : {}
|
|
667
|
-
};
|
|
668
|
-
});
|
|
669
|
-
}
|
|
670
|
-
/** Prints formatted help output for a command using its `CommandDefinition`. */
|
|
671
|
-
function renderHelp(def, parentName) {
|
|
672
|
-
const schema = getCommandSchema([def])[0];
|
|
673
|
-
const programName = parentName ? `${parentName} ${schema.name}` : schema.name;
|
|
674
|
-
const argsPart = schema.arguments?.length ? ` ${schema.arguments.join(" ")}` : "";
|
|
675
|
-
const subCmdPart = schema.subCommands.length ? " <command>" : "";
|
|
676
|
-
console.log(`\n${styleText("bold", "Usage:")} ${programName}${argsPart}${subCmdPart} [options]\n`);
|
|
677
|
-
if (schema.description) console.log(` ${schema.description}\n`);
|
|
678
|
-
if (schema.subCommands.length) {
|
|
679
|
-
console.log(styleText("bold", "Commands:"));
|
|
680
|
-
for (const sub of schema.subCommands) console.log(` ${styleText("cyan", sub.name.padEnd(16))}${sub.description}`);
|
|
681
|
-
console.log();
|
|
682
|
-
}
|
|
683
|
-
const options = [...schema.options, {
|
|
684
|
-
name: "help",
|
|
685
|
-
flags: "-h, --help",
|
|
686
|
-
type: "boolean",
|
|
687
|
-
description: "Show help"
|
|
688
|
-
}];
|
|
689
|
-
console.log(styleText("bold", "Options:"));
|
|
690
|
-
for (const opt of options) {
|
|
691
|
-
const flags = styleText("cyan", opt.flags.padEnd(30));
|
|
692
|
-
const defaultPart = opt.default !== void 0 ? styleText("dim", ` (default: ${opt.default})`) : "";
|
|
693
|
-
console.log(` ${flags}${opt.description}${defaultPart}`);
|
|
694
|
-
}
|
|
695
|
-
console.log();
|
|
696
|
-
}
|
|
697
|
-
function buildParseOptions(def) {
|
|
698
|
-
const result = { help: {
|
|
699
|
-
type: "boolean",
|
|
700
|
-
short: "h"
|
|
701
|
-
} };
|
|
702
|
-
for (const [name, opt] of Object.entries(def.options ?? {})) result[name] = {
|
|
703
|
-
type: opt.type,
|
|
704
|
-
...opt.short ? { short: opt.short } : {},
|
|
705
|
-
...opt.default !== void 0 ? { default: opt.default } : {}
|
|
706
|
-
};
|
|
707
|
-
return result;
|
|
708
|
-
}
|
|
709
|
-
async function runCommand(def, argv, parentName) {
|
|
710
|
-
const parseOptions = buildParseOptions(def);
|
|
711
|
-
let parsed;
|
|
712
|
-
try {
|
|
713
|
-
const result = parseArgs({
|
|
714
|
-
args: argv,
|
|
715
|
-
options: parseOptions,
|
|
716
|
-
allowPositionals: true,
|
|
717
|
-
strict: false
|
|
718
|
-
});
|
|
719
|
-
parsed = {
|
|
720
|
-
values: result.values,
|
|
721
|
-
positionals: result.positionals
|
|
722
|
-
};
|
|
723
|
-
} catch {
|
|
724
|
-
renderHelp(def, parentName);
|
|
725
|
-
process.exit(1);
|
|
726
|
-
}
|
|
727
|
-
if (parsed.values["help"]) {
|
|
728
|
-
renderHelp(def, parentName);
|
|
729
|
-
process.exit(0);
|
|
730
|
-
}
|
|
731
|
-
for (const [name, opt] of Object.entries(def.options ?? {})) if (opt.required && parsed.values[name] === void 0) {
|
|
732
|
-
console.error(styleText("red", `Error: --${name} is required`));
|
|
733
|
-
renderHelp(def, parentName);
|
|
734
|
-
process.exit(1);
|
|
735
|
-
}
|
|
736
|
-
if (!def.run) {
|
|
737
|
-
renderHelp(def, parentName);
|
|
738
|
-
process.exit(0);
|
|
739
|
-
}
|
|
740
|
-
try {
|
|
741
|
-
await def.run(parsed);
|
|
742
|
-
} catch (err) {
|
|
743
|
-
console.error(styleText("red", `Error: ${err instanceof Error ? err.message : String(err)}`));
|
|
744
|
-
renderHelp(def, parentName);
|
|
745
|
-
process.exit(1);
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
function printRootHelp(programName, version, defs) {
|
|
749
|
-
console.log(`\n${styleText("bold", "Usage:")} ${programName} <command> [options]\n`);
|
|
750
|
-
console.log(` Kubb generation — v${version}\n`);
|
|
751
|
-
console.log(styleText("bold", "Commands:"));
|
|
752
|
-
for (const def of defs) console.log(` ${styleText("cyan", def.name.padEnd(16))}${def.description}`);
|
|
753
|
-
console.log();
|
|
754
|
-
console.log(styleText("bold", "Options:"));
|
|
755
|
-
console.log(` ${styleText("cyan", "-v, --version".padEnd(30))}Show version number`);
|
|
756
|
-
console.log(` ${styleText("cyan", "-h, --help".padEnd(30))}Show help`);
|
|
757
|
-
console.log();
|
|
758
|
-
console.log(`Run ${styleText("cyan", `${programName} <command> --help`)} for command-specific help.\n`);
|
|
759
|
-
}
|
|
760
|
-
defineCLIAdapter({
|
|
761
|
-
renderHelp(def, parentName) {
|
|
762
|
-
renderHelp(def, parentName);
|
|
763
|
-
},
|
|
764
|
-
async run(defs, argv, opts) {
|
|
765
|
-
const { programName, defaultCommandName, version } = opts;
|
|
766
|
-
const args = argv.length >= 2 && argv[0]?.includes("node") ? argv.slice(2) : argv;
|
|
767
|
-
if (args[0] === "--version" || args[0] === "-v") {
|
|
768
|
-
console.log(version);
|
|
769
|
-
process.exit(0);
|
|
770
|
-
}
|
|
771
|
-
if (args[0] === "--help" || args[0] === "-h") {
|
|
772
|
-
printRootHelp(programName, version, defs);
|
|
773
|
-
process.exit(0);
|
|
774
|
-
}
|
|
775
|
-
if (args.length === 0) {
|
|
776
|
-
const defaultDef = defs.find((d) => d.name === defaultCommandName);
|
|
777
|
-
if (defaultDef?.run) await runCommand(defaultDef, [], programName);
|
|
778
|
-
else printRootHelp(programName, version, defs);
|
|
779
|
-
return;
|
|
780
|
-
}
|
|
781
|
-
const [first, ...rest] = args;
|
|
782
|
-
const isKnownSubcommand = defs.some((d) => d.name === first);
|
|
783
|
-
let def;
|
|
784
|
-
let commandArgv;
|
|
785
|
-
let parentName;
|
|
786
|
-
if (isKnownSubcommand) {
|
|
787
|
-
def = defs.find((d) => d.name === first);
|
|
788
|
-
commandArgv = rest;
|
|
789
|
-
parentName = programName;
|
|
790
|
-
} else {
|
|
791
|
-
def = defs.find((d) => d.name === defaultCommandName);
|
|
792
|
-
commandArgv = args;
|
|
793
|
-
parentName = programName;
|
|
794
|
-
}
|
|
795
|
-
if (!def) {
|
|
796
|
-
console.error(`Unknown command: ${first}`);
|
|
797
|
-
printRootHelp(programName, version, defs);
|
|
798
|
-
process.exit(1);
|
|
799
|
-
}
|
|
800
|
-
if (def.subCommands?.length) {
|
|
801
|
-
const [subName, ...subRest] = commandArgv;
|
|
802
|
-
const subDef = def.subCommands.find((s) => s.name === subName);
|
|
803
|
-
if (subName === "--help" || subName === "-h") {
|
|
804
|
-
renderHelp(def, parentName);
|
|
805
|
-
process.exit(0);
|
|
806
|
-
}
|
|
807
|
-
if (!subDef) {
|
|
808
|
-
renderHelp(def, parentName);
|
|
809
|
-
process.exit(subName ? 1 : 0);
|
|
810
|
-
}
|
|
811
|
-
await runCommand(subDef, subRest, `${parentName} ${def.name}`);
|
|
812
|
-
return;
|
|
813
|
-
}
|
|
814
|
-
await runCommand(def, commandArgv, parentName);
|
|
815
|
-
}
|
|
816
|
-
});
|
|
817
|
-
/**
|
|
818
|
-
* Parses a CSS hex color string (`#RGB`) into its RGB channels.
|
|
819
|
-
* Falls back to `255` for any channel that cannot be parsed.
|
|
820
|
-
*/
|
|
821
|
-
function parseHex(color) {
|
|
822
|
-
const int = Number.parseInt(color.replace("#", ""), 16);
|
|
823
|
-
return Number.isNaN(int) ? {
|
|
824
|
-
r: 255,
|
|
825
|
-
g: 255,
|
|
826
|
-
b: 255
|
|
827
|
-
} : {
|
|
828
|
-
r: int >> 16 & 255,
|
|
829
|
-
g: int >> 8 & 255,
|
|
830
|
-
b: int & 255
|
|
831
|
-
};
|
|
832
|
-
}
|
|
833
|
-
/**
|
|
834
|
-
* Returns a function that wraps a string in a 24-bit ANSI true-color escape sequence
|
|
835
|
-
* for the given hex color.
|
|
836
|
-
*/
|
|
837
|
-
function hex(color) {
|
|
838
|
-
const { r, g, b } = parseHex(color);
|
|
839
|
-
return (text) => `\x1b[38;2;${r};${g};${b}m${text}\x1b[0m`;
|
|
840
|
-
}
|
|
841
|
-
hex("#F55A17"), hex("#F5A217"), hex("#F58517"), hex("#B45309"), hex("#FFFFFF"), hex("#adadc6"), hex("#FDA4AF");
|
|
842
|
-
/**
|
|
843
|
-
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
844
|
-
*/
|
|
845
|
-
function isValidVarName(name) {
|
|
846
|
-
try {
|
|
847
|
-
new Function(`var ${name}`);
|
|
848
|
-
} catch {
|
|
849
|
-
return false;
|
|
850
|
-
}
|
|
851
|
-
return true;
|
|
852
|
-
}
|
|
853
|
-
//#endregion
|
|
854
|
-
//#region src/utils.ts
|
|
855
|
-
const plainStringTypes = new Set([
|
|
856
|
-
"string",
|
|
857
|
-
"uuid",
|
|
858
|
-
"email",
|
|
859
|
-
"url",
|
|
860
|
-
"datetime"
|
|
861
|
-
]);
|
|
862
|
-
/**
|
|
863
|
-
* Returns `true` when a schema node will be represented as a plain string in generated code.
|
|
864
|
-
*
|
|
865
|
-
* - `string`, `uuid`, `email`, `url`, `datetime` are always plain strings.
|
|
866
|
-
* - `date` and `time` are plain strings when their `representation` is `'string'` rather than `'date'`.
|
|
867
|
-
*/
|
|
868
|
-
function isPlainStringType(node) {
|
|
869
|
-
if (plainStringTypes.has(node.type)) return true;
|
|
870
|
-
const temporal = narrowSchema(node, "date") ?? narrowSchema(node, "time");
|
|
871
|
-
if (temporal) return temporal.representation !== "date";
|
|
872
|
-
return false;
|
|
873
|
-
}
|
|
874
|
-
/**
|
|
875
|
-
* Transforms the `name` field of each parameter node according to the given casing strategy.
|
|
876
|
-
*
|
|
877
|
-
* The original `params` array is never mutated — a new array of cloned nodes is returned.
|
|
878
|
-
* When no `casing` is provided the original array is returned as-is.
|
|
879
|
-
*
|
|
880
|
-
* Use this before passing parameters to schema builders so that property keys
|
|
881
|
-
* in the generated output match the desired casing while the original
|
|
882
|
-
* `OperationNode.parameters` array remains untouched for other consumers.
|
|
883
|
-
*/
|
|
884
|
-
function applyParamsCasing(params, casing) {
|
|
885
|
-
if (!casing) return params;
|
|
886
|
-
return params.map((param) => {
|
|
887
|
-
const transformed = casing === "camelcase" || !isValidVarName(param.name) ? camelCase(param.name) : param.name;
|
|
888
|
-
return {
|
|
889
|
-
...param,
|
|
890
|
-
name: transformed
|
|
891
|
-
};
|
|
892
|
-
});
|
|
893
|
-
}
|
|
894
|
-
//#endregion
|
|
895
|
-
//#region src/visitor.ts
|
|
896
|
-
/**
|
|
897
|
-
* Creates a concurrency-limiting wrapper. At most `concurrency` promises may be
|
|
898
|
-
* in-flight simultaneously; additional calls are queued and dispatched as slots free.
|
|
830
|
+
* ```ts
|
|
831
|
+
* const limit = createLimit(2)
|
|
832
|
+
* await Promise.all([
|
|
833
|
+
* limit(() => taskA()),
|
|
834
|
+
* limit(() => taskB()),
|
|
835
|
+
* limit(() => taskC()),
|
|
836
|
+
* ])
|
|
837
|
+
* // only 2 tasks run at the same time
|
|
838
|
+
* ```
|
|
899
839
|
*/
|
|
900
840
|
function createLimit(concurrency) {
|
|
901
841
|
let active = 0;
|
|
@@ -921,8 +861,15 @@ function createLimit(concurrency) {
|
|
|
921
861
|
/**
|
|
922
862
|
* Returns the immediate traversable children of `node`.
|
|
923
863
|
*
|
|
924
|
-
* For `Schema` nodes, children (properties
|
|
925
|
-
*
|
|
864
|
+
* For `Schema` nodes, children (`properties`, `items`, `members`, and non-boolean
|
|
865
|
+
* `additionalProperties`) are only included
|
|
866
|
+
* when `recurse` is `true`; shallow mode skips them.
|
|
867
|
+
*
|
|
868
|
+
* @example
|
|
869
|
+
* ```ts
|
|
870
|
+
* const children = getChildren(operationNode, true)
|
|
871
|
+
* // returns parameters, requestBody schema (if present), and responses
|
|
872
|
+
* ```
|
|
926
873
|
*/
|
|
927
874
|
function getChildren(node, recurse) {
|
|
928
875
|
switch (node.kind) {
|
|
@@ -951,7 +898,23 @@ function getChildren(node, recurse) {
|
|
|
951
898
|
}
|
|
952
899
|
/**
|
|
953
900
|
* Depth-first traversal for side effects. Visitor return values are ignored.
|
|
954
|
-
* Sibling nodes at each level are visited concurrently up to `options.concurrency`
|
|
901
|
+
* Sibling nodes at each level are visited concurrently up to `options.concurrency`
|
|
902
|
+
* (default: `WALK_CONCURRENCY`).
|
|
903
|
+
*
|
|
904
|
+
* @example
|
|
905
|
+
* ```ts
|
|
906
|
+
* await walk(root, {
|
|
907
|
+
* operation(node) {
|
|
908
|
+
* console.log(node.operationId)
|
|
909
|
+
* },
|
|
910
|
+
* })
|
|
911
|
+
* ```
|
|
912
|
+
*
|
|
913
|
+
* @example
|
|
914
|
+
* ```ts
|
|
915
|
+
* // Visit only the current node
|
|
916
|
+
* await walk(root, { depth: 'shallow', root: () => {} })
|
|
917
|
+
* ```
|
|
955
918
|
*/
|
|
956
919
|
async function walk(node, options) {
|
|
957
920
|
return _walk(node, options, (options.depth ?? visitorDepths.deep) === visitorDepths.deep, createLimit(options.concurrency ?? 30), void 0);
|
|
@@ -1084,8 +1047,18 @@ function transform(node, options) {
|
|
|
1084
1047
|
}
|
|
1085
1048
|
}
|
|
1086
1049
|
/**
|
|
1087
|
-
*
|
|
1088
|
-
*
|
|
1050
|
+
* Composes multiple visitors into one visitor, applied left to right.
|
|
1051
|
+
*
|
|
1052
|
+
* For each node kind, output from one visitor is input to the next.
|
|
1053
|
+
* If a visitor returns `undefined`, the previous node value is kept.
|
|
1054
|
+
*
|
|
1055
|
+
* @example
|
|
1056
|
+
* ```ts
|
|
1057
|
+
* const visitor = composeTransformers(
|
|
1058
|
+
* { operation: (node) => ({ ...node, operationId: `a_${node.operationId}` }) },
|
|
1059
|
+
* { operation: (node) => ({ ...node, operationId: `b_${node.operationId}` }) },
|
|
1060
|
+
* )
|
|
1061
|
+
* ```
|
|
1089
1062
|
*/
|
|
1090
1063
|
function composeTransformers(...visitors) {
|
|
1091
1064
|
return {
|
|
@@ -1110,7 +1083,24 @@ function composeTransformers(...visitors) {
|
|
|
1110
1083
|
};
|
|
1111
1084
|
}
|
|
1112
1085
|
/**
|
|
1113
|
-
*
|
|
1086
|
+
* Runs a depth-first synchronous collection pass.
|
|
1087
|
+
*
|
|
1088
|
+
* Non-`undefined` values returned by visitor callbacks are appended to the result.
|
|
1089
|
+
*
|
|
1090
|
+
* @example
|
|
1091
|
+
* ```ts
|
|
1092
|
+
* const ids = collect(root, {
|
|
1093
|
+
* operation(node) {
|
|
1094
|
+
* return node.operationId
|
|
1095
|
+
* },
|
|
1096
|
+
* })
|
|
1097
|
+
* ```
|
|
1098
|
+
*
|
|
1099
|
+
* @example
|
|
1100
|
+
* ```ts
|
|
1101
|
+
* // Collect from only the current node
|
|
1102
|
+
* const values = collect(root, { depth: 'shallow', root: () => 'root' })
|
|
1103
|
+
* ```
|
|
1114
1104
|
*/
|
|
1115
1105
|
function collect(node, options) {
|
|
1116
1106
|
const { depth, parent, ...visitor } = options;
|
|
@@ -1148,6 +1138,165 @@ function collect(node, options) {
|
|
|
1148
1138
|
return results;
|
|
1149
1139
|
}
|
|
1150
1140
|
//#endregion
|
|
1151
|
-
|
|
1141
|
+
//#region src/resolvers.ts
|
|
1142
|
+
function findDiscriminator(mapping, ref) {
|
|
1143
|
+
if (!mapping || !ref) return null;
|
|
1144
|
+
return Object.entries(mapping).find(([, value]) => value === ref)?.[0] ?? null;
|
|
1145
|
+
}
|
|
1146
|
+
function childName(parentName, propName) {
|
|
1147
|
+
return parentName ? pascalCase([parentName, propName].join(" ")) : null;
|
|
1148
|
+
}
|
|
1149
|
+
function enumPropName(parentName, propName, enumSuffix) {
|
|
1150
|
+
return pascalCase([
|
|
1151
|
+
parentName,
|
|
1152
|
+
propName,
|
|
1153
|
+
enumSuffix
|
|
1154
|
+
].filter(Boolean).join(" "));
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Collects import entries for all `ref` schema nodes in `node`.
|
|
1158
|
+
*/
|
|
1159
|
+
function collectImports({ node, nameMapping, resolve }) {
|
|
1160
|
+
return collect(node, { schema(schemaNode) {
|
|
1161
|
+
const schemaRef = narrowSchema(schemaNode, "ref");
|
|
1162
|
+
if (!schemaRef?.ref) return;
|
|
1163
|
+
const rawName = extractRefName(schemaRef.ref);
|
|
1164
|
+
const result = resolve(nameMapping.get(rawName) ?? rawName);
|
|
1165
|
+
if (!result) return;
|
|
1166
|
+
return result;
|
|
1167
|
+
} });
|
|
1168
|
+
}
|
|
1169
|
+
//#endregion
|
|
1170
|
+
//#region src/transformers.ts
|
|
1171
|
+
/**
|
|
1172
|
+
* Replaces a discriminator property's schema with a string enum of allowed values.
|
|
1173
|
+
*
|
|
1174
|
+
* If `node` is not an object schema, or if the property does not exist, the input
|
|
1175
|
+
* node is returned as-is.
|
|
1176
|
+
*
|
|
1177
|
+
* @example
|
|
1178
|
+
* ```ts
|
|
1179
|
+
* const schema = createSchema({
|
|
1180
|
+
* type: 'object',
|
|
1181
|
+
* properties: [createProperty({ name: 'type', required: true, schema: createSchema({ type: 'string' }) })],
|
|
1182
|
+
* })
|
|
1183
|
+
* const result = setDiscriminatorEnum({ node: schema, propertyName: 'type', values: ['dog', 'cat'] })
|
|
1184
|
+
* ```
|
|
1185
|
+
*/
|
|
1186
|
+
function setDiscriminatorEnum({ node, propertyName, values, enumName }) {
|
|
1187
|
+
const objectNode = narrowSchema(node, "object");
|
|
1188
|
+
if (!objectNode?.properties?.length) return node;
|
|
1189
|
+
if (!objectNode.properties.some((prop) => prop.name === propertyName)) return node;
|
|
1190
|
+
return createSchema({
|
|
1191
|
+
...objectNode,
|
|
1192
|
+
properties: objectNode.properties.map((prop) => {
|
|
1193
|
+
if (prop.name !== propertyName) return prop;
|
|
1194
|
+
return createProperty({
|
|
1195
|
+
...prop,
|
|
1196
|
+
schema: createSchema({
|
|
1197
|
+
type: "enum",
|
|
1198
|
+
primitive: "string",
|
|
1199
|
+
enumValues: values,
|
|
1200
|
+
name: enumName,
|
|
1201
|
+
readOnly: prop.schema.readOnly,
|
|
1202
|
+
writeOnly: prop.schema.writeOnly
|
|
1203
|
+
})
|
|
1204
|
+
});
|
|
1205
|
+
})
|
|
1206
|
+
});
|
|
1207
|
+
}
|
|
1208
|
+
/**
|
|
1209
|
+
* Merges adjacent anonymous object members into a single anonymous object member.
|
|
1210
|
+
*
|
|
1211
|
+
* @example
|
|
1212
|
+
* ```ts
|
|
1213
|
+
* const merged = mergeAdjacentObjects([
|
|
1214
|
+
* createSchema({ type: 'object', properties: [createProperty({ name: 'a', schema: createSchema({ type: 'string' }) })] }),
|
|
1215
|
+
* createSchema({ type: 'object', properties: [createProperty({ name: 'b', schema: createSchema({ type: 'number' }) })] }),
|
|
1216
|
+
* ])
|
|
1217
|
+
* ```
|
|
1218
|
+
*/
|
|
1219
|
+
function mergeAdjacentObjects(members) {
|
|
1220
|
+
return members.reduce((acc, member) => {
|
|
1221
|
+
const objectMember = narrowSchema(member, "object");
|
|
1222
|
+
if (objectMember && !objectMember.name) {
|
|
1223
|
+
const previous = acc.at(-1);
|
|
1224
|
+
const previousObject = previous ? narrowSchema(previous, "object") : void 0;
|
|
1225
|
+
if (previousObject && !previousObject.name) {
|
|
1226
|
+
acc[acc.length - 1] = createSchema({
|
|
1227
|
+
...previousObject,
|
|
1228
|
+
properties: [...previousObject.properties ?? [], ...objectMember.properties ?? []]
|
|
1229
|
+
});
|
|
1230
|
+
return acc;
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
acc.push(member);
|
|
1234
|
+
return acc;
|
|
1235
|
+
}, []);
|
|
1236
|
+
}
|
|
1237
|
+
/**
|
|
1238
|
+
* Removes enum members that are covered by broader scalar primitives in the same union.
|
|
1239
|
+
*
|
|
1240
|
+
* @example
|
|
1241
|
+
* ```ts
|
|
1242
|
+
* const simplified = simplifyUnion([
|
|
1243
|
+
* createSchema({ type: 'enum', primitive: 'string', enumValues: ['active'] }),
|
|
1244
|
+
* createSchema({ type: 'string' }),
|
|
1245
|
+
* ])
|
|
1246
|
+
* // keeps only string member
|
|
1247
|
+
* ```
|
|
1248
|
+
*/
|
|
1249
|
+
function simplifyUnion(members) {
|
|
1250
|
+
const scalarPrimitives = new Set(members.filter((member) => SCALAR_PRIMITIVE_TYPES.has(member.type)).map((m) => m.type));
|
|
1251
|
+
if (!scalarPrimitives.size) return members;
|
|
1252
|
+
return members.filter((member) => {
|
|
1253
|
+
const enumNode = narrowSchema(member, "enum");
|
|
1254
|
+
if (!enumNode) return true;
|
|
1255
|
+
const primitive = enumNode.primitive;
|
|
1256
|
+
if (!primitive) return true;
|
|
1257
|
+
if ((enumNode.namedEnumValues?.length ?? enumNode.enumValues?.length ?? 0) <= 1) return true;
|
|
1258
|
+
if (scalarPrimitives.has(primitive)) return false;
|
|
1259
|
+
if ((primitive === "integer" || primitive === "number") && (scalarPrimitives.has("integer") || scalarPrimitives.has("number"))) return false;
|
|
1260
|
+
return true;
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
function setEnumName(propNode, parentName, propName, enumSuffix) {
|
|
1264
|
+
const enumNode = narrowSchema(propNode, "enum");
|
|
1265
|
+
if (enumNode?.primitive === "boolean") return {
|
|
1266
|
+
...propNode,
|
|
1267
|
+
name: void 0
|
|
1268
|
+
};
|
|
1269
|
+
if (enumNode) return {
|
|
1270
|
+
...propNode,
|
|
1271
|
+
name: enumPropName(parentName, propName, enumSuffix)
|
|
1272
|
+
};
|
|
1273
|
+
return propNode;
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* Walks a schema tree and resolves `ref`/`enum` names through callbacks.
|
|
1277
|
+
*/
|
|
1278
|
+
function resolveNames({ node, nameMapping, resolveName, resolveEnumName }) {
|
|
1279
|
+
return transform(node, { schema(schemaNode) {
|
|
1280
|
+
const schemaRef = narrowSchema(schemaNode, "ref");
|
|
1281
|
+
if (schemaRef && (schemaRef.ref || schemaRef.name)) {
|
|
1282
|
+
const rawRef = schemaRef.ref ?? schemaRef.name;
|
|
1283
|
+
const resolved = resolveName(nameMapping.get(rawRef) ?? rawRef);
|
|
1284
|
+
if (resolved) return {
|
|
1285
|
+
...schemaNode,
|
|
1286
|
+
name: resolved
|
|
1287
|
+
};
|
|
1288
|
+
}
|
|
1289
|
+
const schemaEnum = narrowSchema(schemaNode, "enum");
|
|
1290
|
+
if (schemaEnum?.name) {
|
|
1291
|
+
const resolved = (resolveEnumName ?? resolveName)(schemaEnum.name);
|
|
1292
|
+
if (resolved) return {
|
|
1293
|
+
...schemaNode,
|
|
1294
|
+
name: resolved
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1297
|
+
} });
|
|
1298
|
+
}
|
|
1299
|
+
//#endregion
|
|
1300
|
+
export { SCALAR_PRIMITIVE_TYPES, buildRefMap, caseParams, childName, collect, collectImports, composeTransformers, createDiscriminantNode, createFunctionParameter, createFunctionParameters, createObjectBindingParameter, createOperation, createParameter, createProperty, createResponse, createRoot, createSchema, defineFunctionPrinter, definePrinter, enumPropName, extractRefName, findDiscriminator, functionPrinter, httpMethods, isFunctionParameterNode, isFunctionParametersNode, isObjectBindingParameterNode, isOperationNode, isParameterNode, isPropertyNode, isResponseNode, isRootNode, isSchemaNode, isStringType, mediaTypes, mergeAdjacentObjects, narrowSchema, nodeKinds, refMapToObject, resolveNames, resolveRef, schemaTypes, setDiscriminatorEnum, setEnumName, simplifyUnion, syncOptionality, transform, walk };
|
|
1152
1301
|
|
|
1153
1302
|
//# sourceMappingURL=index.js.map
|