@kubb/ast 5.0.0-alpha.14 → 5.0.0-alpha.16

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/src/constants.ts CHANGED
@@ -62,6 +62,11 @@ export const schemaTypes = {
62
62
  never: 'never',
63
63
  } as const satisfies Record<SchemaType, SchemaType>
64
64
 
65
+ /**
66
+ * Scalar primitive schema types used for union member simplification.
67
+ */
68
+ export const SCALAR_PRIMITIVE_TYPES = new Set(['string', 'number', 'integer', 'bigint', 'boolean'] as const)
69
+
65
70
  export const httpMethods = {
66
71
  get: 'GET',
67
72
  post: 'POST',
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { httpMethods, mediaTypes, nodeKinds, schemaTypes } from './constants.ts'
1
+ export { httpMethods, mediaTypes, nodeKinds, SCALAR_PRIMITIVE_TYPES, schemaTypes } from './constants.ts'
2
2
  export {
3
3
  createFunctionParameter,
4
4
  createFunctionParameters,
@@ -25,6 +25,7 @@ export {
25
25
  narrowSchema,
26
26
  } from './guards.ts'
27
27
  export { definePrinter } from './printer.ts'
28
- export { buildRefMap, refMapToObject, resolveRef } from './refs.ts'
28
+ export { buildRefMap, extractRefName, refMapToObject, resolveRef } from './refs.ts'
29
+ export { applyDiscriminatorEnum, mergeAdjacentAnonymousObjects, simplifyUnionMembers } from './transforms.ts'
29
30
  export { applyParamsCasing, isPlainStringType } from './utils.ts'
30
31
  export { collect, composeTransformers, transform, walk } from './visitor.ts'
package/src/refs.ts CHANGED
@@ -6,6 +6,14 @@ import type { SchemaNode } from './nodes/schema.ts'
6
6
  */
7
7
  export type RefMap = Map<string, SchemaNode>
8
8
 
9
+ /**
10
+ * Extracts the final segment from a reference string.
11
+ * Falls back to the original string when no slash exists.
12
+ */
13
+ export function extractRefName(ref: string): string {
14
+ return ref.split('/').at(-1) ?? ref
15
+ }
16
+
9
17
  /**
10
18
  * Indexes named schemas from `root.schemas` by name. Unnamed schemas are skipped.
11
19
  */
@@ -0,0 +1,114 @@
1
+ import { SCALAR_PRIMITIVE_TYPES } from './constants.ts'
2
+ import { createProperty, createSchema } from './factory.ts'
3
+ import { narrowSchema } from './guards.ts'
4
+ import type { SchemaNode } from './nodes/schema.ts'
5
+
6
+ /**
7
+ * Replaces the discriminator property's schema inside an object node with
8
+ * an enum of the provided values.
9
+ */
10
+ export function applyDiscriminatorEnum({
11
+ node,
12
+ propertyName,
13
+ values,
14
+ enumName,
15
+ }: {
16
+ node: SchemaNode
17
+ propertyName: string
18
+ values: Array<string>
19
+ enumName?: string
20
+ }): SchemaNode {
21
+ const objectNode = narrowSchema(node, 'object')
22
+ if (!objectNode?.properties?.length) {
23
+ return node
24
+ }
25
+
26
+ const hasProperty = objectNode.properties.some((prop) => prop.name === propertyName)
27
+ if (!hasProperty) {
28
+ return node
29
+ }
30
+
31
+ return createSchema({
32
+ ...objectNode,
33
+ properties: objectNode.properties.map((prop) => {
34
+ if (prop.name !== propertyName) {
35
+ return prop
36
+ }
37
+
38
+ return createProperty({
39
+ ...prop,
40
+ schema: createSchema({
41
+ type: 'enum',
42
+ primitive: 'string',
43
+ enumValues: values,
44
+ name: enumName,
45
+ readOnly: prop.schema.readOnly,
46
+ writeOnly: prop.schema.writeOnly,
47
+ }),
48
+ })
49
+ }),
50
+ })
51
+ }
52
+
53
+ /**
54
+ * Merges adjacent anonymous object members into a single anonymous object.
55
+ */
56
+ export function mergeAdjacentAnonymousObjects(members: Array<SchemaNode>): Array<SchemaNode> {
57
+ return members.reduce<Array<SchemaNode>>((acc, member) => {
58
+ const objectMember = narrowSchema(member, 'object')
59
+ if (objectMember && !objectMember.name) {
60
+ const previous = acc.at(-1)
61
+ const previousObject = previous ? narrowSchema(previous, 'object') : undefined
62
+
63
+ if (previousObject && !previousObject.name) {
64
+ acc[acc.length - 1] = createSchema({
65
+ ...previousObject,
66
+ properties: [...(previousObject.properties ?? []), ...(objectMember.properties ?? [])],
67
+ })
68
+ return acc
69
+ }
70
+ }
71
+
72
+ acc.push(member)
73
+ return acc
74
+ }, [])
75
+ }
76
+
77
+ /**
78
+ * Removes enum members subsumed by broader scalar members in the same union.
79
+ */
80
+ export function simplifyUnionMembers(members: Array<SchemaNode>): Array<SchemaNode> {
81
+ const scalarPrimitives = new Set(
82
+ members.filter((member) => SCALAR_PRIMITIVE_TYPES.has(member.type as typeof SCALAR_PRIMITIVE_TYPES extends Set<infer T> ? T : never)).map((m) => m.type),
83
+ )
84
+
85
+ if (!scalarPrimitives.size) {
86
+ return members
87
+ }
88
+
89
+ return members.filter((member) => {
90
+ const enumNode = narrowSchema(member, 'enum')
91
+ if (!enumNode) {
92
+ return true
93
+ }
94
+
95
+ const primitive = enumNode.primitive
96
+ if (!primitive) {
97
+ return true
98
+ }
99
+
100
+ if (!enumNode.enumType) {
101
+ return true
102
+ }
103
+
104
+ if (scalarPrimitives.has(primitive)) {
105
+ return false
106
+ }
107
+
108
+ if ((primitive === 'integer' || primitive === 'number') && (scalarPrimitives.has('integer') || scalarPrimitives.has('number'))) {
109
+ return false
110
+ }
111
+
112
+ return true
113
+ })
114
+ }