@sebspark/openapi-typegen 5.0.5 → 5.0.7

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/index.js DELETED
@@ -1,1087 +0,0 @@
1
- // src/index.ts
2
- import { mkdir, readdir, readFile, stat, writeFile } from "fs/promises";
3
- import { parse, resolve } from "path";
4
- import { pascalCase as pascalCase2 } from "change-case";
5
- import * as YAML from "yaml";
6
-
7
- // src/generator/formatter.ts
8
- import { format as pFormat } from "prettier";
9
- var options = {
10
- parser: "typescript",
11
- singleQuote: true,
12
- semi: false,
13
- trailingComma: "all"
14
- };
15
- var format = async (code) => pFormat(code, options);
16
-
17
- // src/generator/common.ts
18
- import { constantCase, pascalCase } from "change-case";
19
-
20
- // src/generator/document.ts
21
- var document = ({ title, description }) => {
22
- if (title || description) {
23
- const tokens = [];
24
- tokens.push("/**");
25
- if (title) tokens.push(` * ${title}`);
26
- if (description) tokens.push(` * ${description}`);
27
- tokens.push(" */\n");
28
- return tokens.join("\n");
29
- }
30
- return "";
31
- };
32
- var documentClientPath = (path, responses) => documentPath(
33
- path,
34
- responses,
35
- [param("url", "string")],
36
- [param("opts", "RequestOptions", true)]
37
- );
38
- var documentServerPath = (path, responses) => documentPath(path, responses);
39
- var documentPath = (path, responses, argsBefore = [], argsAfter = []) => {
40
- const tokens = [];
41
- tokens.push("/**");
42
- if (path.title) tokens.push(` * ${path.title}`);
43
- if (path.description) tokens.push(` * ${path.description}`);
44
- tokens.push(" *");
45
- tokens.push(...argsBefore);
46
- if (path.args) tokens.push(...documentArgs(path.args));
47
- tokens.push(...argsAfter);
48
- tokens.push(` * @returns {Promise<${responses}>}`);
49
- tokens.push(" */");
50
- return tokens.join("\n");
51
- };
52
- var documentArgs = (args) => {
53
- const tokens = [];
54
- tokens.push(
55
- param(
56
- "args",
57
- "Object",
58
- argsOptional(args),
59
- "The arguments for the request."
60
- )
61
- );
62
- tokens.push(...requestArgs(args.path, "params", "Path parameters"));
63
- tokens.push(...requestArgs(args.query, "query", "Query parameters"));
64
- tokens.push(...requestArgs(args.header, "headers", "Headers"));
65
- tokens.push(...requestArgs(args.body, "body", "Request body"));
66
- return tokens;
67
- };
68
- var buildPath = (path, property) => rxProperVariable.test(property) ? `${path}.${property}` : `${path}["${property}"]`;
69
- var requestArgs = (args, name, title) => {
70
- if (!args) return [];
71
- const tokens = [];
72
- const type = (args.allOf || []).map((e) => e.type).join(AND) || "Object";
73
- tokens.push(
74
- param(
75
- buildPath("args", name),
76
- type,
77
- args.optional,
78
- `${title} for the request.`
79
- )
80
- );
81
- const properties = args.properties.flatMap(
82
- (prop) => requestProperty(buildPath("args", name), prop)
83
- );
84
- tokens.push(...properties);
85
- return tokens;
86
- };
87
- var requestProperty = (path, property) => {
88
- const tokens = [];
89
- const type = property.type.map((t) => t.type).join(OR);
90
- tokens.push(
91
- param(
92
- buildPath(path, property.name),
93
- type,
94
- property.optional,
95
- property.title,
96
- property.description
97
- )
98
- );
99
- return tokens;
100
- };
101
- var param = (name, type, optional = false, title = "", description = "") => {
102
- const tokens = [];
103
- tokens.push(
104
- ` * @param {${type}} ${optional ? "[" : ""}${name}${optional ? "]" : ""}`
105
- );
106
- if (optional || title || description) {
107
- tokens.push(" -");
108
- if (optional) tokens.push(" Optional.");
109
- if (title) tokens.push(` ${title}`);
110
- if (description) tokens.push(` ${description}`);
111
- }
112
- return tokens.join("");
113
- };
114
-
115
- // src/generator/common.ts
116
- var OR = " | ";
117
- var AND = " & ";
118
- var generateType = (parsed) => {
119
- let type;
120
- switch (parsed.type) {
121
- case "enum": {
122
- type = generateEnum(parsed);
123
- break;
124
- }
125
- case "array": {
126
- type = generateArray(parsed);
127
- break;
128
- }
129
- case "object": {
130
- type = generateObject(parsed);
131
- break;
132
- }
133
- case "record": {
134
- type = generateRecord(parsed);
135
- break;
136
- }
137
- case "unknown": {
138
- type = generateUnknown(parsed);
139
- break;
140
- }
141
- case "Date":
142
- case "bigint":
143
- case "boolean":
144
- case "null":
145
- case "number":
146
- case "string":
147
- case "symbol":
148
- case "undefined":
149
- type = generatePrimitive(parsed);
150
- break;
151
- default: {
152
- type = generateCustom(parsed);
153
- }
154
- }
155
- return type.replace(/ [&|] \{\s*\}/g, "");
156
- };
157
- var generateProperty = (property) => {
158
- const types = property.type.map(generateType);
159
- return `${document(property)}${propertyName(property.name)}${property.optional ? "?" : ""}: ${types.join(OR) || "unknown"}`;
160
- };
161
- var preamble = (type) => type.name ? `${document(type)}export type ${typeName(type.name)} = ` : "";
162
- var rxProperVariable = /^[a-zA-Z_<>$][a-zA-Z0-9_<>$]*$/;
163
- var isValidName = (name) => {
164
- const namingConventionRegex = /^([A-Z_]\w*)([a-z_]\w*)(<([a-z_]\w*(,\s*)?)+>)?$/;
165
- const hasCapitalLetterRegex = /[A-Z]/;
166
- if (!namingConventionRegex.test(name)) return false;
167
- if (!hasCapitalLetterRegex.test(name)) {
168
- return false;
169
- }
170
- if (name[0] !== name[0].toUpperCase() && !name.includes("_")) {
171
- return false;
172
- }
173
- return true;
174
- };
175
- var typeName = (name) => {
176
- if (isValidName(name)) {
177
- return name;
178
- }
179
- if (name.includes("<")) {
180
- return name.replace(
181
- /<([^>]+)>/,
182
- (_match, genericContent) => `<${typeName(genericContent)}>`
183
- );
184
- }
185
- const domainStyleTransformed = name.split(".").map((part, index, array) => {
186
- if (index === array.length - 1) {
187
- return pascalCase(part);
188
- }
189
- return part;
190
- }).join("_");
191
- const prefixedIfNumberStart = domainStyleTransformed.match(/^\d/) ? `_${domainStyleTransformed}` : domainStyleTransformed;
192
- const finalName = prefixedIfNumberStart.includes("_") ? prefixedIfNumberStart : pascalCase(prefixedIfNumberStart);
193
- if (finalName.includes("_")) {
194
- const lastUnderscoreIndex = finalName.lastIndexOf("_");
195
- if (lastUnderscoreIndex !== -1 && lastUnderscoreIndex < finalName.length - 1) {
196
- return finalName.substring(0, lastUnderscoreIndex + 1) + finalName.charAt(lastUnderscoreIndex + 1).toUpperCase() + finalName.slice(lastUnderscoreIndex + 2);
197
- }
198
- return finalName;
199
- }
200
- return finalName.charAt(0).toUpperCase() + finalName.slice(1);
201
- };
202
- var propertyName = (name) => {
203
- if (rxProperVariable.test(name.replace(/\./g, "_")))
204
- return name.replace(/\./g, "_");
205
- return `'${name.replace(/\./g, "_")}'`;
206
- };
207
- var extensions = (type) => (type.allOf || []).map(generateType).concat("").join(AND) + (type.oneOf || []).map(generateType).concat("").join(OR);
208
- var generatePrimitive = (parsed) => `${preamble(parsed)}${parsed.type}`;
209
- var generateCustom = (parsed) => `${preamble(parsed)}${typeName(parsed.type)}`;
210
- var generateUnknown = (parsed) => `${preamble(parsed)}unknown`;
211
- var generateObject = (parsed) => {
212
- const lines = [];
213
- lines.push(`${preamble(parsed)}${extensions(parsed)}{`);
214
- lines.push(...parsed.properties.map(generateProperty));
215
- lines.push("}");
216
- if (parsed.discriminator && parsed.name) {
217
- lines.push(generateDiscriminator(parsed.discriminator, parsed.name));
218
- }
219
- return lines.join("\n");
220
- };
221
- var generateRecord = (parsed) => {
222
- const itemType = parsed.items.type === "undefined" ? "unknown" : generateType(parsed.items);
223
- return `Record<string, ${itemType}>`;
224
- };
225
- var generateDiscriminator = (discriminator, name) => {
226
- const lines = [""];
227
- lines.push(`export type ${name}Discriminator = {`);
228
- for (const [key, type] of Object.entries(discriminator.mapping)) {
229
- lines.push(`${key}: ${type.type}`);
230
- }
231
- lines.push("}");
232
- return lines.join("\n");
233
- };
234
- var generateArray = (parsed) => {
235
- const lines = [];
236
- let items = generateType(parsed.items);
237
- if (parsed.items.type === "enum" || "oneOf" in parsed.items) {
238
- items = `(${items})`;
239
- }
240
- lines.push(`${preamble(parsed)}${items}[]`);
241
- return lines.join("\n");
242
- };
243
- var generateEnum = (parsed) => {
244
- if (parsed.name) {
245
- const values = parsed.values.map(serializeValue).join(", ");
246
- const valuesName = constantCase(`${parsed.name}_VALUES`);
247
- return [
248
- `export const ${valuesName} = [${values}] as const`,
249
- `${preamble(parsed)}typeof ${valuesName}[number]`
250
- ].join("\n");
251
- }
252
- return `${preamble(parsed)}${parsed.values.map(serializeValue).join(OR)}`;
253
- };
254
- var generateHeader = (header) => {
255
- return `${preamble(header)}{ ${propertyName(header.name)}${header.optional ? "?" : ""}: ${generateType(header.type)} }`;
256
- };
257
- var generateResponseBody = (type, optional = true) => {
258
- const customType = type.type;
259
- if (customType) return typeName(customType);
260
- const body = type;
261
- if (!body.data && !body.headers) return "undefined";
262
- const tokens = [];
263
- tokens.push(preamble(body));
264
- tokens.push("APIResponse<");
265
- tokens.push(
266
- body.data ? generateType(serialized(body.data, optional)) : "undefined"
267
- );
268
- if (body.headers) {
269
- tokens.push(", ");
270
- tokens.push(body.headers ? generateHeaders(body.headers) : "undefined");
271
- }
272
- tokens.push(">");
273
- return tokens.join("");
274
- };
275
- var serialized = (orig, optional = true) => {
276
- switch (orig.type) {
277
- case "bigint":
278
- case "boolean":
279
- case "enum":
280
- case "null":
281
- case "number":
282
- case "string":
283
- case "symbol":
284
- case "undefined": {
285
- return orig;
286
- }
287
- case "Date": {
288
- return { ...orig, type: "string" };
289
- }
290
- case "array": {
291
- return {
292
- ...orig,
293
- items: serialized(orig.items, optional)
294
- };
295
- }
296
- case "object": {
297
- return orig;
298
- }
299
- default: {
300
- const wrapper = optional ? "PartiallySerialized" : "Serialized";
301
- return { ...orig, type: `${wrapper}<${typeName(orig.type)}>` };
302
- }
303
- }
304
- };
305
- var generateHeaders = (headers) => {
306
- const tokens = [];
307
- for (const header of headers) {
308
- tokens.push(
309
- `${propertyName(header.name)}${header.optional ? "?" : ""}: ${generateType(header.type)}`
310
- );
311
- }
312
- return `{${tokens.join(", ")}}`;
313
- };
314
- var serializeValue = (value) => {
315
- if (typeof value === "string") return `'${value}'`;
316
- return value;
317
- };
318
-
319
- // src/generator/args.ts
320
- var generateClientArgs = (args) => generateArgs(args, false);
321
- var generateServerArgs = (args) => args ? generateArgs(args, true) : "args: Req";
322
- var parts = ["body", "header", "path", "query"];
323
- var generateArgs = (args, isServer) => {
324
- if (args) {
325
- const tokens = [];
326
- for (const part of parts) {
327
- const arg = args[part];
328
- if (arg) {
329
- const partName = part === "path" ? "params" : part === "header" ? "headers" : part;
330
- if (partName === "query" && isServer) {
331
- tokens.push(
332
- `${partName}${arg.optional ? "?" : ""}: QueryParams<${generateType(arg)}>`
333
- );
334
- } else {
335
- tokens.push(
336
- `${partName}${arg.optional ? "?" : ""}: ${wrapArgs(
337
- generateType(arg),
338
- isServer && part === "header"
339
- )}`
340
- );
341
- }
342
- }
343
- }
344
- if (!tokens.length) return "";
345
- const optional = argsOptional(args);
346
- return `args${optional ? "?" : ""}: ${isServer ? "Req & " : ""}{ ${tokens.join(", ")} }, `;
347
- }
348
- return "";
349
- };
350
- var wrapArgs = (args, wrap) => {
351
- if (!wrap) return args;
352
- return `LowerCaseHeaders<${args}>`;
353
- };
354
- var argsOptional = (args) => (
355
- // biome-ignore lint/style/noNonNullAssertion: will never be null
356
- parts.reduce((o, p) => o && (!args[p] || args[p].optional), true)
357
- );
358
-
359
- // src/generator/client.ts
360
- var generateClient = (name, paths) => {
361
- const groupedCalls = {};
362
- for (const path of paths) {
363
- if (!groupedCalls[path.method]) {
364
- groupedCalls[path.method] = [];
365
- }
366
- groupedCalls[path.method]?.push(generateCall(path));
367
- }
368
- const client = [];
369
- const methods = Object.keys(groupedCalls).map(serializeValue).join(OR);
370
- client.push(`export type ${name}Client = Pick<BaseClient, ${methods}> & {`);
371
- Object.entries(groupedCalls).forEach(([method, calls]) => {
372
- client.push(`${method}: {`);
373
- client.push(...calls);
374
- client.push("}");
375
- });
376
- client.push("}");
377
- return client.join("\n");
378
- };
379
- var generateCall = (path) => {
380
- const responses = generateResponses(path);
381
- return `${documentClientPath(path, responses)}
382
- (
383
- url: '${path.url}', ${generateClientArgs(path.args)}opts?: RequestOptions,
384
- ): Promise<${responses}>`;
385
- };
386
- var generateResponses = (path) => Object.entries(path.responses).filter(([code]) => Number.parseInt(code, 10) < 400).map(([, type]) => generateResponseBody(type, false)).join(OR);
387
-
388
- // src/generator/server.ts
389
- var generateServer = (name, paths) => {
390
- const tokens = [];
391
- tokens.push(`export type ${name}ServerPaths = {`);
392
- for (const [url, methods] of Object.entries(groupPathsByUrl(paths))) {
393
- tokens.push(generatePath(url, methods));
394
- }
395
- tokens.push("}");
396
- tokens.push("\n");
397
- tokens.push(
398
- `export type ${name}Server = APIServerDefinition & ${name}ServerPaths`
399
- );
400
- return tokens.join("\n");
401
- };
402
- var groupPathsByUrl = (paths) => paths.reduce(
403
- (group, path) => {
404
- if (!group[path.url]) group[path.url] = [];
405
- group[path.url].push(path);
406
- return group;
407
- },
408
- {}
409
- );
410
- var generatePath = (url, methods) => `'${url}': {
411
- ${methods.map(generateMethod).join("\n")}
412
- }`;
413
- var generateMethod = (path) => {
414
- const responses = generateResponses2(path.responses);
415
- return `${path.method}: {
416
- ${documentServerPath(path, responses)}
417
- handler: (${generateServerArgs(path.args)}) => Promise<${responses}>
418
- pre?: GenericRouteHandler | GenericRouteHandler[]
419
- }`;
420
- };
421
- var generateResponses2 = (responses) => Object.entries(responses).filter(([code]) => Number.parseInt(code, 10) < 500).map(
422
- ([code, response]) => generateResponse(Number.parseInt(code, 10), response)
423
- ).join(OR);
424
- var generateResponse = (code, response) => `[${code}, ${generateResponseBody(response)}]`;
425
-
426
- // src/generator/generator.ts
427
- var generate = (name, doc) => `
428
- /**
429
- * This file was auto-generated.
430
- * Do not make direct changes to the file.
431
- */
432
-
433
- import type {
434
- APIResponse,
435
- APIServerDefinition,
436
- BaseClient,
437
- ExpressRequest,
438
- GenericRouteHandler,
439
- LowerCaseHeaders,
440
- PartiallySerialized,
441
- QueryParams,
442
- RequestOptions,
443
- Serialized,
444
- } from '@sebspark/openapi-core'
445
-
446
- type Req = Pick<ExpressRequest, 'url' | 'baseUrl' | 'cookies' | 'hostname'>
447
-
448
- /* tslint:disable */
449
- /* eslint-disable */
450
-
451
- ${generateComponents(doc.components)}
452
-
453
- ${doc.paths.length ? generateServer(name, doc.paths) : ""}
454
-
455
- ${doc.paths.length ? generateClient(name, doc.paths) : ""}
456
-
457
- `;
458
- var generateComponents = (components) => {
459
- const tokens = [];
460
- for (const schema of components.schemas) {
461
- tokens.push(generateType(schema));
462
- }
463
- for (const header of components.headers) {
464
- tokens.push(generateHeader(header));
465
- }
466
- for (const param2 of components.parameters) {
467
- tokens.push(
468
- generateType({
469
- type: "object",
470
- name: param2.name,
471
- properties: [
472
- {
473
- name: param2.parameterName,
474
- type: [param2.type],
475
- optional: param2.optional
476
- }
477
- ]
478
- })
479
- );
480
- }
481
- for (const req of components.requestBodies) {
482
- tokens.push(generateType(req));
483
- }
484
- for (const res of components.responseBodies) {
485
- tokens.push(generateResponseBody(res));
486
- }
487
- for (const param2 of components.securitySchemes) {
488
- tokens.push(
489
- generateType({
490
- type: "object",
491
- name: param2.name,
492
- properties: [
493
- {
494
- name: param2.parameterName,
495
- type: [param2.type],
496
- optional: param2.optional
497
- }
498
- ]
499
- })
500
- );
501
- }
502
- return tokens.join("\n\n");
503
- };
504
-
505
- // src/parser/common.ts
506
- var parseRef = (ref) => ref.substring(ref.lastIndexOf("/") + 1);
507
- var parseEnumType = (name, schema) => ({ name, type: "enum", values: schema.enum || [] });
508
- var findRef = (components, ref) => {
509
- const [, , path, name] = ref.split("/");
510
- const schemaPath = components[path];
511
- if (!schemaPath || !schemaPath[name])
512
- throw new Error(`Cannot find ref ${ref}`);
513
- return schemaPath[name];
514
- };
515
- var parseDocumentation = (source) => {
516
- const documented = {};
517
- if (source.title) documented.title = source.title;
518
- if (source.description) documented.description = source.description;
519
- return documented;
520
- };
521
-
522
- // src/parser/schema.ts
523
- var parseSchemas = (schemas = {}) => Object.entries(schemas || {}).map(
524
- ([name, schema]) => parseSchema(name, schema)
525
- );
526
- var marshall = (type, format2) => {
527
- if (type === "integer") {
528
- return "number";
529
- }
530
- if (type === "string" && (format2 === "date" || format2 === "date-time")) {
531
- return "Date";
532
- }
533
- return type;
534
- };
535
- var parseSchema = (name, schemaOrRef, generateDocs2 = true) => {
536
- const ref = schemaOrRef.$ref;
537
- if (ref) {
538
- return { name, type: parseRef(ref) };
539
- }
540
- const schema = schemaOrRef;
541
- switch (schema.type) {
542
- case "array":
543
- return parseArraySchema(name, schema);
544
- case "boolean":
545
- case "integer":
546
- case "number":
547
- case "string":
548
- return schema.enum ? parseEnumType(name, schema) : name ? { name, type: marshall(schema.type, schema.format) } : parsePropertyType(schema, generateDocs2)[0];
549
- default:
550
- return parseObjectSchema(name, schema);
551
- }
552
- };
553
- var parseObjectSchema = (name, schema) => {
554
- const type = {
555
- name,
556
- type: "object",
557
- properties: [],
558
- ...parseDocumentation(schema)
559
- };
560
- if (schema.properties) {
561
- type.properties = Object.entries(schema.properties).map(
562
- ([name2, property]) => parseProperty(name2, property, schema.required || [])
563
- );
564
- }
565
- if (schema.allOf) {
566
- type.allOf = schema.allOf.flatMap((s) => parsePropertyType(s));
567
- }
568
- if (schema.oneOf) {
569
- type.oneOf = schema.oneOf.flatMap((s) => parsePropertyType(s));
570
- }
571
- if (schema.anyOf) {
572
- type.oneOf = schema.anyOf.flatMap((s) => parsePropertyType(s));
573
- }
574
- if (schema.discriminator?.mapping) {
575
- const mapping = {};
576
- for (const [prop, ref] of Object.entries(schema.discriminator.mapping)) {
577
- mapping[prop] = { type: parseRef(ref) };
578
- }
579
- type.discriminator = {
580
- propertyName: schema.discriminator.propertyName,
581
- mapping
582
- };
583
- }
584
- if (schema.additionalProperties) {
585
- const record = parseAdditionalProperties(schema.additionalProperties);
586
- if (!type.allOf) {
587
- type.allOf = [];
588
- }
589
- type.allOf.push(record);
590
- }
591
- return type;
592
- };
593
- var parseAdditionalProperties = (schema) => {
594
- let items;
595
- if (schema === true) {
596
- items = { type: "undefined" };
597
- } else {
598
- items = parseSchema(void 0, schema);
599
- }
600
- return {
601
- type: "record",
602
- items
603
- };
604
- };
605
- var parseArraySchema = (name, schema) => {
606
- if (schema.type !== "array") throw new Error("Not an array");
607
- return {
608
- name,
609
- type: "array",
610
- items: schema.items ? parseSchema(void 0, schema.items, false) : { type: "unknown" },
611
- ...parseDocumentation(schema)
612
- };
613
- };
614
- var parseProperty = (name, schema, required) => {
615
- const property = {
616
- name,
617
- optional: !required.includes(name),
618
- type: parsePropertyType(schema),
619
- ...parseDocumentation(schema)
620
- };
621
- return property;
622
- };
623
- var parsePropertyType = (property, generateDocs2 = true) => {
624
- const ref = property.$ref;
625
- if (ref) {
626
- return [{ type: parseRef(ref) }];
627
- }
628
- const schemaObject = property;
629
- const docs = generateDocs2 ? parseDocumentation(schemaObject) : {};
630
- if (schemaObject.enum) {
631
- const enumType = {
632
- type: "enum",
633
- values: schemaObject.enum,
634
- ...docs
635
- };
636
- return [enumType];
637
- }
638
- if (schemaObject.type) {
639
- return (Array.isArray(schemaObject.type) ? schemaObject.type : [schemaObject.type]).map((type) => {
640
- switch (type) {
641
- case "array": {
642
- return parseArraySchema(void 0, schemaObject);
643
- }
644
- case "object": {
645
- return parseObjectSchema(void 0, schemaObject);
646
- }
647
- default: {
648
- return {
649
- type: marshall(type, schemaObject.format),
650
- ...docs
651
- };
652
- }
653
- }
654
- });
655
- }
656
- if (schemaObject.allOf) {
657
- const types = [];
658
- for (const allOf of schemaObject.allOf) {
659
- const type = parseSchema(void 0, allOf);
660
- delete type.name;
661
- types.push(type);
662
- }
663
- return types;
664
- }
665
- return [];
666
- };
667
-
668
- // src/parser/headers.ts
669
- var parseHeaders = (schemas = {}) => Object.entries(schemas || {}).map(
670
- ([name, schema]) => parseHeader(name, schema)
671
- );
672
- var parseHeader = (name, schema) => {
673
- const header = {
674
- name,
675
- optional: !schema.required,
676
- // biome-ignore lint/style/noNonNullAssertion: here it is always defined
677
- type: parseSchema(void 0, schema.schema),
678
- ...parseDocumentation(schema)
679
- };
680
- return header;
681
- };
682
-
683
- // src/parser/parameters.ts
684
- var parseParameters = (schemas = {}) => Object.entries(schemas || {}).map(
685
- ([name, schema]) => parseParameter(name, schema)
686
- );
687
- var parseParameter = (name, schema) => {
688
- const param2 = {
689
- name,
690
- in: schema.in,
691
- parameterName: schema.name,
692
- optional: !schema.required,
693
- // biome-ignore lint/style/noNonNullAssertion: schema is always defined here
694
- type: parseSchema(void 0, schema.schema),
695
- ...parseDocumentation(schema)
696
- };
697
- return param2;
698
- };
699
-
700
- // src/parser/args.ts
701
- var parseArgs = (path, components) => {
702
- if (!path.parameters?.length && !path.security?.length && !path.requestBody)
703
- return void 0;
704
- const args = joinArgs([
705
- parseParameters2(path.parameters, components),
706
- parseSecurity(path.security, components),
707
- parseRequestBody(path.requestBody, components)
708
- ]);
709
- return args;
710
- };
711
- var createArgs = (initializer = {}) => ({
712
- type: "object",
713
- properties: [],
714
- optional: true,
715
- ...initializer
716
- });
717
- var joinArgs = (args) => {
718
- const reqArg = {};
719
- for (const arg of args) {
720
- for (const [prop, val] of Object.entries(arg)) {
721
- const key = prop;
722
- if (reqArg[key]) {
723
- reqArg[key] = joinArg(reqArg[key], val);
724
- } else {
725
- reqArg[key] = val;
726
- }
727
- }
728
- }
729
- return reqArg;
730
- };
731
- var joinArg = (arg1, arg2) => {
732
- const arg = {
733
- type: "object",
734
- optional: arg1.optional && arg2.optional,
735
- properties: arg1.properties.concat(arg2.properties)
736
- };
737
- if (arg1.allOf || arg2.allOf)
738
- arg.allOf = (arg1.allOf || []).concat(arg2.allOf || []);
739
- if (arg1.anyOf || arg2.anyOf)
740
- arg.anyOf = (arg1.anyOf || []).concat(arg2.anyOf || []);
741
- if (arg1.oneOf || arg2.oneOf)
742
- arg.oneOf = (arg1.oneOf || []).concat(arg2.oneOf || []);
743
- if (arg1.description || arg2.description)
744
- arg.description = arg1.description || arg2.description;
745
- if (arg1.title || arg2.title) arg.title = arg1.title || arg2.title;
746
- return arg;
747
- };
748
- var parseSecurity = (security = [], components = {}) => {
749
- const args = {};
750
- for (const secReq of security) {
751
- for (const [name] of Object.entries(secReq)) {
752
- const param2 = findRef(
753
- components,
754
- `#/components/securitySchemes/${name}`
755
- );
756
- const arg = args.header || createArgs({ ...parseDocumentation(param2) });
757
- arg.optional = false;
758
- if (!arg.allOf) arg.allOf = [];
759
- arg.allOf.push({ type: parseRef(name) });
760
- args.header = arg;
761
- }
762
- }
763
- return args;
764
- };
765
- var parseParameters2 = (parameters = [], components = {}) => {
766
- const args = {};
767
- for (const p of parameters) {
768
- const ref = p.$ref;
769
- if (ref) {
770
- const part = ref.split("/")[2];
771
- switch (part) {
772
- case "parameters": {
773
- const param2 = findRef(components, ref);
774
- const arg = args[param2.in] || createArgs({ ...parseDocumentation(param2) });
775
- arg.optional = arg.optional && !param2.required;
776
- if (!arg.allOf) arg.allOf = [];
777
- arg.allOf.push({ type: parseRef(ref) });
778
- args[param2.in] = arg;
779
- break;
780
- }
781
- case "headers": {
782
- const header = findRef(components, ref);
783
- const arg = args.header || createArgs();
784
- const name = parseRef(ref);
785
- arg.properties.push({
786
- name,
787
- optional: !header.required,
788
- // biome-ignore lint/style/noNonNullAssertion: schema is never null here
789
- type: [{ type: parseSchema(void 0, header.schema).type }],
790
- ...parseDocumentation(header.schema || {})
791
- });
792
- args.header = arg;
793
- break;
794
- }
795
- }
796
- } else {
797
- const param2 = p;
798
- const arg = args[param2.in] || createArgs({ ...parseDocumentation(param2) });
799
- arg.properties.push({
800
- name: param2.name,
801
- optional: !param2.required,
802
- type: [parseSchema(void 0, param2.schema)]
803
- });
804
- arg.optional = arg.optional && !param2.required;
805
- args[param2.in] = arg;
806
- }
807
- }
808
- return args;
809
- };
810
- var parseRequestBody = (requestBody, components = {}) => {
811
- const args = {};
812
- if (!requestBody) return args;
813
- const ref = requestBody.$ref;
814
- if (ref) {
815
- const refBody = findRef(components, ref);
816
- args.body = createArgs({
817
- optional: !refBody.required,
818
- allOf: [{ type: parseRef(ref) }]
819
- });
820
- } else {
821
- const body = requestBody;
822
- const bodyArgs = args.body || createArgs({ optional: !body.required, ...parseDocumentation(body) });
823
- if (body.content["application/json"]) {
824
- const schema = body.content["application/json"].schema;
825
- if (schema) {
826
- const parsed = parseSchema(void 0, schema);
827
- if (parsed.type === "object") {
828
- args.body = {
829
- ...parsed,
830
- optional: !body.required
831
- };
832
- } else if (parsed.type) {
833
- args.body = createArgs({
834
- optional: !body.required,
835
- allOf: [parsed],
836
- ...parseDocumentation(body)
837
- });
838
- }
839
- }
840
- }
841
- if (bodyArgs.allOf?.length || bodyArgs.oneOf?.length || bodyArgs.properties.length) {
842
- args.body = bodyArgs;
843
- }
844
- }
845
- return args;
846
- };
847
-
848
- // src/parser/responseBodies.ts
849
- var parseResponseBodies = (responses = {}) => {
850
- const bodies = [];
851
- for (const [name, b] of Object.entries(responses)) {
852
- const body = parseResponseBody(name, b);
853
- bodies.push(body);
854
- }
855
- return bodies;
856
- };
857
- var parseResponseBody = (name, response) => {
858
- const ref = response.$ref;
859
- if (ref) return { type: parseRef(ref) };
860
- const responseObject = response;
861
- const body = {};
862
- if (name) body.name = name;
863
- if (responseObject.description) body.description = responseObject.description;
864
- if (responseObject.content?.["application/json"]?.schema) {
865
- const schema = responseObject.content["application/json"].schema;
866
- body.data = parseSchema(void 0, schema);
867
- }
868
- if (responseObject.headers) {
869
- body.headers = [];
870
- for (const [headerName, header] of Object.entries(responseObject.headers)) {
871
- const ref2 = header.$ref;
872
- if (ref2)
873
- body.headers.push({
874
- name: headerName,
875
- optional: false,
876
- type: { type: parseRef(ref2) },
877
- ...parseDocumentation(header)
878
- });
879
- else body.headers.push(parseHeader(headerName, header));
880
- }
881
- }
882
- return body;
883
- };
884
-
885
- // src/parser/paths.ts
886
- var parsePaths = (doc) => Object.entries(doc.paths || {}).flatMap(
887
- ([name, path]) => parsePath(name, path, doc.components)
888
- );
889
- var parsePath = (url, path, components) => {
890
- const paths = [];
891
- const methods = ["delete", "get", "patch", "post", "put"];
892
- for (const method of methods) {
893
- if (path[method]) {
894
- paths.push(
895
- parseMethod(url, method, path[method], components)
896
- );
897
- }
898
- }
899
- return paths;
900
- };
901
- var parseMethod = (url, method, operation, components) => {
902
- return {
903
- method,
904
- url: parseUrl(url),
905
- responses: parseResponses(operation.responses),
906
- args: parseArgs(operation, components),
907
- ...parseDocumentation(operation)
908
- };
909
- };
910
- var parseUrl = (url) => url.replace(/{([^}]+)}/g, ":$1");
911
- var parseResponses = (responses) => {
912
- return Object.assign(
913
- {},
914
- ...Object.entries(responses).map(([code, response]) => {
915
- return {
916
- [Number.parseInt(code, 10)]: parseResponseBody(void 0, response)
917
- };
918
- })
919
- );
920
- };
921
-
922
- // src/parser/requestBodies.ts
923
- var parseRequestBodies = (requestBodies = {}) => {
924
- const definitions = [];
925
- for (const [name, requestBody] of Object.entries(requestBodies)) {
926
- if (requestBody.content["application/json"].schema) {
927
- definitions.push(
928
- parseSchema(name, requestBody.content["application/json"].schema)
929
- );
930
- }
931
- }
932
- return definitions;
933
- };
934
-
935
- // src/parser/securitySchemes.ts
936
- var parseSecuritySchemes = (schemes = {}) => {
937
- const parameters = [];
938
- for (const [name, scheme] of Object.entries(schemes)) {
939
- parameters.push(parseSecurityScheme(name, scheme));
940
- }
941
- return parameters;
942
- };
943
- var parseSecurityScheme = (name, scheme) => {
944
- switch (scheme.type) {
945
- case "apiKey":
946
- return parseApiKey(name, scheme);
947
- case "http":
948
- return parseHttpSecurity(name, scheme);
949
- case "oauth2":
950
- return parseOAuth(name, scheme);
951
- case "openIdConnect":
952
- return parseOpenIdConnect(name, scheme);
953
- }
954
- throw new Error(`Unknown security scheme '${scheme.type}'`);
955
- };
956
- var parseApiKey = (name, scheme) => {
957
- const _in = scheme.in || "header";
958
- const parameterName = scheme.name;
959
- return {
960
- name,
961
- parameterName,
962
- in: _in,
963
- optional: false,
964
- type: { type: "string" }
965
- };
966
- };
967
- var parseHttpSecurity = (name, _scheme) => ({
968
- name,
969
- in: "header",
970
- parameterName: "Authorization",
971
- optional: false,
972
- type: { type: "string" }
973
- });
974
- var parseOAuth = (name, _scheme) => ({
975
- name,
976
- in: "header",
977
- parameterName: "Authorization",
978
- optional: false,
979
- type: { type: "string" }
980
- });
981
- var parseOpenIdConnect = (name, _scheme) => ({
982
- name,
983
- in: "header",
984
- parameterName: "Authorization",
985
- optional: false,
986
- type: { type: "string" }
987
- });
988
-
989
- // src/parser/index.ts
990
- var parseDocument = (schema) => ({
991
- paths: parsePaths(schema),
992
- components: parseComponents(schema.components)
993
- });
994
- var parseComponents = (components = {}) => ({
995
- schemas: parseSchemas(components.schemas),
996
- headers: parseHeaders(components.headers),
997
- parameters: parseParameters(components.parameters),
998
- requestBodies: parseRequestBodies(components.requestBodies),
999
- responseBodies: parseResponseBodies(components.responses),
1000
- securitySchemes: parseSecuritySchemes(components.securitySchemes)
1001
- });
1002
-
1003
- // src/index.ts
1004
- var generateTypescript = async (name, doc) => {
1005
- const parsed = parseDocument(doc);
1006
- const generated = generate(name, parsed);
1007
- const formatted = await format(generated);
1008
- return formatted;
1009
- };
1010
- var generate2 = async (input, output) => {
1011
- const docs = await readDocs(input);
1012
- const generated = await generateDocs(docs);
1013
- if (!output) return generated.map((d) => d.ts).join("\n\n");
1014
- await saveDocs(output, generated);
1015
- };
1016
- var readDocs = async (input) => {
1017
- const path = resolve(input);
1018
- const stats = await stat(path);
1019
- const filePaths = [];
1020
- if (stats.isFile()) filePaths.push(path);
1021
- if (stats.isDirectory()) {
1022
- const files = await readdir(path);
1023
- filePaths.push(...files.map((f) => resolve(path, f)));
1024
- }
1025
- const readFiles = [];
1026
- for (const p of filePaths) {
1027
- const { name, ext } = parse(p);
1028
- let doc;
1029
- switch (ext) {
1030
- case ".json": {
1031
- console.log(`Reading ${p}`);
1032
- const txt = await readFile(p, "utf8");
1033
- doc = JSON.parse(txt);
1034
- break;
1035
- }
1036
- case ".yml":
1037
- case ".yaml": {
1038
- console.log(`Reading ${p}`);
1039
- const txt = await readFile(p, "utf8");
1040
- doc = YAML.parse(txt);
1041
- break;
1042
- }
1043
- default:
1044
- continue;
1045
- }
1046
- readFiles.push({
1047
- doc,
1048
- name
1049
- });
1050
- }
1051
- return readFiles;
1052
- };
1053
- var generateDocs = async (files) => {
1054
- const generated = [];
1055
- for (const doc of files) {
1056
- console.log(`Generating ${doc.name}`);
1057
- const ts = await generateTypescript(classname(doc.name), doc.doc);
1058
- generated.push({
1059
- ...doc,
1060
- ts
1061
- });
1062
- }
1063
- return generated;
1064
- };
1065
- var saveDocs = async (output, docs) => {
1066
- const stats = await stat(output);
1067
- const dir = stats.isDirectory() ? output : parse(output).dir;
1068
- await mkdir(dir, { recursive: true });
1069
- for (const doc of docs) {
1070
- const path = resolve(dir, `${filename(doc.name)}.ts`);
1071
- console.log(`Writing ${path}`);
1072
- await writeFile(path, doc.ts, "utf8");
1073
- }
1074
- };
1075
- var classname = (name) => {
1076
- return pascalCase2(name.replace(/\d+/g, ""));
1077
- };
1078
- var filename = (name) => {
1079
- return name.replace(/\./g, "_");
1080
- };
1081
- export {
1082
- classname,
1083
- filename,
1084
- generate2 as generate,
1085
- generateTypescript
1086
- };
1087
- //# sourceMappingURL=index.js.map