@sebspark/openapi-typegen 0.1.1 → 1.0.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/README.md +1 -1
- package/cli.mjs +15 -15
- package/dist/index.d.ts +5 -6
- package/dist/index.js +749 -483
- package/package.json +7 -6
package/dist/index.js
CHANGED
|
@@ -30,546 +30,812 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
|
-
generate: () =>
|
|
33
|
+
generate: () => generate2,
|
|
34
|
+
generateTypescript: () => generateTypescript
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(src_exports);
|
|
36
|
-
|
|
37
|
-
// src/generator.ts
|
|
38
|
-
var fastGlob = __toESM(require("fast-glob"));
|
|
39
|
-
var import_promises = require("fs/promises");
|
|
40
37
|
var import_path = require("path");
|
|
41
|
-
var
|
|
38
|
+
var import_change_case2 = require("change-case");
|
|
39
|
+
var import_promises = require("fs/promises");
|
|
40
|
+
var YAML = __toESM(require("yaml"));
|
|
42
41
|
|
|
43
|
-
// src/
|
|
44
|
-
var
|
|
45
|
-
var header = `/**
|
|
46
|
-
* This file was auto-generated.
|
|
47
|
-
* Do not make direct changes to the file.
|
|
48
|
-
*/
|
|
42
|
+
// src/generator/common.ts
|
|
43
|
+
var import_change_case = require("change-case");
|
|
49
44
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
singleQuote: true,
|
|
64
|
-
semi: false
|
|
65
|
-
});
|
|
66
|
-
return formatted;
|
|
45
|
+
// src/generator/document.ts
|
|
46
|
+
var document = ({ title, description }) => {
|
|
47
|
+
if (title || description) {
|
|
48
|
+
const tokens = [];
|
|
49
|
+
tokens.push("/**");
|
|
50
|
+
if (title)
|
|
51
|
+
tokens.push(` * ${title}`);
|
|
52
|
+
if (description)
|
|
53
|
+
tokens.push(` * ${description}`);
|
|
54
|
+
tokens.push(" */\n");
|
|
55
|
+
return tokens.join("\n");
|
|
56
|
+
}
|
|
57
|
+
return "";
|
|
67
58
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
{}
|
|
59
|
+
var documentClientPath = (path, responses) => documentPath(
|
|
60
|
+
path,
|
|
61
|
+
responses,
|
|
62
|
+
[param("url", "string")],
|
|
63
|
+
[param("opts", "RequestOptions", true)]
|
|
64
|
+
);
|
|
65
|
+
var documentServerPath = (path, responses) => documentPath(path, responses);
|
|
66
|
+
var documentPath = (path, responses, argsBefore = [], argsAfter = []) => {
|
|
67
|
+
const tokens = [];
|
|
68
|
+
tokens.push("/**");
|
|
69
|
+
if (path.title)
|
|
70
|
+
tokens.push(` * ${path.title}`);
|
|
71
|
+
if (path.description)
|
|
72
|
+
tokens.push(` * ${path.description}`);
|
|
73
|
+
tokens.push(" *");
|
|
74
|
+
tokens.push(...argsBefore);
|
|
75
|
+
if (path.args)
|
|
76
|
+
tokens.push(...documentArgs(path.args));
|
|
77
|
+
tokens.push(...argsAfter);
|
|
78
|
+
tokens.push(` * @returns {Promise<${responses}>}`);
|
|
79
|
+
tokens.push(" */");
|
|
80
|
+
return tokens.join("\n");
|
|
81
|
+
};
|
|
82
|
+
var documentArgs = (args) => {
|
|
83
|
+
const tokens = [];
|
|
84
|
+
tokens.push(
|
|
85
|
+
param(
|
|
86
|
+
"args",
|
|
87
|
+
"Object",
|
|
88
|
+
argsOptional(args),
|
|
89
|
+
"The arguments for the request."
|
|
90
|
+
)
|
|
80
91
|
);
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
92
|
+
tokens.push(...requestArgs(args.path, "params", "Path parameters"));
|
|
93
|
+
tokens.push(...requestArgs(args.query, "query", "Query parameters"));
|
|
94
|
+
tokens.push(...requestArgs(args.header, "headers", "Headers"));
|
|
95
|
+
tokens.push(...requestArgs(args.body, "body", "Request body"));
|
|
96
|
+
return tokens;
|
|
97
|
+
};
|
|
98
|
+
var buildPath = (path, property) => rxProperVariable.test(property) ? `${path}.${property}` : `${path}["${property}"]`;
|
|
99
|
+
var requestArgs = (args, name, title) => {
|
|
100
|
+
if (!args)
|
|
101
|
+
return [];
|
|
102
|
+
const tokens = [];
|
|
103
|
+
const type = args.extends.map((e) => e.type).join(AND) || "Object";
|
|
104
|
+
tokens.push(
|
|
105
|
+
param(
|
|
106
|
+
buildPath("args", name),
|
|
107
|
+
type,
|
|
108
|
+
args.optional,
|
|
109
|
+
`${title} for the request.`
|
|
110
|
+
)
|
|
111
|
+
);
|
|
112
|
+
const properties = args.properties.flatMap(
|
|
113
|
+
(prop) => requestProperty(buildPath("args", name), prop)
|
|
114
|
+
);
|
|
115
|
+
tokens.push(...properties);
|
|
116
|
+
return tokens;
|
|
117
|
+
};
|
|
118
|
+
var requestProperty = (path, property) => {
|
|
119
|
+
const tokens = [];
|
|
120
|
+
const type = property.type.map((t) => t.type).join(OR);
|
|
121
|
+
tokens.push(
|
|
122
|
+
param(
|
|
123
|
+
buildPath(path, property.name),
|
|
124
|
+
type,
|
|
125
|
+
property.optional,
|
|
126
|
+
property.title,
|
|
127
|
+
property.description
|
|
128
|
+
)
|
|
129
|
+
);
|
|
130
|
+
return tokens;
|
|
131
|
+
};
|
|
132
|
+
var param = (name, type, optional = false, title = "", description = "") => {
|
|
133
|
+
const tokens = [];
|
|
134
|
+
tokens.push(
|
|
135
|
+
` * @param {${type}} ${optional ? "[" : ""}${name}${optional ? "]" : ""}`
|
|
136
|
+
);
|
|
137
|
+
if (optional || title || description) {
|
|
138
|
+
tokens.push(" -");
|
|
139
|
+
if (optional)
|
|
140
|
+
tokens.push(" Optional.");
|
|
141
|
+
if (title)
|
|
142
|
+
tokens.push(` ${title}`);
|
|
143
|
+
if (description)
|
|
144
|
+
tokens.push(` ${description}`);
|
|
145
|
+
}
|
|
146
|
+
return tokens.join("");
|
|
85
147
|
};
|
|
86
148
|
|
|
87
|
-
// src/
|
|
88
|
-
var
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
149
|
+
// src/generator/common.ts
|
|
150
|
+
var OR = " | ";
|
|
151
|
+
var AND = " & ";
|
|
152
|
+
var generateType = (parsed) => {
|
|
153
|
+
let type;
|
|
154
|
+
switch (parsed.type) {
|
|
155
|
+
case "enum": {
|
|
156
|
+
type = generateEnum(parsed);
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
case "array": {
|
|
160
|
+
type = generateArray(parsed);
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
case "object": {
|
|
164
|
+
type = generateObject(parsed);
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
case "Date":
|
|
168
|
+
case "bigint":
|
|
169
|
+
case "boolean":
|
|
170
|
+
case "null":
|
|
171
|
+
case "number":
|
|
172
|
+
case "string":
|
|
173
|
+
case "symbol":
|
|
174
|
+
case "undefined":
|
|
175
|
+
type = generatePrimitive(parsed);
|
|
176
|
+
break;
|
|
177
|
+
default: {
|
|
178
|
+
type = generateCustom(parsed);
|
|
179
|
+
}
|
|
97
180
|
}
|
|
181
|
+
return type.replace(/ & \{\s*\}/g, "");
|
|
98
182
|
};
|
|
99
|
-
var
|
|
100
|
-
|
|
183
|
+
var generateProperty = (property) => {
|
|
184
|
+
const types = property.type.map(generateType);
|
|
185
|
+
return `${document(property)}${propertyName(property.name)}${property.optional ? "?" : ""}: ${types.join(OR)}`;
|
|
101
186
|
};
|
|
102
|
-
var
|
|
103
|
-
|
|
187
|
+
var preamble = (type) => type.name ? `${document(type)}export type ${typeName(type.name)} = ` : "";
|
|
188
|
+
var typeName = (name) => {
|
|
189
|
+
if (rxProperVariable.test(name))
|
|
190
|
+
return name;
|
|
191
|
+
return (0, import_change_case.pascalCase)(name);
|
|
104
192
|
};
|
|
105
|
-
var
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
return
|
|
193
|
+
var propertyName = (name) => {
|
|
194
|
+
if (rxProperVariable.test(name))
|
|
195
|
+
return name;
|
|
196
|
+
return `'${name}'`;
|
|
109
197
|
};
|
|
110
|
-
var
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
198
|
+
var rxProperVariable = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
|
|
199
|
+
var extensions = (type) => type.extends.map(generateType).concat("").join(AND);
|
|
200
|
+
var generatePrimitive = (parsed) => `${preamble(parsed)}${parsed.type}`;
|
|
201
|
+
var generateCustom = (parsed) => `${preamble(parsed)}${typeName(parsed.type)}`;
|
|
202
|
+
var generateObject = (parsed) => {
|
|
203
|
+
const lines = [];
|
|
204
|
+
lines.push(`${preamble(parsed)}${extensions(parsed)}{`);
|
|
205
|
+
lines.push(...parsed.properties.map(generateProperty));
|
|
206
|
+
lines.push("}");
|
|
207
|
+
return lines.join("\n");
|
|
115
208
|
};
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return
|
|
126
|
-
};
|
|
127
|
-
var
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
var guessType = (schema) => {
|
|
142
|
-
if (schema.type) {
|
|
143
|
-
return schema.type;
|
|
144
|
-
} else if (schema.enum) {
|
|
145
|
-
return "string";
|
|
146
|
-
} else if (schema.properties) {
|
|
147
|
-
return "object";
|
|
148
|
-
} else {
|
|
149
|
-
return void 0;
|
|
209
|
+
var generateArray = (parsed) => {
|
|
210
|
+
const lines = [];
|
|
211
|
+
lines.push(`${preamble(parsed)}${parsed.items.type}[]`);
|
|
212
|
+
return lines.join("\n");
|
|
213
|
+
};
|
|
214
|
+
var generateEnum = (parsed) => {
|
|
215
|
+
return `${preamble(parsed)}${parsed.values.map(serializeValue).join(OR)}`;
|
|
216
|
+
};
|
|
217
|
+
var generateHeader = (header) => {
|
|
218
|
+
return `${preamble(header)}{ ${propertyName(header.name)}${header.optional ? "?" : ""}: ${generateType(header.type)} }`;
|
|
219
|
+
};
|
|
220
|
+
var generateResponseBody = (type) => {
|
|
221
|
+
const customType = type.type;
|
|
222
|
+
if (customType)
|
|
223
|
+
return typeName(customType);
|
|
224
|
+
const body = type;
|
|
225
|
+
if (!body.data && !body.headers)
|
|
226
|
+
return "undefined";
|
|
227
|
+
const tokens = [];
|
|
228
|
+
tokens.push(preamble(body));
|
|
229
|
+
tokens.push("APIResponse<");
|
|
230
|
+
tokens.push(body.data ? generateType(body.data) : "undefined");
|
|
231
|
+
if (body.headers) {
|
|
232
|
+
tokens.push(", ");
|
|
233
|
+
tokens.push(body.headers ? generateHeaders(body.headers) : "undefined");
|
|
150
234
|
}
|
|
235
|
+
tokens.push(">");
|
|
236
|
+
return tokens.join("");
|
|
151
237
|
};
|
|
152
|
-
var
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
238
|
+
var generateHeaders = (headers) => {
|
|
239
|
+
const tokens = [];
|
|
240
|
+
for (const header of headers) {
|
|
241
|
+
tokens.push(
|
|
242
|
+
`${propertyName(header.name)}${header.optional ? "?" : ""}: ${generateType(header.type)}`
|
|
243
|
+
);
|
|
156
244
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
} else {
|
|
180
|
-
schemaString = "string";
|
|
181
|
-
}
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
default:
|
|
185
|
-
schemaString = type;
|
|
245
|
+
return `{${tokens.join(", ")}}`;
|
|
246
|
+
};
|
|
247
|
+
var serializeValue = (value) => {
|
|
248
|
+
if (typeof value === "string")
|
|
249
|
+
return `'${value}'`;
|
|
250
|
+
return value;
|
|
251
|
+
};
|
|
252
|
+
|
|
253
|
+
// src/generator/args.ts
|
|
254
|
+
var generateClientArgs = (args) => generateArgs(args, false);
|
|
255
|
+
var generateServerArgs = (args) => args ? generateArgs(args, true) : "args: Req";
|
|
256
|
+
var parts = ["body", "header", "path", "query"];
|
|
257
|
+
var generateArgs = (args, extendsReq) => {
|
|
258
|
+
if (args) {
|
|
259
|
+
const tokens = [];
|
|
260
|
+
for (const part of parts) {
|
|
261
|
+
const arg = args[part];
|
|
262
|
+
if (arg) {
|
|
263
|
+
const partName = part === "path" ? "params" : part === "header" ? "headers" : part;
|
|
264
|
+
tokens.push(
|
|
265
|
+
`${partName}${arg.optional ? "?" : ""}: ${generateType(arg)}`
|
|
266
|
+
);
|
|
186
267
|
}
|
|
187
268
|
}
|
|
269
|
+
if (!tokens.length)
|
|
270
|
+
return "";
|
|
271
|
+
const optional = argsOptional(args);
|
|
272
|
+
return `args${optional ? "?" : ""}: ${extendsReq ? "Req & " : ""}{ ${tokens.join(", ")} }, `;
|
|
188
273
|
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
274
|
+
return "";
|
|
275
|
+
};
|
|
276
|
+
var argsOptional = (args) => (
|
|
277
|
+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
|
278
|
+
parts.reduce((o, p) => o && (!args[p] || args[p].optional), true)
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
// src/generator/client.ts
|
|
282
|
+
var generateClient = (name, paths) => {
|
|
283
|
+
var _a;
|
|
284
|
+
const groupedCalls = {};
|
|
285
|
+
for (const path of paths) {
|
|
286
|
+
if (!groupedCalls[path.method]) {
|
|
287
|
+
groupedCalls[path.method] = [];
|
|
193
288
|
}
|
|
289
|
+
(_a = groupedCalls[path.method]) == null ? void 0 : _a.push(generateCall(path));
|
|
194
290
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
}
|
|
291
|
+
const client = [];
|
|
292
|
+
const methods = Object.keys(groupedCalls).map(serializeValue).join(OR);
|
|
293
|
+
client.push(`export type ${name}Client = Pick<BaseClient, ${methods}> & {`);
|
|
294
|
+
Object.entries(groupedCalls).forEach(([method, calls]) => {
|
|
295
|
+
client.push(`${method}: {`);
|
|
296
|
+
client.push(...calls);
|
|
297
|
+
client.push("}");
|
|
298
|
+
});
|
|
299
|
+
client.push("}");
|
|
300
|
+
return client.join("\n");
|
|
301
|
+
};
|
|
302
|
+
var generateCall = (path) => {
|
|
303
|
+
const responses = generateResponses(path);
|
|
304
|
+
return `${documentClientPath(path, responses)}
|
|
305
|
+
(
|
|
306
|
+
url: '${path.url}', ${generateClientArgs(path.args)}opts?: RequestOptions,
|
|
307
|
+
): Promise<${responses}>`;
|
|
308
|
+
};
|
|
309
|
+
var generateResponses = (path) => Object.entries(path.responses).filter(([code]) => parseInt(code, 10) < 400).map(([, type]) => generateResponseBody(type)).join(OR);
|
|
310
|
+
|
|
311
|
+
// src/generator/server.ts
|
|
312
|
+
var generateServer = (name, paths) => {
|
|
313
|
+
const tokens = [];
|
|
314
|
+
tokens.push(`export type ${name}Server = APIServerDefinition & {`);
|
|
315
|
+
for (const [url, methods] of Object.entries(groupPathsByUrl(paths))) {
|
|
316
|
+
tokens.push(generatePath(url, methods));
|
|
200
317
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
318
|
+
tokens.push("}");
|
|
319
|
+
return tokens.join("\n");
|
|
320
|
+
};
|
|
321
|
+
var groupPathsByUrl = (paths) => paths.reduce(
|
|
322
|
+
(group, path) => {
|
|
323
|
+
if (!group[path.url])
|
|
324
|
+
group[path.url] = [];
|
|
325
|
+
group[path.url].push(path);
|
|
326
|
+
return group;
|
|
327
|
+
},
|
|
328
|
+
{}
|
|
329
|
+
);
|
|
330
|
+
var generatePath = (url, methods) => `'${url}': {
|
|
331
|
+
${methods.map(generateMethod).join("\n")}
|
|
332
|
+
}`;
|
|
333
|
+
var generateMethod = (path) => {
|
|
334
|
+
const responses = generateResponses2(path.responses);
|
|
335
|
+
return `${path.method}: {
|
|
336
|
+
${documentServerPath(path, responses)}
|
|
337
|
+
handler: (${generateServerArgs(path.args)}) => Promise<${responses}>
|
|
338
|
+
pre?: GenericRouteHandler | GenericRouteHandler[]
|
|
339
|
+
}`;
|
|
340
|
+
};
|
|
341
|
+
var generateResponses2 = (responses) => Object.entries(responses).filter(([code]) => parseInt(code, 10) < 400).map(([code, response]) => generateResponse(parseInt(code, 10), response)).join(OR);
|
|
342
|
+
var generateResponse = (code, response) => `[${code}, ${generateResponseBody(response)}]`;
|
|
343
|
+
|
|
344
|
+
// src/generator/generator.ts
|
|
345
|
+
var generate = (name, doc) => `
|
|
346
|
+
/**
|
|
347
|
+
* This file was auto-generated.
|
|
348
|
+
* Do not make direct changes to the file.
|
|
349
|
+
*/
|
|
350
|
+
|
|
351
|
+
import type {
|
|
352
|
+
APIResponse,
|
|
353
|
+
APIServerDefinition,
|
|
354
|
+
BaseClient,
|
|
355
|
+
GenericRouteHandler,
|
|
356
|
+
RequestOptions,
|
|
357
|
+
} from '@sebspark/openapi-core'
|
|
358
|
+
import type { Request } from 'express'
|
|
359
|
+
|
|
360
|
+
type Req = Pick<Request, 'url' | 'baseUrl' | 'cookies' | 'hostname'>
|
|
361
|
+
|
|
362
|
+
/* tslint:disable */
|
|
363
|
+
/* eslint-disable */
|
|
364
|
+
|
|
365
|
+
${generateComponents(doc.components)}
|
|
366
|
+
|
|
367
|
+
${generateServer(name, doc.paths)}
|
|
368
|
+
|
|
369
|
+
${generateClient(name, doc.paths)}
|
|
370
|
+
|
|
371
|
+
`;
|
|
372
|
+
var generateComponents = (components) => {
|
|
373
|
+
const tokens = [];
|
|
374
|
+
for (const schema of components.schemas) {
|
|
375
|
+
tokens.push(generateType(schema));
|
|
206
376
|
}
|
|
207
|
-
|
|
208
|
-
|
|
377
|
+
for (const header of components.headers) {
|
|
378
|
+
tokens.push(generateHeader(header));
|
|
209
379
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
380
|
+
for (const param2 of components.parameters) {
|
|
381
|
+
tokens.push(
|
|
382
|
+
generateType({
|
|
383
|
+
type: "object",
|
|
384
|
+
extends: [],
|
|
385
|
+
name: param2.name,
|
|
386
|
+
properties: [
|
|
387
|
+
{
|
|
388
|
+
name: param2.parameterName,
|
|
389
|
+
type: [param2.type],
|
|
390
|
+
optional: param2.optional
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
})
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
for (const req of components.requestBodies) {
|
|
397
|
+
tokens.push(generateType(req));
|
|
398
|
+
}
|
|
399
|
+
for (const res of components.responseBodies) {
|
|
400
|
+
tokens.push(generateResponseBody(res));
|
|
401
|
+
}
|
|
402
|
+
return tokens.join("\n\n");
|
|
231
403
|
};
|
|
232
404
|
|
|
233
|
-
// src/
|
|
234
|
-
var
|
|
235
|
-
|
|
236
|
-
|
|
405
|
+
// src/generator/formatter.ts
|
|
406
|
+
var import_prettier = require("prettier");
|
|
407
|
+
var options = {
|
|
408
|
+
parser: "typescript",
|
|
409
|
+
singleQuote: true,
|
|
410
|
+
semi: false,
|
|
411
|
+
trailingComma: "all"
|
|
237
412
|
};
|
|
413
|
+
var format = async (code) => (0, import_prettier.format)(code, options);
|
|
238
414
|
|
|
239
|
-
// src/
|
|
240
|
-
var
|
|
241
|
-
|
|
415
|
+
// src/parser/common.ts
|
|
416
|
+
var parseRef = (ref) => ref.substring(ref.lastIndexOf("/") + 1);
|
|
417
|
+
var parseEnumType = (name, schema) => ({ name, type: "enum", values: schema.enum || [] });
|
|
418
|
+
var findRef = (components, ref) => {
|
|
419
|
+
const [, , path, name] = ref.split("/");
|
|
420
|
+
const schemaPath = components[path];
|
|
421
|
+
if (!schemaPath || !schemaPath[name])
|
|
422
|
+
throw new Error(`Cannot find ref ${ref}`);
|
|
423
|
+
return schemaPath[name];
|
|
424
|
+
};
|
|
425
|
+
var parseDocumentation = (source) => {
|
|
426
|
+
const documented = {};
|
|
427
|
+
if (source.title)
|
|
428
|
+
documented.title = source.title;
|
|
429
|
+
if (source.description)
|
|
430
|
+
documented.description = source.description;
|
|
431
|
+
return documented;
|
|
242
432
|
};
|
|
243
433
|
|
|
244
|
-
// src/
|
|
245
|
-
var
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
}
|
|
265
|
-
).join("\n")}
|
|
266
|
-
},`
|
|
267
|
-
).join("\n")}
|
|
268
|
-
}
|
|
269
|
-
`
|
|
270
|
-
);
|
|
271
|
-
return rows;
|
|
272
|
-
};
|
|
273
|
-
var generateClientAPI = (name, routes) => {
|
|
274
|
-
const code = [];
|
|
275
|
-
const clientHandlers = [];
|
|
276
|
-
const verbMap = generateClientType(routes);
|
|
277
|
-
Object.entries(verbMap).forEach(([verb, definitions]) => {
|
|
278
|
-
const type = `${name}Client${(0, import_change_case.pascalCase)(verb)}`;
|
|
279
|
-
clientHandlers.push(`${verb}: ${type}`);
|
|
280
|
-
code.push(`type ${type} = {`);
|
|
281
|
-
definitions.forEach((def) => {
|
|
282
|
-
const args = serializeArgs(def.args);
|
|
283
|
-
const argsString = args ? `, ${args}` : "";
|
|
284
|
-
code.push(
|
|
285
|
-
`(url: '${def.url}'${argsString}): Promise<${def.response.type}>`
|
|
286
|
-
);
|
|
287
|
-
});
|
|
288
|
-
code.push("}");
|
|
289
|
-
});
|
|
290
|
-
code.push(
|
|
291
|
-
`export type ${name}Client = Pick<BaseClient, ${Object.keys(verbMap).map((v) => `'${v}'`).join(" | ")}> & {`
|
|
292
|
-
);
|
|
293
|
-
code.push(clientHandlers.join("\n"));
|
|
294
|
-
code.push("}");
|
|
295
|
-
return code;
|
|
296
|
-
};
|
|
297
|
-
var generateRouteDefinitions = (routes) => routes.map((route) => ({
|
|
298
|
-
method: route.method.toLowerCase(),
|
|
299
|
-
response: route.response,
|
|
300
|
-
url: route.url,
|
|
301
|
-
args: parseArgs(route)
|
|
302
|
-
}));
|
|
303
|
-
var generateClientType = (routes) => routes.reduce((router, routeDefinition) => {
|
|
304
|
-
if (!router[routeDefinition.method])
|
|
305
|
-
router[routeDefinition.method] = [];
|
|
306
|
-
router[routeDefinition.method].push(routeDefinition);
|
|
307
|
-
return router;
|
|
308
|
-
}, {});
|
|
309
|
-
var generateServerType = (routes) => routes.reduce((router, routeDefinition) => {
|
|
310
|
-
const route = router[routeDefinition.url] || {};
|
|
311
|
-
route[routeDefinition.method] = routeDefinition;
|
|
312
|
-
router[routeDefinition.url] = route;
|
|
313
|
-
return router;
|
|
314
|
-
}, {});
|
|
315
|
-
var parseArgs = (route) => {
|
|
316
|
-
const args = {};
|
|
317
|
-
if (route.requestParams !== "never")
|
|
318
|
-
args.params = route.requestParams;
|
|
319
|
-
if (route.requestQuery !== "never")
|
|
320
|
-
args.query = route.requestQuery;
|
|
321
|
-
if (route.requestHeaders !== "never")
|
|
322
|
-
args.headers = route.requestHeaders;
|
|
323
|
-
if (route.requestBody !== "never")
|
|
324
|
-
args.body = route.requestBody;
|
|
325
|
-
if (args.headers || args.params || args.query || args.body)
|
|
326
|
-
return args;
|
|
434
|
+
// src/parser/schema.ts
|
|
435
|
+
var parseSchemas = (schemas = {}) => Object.entries(schemas || {}).map(
|
|
436
|
+
([name, schema]) => parseSchema(name, schema)
|
|
437
|
+
);
|
|
438
|
+
var parseSchema = (name, schemaOrRef) => {
|
|
439
|
+
const ref = schemaOrRef.$ref;
|
|
440
|
+
if (ref) {
|
|
441
|
+
return { name, type: parseRef(ref) };
|
|
442
|
+
}
|
|
443
|
+
const schema = schemaOrRef;
|
|
444
|
+
switch (schema.type) {
|
|
445
|
+
case "array":
|
|
446
|
+
return parseArraySchema(name, schema);
|
|
447
|
+
case "boolean":
|
|
448
|
+
case "integer":
|
|
449
|
+
case "number":
|
|
450
|
+
case "string":
|
|
451
|
+
return schema.enum ? parseEnumType(name, schema) : parsePropertyType(schema)[0];
|
|
452
|
+
default:
|
|
453
|
+
return parseObjectSchema(name, schema);
|
|
454
|
+
}
|
|
327
455
|
};
|
|
328
|
-
var
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
456
|
+
var parseObjectSchema = (name, schema) => {
|
|
457
|
+
const type = {
|
|
458
|
+
name,
|
|
459
|
+
type: "object",
|
|
460
|
+
properties: [],
|
|
461
|
+
extends: [],
|
|
462
|
+
...parseDocumentation(schema)
|
|
463
|
+
};
|
|
464
|
+
if (schema.properties) {
|
|
465
|
+
type.properties = Object.entries(schema.properties).map(
|
|
466
|
+
([name2, property]) => parseProperty(name2, property, schema.required || [])
|
|
467
|
+
);
|
|
468
|
+
}
|
|
469
|
+
if (schema.allOf) {
|
|
470
|
+
type.extends = schema.allOf.flatMap(parsePropertyType);
|
|
471
|
+
}
|
|
472
|
+
return type;
|
|
332
473
|
};
|
|
333
|
-
var
|
|
334
|
-
if (!
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
474
|
+
var parseArraySchema = (name, schema) => {
|
|
475
|
+
if (schema.type !== "array" || !schema.items)
|
|
476
|
+
throw new Error("Not an array");
|
|
477
|
+
return {
|
|
478
|
+
name,
|
|
479
|
+
type: "array",
|
|
480
|
+
items: parsePropertyType(schema.items)[0],
|
|
481
|
+
...parseDocumentation(schema)
|
|
482
|
+
};
|
|
340
483
|
};
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
484
|
+
var parseProperty = (name, schema, required) => {
|
|
485
|
+
const property = {
|
|
486
|
+
name,
|
|
487
|
+
optional: !required.includes(name),
|
|
488
|
+
type: parsePropertyType(schema),
|
|
489
|
+
...parseDocumentation(schema)
|
|
490
|
+
};
|
|
491
|
+
return property;
|
|
492
|
+
};
|
|
493
|
+
var parsePropertyType = (property) => {
|
|
494
|
+
const ref = property.$ref;
|
|
495
|
+
if (ref) {
|
|
496
|
+
return [{ type: parseRef(ref) }];
|
|
497
|
+
}
|
|
498
|
+
const schemaObject = property;
|
|
499
|
+
if (schemaObject.type) {
|
|
500
|
+
return (Array.isArray(schemaObject.type) ? schemaObject.type : [schemaObject.type]).map((type) => {
|
|
501
|
+
switch (type) {
|
|
502
|
+
case "array": {
|
|
503
|
+
return parseArraySchema(void 0, schemaObject);
|
|
504
|
+
}
|
|
505
|
+
case "object": {
|
|
506
|
+
return parseObjectSchema(void 0, schemaObject);
|
|
507
|
+
}
|
|
508
|
+
case "integer": {
|
|
509
|
+
return { type: "number", ...parseDocumentation(schemaObject) };
|
|
510
|
+
}
|
|
511
|
+
default: {
|
|
512
|
+
return { type, ...parseDocumentation(schemaObject) };
|
|
513
|
+
}
|
|
514
|
+
}
|
|
354
515
|
});
|
|
355
516
|
}
|
|
356
|
-
return
|
|
517
|
+
return [];
|
|
357
518
|
};
|
|
358
519
|
|
|
359
|
-
// src/
|
|
360
|
-
var
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
520
|
+
// src/parser/headers.ts
|
|
521
|
+
var parseHeaders = (schemas = {}) => Object.entries(schemas || {}).map(
|
|
522
|
+
([name, schema]) => parseHeader(name, schema)
|
|
523
|
+
);
|
|
524
|
+
var parseHeader = (name, schema) => {
|
|
525
|
+
const header = {
|
|
526
|
+
name,
|
|
527
|
+
optional: !schema.required,
|
|
528
|
+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
|
529
|
+
type: parseSchema(void 0, schema.schema),
|
|
530
|
+
...parseDocumentation(schema)
|
|
368
531
|
};
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
532
|
+
return header;
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
// src/parser/parameters.ts
|
|
536
|
+
var parseParameters = (schemas = {}) => Object.entries(schemas || {}).map(
|
|
537
|
+
([name, schema]) => parseParameter(name, schema)
|
|
538
|
+
);
|
|
539
|
+
var parseParameter = (name, schema) => {
|
|
540
|
+
const param2 = {
|
|
541
|
+
name,
|
|
542
|
+
in: schema.in,
|
|
543
|
+
parameterName: schema.name,
|
|
544
|
+
optional: !schema.required,
|
|
545
|
+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
|
546
|
+
type: parseSchema(void 0, schema.schema),
|
|
547
|
+
...parseDocumentation(schema)
|
|
377
548
|
};
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
549
|
+
return param2;
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
// src/parser/args.ts
|
|
553
|
+
var parseArgs = (path, components) => {
|
|
554
|
+
var _a;
|
|
555
|
+
if (!((_a = path.parameters) == null ? void 0 : _a.length) && !path.requestBody)
|
|
556
|
+
return void 0;
|
|
557
|
+
const args = {
|
|
558
|
+
...parseParameters2(path.parameters, components),
|
|
559
|
+
...parseRequestBody(path.requestBody, components)
|
|
382
560
|
};
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
561
|
+
return args;
|
|
562
|
+
};
|
|
563
|
+
var createArgs = (initializer = {}) => ({
|
|
564
|
+
type: "object",
|
|
565
|
+
extends: [],
|
|
566
|
+
properties: [],
|
|
567
|
+
optional: true,
|
|
568
|
+
...initializer
|
|
569
|
+
});
|
|
570
|
+
var parseParameters2 = (parameters = [], components = {}) => {
|
|
571
|
+
const args = {};
|
|
572
|
+
for (const p of parameters) {
|
|
573
|
+
const ref = p.$ref;
|
|
574
|
+
if (ref) {
|
|
575
|
+
const part = ref.split("/")[2];
|
|
576
|
+
switch (part) {
|
|
577
|
+
case "parameters": {
|
|
578
|
+
const param2 = findRef(components, ref);
|
|
579
|
+
const arg = args[param2.in] || createArgs({ ...parseDocumentation(param2) });
|
|
580
|
+
arg.optional = arg.optional && !param2.required;
|
|
581
|
+
arg.extends.push({ type: parseRef(ref) });
|
|
582
|
+
args[param2.in] = arg;
|
|
583
|
+
break;
|
|
584
|
+
}
|
|
585
|
+
case "headers": {
|
|
586
|
+
const header = findRef(components, ref);
|
|
587
|
+
const arg = args.header || createArgs();
|
|
588
|
+
const name = parseRef(ref);
|
|
589
|
+
arg.properties.push({
|
|
590
|
+
name,
|
|
591
|
+
optional: !header.required,
|
|
592
|
+
// biome-ignore lint/style/noNonNullAssertion: <explanation>
|
|
593
|
+
type: [{ type: parseSchema(void 0, header.schema).type }],
|
|
594
|
+
...parseDocumentation(header.schema || {})
|
|
595
|
+
});
|
|
596
|
+
args.header = arg;
|
|
597
|
+
break;
|
|
598
|
+
}
|
|
389
599
|
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
const generateBody = (body, addImport) => {
|
|
401
|
-
var _a, _b;
|
|
402
|
-
if ((_a = body == null ? void 0 : body.content) == null ? void 0 : _a["application/json"]) {
|
|
403
|
-
const content = (_b = body.content["application/json"]) == null ? void 0 : _b.schema;
|
|
404
|
-
return generateFromSchemaObject(content, addImport);
|
|
600
|
+
} else {
|
|
601
|
+
const param2 = p;
|
|
602
|
+
const arg = args[param2.in] || createArgs({ ...parseDocumentation(param2) });
|
|
603
|
+
arg.properties.push({
|
|
604
|
+
name: param2.name,
|
|
605
|
+
optional: !param2.required,
|
|
606
|
+
type: [parseSchema(void 0, param2.schema)]
|
|
607
|
+
});
|
|
608
|
+
arg.optional = arg.optional && !param2.required;
|
|
609
|
+
args[param2.in] = arg;
|
|
405
610
|
}
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
611
|
+
}
|
|
612
|
+
return args;
|
|
613
|
+
};
|
|
614
|
+
var parseRequestBody = (requestBody, components = {}) => {
|
|
615
|
+
const args = {};
|
|
616
|
+
if (!requestBody)
|
|
617
|
+
return args;
|
|
618
|
+
const ref = requestBody.$ref;
|
|
619
|
+
if (ref) {
|
|
620
|
+
const refBody = findRef(components, ref);
|
|
621
|
+
args.body = createArgs({
|
|
622
|
+
optional: !refBody.required,
|
|
623
|
+
extends: [{ type: parseRef(ref) }]
|
|
624
|
+
});
|
|
625
|
+
} else {
|
|
626
|
+
const body = requestBody;
|
|
627
|
+
const bodyArgs = args.body || createArgs({ optional: !body.required, ...parseDocumentation(body) });
|
|
628
|
+
if (body.content["application/json"]) {
|
|
629
|
+
const schema = body.content["application/json"].schema;
|
|
630
|
+
if (schema) {
|
|
631
|
+
const parsed = parseSchema(void 0, schema);
|
|
632
|
+
if (parsed.type === "object") {
|
|
633
|
+
args.body = {
|
|
634
|
+
...parsed,
|
|
635
|
+
optional: !body.required
|
|
636
|
+
};
|
|
637
|
+
} else if (parsed.type) {
|
|
638
|
+
args.body = createArgs({
|
|
639
|
+
optional: !body.required,
|
|
640
|
+
extends: [parsed],
|
|
641
|
+
...parseDocumentation(body)
|
|
642
|
+
});
|
|
643
|
+
}
|
|
418
644
|
}
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
};
|
|
426
|
-
const generateRoutes = (path, item, addImport) => {
|
|
427
|
-
const verbs = ["get", "post", "put", "patch", "delete"];
|
|
428
|
-
const routes = verbs.map((verb) => {
|
|
429
|
-
const operation = item[verb];
|
|
430
|
-
if (!operation)
|
|
431
|
-
return void 0;
|
|
432
|
-
const route = {
|
|
433
|
-
url: expressifyPath(path),
|
|
434
|
-
method: verb,
|
|
435
|
-
requestBody: generateBody(
|
|
436
|
-
operation.requestBody,
|
|
437
|
-
addImport
|
|
438
|
-
),
|
|
439
|
-
requestParams: generateProps(
|
|
440
|
-
operation.parameters || [],
|
|
441
|
-
"path",
|
|
442
|
-
addImport
|
|
443
|
-
),
|
|
444
|
-
requestQuery: generateProps(
|
|
445
|
-
operation.parameters || [],
|
|
446
|
-
"query",
|
|
447
|
-
addImport
|
|
448
|
-
),
|
|
449
|
-
requestHeaders: generateProps(
|
|
450
|
-
operation.parameters || [],
|
|
451
|
-
"header",
|
|
452
|
-
addImport
|
|
453
|
-
),
|
|
454
|
-
response: generateResponses(operation.responses, addImport)[0],
|
|
455
|
-
errorResponses: generateResponses(
|
|
456
|
-
operation.responses,
|
|
457
|
-
addImport,
|
|
458
|
-
true
|
|
459
|
-
)
|
|
460
|
-
};
|
|
461
|
-
return route;
|
|
462
|
-
}).filter((r) => r);
|
|
463
|
-
return routes;
|
|
464
|
-
};
|
|
465
|
-
const generatePaths = (paths) => {
|
|
466
|
-
const imports = [];
|
|
467
|
-
const routes = Object.entries(paths).flatMap(
|
|
468
|
-
([path, item]) => generateRoutes(path, item, (imp) => imports.push(imp))
|
|
469
|
-
);
|
|
470
|
-
return [routes, imports];
|
|
471
|
-
};
|
|
472
|
-
return {
|
|
473
|
-
generate: generatePaths
|
|
474
|
-
};
|
|
645
|
+
}
|
|
646
|
+
if (bodyArgs.extends.length || bodyArgs.properties.length) {
|
|
647
|
+
args.body = bodyArgs;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return args;
|
|
475
651
|
};
|
|
476
652
|
|
|
477
|
-
// src/
|
|
478
|
-
var
|
|
479
|
-
|
|
480
|
-
const [
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
653
|
+
// src/parser/responseBodies.ts
|
|
654
|
+
var parseResponseBodies = (responses = {}) => {
|
|
655
|
+
const bodies = [];
|
|
656
|
+
for (const [name, b] of Object.entries(responses)) {
|
|
657
|
+
const body = parseResponseBody(name, b);
|
|
658
|
+
bodies.push(body);
|
|
659
|
+
}
|
|
660
|
+
return bodies;
|
|
661
|
+
};
|
|
662
|
+
var parseResponseBody = (name, response) => {
|
|
663
|
+
var _a, _b;
|
|
664
|
+
const ref = response.$ref;
|
|
665
|
+
if (ref)
|
|
666
|
+
return { type: parseRef(ref) };
|
|
667
|
+
const responseObject = response;
|
|
668
|
+
const body = {};
|
|
669
|
+
if (name)
|
|
670
|
+
body.name = name;
|
|
671
|
+
if (responseObject.description)
|
|
672
|
+
body.description = responseObject.description;
|
|
673
|
+
if ((_b = (_a = responseObject.content) == null ? void 0 : _a["application/json"]) == null ? void 0 : _b.schema) {
|
|
674
|
+
const schema = responseObject.content["application/json"].schema;
|
|
675
|
+
body.data = parseSchema(void 0, schema);
|
|
676
|
+
}
|
|
677
|
+
if (responseObject.headers) {
|
|
678
|
+
body.headers = [];
|
|
679
|
+
for (const [headerName, header] of Object.entries(responseObject.headers)) {
|
|
680
|
+
const ref2 = header.$ref;
|
|
681
|
+
if (ref2)
|
|
682
|
+
body.headers.push({
|
|
683
|
+
name: headerName,
|
|
684
|
+
optional: false,
|
|
685
|
+
type: { type: parseRef(ref2) },
|
|
686
|
+
...parseDocumentation(header)
|
|
687
|
+
});
|
|
688
|
+
else
|
|
689
|
+
body.headers.push(parseHeader(headerName, header));
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
return body;
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
// src/parser/paths.ts
|
|
696
|
+
var parsePaths = (doc) => Object.entries(doc.paths || {}).flatMap(
|
|
697
|
+
([name, path]) => parsePath(name, path, doc.components)
|
|
698
|
+
);
|
|
699
|
+
var parsePath = (url, path, components) => {
|
|
700
|
+
const paths = [];
|
|
701
|
+
const methods = ["delete", "get", "patch", "post", "put"];
|
|
702
|
+
for (const method of methods) {
|
|
703
|
+
if (path[method]) {
|
|
704
|
+
paths.push(
|
|
705
|
+
parseMethod(url, method, path[method], components)
|
|
706
|
+
);
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
return paths;
|
|
710
|
+
};
|
|
711
|
+
var parseMethod = (url, method, operation, components) => {
|
|
488
712
|
return {
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
713
|
+
method,
|
|
714
|
+
url: parseUrl(url),
|
|
715
|
+
responses: parseResponses(operation.responses),
|
|
716
|
+
args: parseArgs(operation, components),
|
|
717
|
+
...parseDocumentation(operation)
|
|
493
718
|
};
|
|
494
719
|
};
|
|
495
|
-
var
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
...formattedImports,
|
|
506
|
-
...formattedTypes,
|
|
507
|
-
...formattedRoutes
|
|
508
|
-
]);
|
|
509
|
-
return formatted;
|
|
510
|
-
};
|
|
511
|
-
var generateOpenApi = async (schema) => {
|
|
512
|
-
const data = generateData(schema);
|
|
513
|
-
const formatted = await generateFormattedString(data);
|
|
514
|
-
return formatted;
|
|
720
|
+
var parseUrl = (url) => url.replace(/{([^}]+)}/g, ":$1");
|
|
721
|
+
var parseResponses = (responses) => {
|
|
722
|
+
return Object.assign(
|
|
723
|
+
{},
|
|
724
|
+
...Object.entries(responses).map(([code, response]) => {
|
|
725
|
+
return {
|
|
726
|
+
[parseInt(code, 10)]: parseResponseBody(void 0, response)
|
|
727
|
+
};
|
|
728
|
+
})
|
|
729
|
+
);
|
|
515
730
|
};
|
|
516
731
|
|
|
517
|
-
// src/
|
|
518
|
-
var
|
|
519
|
-
const
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
for (const file of files) {
|
|
526
|
-
const { name } = (0, import_path.parse)(file);
|
|
527
|
-
const content = await (0, import_promises.readFile)(file, "utf-8");
|
|
528
|
-
const parsed = file.endsWith(".yaml") || file.endsWith(".yml") ? (0, import_yaml.parse)(content) : JSON.parse(content);
|
|
529
|
-
if (parsed["asyncapi"]) {
|
|
530
|
-
} else if (parsed["openapi"]) {
|
|
531
|
-
schemas.openApi[name] = parsed;
|
|
532
|
-
} else if (parsed["components"]) {
|
|
533
|
-
schemas.sharedTypes[name] = parsed;
|
|
732
|
+
// src/parser/requestBodies.ts
|
|
733
|
+
var parseRequestBodies = (requestBodies = {}) => {
|
|
734
|
+
const definitions = [];
|
|
735
|
+
for (const [name, requestBody] of Object.entries(requestBodies)) {
|
|
736
|
+
if (requestBody.content["application/json"].schema) {
|
|
737
|
+
definitions.push(
|
|
738
|
+
parseSchema(name, requestBody.content["application/json"].schema)
|
|
739
|
+
);
|
|
534
740
|
}
|
|
535
741
|
}
|
|
536
|
-
return
|
|
537
|
-
};
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
);
|
|
742
|
+
return definitions;
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
// src/parser/index.ts
|
|
746
|
+
var parseDocument = (schema) => ({
|
|
747
|
+
paths: parsePaths(schema),
|
|
748
|
+
components: parseComponents(schema.components)
|
|
749
|
+
});
|
|
750
|
+
var parseComponents = (components = {}) => ({
|
|
751
|
+
schemas: parseSchemas(components.schemas),
|
|
752
|
+
headers: parseHeaders(components.headers),
|
|
753
|
+
parameters: parseParameters(components.parameters),
|
|
754
|
+
requestBodies: parseRequestBodies(components.requestBodies),
|
|
755
|
+
responseBodies: parseResponseBodies(components.responses)
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
// src/index.ts
|
|
759
|
+
var generateTypescript = async (name, doc) => {
|
|
760
|
+
const parsed = parseDocument(doc);
|
|
761
|
+
const generated = generate(name, parsed);
|
|
762
|
+
const formatted = await format(generated);
|
|
763
|
+
return formatted;
|
|
764
|
+
};
|
|
765
|
+
var generate2 = async (input, output) => {
|
|
766
|
+
const docs = await readDocs(input);
|
|
767
|
+
const generated = await generateDocs(docs);
|
|
557
768
|
if (!output)
|
|
558
|
-
return
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
await (0, import_promises.
|
|
769
|
+
return generated.map((d) => d.ts).join("\n\n");
|
|
770
|
+
await saveDocs(output, generated);
|
|
771
|
+
};
|
|
772
|
+
var readDocs = async (input) => {
|
|
773
|
+
const path = (0, import_path.resolve)(input);
|
|
774
|
+
const stats = await (0, import_promises.stat)(path);
|
|
775
|
+
const filePaths = [];
|
|
776
|
+
if (stats.isFile())
|
|
777
|
+
filePaths.push(path);
|
|
778
|
+
if (stats.isDirectory()) {
|
|
779
|
+
const files = await (0, import_promises.readdir)(path);
|
|
780
|
+
filePaths.push(...files.map((f) => (0, import_path.resolve)(path, f)));
|
|
569
781
|
}
|
|
570
|
-
|
|
782
|
+
const readFiles = [];
|
|
783
|
+
for (const p of filePaths) {
|
|
784
|
+
const { name, ext } = (0, import_path.parse)(p);
|
|
785
|
+
let doc;
|
|
786
|
+
switch (ext) {
|
|
787
|
+
case ".json": {
|
|
788
|
+
console.log(`Reading ${p}`);
|
|
789
|
+
const txt = await (0, import_promises.readFile)(p, "utf8");
|
|
790
|
+
doc = JSON.parse(txt);
|
|
791
|
+
break;
|
|
792
|
+
}
|
|
793
|
+
case ".yml":
|
|
794
|
+
case ".yaml": {
|
|
795
|
+
console.log(`Reading ${p}`);
|
|
796
|
+
const txt = await (0, import_promises.readFile)(p, "utf8");
|
|
797
|
+
doc = YAML.parse(txt);
|
|
798
|
+
break;
|
|
799
|
+
}
|
|
800
|
+
default:
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
readFiles.push({
|
|
804
|
+
doc,
|
|
805
|
+
name: formatName(name)
|
|
806
|
+
});
|
|
807
|
+
}
|
|
808
|
+
return readFiles;
|
|
809
|
+
};
|
|
810
|
+
var generateDocs = async (files) => {
|
|
811
|
+
const generated = [];
|
|
812
|
+
for (const doc of files) {
|
|
813
|
+
console.log(`Generating ${doc.name}`);
|
|
814
|
+
const ts = await generateTypescript(doc.name, doc.doc);
|
|
815
|
+
generated.push({
|
|
816
|
+
...doc,
|
|
817
|
+
ts
|
|
818
|
+
});
|
|
819
|
+
}
|
|
820
|
+
return generated;
|
|
821
|
+
};
|
|
822
|
+
var saveDocs = async (output, docs) => {
|
|
823
|
+
const stats = await (0, import_promises.stat)(output);
|
|
824
|
+
const dir = stats.isDirectory() ? output : (0, import_path.parse)(output).dir;
|
|
825
|
+
await (0, import_promises.mkdir)(dir, { recursive: true });
|
|
826
|
+
for (const doc of docs) {
|
|
827
|
+
const path = (0, import_path.resolve)(dir, `${doc.name}.ts`);
|
|
828
|
+
console.log(`Writing ${path}`);
|
|
829
|
+
await (0, import_promises.writeFile)(path, doc.ts, "utf8");
|
|
830
|
+
}
|
|
831
|
+
};
|
|
832
|
+
var formatName = (name) => {
|
|
833
|
+
if (name[0].toUpperCase() === name[0])
|
|
834
|
+
return name;
|
|
835
|
+
return (0, import_change_case2.pascalCase)(name);
|
|
571
836
|
};
|
|
572
837
|
// Annotate the CommonJS export names for ESM import in node:
|
|
573
838
|
0 && (module.exports = {
|
|
574
|
-
generate
|
|
839
|
+
generate,
|
|
840
|
+
generateTypescript
|
|
575
841
|
});
|