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