@pikku/openapi-parser 0.12.20 → 0.12.21
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/CHANGELOG.md +25 -0
- package/dist/auth-config.d.ts +3 -3
- package/package.json +8 -6
- package/src/auth-config.ts +0 -94
- package/src/codegen.test.ts +0 -973
- package/src/codegen.ts +0 -1670
- package/src/index.ts +0 -24
- package/src/naming.test.ts +0 -260
- package/src/naming.ts +0 -369
- package/src/openapi-to-zod-schema.test.ts +0 -664
- package/src/openapi-to-zod-schema.ts +0 -583
- package/src/parse-openapi.test.ts +0 -316
- package/src/parse-openapi.ts +0 -467
- package/src/zod-codegen.ts +0 -9
- package/tsconfig.json +0 -12
- package/tsconfig.tsbuildinfo +0 -1
package/src/parse-openapi.ts
DELETED
|
@@ -1,467 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Parses OpenAPI YAML/JSON specs, resolves $ref pointers, and produces a normalized IR.
|
|
3
|
-
*/
|
|
4
|
-
import { createHash } from 'crypto'
|
|
5
|
-
import { readFile } from 'fs/promises'
|
|
6
|
-
import { parse as parseYAML } from 'yaml'
|
|
7
|
-
|
|
8
|
-
import type { OpenAPISchema } from './zod-codegen.js'
|
|
9
|
-
|
|
10
|
-
export interface ErrorResponse {
|
|
11
|
-
statusCode: number
|
|
12
|
-
description: string
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export interface SecuritySchemeInfo {
|
|
16
|
-
type: 'oauth2' | 'http' | 'apiKey'
|
|
17
|
-
scheme?: string
|
|
18
|
-
bearerFormat?: string
|
|
19
|
-
name?: string
|
|
20
|
-
in?: string
|
|
21
|
-
flows?: {
|
|
22
|
-
authorizationUrl?: string
|
|
23
|
-
tokenUrl?: string
|
|
24
|
-
scopes?: Record<string, string>
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface ParsedSpec {
|
|
29
|
-
info: { title: string; version: string; description?: string }
|
|
30
|
-
baseUrl: string
|
|
31
|
-
serverUrls: string[]
|
|
32
|
-
authType: 'bearer' | 'oauth2' | 'apiKey' | 'none'
|
|
33
|
-
operations: ParsedOperation[]
|
|
34
|
-
componentSchemas: Record<string, OpenAPISchema>
|
|
35
|
-
securitySchemes: Record<string, SecuritySchemeInfo>
|
|
36
|
-
tagDescriptions: Record<string, string>
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export interface ParsedOperation {
|
|
40
|
-
operationId?: string
|
|
41
|
-
method: string
|
|
42
|
-
path: string
|
|
43
|
-
summary?: string
|
|
44
|
-
description?: string
|
|
45
|
-
tags: string[]
|
|
46
|
-
pathParams: ParsedParam[]
|
|
47
|
-
queryParams: ParsedParam[]
|
|
48
|
-
headerParams: ParsedParam[]
|
|
49
|
-
requestBody?: OpenAPISchema
|
|
50
|
-
requestBodyDescription?: string
|
|
51
|
-
requestBodyRequired?: boolean
|
|
52
|
-
responseSchema?: OpenAPISchema
|
|
53
|
-
responseDescription?: string
|
|
54
|
-
errorResponses: ErrorResponse[]
|
|
55
|
-
deprecated: boolean
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface ParsedParam {
|
|
59
|
-
name: string
|
|
60
|
-
required: boolean
|
|
61
|
-
schema: OpenAPISchema
|
|
62
|
-
description?: string
|
|
63
|
-
example?: unknown
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Read and parse an OpenAPI spec from a file path.
|
|
68
|
-
* Supports both YAML (.yaml, .yml) and JSON (.json) files.
|
|
69
|
-
*/
|
|
70
|
-
export async function parseOpenAPISpec(filePath: string): Promise<ParsedSpec> {
|
|
71
|
-
const content = await readFile(filePath, 'utf-8')
|
|
72
|
-
|
|
73
|
-
let doc: any
|
|
74
|
-
if (filePath.endsWith('.json')) {
|
|
75
|
-
doc = JSON.parse(content)
|
|
76
|
-
} else {
|
|
77
|
-
doc = parseYAML(content)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Validate spec version
|
|
81
|
-
const specVersion = doc.openapi ?? doc.swagger
|
|
82
|
-
if (!specVersion) {
|
|
83
|
-
throw new Error(
|
|
84
|
-
'Not a valid OpenAPI/Swagger spec: missing "openapi" or "swagger" version field.'
|
|
85
|
-
)
|
|
86
|
-
}
|
|
87
|
-
const major = String(specVersion).split('.')[0]
|
|
88
|
-
if (major !== '2' && major !== '3') {
|
|
89
|
-
throw new Error(
|
|
90
|
-
`Unsupported spec version "${specVersion}". Only OpenAPI 3.x and Swagger 2.x are supported.`
|
|
91
|
-
)
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// Resolve all $ref pointers in-place
|
|
95
|
-
resolveRefs(doc, doc)
|
|
96
|
-
|
|
97
|
-
const info = {
|
|
98
|
-
title: doc.info?.title ?? 'Unknown API',
|
|
99
|
-
version: doc.info?.version ?? '1.0.0',
|
|
100
|
-
description: doc.info?.description,
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const serverUrls = extractServerUrls(doc)
|
|
104
|
-
const baseUrl = serverUrls[0] ?? ''
|
|
105
|
-
const authType = detectAuthType(doc)
|
|
106
|
-
const securitySchemes = extractSecuritySchemes(doc)
|
|
107
|
-
const tagDescriptions = extractTagDescriptions(doc)
|
|
108
|
-
|
|
109
|
-
// Extract component schemas (OpenAPI 3.x: components.schemas, Swagger 2.x: definitions)
|
|
110
|
-
const componentSchemas: Record<string, OpenAPISchema> = {}
|
|
111
|
-
const rawSchemas = doc.components?.schemas ?? doc.definitions ?? {}
|
|
112
|
-
for (const [name, schema] of Object.entries(rawSchemas)) {
|
|
113
|
-
componentSchemas[name] = schema as OpenAPISchema
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Extract operations (skip deprecated)
|
|
117
|
-
const operations: ParsedOperation[] = []
|
|
118
|
-
if (doc.paths) {
|
|
119
|
-
for (const [path, pathItem] of Object.entries(
|
|
120
|
-
doc.paths as Record<string, any>
|
|
121
|
-
)) {
|
|
122
|
-
// Shared parameters at the path level
|
|
123
|
-
const sharedParams: any[] = pathItem.parameters ?? []
|
|
124
|
-
|
|
125
|
-
for (const method of ['get', 'post', 'put', 'patch', 'delete'] as const) {
|
|
126
|
-
const op = pathItem[method]
|
|
127
|
-
if (!op) continue
|
|
128
|
-
|
|
129
|
-
// Skip deprecated operations
|
|
130
|
-
if (op.deprecated === true) continue
|
|
131
|
-
|
|
132
|
-
const allParams: any[] = [...sharedParams, ...(op.parameters ?? [])]
|
|
133
|
-
|
|
134
|
-
// OpenAPI 3.x: op.requestBody, Swagger 2.x: parameters[].in === 'body'
|
|
135
|
-
const body3 = op.requestBody
|
|
136
|
-
const body2 = allParams.find((p: any) => p.in === 'body')
|
|
137
|
-
|
|
138
|
-
operations.push({
|
|
139
|
-
operationId: op.operationId,
|
|
140
|
-
method,
|
|
141
|
-
path,
|
|
142
|
-
summary: op.summary,
|
|
143
|
-
description: op.description,
|
|
144
|
-
tags: op.tags ?? [],
|
|
145
|
-
pathParams: extractParams(allParams, 'path'),
|
|
146
|
-
queryParams: extractParams(allParams, 'query'),
|
|
147
|
-
headerParams: extractParams(allParams, 'header'),
|
|
148
|
-
requestBody: extractRequestBody(op),
|
|
149
|
-
requestBodyDescription: body3?.description ?? body2?.description,
|
|
150
|
-
requestBodyRequired: body3?.required ?? body2?.required,
|
|
151
|
-
responseSchema: extractResponseSchema(op),
|
|
152
|
-
responseDescription: extractResponseDescription(op),
|
|
153
|
-
errorResponses: extractErrorResponses(op),
|
|
154
|
-
deprecated: false,
|
|
155
|
-
})
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
return {
|
|
161
|
-
info,
|
|
162
|
-
baseUrl,
|
|
163
|
-
serverUrls,
|
|
164
|
-
authType,
|
|
165
|
-
operations,
|
|
166
|
-
componentSchemas,
|
|
167
|
-
securitySchemes,
|
|
168
|
-
tagDescriptions,
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
/** Recursively resolve $ref pointers in-place, with cycle detection */
|
|
173
|
-
function resolveRefs(node: any, root: any, visited?: Set<any>): any {
|
|
174
|
-
if (node === null || typeof node !== 'object') return node
|
|
175
|
-
|
|
176
|
-
const seen = visited ?? new Set<any>()
|
|
177
|
-
if (seen.has(node)) return node
|
|
178
|
-
seen.add(node)
|
|
179
|
-
|
|
180
|
-
if (Array.isArray(node)) {
|
|
181
|
-
for (let i = 0; i < node.length; i++) {
|
|
182
|
-
node[i] = resolveRefs(node[i], root, seen)
|
|
183
|
-
}
|
|
184
|
-
return node
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
if (typeof node.$ref === 'string') {
|
|
188
|
-
const resolved = resolveRefPath(node.$ref, root)
|
|
189
|
-
if (resolved && typeof resolved === 'object') {
|
|
190
|
-
// Merge any sibling properties (like description overrides)
|
|
191
|
-
const { $ref, ...siblings } = node
|
|
192
|
-
const result = { ...resolved, ...siblings }
|
|
193
|
-
// Don't recurse into the merged result — it shares structure with
|
|
194
|
-
// the original resolved object and may be circular
|
|
195
|
-
return result
|
|
196
|
-
}
|
|
197
|
-
return node
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
for (const key of Object.keys(node)) {
|
|
201
|
-
node[key] = resolveRefs(node[key], root, seen)
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
return node
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function resolveRefPath(ref: string, root: any): any {
|
|
208
|
-
if (!ref.startsWith('#/')) return undefined
|
|
209
|
-
const parts = ref.slice(2).split('/')
|
|
210
|
-
let current = root
|
|
211
|
-
for (const part of parts) {
|
|
212
|
-
const decoded = part.replace(/~1/g, '/').replace(/~0/g, '~')
|
|
213
|
-
if (current == null || typeof current !== 'object') return undefined
|
|
214
|
-
current = current[decoded]
|
|
215
|
-
}
|
|
216
|
-
return current
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function extractServerUrls(doc: any): string[] {
|
|
220
|
-
// OpenAPI 3.x
|
|
221
|
-
if (doc.servers && doc.servers.length > 0) {
|
|
222
|
-
return doc.servers.map((s: any) => s.url).filter((url: string) => !!url)
|
|
223
|
-
}
|
|
224
|
-
// Swagger 2.x
|
|
225
|
-
if (doc.host) {
|
|
226
|
-
const schemes = doc.schemes?.length ? doc.schemes : ['https']
|
|
227
|
-
const basePath = doc.basePath ?? ''
|
|
228
|
-
return schemes.map((scheme: string) => `${scheme}://${doc.host}${basePath}`)
|
|
229
|
-
}
|
|
230
|
-
return []
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
function detectAuthType(doc: any): 'bearer' | 'oauth2' | 'apiKey' | 'none' {
|
|
234
|
-
const securitySchemes =
|
|
235
|
-
doc.components?.securitySchemes ?? doc.securityDefinitions ?? {}
|
|
236
|
-
|
|
237
|
-
for (const scheme of Object.values(securitySchemes) as any[]) {
|
|
238
|
-
if (scheme.type === 'oauth2') return 'oauth2'
|
|
239
|
-
if (scheme.type === 'http' && scheme.scheme === 'bearer') return 'bearer'
|
|
240
|
-
if (scheme.type === 'apiKey') return 'apiKey'
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
return 'none'
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Build an OpenAPI schema object from v2-style parameter-level properties
|
|
248
|
-
* (type, enum, items, format, default) that aren't nested under `schema`.
|
|
249
|
-
*/
|
|
250
|
-
function paramToSchema(p: any): OpenAPISchema {
|
|
251
|
-
const schema: any = { type: p.type ?? 'string' }
|
|
252
|
-
if (p.enum) schema.enum = p.enum
|
|
253
|
-
if (p.items) schema.items = p.items
|
|
254
|
-
if (p.format) schema.format = p.format
|
|
255
|
-
if (p.default !== undefined) schema.default = p.default
|
|
256
|
-
return schema
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function extractParams(
|
|
260
|
-
params: any[],
|
|
261
|
-
location: 'path' | 'query' | 'header'
|
|
262
|
-
): ParsedParam[] {
|
|
263
|
-
return params
|
|
264
|
-
.filter((p) => p.in === location)
|
|
265
|
-
.map((p) => ({
|
|
266
|
-
name: p.name,
|
|
267
|
-
required: p.required ?? location === 'path',
|
|
268
|
-
schema: (p.schema ?? paramToSchema(p)) as OpenAPISchema,
|
|
269
|
-
description: p.description,
|
|
270
|
-
example: p.example,
|
|
271
|
-
}))
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
function extractRequestBody(op: any): OpenAPISchema | undefined {
|
|
275
|
-
// OpenAPI 3.x: op.requestBody.content['application/json'].schema
|
|
276
|
-
const body = op.requestBody
|
|
277
|
-
if (body) {
|
|
278
|
-
const content = body.content
|
|
279
|
-
if (content) {
|
|
280
|
-
const jsonContent = content['application/json']
|
|
281
|
-
if (jsonContent?.schema) return jsonContent.schema as OpenAPISchema
|
|
282
|
-
|
|
283
|
-
const firstKey = Object.keys(content)[0]
|
|
284
|
-
if (firstKey && content[firstKey]?.schema) {
|
|
285
|
-
return content[firstKey].schema as OpenAPISchema
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Swagger 2.x: parameters[].in === 'body' → schema
|
|
291
|
-
if (op.parameters) {
|
|
292
|
-
const bodyParam = op.parameters.find((p: any) => p.in === 'body')
|
|
293
|
-
if (bodyParam?.schema) return bodyParam.schema as OpenAPISchema
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
return undefined
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
function extractResponseDescription(op: any): string | undefined {
|
|
300
|
-
const responses = op.responses
|
|
301
|
-
if (!responses) return undefined
|
|
302
|
-
for (const code of ['200', '201', '202']) {
|
|
303
|
-
const resp = responses[code]
|
|
304
|
-
if (resp?.description) return resp.description
|
|
305
|
-
}
|
|
306
|
-
return undefined
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
function extractResponseSchema(op: any): OpenAPISchema | undefined {
|
|
310
|
-
const responses = op.responses
|
|
311
|
-
if (!responses) return undefined
|
|
312
|
-
|
|
313
|
-
// Look for 2xx responses in order of preference
|
|
314
|
-
for (const code of ['200', '201', '202', '204']) {
|
|
315
|
-
const resp = responses[code]
|
|
316
|
-
if (!resp) continue
|
|
317
|
-
|
|
318
|
-
// OpenAPI 3.x: resp.content['application/json'].schema
|
|
319
|
-
const content = resp.content
|
|
320
|
-
if (content) {
|
|
321
|
-
const jsonContent = content['application/json']
|
|
322
|
-
if (jsonContent?.schema) return jsonContent.schema as OpenAPISchema
|
|
323
|
-
|
|
324
|
-
const firstKey = Object.keys(content)[0]
|
|
325
|
-
if (firstKey && content[firstKey]?.schema) {
|
|
326
|
-
return content[firstKey].schema as OpenAPISchema
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// Swagger 2.x: resp.schema directly
|
|
331
|
-
if (resp.schema) return resp.schema as OpenAPISchema
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
// Fallback: any 2xx
|
|
335
|
-
for (const [code, resp] of Object.entries(responses) as [string, any][]) {
|
|
336
|
-
if (!code.startsWith('2')) continue
|
|
337
|
-
if (resp.content) {
|
|
338
|
-
const jsonContent = resp.content['application/json']
|
|
339
|
-
if (jsonContent?.schema) return jsonContent.schema as OpenAPISchema
|
|
340
|
-
}
|
|
341
|
-
if (resp.schema) return resp.schema as OpenAPISchema
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
return undefined
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function extractErrorResponses(op: any): ErrorResponse[] {
|
|
348
|
-
const responses = op.responses
|
|
349
|
-
if (!responses) return []
|
|
350
|
-
|
|
351
|
-
const errors: ErrorResponse[] = []
|
|
352
|
-
for (const [code, resp] of Object.entries(responses) as [string, any][]) {
|
|
353
|
-
const statusCode = parseInt(code, 10)
|
|
354
|
-
if (isNaN(statusCode)) continue
|
|
355
|
-
if (statusCode >= 400) {
|
|
356
|
-
errors.push({
|
|
357
|
-
statusCode,
|
|
358
|
-
description: resp.description ?? `Error ${statusCode}`,
|
|
359
|
-
})
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
return errors
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
function extractSecuritySchemes(doc: any): Record<string, SecuritySchemeInfo> {
|
|
366
|
-
const raw = doc.components?.securitySchemes ?? doc.securityDefinitions ?? {}
|
|
367
|
-
const result: Record<string, SecuritySchemeInfo> = {}
|
|
368
|
-
|
|
369
|
-
for (const [name, scheme] of Object.entries(raw) as [string, any][]) {
|
|
370
|
-
const info: SecuritySchemeInfo = {
|
|
371
|
-
type: scheme.type === 'http' ? 'http' : scheme.type,
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
if (scheme.type === 'http') {
|
|
375
|
-
info.scheme = scheme.scheme
|
|
376
|
-
info.bearerFormat = scheme.bearerFormat
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if (scheme.type === 'apiKey') {
|
|
380
|
-
info.name = scheme.name
|
|
381
|
-
info.in = scheme.in
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
if (scheme.type === 'oauth2') {
|
|
385
|
-
// Extract flows — prefer authorizationCode, then implicit, then clientCredentials
|
|
386
|
-
const flows = scheme.flows ?? {}
|
|
387
|
-
const flow =
|
|
388
|
-
flows.authorizationCode ??
|
|
389
|
-
flows.implicit ??
|
|
390
|
-
flows.clientCredentials ??
|
|
391
|
-
flows.password
|
|
392
|
-
|
|
393
|
-
if (flow) {
|
|
394
|
-
info.flows = {
|
|
395
|
-
authorizationUrl: flow.authorizationUrl,
|
|
396
|
-
tokenUrl: flow.tokenUrl,
|
|
397
|
-
scopes: flow.scopes,
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
result[name] = info
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
return result
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
/**
|
|
409
|
-
* Compute a SHA-256 hash of the contract-relevant parts of a parsed spec.
|
|
410
|
-
* Excludes presentation fields (summary, description, tags, operationId)
|
|
411
|
-
* so that only structural API changes produce a different hash.
|
|
412
|
-
*/
|
|
413
|
-
export function computeContractHash(spec: ParsedSpec): string {
|
|
414
|
-
const contract = {
|
|
415
|
-
operations: spec.operations.map((op) => ({
|
|
416
|
-
method: op.method,
|
|
417
|
-
path: op.path,
|
|
418
|
-
pathParams: op.pathParams.map((p) => ({
|
|
419
|
-
name: p.name,
|
|
420
|
-
required: p.required,
|
|
421
|
-
schema: p.schema,
|
|
422
|
-
})),
|
|
423
|
-
queryParams: op.queryParams.map((p) => ({
|
|
424
|
-
name: p.name,
|
|
425
|
-
required: p.required,
|
|
426
|
-
schema: p.schema,
|
|
427
|
-
})),
|
|
428
|
-
headerParams: op.headerParams.map((p) => ({
|
|
429
|
-
name: p.name,
|
|
430
|
-
required: p.required,
|
|
431
|
-
schema: p.schema,
|
|
432
|
-
})),
|
|
433
|
-
requestBody: op.requestBody,
|
|
434
|
-
requestBodyRequired: op.requestBodyRequired,
|
|
435
|
-
responseSchema: op.responseSchema,
|
|
436
|
-
errorResponses: op.errorResponses,
|
|
437
|
-
})),
|
|
438
|
-
componentSchemas: spec.componentSchemas,
|
|
439
|
-
securitySchemes: spec.securitySchemes,
|
|
440
|
-
serverUrls: spec.serverUrls,
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
// Use a cycle-safe JSON serializer since resolved $ref schemas
|
|
444
|
-
// can contain circular object references
|
|
445
|
-
const seen = new WeakSet()
|
|
446
|
-
const json = JSON.stringify(contract, (_key, value) => {
|
|
447
|
-
if (typeof value === 'object' && value !== null) {
|
|
448
|
-
if (seen.has(value)) return '[Circular]'
|
|
449
|
-
seen.add(value)
|
|
450
|
-
}
|
|
451
|
-
return value
|
|
452
|
-
})
|
|
453
|
-
|
|
454
|
-
return createHash('sha256').update(json).digest('hex').slice(0, 16)
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
function extractTagDescriptions(doc: any): Record<string, string> {
|
|
458
|
-
const result: Record<string, string> = {}
|
|
459
|
-
if (Array.isArray(doc.tags)) {
|
|
460
|
-
for (const tag of doc.tags) {
|
|
461
|
-
if (tag.name && tag.description) {
|
|
462
|
-
result[tag.name] = tag.description
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
return result
|
|
467
|
-
}
|
package/src/zod-codegen.ts
DELETED
package/tsconfig.json
DELETED
package/tsconfig.tsbuildinfo
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"root":["./src/auth-config.ts","./src/codegen.ts","./src/index.ts","./src/naming.ts","./src/openapi-to-zod-schema.ts","./src/parse-openapi.ts","./src/zod-codegen.ts"],"version":"6.0.3"}
|