@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubb/adapter-oas",
3
- "version": "5.0.0-alpha.16",
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.16",
50
- "@kubb/core": "5.0.0-alpha.16"
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 getImports({ node, nameMapping, resolve })
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
@@ -1,5 +1,4 @@
1
- import type { SchemaType } from '@kubb/ast/types'
2
- import type { ParserOptions } from './types.ts'
1
+ import type { ParserOptions, SchemaType } from '@kubb/ast/types'
3
2
 
4
3
  /**
5
4
  * Default values for all `Options` fields.
package/src/parser.ts CHANGED
@@ -1,18 +1,26 @@
1
1
  import { URLPath } from '@internals/utils'
2
2
  import {
3
- applyDiscriminatorEnum,
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
- mergeAdjacentAnonymousObjects,
16
+ mergeAdjacentObjects,
13
17
  narrowSchema,
18
+ type ParserOptions,
19
+ resolveNames,
14
20
  schemaTypes,
15
- simplifyUnionMembers,
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 `getImports()` to resolve imports without holding
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 = resolveDiscriminatorValue(deref.discriminator.mapping, childRef)
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 `mergeAdjacentAnonymousObjects`.
360
+ // Merge consecutive anonymous object members within the synthetic portion — see `mergeAdjacentObjects`.
358
361
  return createSchema({
359
362
  type: 'intersection',
360
- members: [...mergeAdjacentAnonymousObjects(allOfMembers.slice(0, syntheticStart)), ...mergeAdjacentAnonymousObjects(allOfMembers.slice(syntheticStart))],
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
- return createSchema({
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: unionMembers.map((s) => {
398
- const ref = isReference(s) ? s.$ref : undefined
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
- if (!discriminatorValue || !discriminator) return memberNode
444
+ if (!sharedPropertiesNode) {
445
+ return unionNode
446
+ }
419
447
 
420
- return createSchema({
421
- type: 'intersection',
422
- members: [memberNode, createDiscriminantNode(discriminator.propertyName, discriminatorValue)],
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: simplifyUnionMembers(unionMembers.map((s) => convertSchema({ schema: s as SchemaObject }, rawOptions))),
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 enumType = (enumPrimitive === 'number' || enumPrimitive === 'integer' ? 'number' : enumPrimitive === 'boolean' ? 'boolean' : 'string') as
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
- enumType,
589
+ primitive: enumPrimitiveType,
563
590
  namedEnumValues: sourceValues.map((label, index) => ({
564
591
  name: String(label),
565
592
  value: extensionKey ? (filteredValues[index] ?? label) : label,
566
- format: enumType,
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 childName = resolveChildName(name, propName)
599
- const propNode = convertSchema({ schema: resolvedPropSchema, name: childName }, rawOptions)
600
- let schemaNode = applyEnumName(propNode, name, propName, options.enumSuffix)
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) => applyEnumName(item, name, propName, options.enumSuffix))
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 ? resolveEnumPropName(name, discPropName, options.enumSuffix) : undefined
661
- return applyDiscriminatorEnum({ node: objectNode, propertyName: discPropName, values, enumName })
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 ? resolveEnumPropName(undefined, name, options.enumSuffix) : undefined
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 => resolveRefsNode({ node, nameMapping, resolveName, resolveEnumName })
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.
@@ -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
- }
@@ -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
- }