@kubb/swagger-ts 2.10.0 → 2.11.1
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/chunk-QIZFD754.js +613 -0
- package/dist/chunk-QIZFD754.js.map +1 -0
- package/dist/chunk-Y5R6DTFD.cjs +613 -0
- package/dist/chunk-Y5R6DTFD.cjs.map +1 -0
- package/dist/components.cjs +2 -4
- package/dist/components.d.cts +7 -26
- package/dist/components.d.ts +7 -26
- package/dist/components.js +3 -5
- package/dist/index.cjs +2 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +116 -4
- package/dist/index.d.ts +116 -4
- package/dist/index.js +3 -6
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/src/OperationGenerator.tsx +20 -26
- package/src/SchemaGenerator.tsx +63 -0
- package/src/components/OasType.tsx +2 -2
- package/src/components/{Query.tsx → OperationSchema.tsx} +36 -27
- package/src/components/__snapshots__/Schema/pets.ts +27 -0
- package/src/components/__snapshots__/Schema/showPetById.ts +32 -0
- package/src/components/index.ts +1 -2
- package/src/plugin.ts +20 -57
- package/src/typeParser.ts +324 -0
- package/dist/chunk-75HLNTZM.cjs +0 -823
- package/dist/chunk-75HLNTZM.cjs.map +0 -1
- package/dist/chunk-EX53MIMI.js +0 -823
- package/dist/chunk-EX53MIMI.js.map +0 -1
- package/dist/types-DHrYEdS6.d.cts +0 -117
- package/dist/types-DHrYEdS6.d.ts +0 -117
- package/src/TypeBuilder.ts +0 -61
- package/src/TypeGenerator.ts +0 -415
- package/src/components/Mutation.tsx +0 -142
@@ -0,0 +1,324 @@
|
|
1
|
+
import transformers from '@kubb/core/transformers'
|
2
|
+
import { print } from '@kubb/parser'
|
3
|
+
import * as factory from '@kubb/parser/factory'
|
4
|
+
import { isKeyword, SchemaGenerator, schemaKeywords } from '@kubb/swagger'
|
5
|
+
|
6
|
+
import type { ts } from '@kubb/parser'
|
7
|
+
import type { Schema, SchemaKeywordMapper, SchemaMapper } from '@kubb/swagger'
|
8
|
+
|
9
|
+
export const typeKeywordMapper = {
|
10
|
+
any: () => factory.keywordTypeNodes.any,
|
11
|
+
unknown: () => factory.keywordTypeNodes.unknown,
|
12
|
+
number: () => factory.keywordTypeNodes.number,
|
13
|
+
integer: () => factory.keywordTypeNodes.number,
|
14
|
+
object: (nodes?: ts.TypeElement[]) => {
|
15
|
+
if (!nodes) {
|
16
|
+
return factory.keywordTypeNodes.object
|
17
|
+
}
|
18
|
+
|
19
|
+
return factory.createTypeLiteralNode(nodes)
|
20
|
+
},
|
21
|
+
lazy: undefined,
|
22
|
+
string: () => factory.keywordTypeNodes.string,
|
23
|
+
boolean: () => factory.keywordTypeNodes.boolean,
|
24
|
+
undefined: () => factory.keywordTypeNodes.undefined,
|
25
|
+
nullable: undefined,
|
26
|
+
null: () => factory.keywordTypeNodes.null,
|
27
|
+
nullish: undefined,
|
28
|
+
array: (nodes?: ts.TypeNode[]) => {
|
29
|
+
if (!nodes) {
|
30
|
+
return undefined
|
31
|
+
}
|
32
|
+
|
33
|
+
return factory.createArrayDeclaration({ nodes })
|
34
|
+
},
|
35
|
+
tuple: (nodes?: ts.TypeNode[]) => {
|
36
|
+
if (!nodes) {
|
37
|
+
return undefined
|
38
|
+
}
|
39
|
+
|
40
|
+
return factory.createTupleTypeNode(nodes)
|
41
|
+
},
|
42
|
+
enum: (name?: string) => {
|
43
|
+
if (!name) {
|
44
|
+
return undefined
|
45
|
+
}
|
46
|
+
|
47
|
+
return factory.createTypeReferenceNode(name, undefined)
|
48
|
+
},
|
49
|
+
union: (nodes?: ts.TypeNode[]) => {
|
50
|
+
if (!nodes) {
|
51
|
+
return undefined
|
52
|
+
}
|
53
|
+
|
54
|
+
return factory.createUnionDeclaration({
|
55
|
+
withParentheses: true,
|
56
|
+
nodes,
|
57
|
+
})
|
58
|
+
},
|
59
|
+
const: (name?: string | number, format?: 'string' | 'number') => {
|
60
|
+
if (!name) {
|
61
|
+
return undefined
|
62
|
+
}
|
63
|
+
|
64
|
+
if (format === 'number') {
|
65
|
+
return factory.createLiteralTypeNode(factory.createNumericLiteral(name))
|
66
|
+
}
|
67
|
+
|
68
|
+
return factory.createLiteralTypeNode(factory.createStringLiteral(name.toString()))
|
69
|
+
},
|
70
|
+
datetime: () => factory.keywordTypeNodes.string,
|
71
|
+
date: () => factory.createTypeReferenceNode(factory.createIdentifier('Date')),
|
72
|
+
uuid: undefined,
|
73
|
+
url: undefined,
|
74
|
+
strict: undefined,
|
75
|
+
default: undefined,
|
76
|
+
and: (nodes?: ts.TypeNode[]) => {
|
77
|
+
if (!nodes) {
|
78
|
+
return undefined
|
79
|
+
}
|
80
|
+
|
81
|
+
return factory.createIntersectionDeclaration({
|
82
|
+
withParentheses: true,
|
83
|
+
nodes,
|
84
|
+
})
|
85
|
+
},
|
86
|
+
describe: undefined,
|
87
|
+
min: undefined,
|
88
|
+
max: undefined,
|
89
|
+
optional: undefined,
|
90
|
+
matches: undefined,
|
91
|
+
email: undefined,
|
92
|
+
firstName: undefined,
|
93
|
+
lastName: undefined,
|
94
|
+
password: undefined,
|
95
|
+
phone: undefined,
|
96
|
+
readOnly: undefined,
|
97
|
+
ref: (propertyName?: string) => {
|
98
|
+
if (!propertyName) {
|
99
|
+
return undefined
|
100
|
+
}
|
101
|
+
|
102
|
+
return factory.createTypeReferenceNode(propertyName, undefined)
|
103
|
+
},
|
104
|
+
blob: () => factory.createTypeReferenceNode('Blob', []),
|
105
|
+
deprecated: undefined,
|
106
|
+
example: undefined,
|
107
|
+
type: undefined,
|
108
|
+
format: undefined,
|
109
|
+
catchall: undefined,
|
110
|
+
} satisfies SchemaMapper<(ctx?: any) => ts.Node | null | undefined>
|
111
|
+
|
112
|
+
type ParserOptions = {
|
113
|
+
name: string
|
114
|
+
typeName?: string
|
115
|
+
description?: string
|
116
|
+
/**
|
117
|
+
* @default `'questionToken'`
|
118
|
+
*/
|
119
|
+
optionalType: 'questionToken' | 'undefined' | 'questionTokenAndUndefined'
|
120
|
+
/**
|
121
|
+
* @default `'asConst'`
|
122
|
+
*/
|
123
|
+
enumType: 'enum' | 'asConst' | 'asPascalConst' | 'constEnum' | 'literal'
|
124
|
+
keysToOmit?: string[]
|
125
|
+
mapper?: typeof typeKeywordMapper
|
126
|
+
}
|
127
|
+
|
128
|
+
export function parseTypeMeta(item: Schema, options: ParserOptions): ts.Node | null | undefined {
|
129
|
+
const mapper = options.mapper || typeKeywordMapper
|
130
|
+
const value = mapper[item.keyword as keyof typeof mapper]
|
131
|
+
|
132
|
+
if (!value) {
|
133
|
+
return undefined
|
134
|
+
}
|
135
|
+
|
136
|
+
if (isKeyword(item, schemaKeywords.union)) {
|
137
|
+
const value = mapper[item.keyword as keyof typeof mapper] as typeof typeKeywordMapper['union']
|
138
|
+
return value(item.args.map(orItem => parseTypeMeta(orItem, options)).filter(Boolean) as ts.TypeNode[])
|
139
|
+
}
|
140
|
+
|
141
|
+
if (isKeyword(item, schemaKeywords.and)) {
|
142
|
+
const value = mapper[item.keyword as keyof typeof mapper] as typeof typeKeywordMapper['and']
|
143
|
+
return value(item.args.map(orItem => parseTypeMeta(orItem, options)).filter(Boolean) as ts.TypeNode[])
|
144
|
+
}
|
145
|
+
|
146
|
+
if (isKeyword(item, schemaKeywords.array)) {
|
147
|
+
const value = mapper[item.keyword as keyof typeof mapper] as typeof typeKeywordMapper['array']
|
148
|
+
return value(item.args.items.map(orItem => parseTypeMeta(orItem, options)).filter(Boolean) as ts.TypeNode[])
|
149
|
+
}
|
150
|
+
|
151
|
+
if (isKeyword(item, schemaKeywords.enum)) {
|
152
|
+
const value = mapper[item.keyword as keyof typeof mapper] as typeof typeKeywordMapper['enum']
|
153
|
+
return value(item.args.typeName)
|
154
|
+
}
|
155
|
+
|
156
|
+
if (isKeyword(item, schemaKeywords.ref)) {
|
157
|
+
const value = mapper[item.keyword as keyof typeof mapper] as typeof typeKeywordMapper['ref']
|
158
|
+
return value(item.args.name)
|
159
|
+
}
|
160
|
+
|
161
|
+
if (isKeyword(item, schemaKeywords.blob)) {
|
162
|
+
return value()
|
163
|
+
}
|
164
|
+
|
165
|
+
if (isKeyword(item, schemaKeywords.tuple)) {
|
166
|
+
const value = mapper[item.keyword as keyof typeof mapper] as typeof typeKeywordMapper['tuple']
|
167
|
+
return value(
|
168
|
+
item.args.map(tupleItem => parseTypeMeta(tupleItem, options)).filter(Boolean) as ts.TypeNode[],
|
169
|
+
)
|
170
|
+
}
|
171
|
+
|
172
|
+
if (isKeyword(item, schemaKeywords.const)) {
|
173
|
+
const value = mapper[item.keyword as keyof typeof mapper] as typeof typeKeywordMapper['const']
|
174
|
+
|
175
|
+
return value(item.args.name, item.args.format)
|
176
|
+
}
|
177
|
+
|
178
|
+
if (isKeyword(item, schemaKeywords.object)) {
|
179
|
+
const value = mapper[item.keyword as keyof typeof mapper] as typeof typeKeywordMapper['object']
|
180
|
+
|
181
|
+
const properties = Object.entries(item.args?.properties || {})
|
182
|
+
.filter((item) => {
|
183
|
+
const schemas = item[1]
|
184
|
+
return schemas && typeof schemas.map === 'function'
|
185
|
+
})
|
186
|
+
.map((item) => {
|
187
|
+
const name = item[0]
|
188
|
+
const schemas = item[1]
|
189
|
+
|
190
|
+
const isNullish = schemas.some(item => item.keyword === schemaKeywords.nullish)
|
191
|
+
const isNullable = schemas.some(item => item.keyword === schemaKeywords.nullable)
|
192
|
+
const isOptional = schemas.some(item => item.keyword === schemaKeywords.optional)
|
193
|
+
const isReadonly = schemas.some(item => item.keyword === schemaKeywords.readOnly)
|
194
|
+
const describeSchema = schemas.find(item => item.keyword === schemaKeywords.describe) as SchemaKeywordMapper['describe'] | undefined
|
195
|
+
const deprecatedSchema = schemas.find(item => item.keyword === schemaKeywords.deprecated) as SchemaKeywordMapper['deprecated'] | undefined
|
196
|
+
const defaultSchema = schemas.find(item => item.keyword === schemaKeywords.default) as SchemaKeywordMapper['default'] | undefined
|
197
|
+
const exampleSchema = schemas.find(item => item.keyword === schemaKeywords.example) as SchemaKeywordMapper['example'] | undefined
|
198
|
+
const typeSchema = schemas.find(item => item.keyword === schemaKeywords.type) as SchemaKeywordMapper['type'] | undefined
|
199
|
+
const formatSchema = schemas.find(item => item.keyword === schemaKeywords.format) as SchemaKeywordMapper['format'] | undefined
|
200
|
+
|
201
|
+
let type = schemas
|
202
|
+
.map((item) => parseTypeMeta(item, options))
|
203
|
+
.filter(Boolean)[0] as ts.TypeNode
|
204
|
+
|
205
|
+
if (isNullable) {
|
206
|
+
type = factory.createUnionDeclaration({ nodes: [type, factory.keywordTypeNodes.null] }) as ts.TypeNode
|
207
|
+
}
|
208
|
+
|
209
|
+
if (isNullish && ['undefined', 'questionTokenAndUndefined'].includes(options.optionalType as string)) {
|
210
|
+
type = factory.createUnionDeclaration({ nodes: [type, factory.keywordTypeNodes.undefined] }) as ts.TypeNode
|
211
|
+
}
|
212
|
+
|
213
|
+
if (isOptional && ['undefined', 'questionTokenAndUndefined'].includes(options.optionalType as string)) {
|
214
|
+
type = factory.createUnionDeclaration({ nodes: [type, factory.keywordTypeNodes.undefined] }) as ts.TypeNode
|
215
|
+
}
|
216
|
+
|
217
|
+
const propertySignature = factory.createPropertySignature({
|
218
|
+
questionToken: isOptional && ['questionToken', 'questionTokenAndUndefined'].includes(options.optionalType as string),
|
219
|
+
name,
|
220
|
+
type,
|
221
|
+
readOnly: isReadonly,
|
222
|
+
})
|
223
|
+
|
224
|
+
return factory.appendJSDocToNode({
|
225
|
+
node: propertySignature,
|
226
|
+
comments: [
|
227
|
+
describeSchema ? `@description ${transformers.jsStringEscape(describeSchema.args)}` : undefined,
|
228
|
+
deprecatedSchema ? `@deprecated` : undefined,
|
229
|
+
defaultSchema
|
230
|
+
? `@default ${defaultSchema.args}`
|
231
|
+
: undefined,
|
232
|
+
exampleSchema ? `@example ${exampleSchema.args}` : undefined,
|
233
|
+
typeSchema
|
234
|
+
? `@type ${typeSchema.args}${!isOptional ? '' : ' | undefined'} ${formatSchema?.args || ''}`
|
235
|
+
: undefined,
|
236
|
+
].filter(Boolean),
|
237
|
+
})
|
238
|
+
})
|
239
|
+
|
240
|
+
const additionalProperties = item.args?.additionalProperties?.length
|
241
|
+
? factory.createIndexSignature(item.args.additionalProperties.map(schema => parseTypeMeta(schema, options)).filter(Boolean).at(0) as ts.TypeNode)
|
242
|
+
: undefined
|
243
|
+
|
244
|
+
return value([...properties, additionalProperties].filter(Boolean))
|
245
|
+
}
|
246
|
+
|
247
|
+
if (item.keyword in mapper) {
|
248
|
+
return value()
|
249
|
+
}
|
250
|
+
|
251
|
+
return undefined
|
252
|
+
}
|
253
|
+
|
254
|
+
export function typeParser(
|
255
|
+
schemas: Schema[],
|
256
|
+
options: ParserOptions,
|
257
|
+
): string {
|
258
|
+
const nodes: ts.Node[] = []
|
259
|
+
const extraNodes: ts.Node[] = []
|
260
|
+
|
261
|
+
if (!schemas.length) {
|
262
|
+
return ''
|
263
|
+
}
|
264
|
+
|
265
|
+
const isNullish = schemas.some(item => item.keyword === schemaKeywords.nullish)
|
266
|
+
const isNullable = schemas.some(item => item.keyword === schemaKeywords.nullable)
|
267
|
+
const isOptional = schemas.some(item => item.keyword === schemaKeywords.optional)
|
268
|
+
|
269
|
+
let type = schemas.map((schema) => parseTypeMeta(schema, options)).filter(Boolean).at(0) as ts.TypeNode
|
270
|
+
|| typeKeywordMapper.undefined()
|
271
|
+
|
272
|
+
if (isNullable) {
|
273
|
+
type = factory.createUnionDeclaration({ nodes: [type, factory.keywordTypeNodes.null] }) as ts.TypeNode
|
274
|
+
}
|
275
|
+
|
276
|
+
if (isNullish && ['undefined', 'questionTokenAndUndefined'].includes(options.optionalType as string)) {
|
277
|
+
type = factory.createUnionDeclaration({ nodes: [type, factory.keywordTypeNodes.undefined] }) as ts.TypeNode
|
278
|
+
}
|
279
|
+
|
280
|
+
if (isOptional && ['undefined', 'questionTokenAndUndefined'].includes(options.optionalType as string)) {
|
281
|
+
type = factory.createUnionDeclaration({ nodes: [type, factory.keywordTypeNodes.undefined] }) as ts.TypeNode
|
282
|
+
}
|
283
|
+
|
284
|
+
const node = factory.createTypeAliasDeclaration({
|
285
|
+
modifiers: [factory.modifiers.export],
|
286
|
+
name: options.name,
|
287
|
+
type: options.keysToOmit?.length ? factory.createOmitDeclaration({ keys: options.keysToOmit, type, nonNullable: true }) : type,
|
288
|
+
})
|
289
|
+
|
290
|
+
const enumSchemas = SchemaGenerator.deepSearch(schemas, schemaKeywords.enum)
|
291
|
+
if (enumSchemas) {
|
292
|
+
enumSchemas.forEach(enumSchema => {
|
293
|
+
extraNodes.push(...factory.createEnumDeclaration({
|
294
|
+
name: transformers.camelCase(enumSchema.args.name),
|
295
|
+
typeName: enumSchema.args.typeName,
|
296
|
+
enums: enumSchema.args.items.map(item => item.value === undefined ? undefined : [transformers.trimQuotes(item.name?.toString()), item.value]).filter(
|
297
|
+
Boolean,
|
298
|
+
) as unknown as [
|
299
|
+
string,
|
300
|
+
string,
|
301
|
+
][],
|
302
|
+
type: options.enumType,
|
303
|
+
}))
|
304
|
+
})
|
305
|
+
}
|
306
|
+
|
307
|
+
nodes.push(
|
308
|
+
factory.appendJSDocToNode({
|
309
|
+
node,
|
310
|
+
comments: [
|
311
|
+
options.description ? `@description ${transformers.jsStringEscape(options.description)}` : undefined,
|
312
|
+
].filter(Boolean),
|
313
|
+
}),
|
314
|
+
)
|
315
|
+
|
316
|
+
const filterdNodes = nodes.filter(
|
317
|
+
(node: ts.Node) =>
|
318
|
+
!extraNodes.some(
|
319
|
+
(extraNode: ts.Node) => (extraNode as ts.TypeAliasDeclaration)?.name?.escapedText === (node as ts.TypeAliasDeclaration)?.name?.escapedText,
|
320
|
+
),
|
321
|
+
)
|
322
|
+
|
323
|
+
return print([...extraNodes, ...filterdNodes])
|
324
|
+
}
|