@kubb/adapter-oas 5.0.0-alpha.16 → 5.0.0-alpha.17
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 +64 -125
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -25
- package/dist/index.js +66 -123
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/adapter.ts +10 -3
- package/src/constants.ts +1 -2
- package/src/parser.ts +79 -52
- package/src/types.ts +1 -26
- package/src/discriminator.ts +0 -25
- package/src/infer.ts +0 -85
- package/src/naming.ts +0 -25
- package/src/refResolver.ts +0 -65
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubb/adapter-oas",
|
|
3
|
-
"version": "5.0.0-alpha.
|
|
3
|
+
"version": "5.0.0-alpha.17",
|
|
4
4
|
"description": "OpenAPI / Swagger adapter for Kubb — converts OAS input into a @kubb/ast RootNode.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openapi",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"openapi-types": "^12.1.3",
|
|
47
47
|
"remeda": "^2.33.6",
|
|
48
48
|
"swagger2openapi": "^7.0.8",
|
|
49
|
-
"@kubb/ast": "5.0.0-alpha.
|
|
50
|
-
"@kubb/core": "5.0.0-alpha.
|
|
49
|
+
"@kubb/ast": "5.0.0-alpha.17",
|
|
50
|
+
"@kubb/core": "5.0.0-alpha.17"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@types/swagger2openapi": "^7.0.4",
|
package/src/adapter.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import path from 'node:path'
|
|
2
|
-
import { createRoot } from '@kubb/ast'
|
|
2
|
+
import { collectImports, createRoot } from '@kubb/ast'
|
|
3
3
|
import type { AdapterSource } from '@kubb/core'
|
|
4
4
|
import { createAdapter } from '@kubb/core'
|
|
5
5
|
import { DEFAULT_PARSER_OPTIONS } from './constants.ts'
|
|
6
6
|
import { resolveServerUrl } from './oas/resolveServerUrl.ts'
|
|
7
7
|
import { parseFromConfig } from './oas/utils.ts'
|
|
8
8
|
import { createOasParser } from './parser.ts'
|
|
9
|
-
import { getImports } from './refResolver.ts'
|
|
10
9
|
import type { OasAdapter } from './types.ts'
|
|
11
10
|
|
|
12
11
|
export const adapterOasName = 'oas' satisfies OasAdapter['name']
|
|
@@ -65,7 +64,15 @@ export const adapterOas = createAdapter<OasAdapter>((options) => {
|
|
|
65
64
|
nameMapping,
|
|
66
65
|
},
|
|
67
66
|
getImports(node, resolve) {
|
|
68
|
-
return
|
|
67
|
+
return collectImports({
|
|
68
|
+
node,
|
|
69
|
+
nameMapping,
|
|
70
|
+
resolve: (schemaName) => {
|
|
71
|
+
const result = resolve(schemaName)
|
|
72
|
+
if (!result) return
|
|
73
|
+
return { name: [result.name], path: result.path }
|
|
74
|
+
},
|
|
75
|
+
})
|
|
69
76
|
},
|
|
70
77
|
async parse(source) {
|
|
71
78
|
const fakeConfig = sourceToFakeConfig(source)
|
package/src/constants.ts
CHANGED
package/src/parser.ts
CHANGED
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { URLPath } from '@internals/utils'
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
childName,
|
|
4
|
+
createDiscriminantNode,
|
|
4
5
|
createOperation,
|
|
5
6
|
createParameter,
|
|
6
7
|
createProperty,
|
|
7
8
|
createResponse,
|
|
8
9
|
createRoot,
|
|
9
10
|
createSchema,
|
|
11
|
+
enumPropName,
|
|
10
12
|
extractRefName,
|
|
13
|
+
findDiscriminator,
|
|
14
|
+
type InferSchemaNode,
|
|
11
15
|
mediaTypes,
|
|
12
|
-
|
|
16
|
+
mergeAdjacentObjects,
|
|
13
17
|
narrowSchema,
|
|
18
|
+
type ParserOptions,
|
|
19
|
+
resolveNames,
|
|
14
20
|
schemaTypes,
|
|
15
|
-
|
|
21
|
+
setDiscriminatorEnum,
|
|
22
|
+
setEnumName,
|
|
23
|
+
simplifyUnion,
|
|
16
24
|
} from '@kubb/ast'
|
|
17
25
|
import type {
|
|
18
26
|
DistributiveOmit,
|
|
@@ -31,14 +39,9 @@ import type {
|
|
|
31
39
|
StatusCode,
|
|
32
40
|
} from '@kubb/ast/types'
|
|
33
41
|
import { DEFAULT_PARSER_OPTIONS, enumExtensionKeys, formatMap } from './constants.ts'
|
|
34
|
-
import { createDiscriminantNode, resolveDiscriminatorValue } from './discriminator.ts'
|
|
35
|
-
import type { InferSchemaNode } from './infer.ts'
|
|
36
|
-
import { applyEnumName, resolveChildName, resolveEnumPropName } from './naming.ts'
|
|
37
42
|
import type { Oas } from './oas/Oas.ts'
|
|
38
43
|
import type { contentType, Operation, ReferenceObject, SchemaObject } from './oas/types.ts'
|
|
39
44
|
import { flattenSchema, isDiscriminator, isNullable, isReference } from './oas/utils.ts'
|
|
40
|
-
import { resolveRefs as resolveRefsNode } from './refResolver.ts'
|
|
41
|
-
import type { ParserOptions } from './types.ts'
|
|
42
45
|
|
|
43
46
|
/**
|
|
44
47
|
* Construction-time options for `createOasParser`.
|
|
@@ -119,7 +122,7 @@ export type OasParser = {
|
|
|
119
122
|
* Map from original `$ref` paths to their collision-resolved schema names.
|
|
120
123
|
* e.g. `'#/components/schemas/Order'` → `'OrderSchema'`
|
|
121
124
|
*
|
|
122
|
-
* Pass this to the standalone `
|
|
125
|
+
* Pass this to the standalone `collectImports()` to resolve imports without holding
|
|
123
126
|
* a reference to the full parser or OAS instance.
|
|
124
127
|
*/
|
|
125
128
|
nameMapping: Map<string, string>
|
|
@@ -306,7 +309,7 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
306
309
|
const inOneOf = parentUnion.some((oneOfItem) => isReference(oneOfItem) && oneOfItem.$ref === childRef)
|
|
307
310
|
const inMapping = Object.values(deref.discriminator.mapping ?? {}).some((v) => v === childRef)
|
|
308
311
|
if (inOneOf || inMapping) {
|
|
309
|
-
const discriminatorValue =
|
|
312
|
+
const discriminatorValue = findDiscriminator(deref.discriminator.mapping, childRef)
|
|
310
313
|
if (discriminatorValue) {
|
|
311
314
|
filteredDiscriminantValues.push({ propertyName: deref.discriminator.propertyName, value: discriminatorValue })
|
|
312
315
|
}
|
|
@@ -351,13 +354,13 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
351
354
|
// Inject a synthetic single-property object for each discriminant value collected from
|
|
352
355
|
// filtered discriminator parents so that child schemas carry the narrowed literal type.
|
|
353
356
|
for (const { propertyName, value } of filteredDiscriminantValues) {
|
|
354
|
-
allOfMembers.push(createDiscriminantNode(propertyName, value))
|
|
357
|
+
allOfMembers.push(createDiscriminantNode({ propertyName, value }))
|
|
355
358
|
}
|
|
356
359
|
|
|
357
|
-
// Merge consecutive anonymous object members within the synthetic portion — see `
|
|
360
|
+
// Merge consecutive anonymous object members within the synthetic portion — see `mergeAdjacentObjects`.
|
|
358
361
|
return createSchema({
|
|
359
362
|
type: 'intersection',
|
|
360
|
-
members: [...
|
|
363
|
+
members: [...mergeAdjacentObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentObjects(allOfMembers.slice(syntheticStart))],
|
|
361
364
|
...renderSchemaBase(schema, name, nullable, defaultValue),
|
|
362
365
|
})
|
|
363
366
|
}
|
|
@@ -371,6 +374,21 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
371
374
|
* adding common fields next to a discriminated union.
|
|
372
375
|
*/
|
|
373
376
|
function convertUnion({ schema, name, nullable, defaultValue, rawOptions }: SchemaContext): SchemaNode {
|
|
377
|
+
function pickDiscriminatorPropertyNode(node: SchemaNode, propertyName: string): SchemaNode | undefined {
|
|
378
|
+
const objectNode = narrowSchema(node, 'object')
|
|
379
|
+
const discriminatorProperty = objectNode?.properties?.find((property) => property.name === propertyName)
|
|
380
|
+
|
|
381
|
+
if (!discriminatorProperty) {
|
|
382
|
+
return undefined
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
return createSchema({
|
|
386
|
+
type: 'object',
|
|
387
|
+
primitive: 'object',
|
|
388
|
+
properties: [discriminatorProperty],
|
|
389
|
+
})
|
|
390
|
+
}
|
|
391
|
+
|
|
374
392
|
const unionMembers = [...(schema.oneOf ?? []), ...(schema.anyOf ?? [])]
|
|
375
393
|
const unionBase = {
|
|
376
394
|
...renderSchemaBase(schema, name, nullable, defaultValue),
|
|
@@ -391,44 +409,53 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
391
409
|
: undefined
|
|
392
410
|
|
|
393
411
|
if (sharedPropertiesNode || discriminator?.mapping) {
|
|
394
|
-
|
|
412
|
+
const members = unionMembers.map((s) => {
|
|
413
|
+
const ref = isReference(s) ? s.$ref : undefined
|
|
414
|
+
const discriminatorValue = findDiscriminator(discriminator?.mapping, ref)
|
|
415
|
+
const memberNode = convertSchema({ schema: s as SchemaObject }, rawOptions)
|
|
416
|
+
|
|
417
|
+
if (!discriminatorValue || !discriminator) {
|
|
418
|
+
return memberNode
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
const narrowedDiscriminatorNode = sharedPropertiesNode
|
|
422
|
+
? pickDiscriminatorPropertyNode(
|
|
423
|
+
setDiscriminatorEnum({
|
|
424
|
+
node: sharedPropertiesNode,
|
|
425
|
+
propertyName: discriminator.propertyName,
|
|
426
|
+
values: [discriminatorValue],
|
|
427
|
+
}),
|
|
428
|
+
discriminator.propertyName,
|
|
429
|
+
)
|
|
430
|
+
: undefined
|
|
431
|
+
|
|
432
|
+
return createSchema({
|
|
433
|
+
type: 'intersection',
|
|
434
|
+
members: [memberNode, narrowedDiscriminatorNode ?? createDiscriminantNode({ propertyName: discriminator.propertyName, value: discriminatorValue })],
|
|
435
|
+
})
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
const unionNode = createSchema({
|
|
395
439
|
type: 'union',
|
|
396
440
|
...unionBase,
|
|
397
|
-
members
|
|
398
|
-
|
|
399
|
-
const discriminatorValue = resolveDiscriminatorValue(discriminator?.mapping, ref)
|
|
400
|
-
const memberNode = convertSchema({ schema: s as SchemaObject }, rawOptions)
|
|
401
|
-
|
|
402
|
-
if (sharedPropertiesNode) {
|
|
403
|
-
const narrowedProperties =
|
|
404
|
-
discriminatorValue && discriminator
|
|
405
|
-
? applyDiscriminatorEnum({
|
|
406
|
-
node: sharedPropertiesNode,
|
|
407
|
-
propertyName: discriminator.propertyName,
|
|
408
|
-
values: [discriminatorValue],
|
|
409
|
-
})
|
|
410
|
-
: sharedPropertiesNode
|
|
411
|
-
|
|
412
|
-
return createSchema({
|
|
413
|
-
type: 'intersection',
|
|
414
|
-
members: [memberNode, narrowedProperties],
|
|
415
|
-
})
|
|
416
|
-
}
|
|
441
|
+
members,
|
|
442
|
+
})
|
|
417
443
|
|
|
418
|
-
|
|
444
|
+
if (!sharedPropertiesNode) {
|
|
445
|
+
return unionNode
|
|
446
|
+
}
|
|
419
447
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
}),
|
|
448
|
+
return createSchema({
|
|
449
|
+
type: 'intersection',
|
|
450
|
+
...renderSchemaBase(schema, name, nullable, defaultValue),
|
|
451
|
+
members: [unionNode, sharedPropertiesNode],
|
|
425
452
|
})
|
|
426
453
|
}
|
|
427
454
|
|
|
428
455
|
return createSchema({
|
|
429
456
|
type: 'union',
|
|
430
457
|
...unionBase,
|
|
431
|
-
members:
|
|
458
|
+
members: simplifyUnion(unionMembers.map((s) => convertSchema({ schema: s as SchemaObject }, rawOptions))),
|
|
432
459
|
})
|
|
433
460
|
}
|
|
434
461
|
|
|
@@ -549,7 +576,7 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
549
576
|
// x-enumNames / x-enum-varnames: named variants with explicit labels take priority.
|
|
550
577
|
const extensionKey = enumExtensionKeys.find((key) => key in schema)
|
|
551
578
|
if (extensionKey || enumPrimitive === 'number' || enumPrimitive === 'integer' || enumPrimitive === 'boolean') {
|
|
552
|
-
const
|
|
579
|
+
const enumPrimitiveType = (enumPrimitive === 'number' || enumPrimitive === 'integer' ? 'number' : enumPrimitive === 'boolean' ? 'boolean' : 'string') as
|
|
553
580
|
| 'number'
|
|
554
581
|
| 'boolean'
|
|
555
582
|
| 'string'
|
|
@@ -559,11 +586,11 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
559
586
|
|
|
560
587
|
return createSchema({
|
|
561
588
|
...enumBase,
|
|
562
|
-
|
|
589
|
+
primitive: enumPrimitiveType,
|
|
563
590
|
namedEnumValues: sourceValues.map((label, index) => ({
|
|
564
591
|
name: String(label),
|
|
565
592
|
value: extensionKey ? (filteredValues[index] ?? label) : label,
|
|
566
|
-
|
|
593
|
+
primitive: enumPrimitiveType,
|
|
567
594
|
})),
|
|
568
595
|
})
|
|
569
596
|
}
|
|
@@ -595,13 +622,13 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
595
622
|
const resolvedPropSchema = propSchema as SchemaObject
|
|
596
623
|
const propNullable = isNullable(resolvedPropSchema)
|
|
597
624
|
|
|
598
|
-
const
|
|
599
|
-
const propNode = convertSchema({ schema: resolvedPropSchema, name:
|
|
600
|
-
let schemaNode =
|
|
625
|
+
const resolvedChildName = childName(name, propName)
|
|
626
|
+
const propNode = convertSchema({ schema: resolvedPropSchema, name: resolvedChildName }, rawOptions)
|
|
627
|
+
let schemaNode = setEnumName(propNode, name, propName, options.enumSuffix)
|
|
601
628
|
|
|
602
629
|
const tupleNode = narrowSchema(schemaNode, 'tuple')
|
|
603
630
|
if (tupleNode?.items) {
|
|
604
|
-
const namedItems = tupleNode.items.map((item) =>
|
|
631
|
+
const namedItems = tupleNode.items.map((item) => setEnumName(item, name, propName, options.enumSuffix))
|
|
605
632
|
if (namedItems.some((item, i) => item !== tupleNode.items![i])) {
|
|
606
633
|
schemaNode = { ...tupleNode, items: namedItems }
|
|
607
634
|
}
|
|
@@ -657,8 +684,8 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
657
684
|
if (isDiscriminator(schema) && schema.discriminator.mapping) {
|
|
658
685
|
const discPropName = schema.discriminator.propertyName
|
|
659
686
|
const values = Object.keys(schema.discriminator.mapping)
|
|
660
|
-
const enumName = name ?
|
|
661
|
-
return
|
|
687
|
+
const enumName = name ? enumPropName(name, discPropName, options.enumSuffix) : undefined
|
|
688
|
+
return setDiscriminatorEnum({ node: objectNode, propertyName: discPropName, values, enumName })
|
|
662
689
|
}
|
|
663
690
|
|
|
664
691
|
return objectNode
|
|
@@ -697,7 +724,7 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
697
724
|
const rawItems = schema.items as SchemaObject | undefined
|
|
698
725
|
// When the items schema contains an inline enum, derive a named identifier
|
|
699
726
|
// so generators can emit a standalone enum declaration.
|
|
700
|
-
const itemName = rawItems?.enum?.length && name ?
|
|
727
|
+
const itemName = rawItems?.enum?.length && name ? enumPropName(undefined, name, options.enumSuffix) : undefined
|
|
701
728
|
const items = rawItems ? [convertSchema({ schema: rawItems, name: itemName }, rawOptions)] : []
|
|
702
729
|
|
|
703
730
|
return createSchema({
|
|
@@ -991,7 +1018,7 @@ export function createOasParser(oas: Oas, { contentType }: OasParserOptions = {}
|
|
|
991
1018
|
node: SchemaNode,
|
|
992
1019
|
resolveName: (ref: string) => string | undefined,
|
|
993
1020
|
resolveEnumName?: (name: string) => string | undefined,
|
|
994
|
-
): SchemaNode =>
|
|
1021
|
+
): SchemaNode => resolveNames({ node, nameMapping, resolveName, resolveEnumName })
|
|
995
1022
|
|
|
996
1023
|
return {
|
|
997
1024
|
parse,
|
package/src/types.ts
CHANGED
|
@@ -1,33 +1,8 @@
|
|
|
1
|
+
import type { ParserOptions } from '@kubb/ast/types'
|
|
1
2
|
import type { AdapterFactoryOptions } from '@kubb/core'
|
|
2
3
|
import type { Oas as OasClass } from './oas/Oas.ts'
|
|
3
4
|
import type { contentType } from './oas/types.ts'
|
|
4
5
|
|
|
5
|
-
/**
|
|
6
|
-
* Controls how various OAS constructs are mapped to Kubb AST nodes.
|
|
7
|
-
*/
|
|
8
|
-
export type ParserOptions = {
|
|
9
|
-
/**
|
|
10
|
-
* How `format: 'date-time'` schemas are represented. `false` falls through to a plain string.
|
|
11
|
-
*/
|
|
12
|
-
dateType: false | 'string' | 'stringOffset' | 'stringLocal' | 'date'
|
|
13
|
-
/**
|
|
14
|
-
* Whether `type: 'integer'` and `format: 'int64'` produce `number` or `bigint` nodes.
|
|
15
|
-
*/
|
|
16
|
-
integerType?: 'number' | 'bigint'
|
|
17
|
-
/**
|
|
18
|
-
* AST type used when no schema type can be inferred.
|
|
19
|
-
*/
|
|
20
|
-
unknownType: 'any' | 'unknown' | 'void'
|
|
21
|
-
/**
|
|
22
|
-
* AST type used for completely empty schemas (`{}`).
|
|
23
|
-
*/
|
|
24
|
-
emptySchemaType: 'any' | 'unknown' | 'void'
|
|
25
|
-
/**
|
|
26
|
-
* Suffix appended to derived enum names when building property schema names.
|
|
27
|
-
*/
|
|
28
|
-
enumSuffix: 'enum' | (string & {})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
6
|
export type OasAdapterOptions = {
|
|
32
7
|
/**
|
|
33
8
|
* Validate the OpenAPI spec before parsing.
|
package/src/discriminator.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { createProperty, createSchema } from '@kubb/ast'
|
|
2
|
-
import type { SchemaNode } from '@kubb/ast/types'
|
|
3
|
-
|
|
4
|
-
export function resolveDiscriminatorValue(mapping: Record<string, string> | undefined, ref: string | undefined): string | undefined {
|
|
5
|
-
if (!mapping || !ref) return undefined
|
|
6
|
-
return Object.entries(mapping).find(([, value]) => value === ref)?.[0]
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function createDiscriminantNode(propertyName: string, value: string): SchemaNode {
|
|
10
|
-
return createSchema({
|
|
11
|
-
type: 'object',
|
|
12
|
-
primitive: 'object',
|
|
13
|
-
properties: [
|
|
14
|
-
createProperty({
|
|
15
|
-
name: propertyName,
|
|
16
|
-
schema: createSchema({
|
|
17
|
-
type: 'enum',
|
|
18
|
-
primitive: 'string',
|
|
19
|
-
enumValues: [value],
|
|
20
|
-
}),
|
|
21
|
-
required: true,
|
|
22
|
-
}),
|
|
23
|
-
],
|
|
24
|
-
})
|
|
25
|
-
}
|
package/src/infer.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ArraySchemaNode,
|
|
3
|
-
DateSchemaNode,
|
|
4
|
-
DatetimeSchemaNode,
|
|
5
|
-
EnumSchemaNode,
|
|
6
|
-
IntersectionSchemaNode,
|
|
7
|
-
NumberSchemaNode,
|
|
8
|
-
ObjectSchemaNode,
|
|
9
|
-
RefSchemaNode,
|
|
10
|
-
ScalarSchemaNode,
|
|
11
|
-
SchemaNode,
|
|
12
|
-
StringSchemaNode,
|
|
13
|
-
TimeSchemaNode,
|
|
14
|
-
UnionSchemaNode,
|
|
15
|
-
} from '@kubb/ast/types'
|
|
16
|
-
import type { SchemaObject } from './oas/types.ts'
|
|
17
|
-
import type { ParserOptions } from './types.ts'
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Maps each `dateType` option value to the AST node produced by `format: 'date-time'`.
|
|
21
|
-
*/
|
|
22
|
-
type DateTimeNodeByDateType = {
|
|
23
|
-
date: DateSchemaNode
|
|
24
|
-
string: DatetimeSchemaNode
|
|
25
|
-
stringOffset: DatetimeSchemaNode
|
|
26
|
-
stringLocal: DatetimeSchemaNode
|
|
27
|
-
false: StringSchemaNode
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Resolves the AST node produced by `format: 'date-time'` based on the `dateType` option.
|
|
32
|
-
*/
|
|
33
|
-
type ResolveDateTimeNode<TDateType extends ParserOptions['dateType']> = DateTimeNodeByDateType[TDateType extends keyof DateTimeNodeByDateType
|
|
34
|
-
? TDateType
|
|
35
|
-
: 'string']
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Single source of truth: ordered list of `[shape, SchemaNode]` pairs.
|
|
39
|
-
* `InferSchemaNode` walks this tuple in order and returns the node type of the first matching entry.
|
|
40
|
-
* Parameterized over `TDateType` so `format: 'date-time'` resolves to the correct node based on the option.
|
|
41
|
-
*/
|
|
42
|
-
type SchemaNodeMap<TDateType extends ParserOptions['dateType'] = 'string'> = [
|
|
43
|
-
[{ $ref: string }, RefSchemaNode],
|
|
44
|
-
[{ allOf: ReadonlyArray<unknown>; properties: object }, IntersectionSchemaNode],
|
|
45
|
-
[{ allOf: readonly [unknown, unknown, ...unknown[]] }, IntersectionSchemaNode],
|
|
46
|
-
[{ allOf: ReadonlyArray<unknown> }, SchemaNode],
|
|
47
|
-
[{ oneOf: ReadonlyArray<unknown> }, UnionSchemaNode],
|
|
48
|
-
[{ anyOf: ReadonlyArray<unknown> }, UnionSchemaNode],
|
|
49
|
-
[{ const: null }, ScalarSchemaNode],
|
|
50
|
-
[{ const: string | number | boolean }, EnumSchemaNode],
|
|
51
|
-
[{ type: ReadonlyArray<string> }, UnionSchemaNode],
|
|
52
|
-
[{ type: 'array'; enum: ReadonlyArray<unknown> }, ArraySchemaNode],
|
|
53
|
-
[{ enum: ReadonlyArray<unknown> }, EnumSchemaNode],
|
|
54
|
-
[{ type: 'object' }, ObjectSchemaNode],
|
|
55
|
-
[{ additionalProperties: boolean | {} }, ObjectSchemaNode],
|
|
56
|
-
[{ type: 'array' }, ArraySchemaNode],
|
|
57
|
-
[{ items: object }, ArraySchemaNode],
|
|
58
|
-
[{ prefixItems: ReadonlyArray<unknown> }, ArraySchemaNode],
|
|
59
|
-
[{ type: string; format: 'date-time' }, ResolveDateTimeNode<TDateType>],
|
|
60
|
-
[{ type: string; format: 'date' }, DateSchemaNode],
|
|
61
|
-
[{ type: string; format: 'time' }, TimeSchemaNode],
|
|
62
|
-
[{ format: 'date-time' }, ResolveDateTimeNode<TDateType>],
|
|
63
|
-
[{ format: 'date' }, DateSchemaNode],
|
|
64
|
-
[{ format: 'time' }, TimeSchemaNode],
|
|
65
|
-
[{ type: 'string' }, StringSchemaNode],
|
|
66
|
-
[{ type: 'number' }, NumberSchemaNode],
|
|
67
|
-
[{ type: 'integer' }, NumberSchemaNode],
|
|
68
|
-
[{ type: 'bigint' }, NumberSchemaNode],
|
|
69
|
-
[{ type: string }, ScalarSchemaNode],
|
|
70
|
-
[{ minLength: number }, StringSchemaNode],
|
|
71
|
-
[{ maxLength: number }, StringSchemaNode],
|
|
72
|
-
[{ pattern: string }, StringSchemaNode],
|
|
73
|
-
[{ minimum: number }, NumberSchemaNode],
|
|
74
|
-
[{ maximum: number }, NumberSchemaNode],
|
|
75
|
-
]
|
|
76
|
-
|
|
77
|
-
export type InferSchemaNode<
|
|
78
|
-
TSchema extends SchemaObject,
|
|
79
|
-
TDateType extends ParserOptions['dateType'] = 'string',
|
|
80
|
-
TEntries extends ReadonlyArray<[object, SchemaNode]> = SchemaNodeMap<TDateType>,
|
|
81
|
-
> = TEntries extends [infer TEntry extends [object, SchemaNode], ...infer TRest extends ReadonlyArray<[object, SchemaNode]>]
|
|
82
|
-
? TSchema extends TEntry[0]
|
|
83
|
-
? TEntry[1]
|
|
84
|
-
: InferSchemaNode<TSchema, TDateType, TRest>
|
|
85
|
-
: SchemaNode
|
package/src/naming.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { pascalCase } from '@internals/utils'
|
|
2
|
-
import { narrowSchema } from '@kubb/ast'
|
|
3
|
-
import type { SchemaNode } from '@kubb/ast/types'
|
|
4
|
-
|
|
5
|
-
export function resolveChildName(parentName: string | undefined, propName: string): string | undefined {
|
|
6
|
-
return parentName ? pascalCase([parentName, propName].join(' ')) : undefined
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function resolveEnumPropName(parentName: string | undefined, propName: string, enumSuffix: string): string {
|
|
10
|
-
return pascalCase([parentName, propName, enumSuffix].filter(Boolean).join(' '))
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export function applyEnumName(propNode: SchemaNode, parentName: string | undefined, propName: string, enumSuffix: string): SchemaNode {
|
|
14
|
-
const enumNode = narrowSchema(propNode, 'enum')
|
|
15
|
-
|
|
16
|
-
if (enumNode?.primitive === 'boolean') {
|
|
17
|
-
return { ...propNode, name: undefined }
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (enumNode) {
|
|
21
|
-
return { ...propNode, name: resolveEnumPropName(parentName, propName, enumSuffix) }
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return propNode
|
|
25
|
-
}
|
package/src/refResolver.ts
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { collect, extractRefName, narrowSchema, schemaTypes, transform } from '@kubb/ast'
|
|
2
|
-
import type { SchemaNode } from '@kubb/ast/types'
|
|
3
|
-
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Collects import entries for all `ref` schema nodes in `node`.
|
|
7
|
-
*/
|
|
8
|
-
export function getImports({
|
|
9
|
-
node,
|
|
10
|
-
nameMapping,
|
|
11
|
-
resolve,
|
|
12
|
-
}: {
|
|
13
|
-
node: SchemaNode
|
|
14
|
-
nameMapping: Map<string, string>
|
|
15
|
-
resolve: (schemaName: string) => { name: string; path: string } | undefined
|
|
16
|
-
}): Array<KubbFile.Import> {
|
|
17
|
-
return collect<KubbFile.Import>(node, {
|
|
18
|
-
schema(schemaNode): KubbFile.Import | undefined {
|
|
19
|
-
if (schemaNode.type !== 'ref' || !schemaNode.ref) return
|
|
20
|
-
|
|
21
|
-
const rawName = extractRefName(schemaNode.ref)
|
|
22
|
-
const schemaName = nameMapping.get(rawName) ?? rawName
|
|
23
|
-
const result = resolve(schemaName)
|
|
24
|
-
if (!result) return
|
|
25
|
-
|
|
26
|
-
return { name: [result.name], path: result.path }
|
|
27
|
-
},
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Walks a schema tree and resolves `ref`/`enum` names through callbacks.
|
|
33
|
-
*/
|
|
34
|
-
export function resolveRefs({
|
|
35
|
-
node,
|
|
36
|
-
nameMapping,
|
|
37
|
-
resolveName,
|
|
38
|
-
resolveEnumName,
|
|
39
|
-
}: {
|
|
40
|
-
node: SchemaNode
|
|
41
|
-
nameMapping: Map<string, string>
|
|
42
|
-
resolveName: (ref: string) => string | undefined
|
|
43
|
-
resolveEnumName?: (name: string) => string | undefined
|
|
44
|
-
}): SchemaNode {
|
|
45
|
-
return transform(node, {
|
|
46
|
-
schema(schemaNode) {
|
|
47
|
-
const schemaRef = narrowSchema(schemaNode, schemaTypes.ref)
|
|
48
|
-
|
|
49
|
-
if (schemaRef && (schemaRef.ref || schemaRef.name)) {
|
|
50
|
-
const rawRef = schemaRef.ref ?? schemaRef.name!
|
|
51
|
-
const resolved = resolveName(nameMapping.get(rawRef) ?? rawRef)
|
|
52
|
-
if (resolved) {
|
|
53
|
-
return { ...schemaNode, name: resolved }
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (schemaNode.type === 'enum' && schemaNode.name) {
|
|
58
|
-
const resolved = (resolveEnumName ?? resolveName)(schemaNode.name)
|
|
59
|
-
if (resolved) {
|
|
60
|
-
return { ...schemaNode, name: resolved }
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
},
|
|
64
|
-
}) as SchemaNode
|
|
65
|
-
}
|