@kubb/plugin-oas 3.15.1 → 3.16.0
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/{OperationGenerator-DyM5QANw.d.ts → OperationGenerator-C7NPZtOM.d.ts} +7 -21
- package/dist/{OperationGenerator-LFwakDt7.d.cts → OperationGenerator-DJE2XQ83.d.cts} +7 -21
- package/dist/{chunk-2LJ3ZJZP.cjs → chunk-CNSA5TDG.cjs} +34 -42
- package/dist/chunk-CNSA5TDG.cjs.map +1 -0
- package/dist/{chunk-JSR2ZSPP.js → chunk-ISOHAFCA.js} +33 -42
- package/dist/chunk-ISOHAFCA.js.map +1 -0
- package/dist/{chunk-S7ZYTJXL.js → chunk-MBX66JAT.js} +5 -5
- package/dist/chunk-MBX66JAT.js.map +1 -0
- package/dist/{chunk-S3UPJP7I.cjs → chunk-QJMOOF2A.cjs} +5 -5
- package/dist/chunk-QJMOOF2A.cjs.map +1 -0
- package/dist/components.d.cts +1 -1
- package/dist/components.d.ts +1 -1
- package/dist/generators.cjs +2 -2
- package/dist/generators.d.cts +1 -1
- package/dist/generators.d.ts +1 -1
- package/dist/generators.js +1 -1
- package/dist/hooks.cjs +2 -2
- package/dist/hooks.d.cts +1 -1
- package/dist/hooks.d.ts +1 -1
- package/dist/hooks.js +1 -1
- package/dist/index.cjs +126 -191
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +122 -188
- package/dist/index.js.map +1 -1
- package/dist/utils.d.cts +1 -1
- package/dist/utils.d.ts +1 -1
- package/package.json +8 -7
- package/src/OperationGenerator.ts +126 -223
- package/src/SchemaGenerator.ts +31 -45
- package/src/generator.tsx +4 -12
- package/src/types.ts +0 -1
- package/dist/chunk-2LJ3ZJZP.cjs.map +0 -1
- package/dist/chunk-JSR2ZSPP.js.map +0 -1
- package/dist/chunk-S3UPJP7I.cjs.map +0 -1
- package/dist/chunk-S7ZYTJXL.js.map +0 -1
|
@@ -3,11 +3,11 @@ import transformers from '@kubb/core/transformers'
|
|
|
3
3
|
|
|
4
4
|
import type { PluginFactoryOptions, PluginManager } from '@kubb/core'
|
|
5
5
|
import type { KubbFile } from '@kubb/core/fs'
|
|
6
|
-
|
|
7
6
|
import type { Plugin } from '@kubb/core'
|
|
8
7
|
import type { HttpMethod, Oas, OasTypes, Operation, SchemaObject, contentType } from '@kubb/oas'
|
|
9
8
|
import type { Generator } from './generator.tsx'
|
|
10
|
-
import type { Exclude, Include, OperationSchemas,
|
|
9
|
+
import type { Exclude, Include, OperationSchemas, Override } from './types.ts'
|
|
10
|
+
import pLimit from 'p-limit'
|
|
11
11
|
|
|
12
12
|
export type OperationMethodResult<TFileMeta extends FileMetaBase> = Promise<KubbFile.File<TFileMeta> | Array<KubbFile.File<TFileMeta>> | null>
|
|
13
13
|
|
|
@@ -29,101 +29,75 @@ export class OperationGenerator<
|
|
|
29
29
|
TPluginOptions extends PluginFactoryOptions = PluginFactoryOptions,
|
|
30
30
|
TFileMeta extends FileMetaBase = FileMetaBase,
|
|
31
31
|
> extends BaseGenerator<TPluginOptions['resolvedOptions'], Context<TPluginOptions['resolvedOptions'], TPluginOptions>> {
|
|
32
|
-
#operationsByMethod: OperationsByMethod = {}
|
|
33
|
-
get operationsByMethod(): OperationsByMethod {
|
|
34
|
-
return this.#operationsByMethod
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
set operationsByMethod(paths: OperationsByMethod) {
|
|
38
|
-
this.#operationsByMethod = paths
|
|
39
|
-
}
|
|
40
|
-
|
|
41
32
|
#getOptions(operation: Operation, method: HttpMethod): Partial<TPluginOptions['resolvedOptions']> {
|
|
42
33
|
const { override = [] } = this.context
|
|
34
|
+
const operationId = operation.getOperationId({ friendlyCase: true })
|
|
35
|
+
const contentType = operation.getContentType()
|
|
43
36
|
|
|
44
37
|
return (
|
|
45
38
|
override.find(({ pattern, type }) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
39
|
+
switch (type) {
|
|
40
|
+
case 'tag':
|
|
41
|
+
return operation.getTags().some((tag) => tag.name.match(pattern))
|
|
42
|
+
case 'operationId':
|
|
43
|
+
return !!operationId.match(pattern)
|
|
44
|
+
case 'path':
|
|
45
|
+
return !!operation.path.match(pattern)
|
|
46
|
+
case 'method':
|
|
47
|
+
return !!method.match(pattern)
|
|
48
|
+
case 'contentType':
|
|
49
|
+
return !!contentType.match(pattern)
|
|
50
|
+
default:
|
|
51
|
+
return false
|
|
56
52
|
}
|
|
57
|
-
|
|
58
|
-
if (type === 'method') {
|
|
59
|
-
return !!method.match(pattern)
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (type === 'contentType') {
|
|
63
|
-
return !!operation.getContentType().match(pattern)
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return false
|
|
67
53
|
})?.options || {}
|
|
68
54
|
)
|
|
69
55
|
}
|
|
70
56
|
|
|
71
57
|
#isExcluded(operation: Operation, method: HttpMethod): boolean {
|
|
72
58
|
const { exclude = [] } = this.context
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (type === 'contentType' && !matched) {
|
|
93
|
-
return !!operation.getContentType().match(pattern)
|
|
59
|
+
const operationId = operation.getOperationId({ friendlyCase: true })
|
|
60
|
+
const contentType = operation.getContentType()
|
|
61
|
+
|
|
62
|
+
return exclude.some(({ pattern, type }) => {
|
|
63
|
+
switch (type) {
|
|
64
|
+
case 'tag':
|
|
65
|
+
return operation.getTags().some((tag) => tag.name.match(pattern))
|
|
66
|
+
case 'operationId':
|
|
67
|
+
return !!operationId.match(pattern)
|
|
68
|
+
case 'path':
|
|
69
|
+
return !!operation.path.match(pattern)
|
|
70
|
+
case 'method':
|
|
71
|
+
return !!method.match(pattern)
|
|
72
|
+
case 'contentType':
|
|
73
|
+
return !!contentType.match(pattern)
|
|
74
|
+
default:
|
|
75
|
+
return false
|
|
94
76
|
}
|
|
95
77
|
})
|
|
96
|
-
|
|
97
|
-
return matched
|
|
98
78
|
}
|
|
99
79
|
|
|
100
80
|
#isIncluded(operation: Operation, method: HttpMethod): boolean {
|
|
101
81
|
const { include = [] } = this.context
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (type === 'contentType' && !matched) {
|
|
122
|
-
matched = !!operation.getContentType().match(pattern)
|
|
82
|
+
const operationId = operation.getOperationId({ friendlyCase: true })
|
|
83
|
+
const contentType = operation.getContentType()
|
|
84
|
+
|
|
85
|
+
return include.some(({ pattern, type }) => {
|
|
86
|
+
switch (type) {
|
|
87
|
+
case 'tag':
|
|
88
|
+
return operation.getTags().some((tag) => tag.name.match(pattern))
|
|
89
|
+
case 'operationId':
|
|
90
|
+
return !!operationId.match(pattern)
|
|
91
|
+
case 'path':
|
|
92
|
+
return !!operation.path.match(pattern)
|
|
93
|
+
case 'method':
|
|
94
|
+
return !!method.match(pattern)
|
|
95
|
+
case 'contentType':
|
|
96
|
+
return !!contentType.match(pattern)
|
|
97
|
+
default:
|
|
98
|
+
return false
|
|
123
99
|
}
|
|
124
100
|
})
|
|
125
|
-
|
|
126
|
-
return matched
|
|
127
101
|
}
|
|
128
102
|
|
|
129
103
|
getSchemas(
|
|
@@ -134,220 +108,149 @@ export class OperationGenerator<
|
|
|
134
108
|
resolveName?: (name: string) => string
|
|
135
109
|
} = {},
|
|
136
110
|
): OperationSchemas {
|
|
111
|
+
const operationId = operation.getOperationId({ friendlyCase: true })
|
|
112
|
+
const method = operation.method
|
|
113
|
+
const operationName = transformers.pascalCase(operationId)
|
|
114
|
+
|
|
115
|
+
const resolveKeys = (schema?: SchemaObject) => (schema?.properties ? Object.keys(schema.properties) : undefined)
|
|
116
|
+
|
|
137
117
|
const pathParamsSchema = this.context.oas.getParametersSchema(operation, 'path')
|
|
138
118
|
const queryParamsSchema = this.context.oas.getParametersSchema(operation, 'query')
|
|
139
119
|
const headerParamsSchema = this.context.oas.getParametersSchema(operation, 'header')
|
|
140
120
|
const requestSchema = this.context.oas.getRequestSchema(operation)
|
|
141
121
|
const statusCodes = operation.getResponseStatusCodes().map((statusCode) => {
|
|
142
|
-
|
|
143
|
-
if (name === 'default') {
|
|
144
|
-
name = 'error'
|
|
145
|
-
}
|
|
146
|
-
|
|
122
|
+
const name = statusCode === 'default' ? 'error' : statusCode
|
|
147
123
|
const schema = this.context.oas.getResponseSchema(operation, statusCode)
|
|
124
|
+
const keys = resolveKeys(schema)
|
|
148
125
|
|
|
149
126
|
return {
|
|
150
|
-
name: resolveName(transformers.pascalCase(`${
|
|
127
|
+
name: resolveName(transformers.pascalCase(`${operationId} ${name}`)),
|
|
151
128
|
description: (operation.getResponseByStatusCode(statusCode) as OasTypes.ResponseObject)?.description,
|
|
152
129
|
schema,
|
|
153
130
|
operation,
|
|
154
|
-
operationName
|
|
131
|
+
operationName,
|
|
155
132
|
statusCode: name === 'error' ? undefined : Number(statusCode),
|
|
156
|
-
keys
|
|
157
|
-
keysToOmit: schema?.properties
|
|
158
|
-
? Object.keys(schema.properties).filter((key) => {
|
|
159
|
-
const item = schema.properties?.[key] as OasTypes.SchemaObject
|
|
160
|
-
return item?.writeOnly
|
|
161
|
-
})
|
|
162
|
-
: undefined,
|
|
133
|
+
keys,
|
|
134
|
+
keysToOmit: keys?.filter((key) => (schema?.properties?.[key] as OasTypes.SchemaObject)?.writeOnly),
|
|
163
135
|
}
|
|
164
136
|
})
|
|
165
|
-
|
|
137
|
+
|
|
138
|
+
const successful = statusCodes.filter((item) => item.statusCode?.toString().startsWith('2'))
|
|
139
|
+
const errors = statusCodes.filter((item) => item.statusCode?.toString().startsWith('4') || item.statusCode?.toString().startsWith('5'))
|
|
166
140
|
|
|
167
141
|
return {
|
|
168
142
|
pathParams: pathParamsSchema
|
|
169
143
|
? {
|
|
170
|
-
name: resolveName(transformers.pascalCase(`${
|
|
144
|
+
name: resolveName(transformers.pascalCase(`${operationId} PathParams`)),
|
|
171
145
|
operation,
|
|
172
|
-
operationName
|
|
146
|
+
operationName,
|
|
173
147
|
schema: pathParamsSchema,
|
|
174
|
-
keys:
|
|
148
|
+
keys: resolveKeys(pathParamsSchema),
|
|
175
149
|
}
|
|
176
150
|
: undefined,
|
|
177
151
|
queryParams: queryParamsSchema
|
|
178
152
|
? {
|
|
179
|
-
name: resolveName(transformers.pascalCase(`${
|
|
153
|
+
name: resolveName(transformers.pascalCase(`${operationId} QueryParams`)),
|
|
180
154
|
operation,
|
|
181
|
-
operationName
|
|
155
|
+
operationName,
|
|
182
156
|
schema: queryParamsSchema,
|
|
183
|
-
keys:
|
|
157
|
+
keys: resolveKeys(queryParamsSchema) || [],
|
|
184
158
|
}
|
|
185
159
|
: undefined,
|
|
186
160
|
headerParams: headerParamsSchema
|
|
187
161
|
? {
|
|
188
|
-
name: resolveName(transformers.pascalCase(`${
|
|
162
|
+
name: resolveName(transformers.pascalCase(`${operationId} HeaderParams`)),
|
|
189
163
|
operation,
|
|
190
|
-
operationName
|
|
164
|
+
operationName,
|
|
191
165
|
schema: headerParamsSchema,
|
|
192
|
-
keys:
|
|
166
|
+
keys: resolveKeys(headerParamsSchema),
|
|
193
167
|
}
|
|
194
168
|
: undefined,
|
|
195
169
|
request: requestSchema
|
|
196
170
|
? {
|
|
197
|
-
name: resolveName(
|
|
198
|
-
transformers.pascalCase(`${operation.getOperationId({ friendlyCase: true })} ${operation.method === 'get' ? 'queryRequest' : 'mutationRequest'}`),
|
|
199
|
-
),
|
|
171
|
+
name: resolveName(transformers.pascalCase(`${operationId} ${method === 'get' ? 'queryRequest' : 'mutationRequest'}`)),
|
|
200
172
|
description: (operation.schema.requestBody as OasTypes.RequestBodyObject)?.description,
|
|
201
173
|
operation,
|
|
202
|
-
operationName
|
|
174
|
+
operationName,
|
|
203
175
|
schema: requestSchema,
|
|
204
|
-
keys:
|
|
205
|
-
keysToOmit: requestSchema.properties
|
|
206
|
-
? Object.keys(requestSchema.properties).filter((key) => {
|
|
207
|
-
const item = requestSchema.properties?.[key] as OasTypes.SchemaObject
|
|
208
|
-
|
|
209
|
-
return item?.readOnly
|
|
210
|
-
})
|
|
211
|
-
: undefined,
|
|
176
|
+
keys: resolveKeys(requestSchema),
|
|
177
|
+
keysToOmit: resolveKeys(requestSchema)?.filter((key) => (requestSchema.properties?.[key] as OasTypes.SchemaObject)?.readOnly),
|
|
212
178
|
}
|
|
213
179
|
: undefined,
|
|
214
180
|
response: {
|
|
215
|
-
name: resolveName(
|
|
216
|
-
transformers.pascalCase(`${operation.getOperationId({ friendlyCase: true })} ${operation.method === 'get' ? 'queryResponse' : 'mutationResponse'}`),
|
|
217
|
-
),
|
|
181
|
+
name: resolveName(transformers.pascalCase(`${operationId} ${method === 'get' ? 'queryResponse' : 'mutationResponse'}`)),
|
|
218
182
|
operation,
|
|
219
|
-
operationName
|
|
183
|
+
operationName,
|
|
220
184
|
schema: {
|
|
221
|
-
oneOf:
|
|
222
|
-
? statusCodes
|
|
223
|
-
.filter((item) => item.statusCode?.toString().startsWith('2'))
|
|
224
|
-
.map((item) => {
|
|
225
|
-
return {
|
|
226
|
-
...item.schema,
|
|
227
|
-
$ref: resolveName(transformers.pascalCase(`${operation.getOperationId({ friendlyCase: true })} ${item.statusCode}`)),
|
|
228
|
-
}
|
|
229
|
-
})
|
|
230
|
-
: undefined,
|
|
185
|
+
oneOf: successful.map((item) => ({ ...item.schema, $ref: item.name })) || undefined,
|
|
231
186
|
} as SchemaObject,
|
|
232
187
|
},
|
|
233
|
-
responses:
|
|
234
|
-
errors
|
|
188
|
+
responses: successful,
|
|
189
|
+
errors,
|
|
235
190
|
statusCodes,
|
|
236
191
|
}
|
|
237
192
|
}
|
|
238
193
|
|
|
239
|
-
async
|
|
194
|
+
async getOperations(): Promise<Array<{ path: string; method: HttpMethod; operation: Operation }>> {
|
|
240
195
|
const { oas } = this.context
|
|
241
196
|
|
|
242
197
|
const paths = oas.getPaths()
|
|
243
|
-
this.operationsByMethod = Object.entries(paths).reduce((acc, [path, method]) => {
|
|
244
|
-
const methods = Object.keys(method) as HttpMethod[]
|
|
245
198
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
if (isIncluded && !isExcluded) {
|
|
253
|
-
if (!acc[path]) {
|
|
254
|
-
acc[path] = {} as OperationsByMethod['get']
|
|
255
|
-
}
|
|
256
|
-
acc[path] = {
|
|
257
|
-
...acc[path],
|
|
258
|
-
[method]: {
|
|
259
|
-
operation,
|
|
260
|
-
schemas: this.getSchemas(operation),
|
|
261
|
-
},
|
|
262
|
-
} as OperationsByMethod['get']
|
|
199
|
+
return Object.entries(paths).flatMap(([path, methods]) =>
|
|
200
|
+
Object.entries(methods)
|
|
201
|
+
.map((values) => {
|
|
202
|
+
const [method, operation] = values as [HttpMethod, Operation]
|
|
203
|
+
if (this.#isExcluded(operation, method)) {
|
|
204
|
+
return null
|
|
263
205
|
}
|
|
264
|
-
}
|
|
265
|
-
})
|
|
266
|
-
|
|
267
|
-
return acc
|
|
268
|
-
}, {} as OperationsByMethod)
|
|
269
|
-
|
|
270
|
-
const promises = Object.keys(this.operationsByMethod).reduce((acc, path) => {
|
|
271
|
-
const methods = this.operationsByMethod[path] ? (Object.keys(this.operationsByMethod[path]!) as HttpMethod[]) : []
|
|
272
|
-
|
|
273
|
-
methods.forEach((method) => {
|
|
274
|
-
const { operation } = this.operationsByMethod[path]?.[method]!
|
|
275
|
-
const options = this.#getOptions(operation, method)
|
|
276
206
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
if (typeof methodToCall === 'function') {
|
|
280
|
-
const promiseMethod = methodToCall?.call(this, operation, {
|
|
281
|
-
...this.options,
|
|
282
|
-
...options,
|
|
283
|
-
})
|
|
284
|
-
|
|
285
|
-
if (promiseMethod) {
|
|
286
|
-
acc.push(promiseMethod)
|
|
207
|
+
if (this.context.include && !this.#isIncluded(operation, method)) {
|
|
208
|
+
return null
|
|
287
209
|
}
|
|
288
|
-
}
|
|
289
210
|
|
|
290
|
-
|
|
291
|
-
...this.options,
|
|
292
|
-
...options,
|
|
211
|
+
return operation ? { path, method: method as HttpMethod, operation } : null
|
|
293
212
|
})
|
|
213
|
+
.filter(Boolean),
|
|
214
|
+
)
|
|
215
|
+
}
|
|
294
216
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
generators?.forEach((generator) => {
|
|
300
|
-
const promise = generator.operation?.({
|
|
301
|
-
instance: this,
|
|
302
|
-
operation,
|
|
303
|
-
options: {
|
|
304
|
-
...this.options,
|
|
305
|
-
...options,
|
|
306
|
-
},
|
|
307
|
-
} as any) as Promise<Array<KubbFile.File<TFileMeta>>>
|
|
217
|
+
async build(...generators: Array<Generator<TPluginOptions>>): Promise<Array<KubbFile.File<TFileMeta>>> {
|
|
218
|
+
const operations = await this.getOperations()
|
|
308
219
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
})
|
|
313
|
-
})
|
|
220
|
+
const generatorLimit = pLimit(1)
|
|
221
|
+
const operationLimit = pLimit(10)
|
|
314
222
|
|
|
315
|
-
|
|
316
|
-
|
|
223
|
+
const writeTasks = generators.map((generator) =>
|
|
224
|
+
generatorLimit(async () => {
|
|
225
|
+
const operationTasks = operations.map(({ operation, method }) =>
|
|
226
|
+
operationLimit(async () => {
|
|
227
|
+
const options = this.#getOptions(operation, method)
|
|
317
228
|
|
|
318
|
-
|
|
229
|
+
const result = await generator.operation?.({
|
|
230
|
+
instance: this,
|
|
231
|
+
operation,
|
|
232
|
+
options: { ...this.options, ...options },
|
|
233
|
+
})
|
|
319
234
|
|
|
320
|
-
|
|
235
|
+
return result ?? []
|
|
236
|
+
}),
|
|
237
|
+
)
|
|
321
238
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
instance: this,
|
|
325
|
-
operations: operations.flat().filter(Boolean),
|
|
326
|
-
operationsByMethod: this.operationsByMethod,
|
|
327
|
-
options: this.options,
|
|
328
|
-
} as any) as Promise<Array<KubbFile.File<TFileMeta>>>
|
|
239
|
+
const operationResults = await Promise.all(operationTasks)
|
|
240
|
+
const opResultsFlat = operationResults.flat()
|
|
329
241
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
242
|
+
const operationsResult = await generator.operations?.({
|
|
243
|
+
instance: this,
|
|
244
|
+
operations: operations.map((op) => op.operation),
|
|
245
|
+
options: this.options,
|
|
246
|
+
})
|
|
334
247
|
|
|
335
|
-
|
|
248
|
+
return [...opResultsFlat, ...(operationsResult ?? [])] as unknown as KubbFile.File<TFileMeta>
|
|
249
|
+
}),
|
|
250
|
+
)
|
|
336
251
|
|
|
337
|
-
|
|
338
|
-
return files.flat().filter(Boolean)
|
|
339
|
-
}
|
|
252
|
+
const nestedResults = await Promise.all(writeTasks)
|
|
340
253
|
|
|
341
|
-
|
|
342
|
-
* Operation
|
|
343
|
-
*/
|
|
344
|
-
async operation(_operation: Operation, _options: TPluginOptions['resolvedOptions']): OperationMethodResult<TFileMeta> {
|
|
345
|
-
return []
|
|
346
|
-
}
|
|
347
|
-
/**
|
|
348
|
-
* Combination of GET, POST, PATCH, PUT, DELETE
|
|
349
|
-
*/
|
|
350
|
-
async all(_operations: Operation[], _paths: OperationsByMethod): OperationMethodResult<TFileMeta> {
|
|
351
|
-
return []
|
|
254
|
+
return nestedResults.flat()
|
|
352
255
|
}
|
|
353
256
|
}
|
package/src/SchemaGenerator.ts
CHANGED
|
@@ -12,6 +12,7 @@ import { isKeyword, schemaKeywords } from './SchemaMapper.ts'
|
|
|
12
12
|
import type { OperationSchema, Override, Refs } from './types.ts'
|
|
13
13
|
import { getSchemaFactory } from './utils/getSchemaFactory.ts'
|
|
14
14
|
import { getSchemas } from './utils/getSchemas.ts'
|
|
15
|
+
import pLimit from 'p-limit'
|
|
15
16
|
|
|
16
17
|
export type GetSchemaGeneratorOptions<T extends SchemaGenerator<any, any, any>> = T extends SchemaGenerator<infer Options, any, any> ? Options : never
|
|
17
18
|
|
|
@@ -1082,58 +1083,43 @@ export class SchemaGenerator<
|
|
|
1082
1083
|
|
|
1083
1084
|
async build(...generators: Array<Generator<TPluginOptions>>): Promise<Array<KubbFile.File<TFileMeta>>> {
|
|
1084
1085
|
const { oas, contentType, include } = this.context
|
|
1085
|
-
|
|
1086
1086
|
const schemas = getSchemas({ oas, contentType, includes: include })
|
|
1087
|
+
const schemaEntries = Object.entries(schemas)
|
|
1087
1088
|
|
|
1088
|
-
const
|
|
1089
|
-
|
|
1090
|
-
return acc
|
|
1091
|
-
}
|
|
1092
|
-
|
|
1093
|
-
const options = this.#getOptions({ name })
|
|
1094
|
-
const promiseOperation = this.schema.call(this, name, value, {
|
|
1095
|
-
...this.options,
|
|
1096
|
-
...options,
|
|
1097
|
-
})
|
|
1098
|
-
|
|
1099
|
-
if (promiseOperation) {
|
|
1100
|
-
acc.push(promiseOperation)
|
|
1101
|
-
}
|
|
1102
|
-
|
|
1103
|
-
generators?.forEach((generator) => {
|
|
1104
|
-
const tree = this.parse({ schemaObject: value, name: name })
|
|
1089
|
+
const generatorLimit = pLimit(1)
|
|
1090
|
+
const schemaLimit = pLimit(10)
|
|
1105
1091
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
tree,
|
|
1112
|
-
},
|
|
1113
|
-
options: {
|
|
1114
|
-
...this.options,
|
|
1115
|
-
...options,
|
|
1116
|
-
},
|
|
1117
|
-
} as any) as Promise<Array<KubbFile.File<TFileMeta>>>
|
|
1092
|
+
const writeTasks = generators.map((generator) =>
|
|
1093
|
+
generatorLimit(async () => {
|
|
1094
|
+
const schemaTasks = schemaEntries.map(([name, schemaObject]) =>
|
|
1095
|
+
schemaLimit(async () => {
|
|
1096
|
+
const options = this.#getOptions({ name })
|
|
1097
|
+
const tree = this.parse({ name, schemaObject })
|
|
1118
1098
|
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1099
|
+
const result = await generator.schema?.({
|
|
1100
|
+
instance: this,
|
|
1101
|
+
schema: {
|
|
1102
|
+
name,
|
|
1103
|
+
value: schemaObject,
|
|
1104
|
+
tree,
|
|
1105
|
+
},
|
|
1106
|
+
options: {
|
|
1107
|
+
...this.options,
|
|
1108
|
+
...options,
|
|
1109
|
+
},
|
|
1110
|
+
})
|
|
1123
1111
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1112
|
+
return result ?? []
|
|
1113
|
+
}),
|
|
1114
|
+
)
|
|
1126
1115
|
|
|
1127
|
-
|
|
1116
|
+
const schemaResults = await Promise.all(schemaTasks)
|
|
1117
|
+
return schemaResults.flat() as unknown as KubbFile.File<TFileMeta>
|
|
1118
|
+
}),
|
|
1119
|
+
)
|
|
1128
1120
|
|
|
1129
|
-
|
|
1130
|
-
return files.flat().filter(Boolean)
|
|
1131
|
-
}
|
|
1121
|
+
const nestedResults = await Promise.all(writeTasks)
|
|
1132
1122
|
|
|
1133
|
-
|
|
1134
|
-
* Schema
|
|
1135
|
-
*/
|
|
1136
|
-
async schema(_name: string, _object: SchemaObject, _options: TOptions): SchemaMethodResult<TFileMeta> {
|
|
1137
|
-
return []
|
|
1123
|
+
return nestedResults.flat()
|
|
1138
1124
|
}
|
|
1139
1125
|
}
|
package/src/generator.tsx
CHANGED
|
@@ -7,13 +7,11 @@ import { Oas } from './components/Oas.tsx'
|
|
|
7
7
|
import type { OperationGenerator } from './OperationGenerator.ts'
|
|
8
8
|
import type { SchemaGenerator, SchemaGeneratorOptions } from './SchemaGenerator.ts'
|
|
9
9
|
import type { Schema } from './SchemaMapper.ts'
|
|
10
|
-
import type { OperationsByMethod } from './types.ts'
|
|
11
10
|
|
|
12
11
|
type OperationsProps<TOptions extends PluginFactoryOptions> = {
|
|
13
12
|
instance: Omit<OperationGenerator<TOptions>, 'build'>
|
|
14
13
|
options: TOptions['resolvedOptions']
|
|
15
14
|
operations: Array<Operation>
|
|
16
|
-
operationsByMethod: OperationsByMethod
|
|
17
15
|
}
|
|
18
16
|
|
|
19
17
|
type OperationProps<TOptions extends PluginFactoryOptions> = {
|
|
@@ -62,7 +60,7 @@ export type ReactGeneratorOptions<TOptions extends PluginFactoryOptions> = {
|
|
|
62
60
|
export function createReactGenerator<TOptions extends PluginFactoryOptions>(parseOptions: ReactGeneratorOptions<TOptions>): Generator<TOptions> {
|
|
63
61
|
return {
|
|
64
62
|
...parseOptions,
|
|
65
|
-
async operations({ instance, options, operations
|
|
63
|
+
async operations({ instance, options, operations }) {
|
|
66
64
|
if (!parseOptions.Operations) {
|
|
67
65
|
return []
|
|
68
66
|
}
|
|
@@ -71,17 +69,15 @@ export function createReactGenerator<TOptions extends PluginFactoryOptions>(pars
|
|
|
71
69
|
const root = createRoot({
|
|
72
70
|
logger: pluginManager.logger,
|
|
73
71
|
})
|
|
74
|
-
|
|
75
72
|
const Component = parseOptions.Operations.bind(this)
|
|
76
73
|
|
|
77
74
|
root.render(
|
|
78
75
|
<App pluginManager={pluginManager} plugin={plugin} mode={mode}>
|
|
79
76
|
<Oas oas={oas} operations={operations} generator={instance}>
|
|
80
|
-
<Component operations={operations} instance={instance}
|
|
77
|
+
<Component operations={operations} instance={instance} options={options} />
|
|
81
78
|
</Oas>
|
|
82
79
|
</App>,
|
|
83
80
|
)
|
|
84
|
-
|
|
85
81
|
return root.files
|
|
86
82
|
},
|
|
87
83
|
async operation({ instance, operation, options }) {
|
|
@@ -93,7 +89,6 @@ export function createReactGenerator<TOptions extends PluginFactoryOptions>(pars
|
|
|
93
89
|
const root = createRoot({
|
|
94
90
|
logger: pluginManager.logger,
|
|
95
91
|
})
|
|
96
|
-
|
|
97
92
|
const Component = parseOptions.Operation.bind(this)
|
|
98
93
|
|
|
99
94
|
root.render(
|
|
@@ -105,7 +100,6 @@ export function createReactGenerator<TOptions extends PluginFactoryOptions>(pars
|
|
|
105
100
|
</Oas>
|
|
106
101
|
</App>,
|
|
107
102
|
)
|
|
108
|
-
|
|
109
103
|
return root.files
|
|
110
104
|
},
|
|
111
105
|
async schema({ instance, schema, options }) {
|
|
@@ -114,12 +108,11 @@ export function createReactGenerator<TOptions extends PluginFactoryOptions>(pars
|
|
|
114
108
|
}
|
|
115
109
|
|
|
116
110
|
const { pluginManager, oas, plugin, mode } = instance.context
|
|
111
|
+
|
|
112
|
+
const Component = parseOptions.Schema.bind(this)
|
|
117
113
|
const root = createRoot({
|
|
118
114
|
logger: pluginManager.logger,
|
|
119
115
|
})
|
|
120
|
-
|
|
121
|
-
const Component = parseOptions.Schema.bind(this)
|
|
122
|
-
|
|
123
116
|
root.render(
|
|
124
117
|
<App pluginManager={pluginManager} plugin={{ ...plugin, options }} mode={mode}>
|
|
125
118
|
<Oas oas={oas}>
|
|
@@ -129,7 +122,6 @@ export function createReactGenerator<TOptions extends PluginFactoryOptions>(pars
|
|
|
129
122
|
</Oas>
|
|
130
123
|
</App>,
|
|
131
124
|
)
|
|
132
|
-
|
|
133
125
|
return root.files
|
|
134
126
|
},
|
|
135
127
|
}
|
package/src/types.ts
CHANGED
|
@@ -122,7 +122,6 @@ export type OperationSchemas = {
|
|
|
122
122
|
errors?: Array<OperationSchema>
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
export type OperationsByMethod = Record<string, Record<HttpMethod, { operation: Operation; schemas: OperationSchemas }>>
|
|
126
125
|
type ByTag = {
|
|
127
126
|
type: 'tag'
|
|
128
127
|
pattern: string | RegExp
|