create-swagger-client 0.1.0 → 0.1.1
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 +11 -573
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -1,460 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
import openapiTS, { astToString } from "openapi-typescript";
|
|
3
|
-
|
|
4
|
-
// node:path
|
|
5
|
-
function assertPath(path) {
|
|
6
|
-
if (typeof path !== "string")
|
|
7
|
-
throw TypeError("Path must be a string. Received " + JSON.stringify(path));
|
|
8
|
-
}
|
|
9
|
-
function normalizeStringPosix(path, allowAboveRoot) {
|
|
10
|
-
var res = "", lastSegmentLength = 0, lastSlash = -1, dots = 0, code;
|
|
11
|
-
for (var i = 0;i <= path.length; ++i) {
|
|
12
|
-
if (i < path.length)
|
|
13
|
-
code = path.charCodeAt(i);
|
|
14
|
-
else if (code === 47)
|
|
15
|
-
break;
|
|
16
|
-
else
|
|
17
|
-
code = 47;
|
|
18
|
-
if (code === 47) {
|
|
19
|
-
if (lastSlash === i - 1 || dots === 1)
|
|
20
|
-
;
|
|
21
|
-
else if (lastSlash !== i - 1 && dots === 2) {
|
|
22
|
-
if (res.length < 2 || lastSegmentLength !== 2 || res.charCodeAt(res.length - 1) !== 46 || res.charCodeAt(res.length - 2) !== 46) {
|
|
23
|
-
if (res.length > 2) {
|
|
24
|
-
var lastSlashIndex = res.lastIndexOf("/");
|
|
25
|
-
if (lastSlashIndex !== res.length - 1) {
|
|
26
|
-
if (lastSlashIndex === -1)
|
|
27
|
-
res = "", lastSegmentLength = 0;
|
|
28
|
-
else
|
|
29
|
-
res = res.slice(0, lastSlashIndex), lastSegmentLength = res.length - 1 - res.lastIndexOf("/");
|
|
30
|
-
lastSlash = i, dots = 0;
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
} else if (res.length === 2 || res.length === 1) {
|
|
34
|
-
res = "", lastSegmentLength = 0, lastSlash = i, dots = 0;
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
if (allowAboveRoot) {
|
|
39
|
-
if (res.length > 0)
|
|
40
|
-
res += "/..";
|
|
41
|
-
else
|
|
42
|
-
res = "..";
|
|
43
|
-
lastSegmentLength = 2;
|
|
44
|
-
}
|
|
45
|
-
} else {
|
|
46
|
-
if (res.length > 0)
|
|
47
|
-
res += "/" + path.slice(lastSlash + 1, i);
|
|
48
|
-
else
|
|
49
|
-
res = path.slice(lastSlash + 1, i);
|
|
50
|
-
lastSegmentLength = i - lastSlash - 1;
|
|
51
|
-
}
|
|
52
|
-
lastSlash = i, dots = 0;
|
|
53
|
-
} else if (code === 46 && dots !== -1)
|
|
54
|
-
++dots;
|
|
55
|
-
else
|
|
56
|
-
dots = -1;
|
|
57
|
-
}
|
|
58
|
-
return res;
|
|
59
|
-
}
|
|
60
|
-
function _format(sep, pathObject) {
|
|
61
|
-
var dir = pathObject.dir || pathObject.root, base = pathObject.base || (pathObject.name || "") + (pathObject.ext || "");
|
|
62
|
-
if (!dir)
|
|
63
|
-
return base;
|
|
64
|
-
if (dir === pathObject.root)
|
|
65
|
-
return dir + base;
|
|
66
|
-
return dir + sep + base;
|
|
67
|
-
}
|
|
68
|
-
function resolve() {
|
|
69
|
-
var resolvedPath = "", resolvedAbsolute = false, cwd;
|
|
70
|
-
for (var i = arguments.length - 1;i >= -1 && !resolvedAbsolute; i--) {
|
|
71
|
-
var path;
|
|
72
|
-
if (i >= 0)
|
|
73
|
-
path = arguments[i];
|
|
74
|
-
else {
|
|
75
|
-
if (cwd === undefined)
|
|
76
|
-
cwd = process.cwd();
|
|
77
|
-
path = cwd;
|
|
78
|
-
}
|
|
79
|
-
if (assertPath(path), path.length === 0)
|
|
80
|
-
continue;
|
|
81
|
-
resolvedPath = path + "/" + resolvedPath, resolvedAbsolute = path.charCodeAt(0) === 47;
|
|
82
|
-
}
|
|
83
|
-
if (resolvedPath = normalizeStringPosix(resolvedPath, !resolvedAbsolute), resolvedAbsolute)
|
|
84
|
-
if (resolvedPath.length > 0)
|
|
85
|
-
return "/" + resolvedPath;
|
|
86
|
-
else
|
|
87
|
-
return "/";
|
|
88
|
-
else if (resolvedPath.length > 0)
|
|
89
|
-
return resolvedPath;
|
|
90
|
-
else
|
|
91
|
-
return ".";
|
|
92
|
-
}
|
|
93
|
-
function normalize(path) {
|
|
94
|
-
if (assertPath(path), path.length === 0)
|
|
95
|
-
return ".";
|
|
96
|
-
var isAbsolute = path.charCodeAt(0) === 47, trailingSeparator = path.charCodeAt(path.length - 1) === 47;
|
|
97
|
-
if (path = normalizeStringPosix(path, !isAbsolute), path.length === 0 && !isAbsolute)
|
|
98
|
-
path = ".";
|
|
99
|
-
if (path.length > 0 && trailingSeparator)
|
|
100
|
-
path += "/";
|
|
101
|
-
if (isAbsolute)
|
|
102
|
-
return "/" + path;
|
|
103
|
-
return path;
|
|
104
|
-
}
|
|
105
|
-
function isAbsolute(path) {
|
|
106
|
-
return assertPath(path), path.length > 0 && path.charCodeAt(0) === 47;
|
|
107
|
-
}
|
|
108
|
-
function join() {
|
|
109
|
-
if (arguments.length === 0)
|
|
110
|
-
return ".";
|
|
111
|
-
var joined;
|
|
112
|
-
for (var i = 0;i < arguments.length; ++i) {
|
|
113
|
-
var arg = arguments[i];
|
|
114
|
-
if (assertPath(arg), arg.length > 0)
|
|
115
|
-
if (joined === undefined)
|
|
116
|
-
joined = arg;
|
|
117
|
-
else
|
|
118
|
-
joined += "/" + arg;
|
|
119
|
-
}
|
|
120
|
-
if (joined === undefined)
|
|
121
|
-
return ".";
|
|
122
|
-
return normalize(joined);
|
|
123
|
-
}
|
|
124
|
-
function relative(from, to) {
|
|
125
|
-
if (assertPath(from), assertPath(to), from === to)
|
|
126
|
-
return "";
|
|
127
|
-
if (from = resolve(from), to = resolve(to), from === to)
|
|
128
|
-
return "";
|
|
129
|
-
var fromStart = 1;
|
|
130
|
-
for (;fromStart < from.length; ++fromStart)
|
|
131
|
-
if (from.charCodeAt(fromStart) !== 47)
|
|
132
|
-
break;
|
|
133
|
-
var fromEnd = from.length, fromLen = fromEnd - fromStart, toStart = 1;
|
|
134
|
-
for (;toStart < to.length; ++toStart)
|
|
135
|
-
if (to.charCodeAt(toStart) !== 47)
|
|
136
|
-
break;
|
|
137
|
-
var toEnd = to.length, toLen = toEnd - toStart, length = fromLen < toLen ? fromLen : toLen, lastCommonSep = -1, i = 0;
|
|
138
|
-
for (;i <= length; ++i) {
|
|
139
|
-
if (i === length) {
|
|
140
|
-
if (toLen > length) {
|
|
141
|
-
if (to.charCodeAt(toStart + i) === 47)
|
|
142
|
-
return to.slice(toStart + i + 1);
|
|
143
|
-
else if (i === 0)
|
|
144
|
-
return to.slice(toStart + i);
|
|
145
|
-
} else if (fromLen > length) {
|
|
146
|
-
if (from.charCodeAt(fromStart + i) === 47)
|
|
147
|
-
lastCommonSep = i;
|
|
148
|
-
else if (i === 0)
|
|
149
|
-
lastCommonSep = 0;
|
|
150
|
-
}
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
153
|
-
var fromCode = from.charCodeAt(fromStart + i), toCode = to.charCodeAt(toStart + i);
|
|
154
|
-
if (fromCode !== toCode)
|
|
155
|
-
break;
|
|
156
|
-
else if (fromCode === 47)
|
|
157
|
-
lastCommonSep = i;
|
|
158
|
-
}
|
|
159
|
-
var out = "";
|
|
160
|
-
for (i = fromStart + lastCommonSep + 1;i <= fromEnd; ++i)
|
|
161
|
-
if (i === fromEnd || from.charCodeAt(i) === 47)
|
|
162
|
-
if (out.length === 0)
|
|
163
|
-
out += "..";
|
|
164
|
-
else
|
|
165
|
-
out += "/..";
|
|
166
|
-
if (out.length > 0)
|
|
167
|
-
return out + to.slice(toStart + lastCommonSep);
|
|
168
|
-
else {
|
|
169
|
-
if (toStart += lastCommonSep, to.charCodeAt(toStart) === 47)
|
|
170
|
-
++toStart;
|
|
171
|
-
return to.slice(toStart);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
function _makeLong(path) {
|
|
175
|
-
return path;
|
|
176
|
-
}
|
|
177
|
-
function dirname(path) {
|
|
178
|
-
if (assertPath(path), path.length === 0)
|
|
179
|
-
return ".";
|
|
180
|
-
var code = path.charCodeAt(0), hasRoot = code === 47, end = -1, matchedSlash = true;
|
|
181
|
-
for (var i = path.length - 1;i >= 1; --i)
|
|
182
|
-
if (code = path.charCodeAt(i), code === 47) {
|
|
183
|
-
if (!matchedSlash) {
|
|
184
|
-
end = i;
|
|
185
|
-
break;
|
|
186
|
-
}
|
|
187
|
-
} else
|
|
188
|
-
matchedSlash = false;
|
|
189
|
-
if (end === -1)
|
|
190
|
-
return hasRoot ? "/" : ".";
|
|
191
|
-
if (hasRoot && end === 1)
|
|
192
|
-
return "//";
|
|
193
|
-
return path.slice(0, end);
|
|
194
|
-
}
|
|
195
|
-
function basename(path, ext) {
|
|
196
|
-
if (ext !== undefined && typeof ext !== "string")
|
|
197
|
-
throw TypeError('"ext" argument must be a string');
|
|
198
|
-
assertPath(path);
|
|
199
|
-
var start = 0, end = -1, matchedSlash = true, i;
|
|
200
|
-
if (ext !== undefined && ext.length > 0 && ext.length <= path.length) {
|
|
201
|
-
if (ext.length === path.length && ext === path)
|
|
202
|
-
return "";
|
|
203
|
-
var extIdx = ext.length - 1, firstNonSlashEnd = -1;
|
|
204
|
-
for (i = path.length - 1;i >= 0; --i) {
|
|
205
|
-
var code = path.charCodeAt(i);
|
|
206
|
-
if (code === 47) {
|
|
207
|
-
if (!matchedSlash) {
|
|
208
|
-
start = i + 1;
|
|
209
|
-
break;
|
|
210
|
-
}
|
|
211
|
-
} else {
|
|
212
|
-
if (firstNonSlashEnd === -1)
|
|
213
|
-
matchedSlash = false, firstNonSlashEnd = i + 1;
|
|
214
|
-
if (extIdx >= 0)
|
|
215
|
-
if (code === ext.charCodeAt(extIdx)) {
|
|
216
|
-
if (--extIdx === -1)
|
|
217
|
-
end = i;
|
|
218
|
-
} else
|
|
219
|
-
extIdx = -1, end = firstNonSlashEnd;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
if (start === end)
|
|
223
|
-
end = firstNonSlashEnd;
|
|
224
|
-
else if (end === -1)
|
|
225
|
-
end = path.length;
|
|
226
|
-
return path.slice(start, end);
|
|
227
|
-
} else {
|
|
228
|
-
for (i = path.length - 1;i >= 0; --i)
|
|
229
|
-
if (path.charCodeAt(i) === 47) {
|
|
230
|
-
if (!matchedSlash) {
|
|
231
|
-
start = i + 1;
|
|
232
|
-
break;
|
|
233
|
-
}
|
|
234
|
-
} else if (end === -1)
|
|
235
|
-
matchedSlash = false, end = i + 1;
|
|
236
|
-
if (end === -1)
|
|
237
|
-
return "";
|
|
238
|
-
return path.slice(start, end);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
function extname(path) {
|
|
242
|
-
assertPath(path);
|
|
243
|
-
var startDot = -1, startPart = 0, end = -1, matchedSlash = true, preDotState = 0;
|
|
244
|
-
for (var i = path.length - 1;i >= 0; --i) {
|
|
245
|
-
var code = path.charCodeAt(i);
|
|
246
|
-
if (code === 47) {
|
|
247
|
-
if (!matchedSlash) {
|
|
248
|
-
startPart = i + 1;
|
|
249
|
-
break;
|
|
250
|
-
}
|
|
251
|
-
continue;
|
|
252
|
-
}
|
|
253
|
-
if (end === -1)
|
|
254
|
-
matchedSlash = false, end = i + 1;
|
|
255
|
-
if (code === 46) {
|
|
256
|
-
if (startDot === -1)
|
|
257
|
-
startDot = i;
|
|
258
|
-
else if (preDotState !== 1)
|
|
259
|
-
preDotState = 1;
|
|
260
|
-
} else if (startDot !== -1)
|
|
261
|
-
preDotState = -1;
|
|
262
|
-
}
|
|
263
|
-
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1)
|
|
264
|
-
return "";
|
|
265
|
-
return path.slice(startDot, end);
|
|
266
|
-
}
|
|
267
|
-
function format(pathObject) {
|
|
268
|
-
if (pathObject === null || typeof pathObject !== "object")
|
|
269
|
-
throw TypeError('The "pathObject" argument must be of type Object. Received type ' + typeof pathObject);
|
|
270
|
-
return _format("/", pathObject);
|
|
271
|
-
}
|
|
272
|
-
function parse(path) {
|
|
273
|
-
assertPath(path);
|
|
274
|
-
var ret = { root: "", dir: "", base: "", ext: "", name: "" };
|
|
275
|
-
if (path.length === 0)
|
|
276
|
-
return ret;
|
|
277
|
-
var code = path.charCodeAt(0), isAbsolute2 = code === 47, start;
|
|
278
|
-
if (isAbsolute2)
|
|
279
|
-
ret.root = "/", start = 1;
|
|
280
|
-
else
|
|
281
|
-
start = 0;
|
|
282
|
-
var startDot = -1, startPart = 0, end = -1, matchedSlash = true, i = path.length - 1, preDotState = 0;
|
|
283
|
-
for (;i >= start; --i) {
|
|
284
|
-
if (code = path.charCodeAt(i), code === 47) {
|
|
285
|
-
if (!matchedSlash) {
|
|
286
|
-
startPart = i + 1;
|
|
287
|
-
break;
|
|
288
|
-
}
|
|
289
|
-
continue;
|
|
290
|
-
}
|
|
291
|
-
if (end === -1)
|
|
292
|
-
matchedSlash = false, end = i + 1;
|
|
293
|
-
if (code === 46) {
|
|
294
|
-
if (startDot === -1)
|
|
295
|
-
startDot = i;
|
|
296
|
-
else if (preDotState !== 1)
|
|
297
|
-
preDotState = 1;
|
|
298
|
-
} else if (startDot !== -1)
|
|
299
|
-
preDotState = -1;
|
|
300
|
-
}
|
|
301
|
-
if (startDot === -1 || end === -1 || preDotState === 0 || preDotState === 1 && startDot === end - 1 && startDot === startPart + 1) {
|
|
302
|
-
if (end !== -1)
|
|
303
|
-
if (startPart === 0 && isAbsolute2)
|
|
304
|
-
ret.base = ret.name = path.slice(1, end);
|
|
305
|
-
else
|
|
306
|
-
ret.base = ret.name = path.slice(startPart, end);
|
|
307
|
-
} else {
|
|
308
|
-
if (startPart === 0 && isAbsolute2)
|
|
309
|
-
ret.name = path.slice(1, startDot), ret.base = path.slice(1, end);
|
|
310
|
-
else
|
|
311
|
-
ret.name = path.slice(startPart, startDot), ret.base = path.slice(startPart, end);
|
|
312
|
-
ret.ext = path.slice(startDot, end);
|
|
313
|
-
}
|
|
314
|
-
if (startPart > 0)
|
|
315
|
-
ret.dir = path.slice(0, startPart - 1);
|
|
316
|
-
else if (isAbsolute2)
|
|
317
|
-
ret.dir = "/";
|
|
318
|
-
return ret;
|
|
319
|
-
}
|
|
320
|
-
var sep = "/";
|
|
321
|
-
var delimiter = ":";
|
|
322
|
-
var posix = ((p) => (p.posix = p, p))({ resolve, normalize, isAbsolute, join, relative, _makeLong, dirname, basename, extname, format, parse, sep, delimiter, win32: null, posix: null });
|
|
323
|
-
|
|
324
|
-
// index.ts
|
|
325
|
-
import * as tsMorph from "ts-morph";
|
|
326
|
-
var args = process.argv.slice(2);
|
|
327
|
-
var source = args[0];
|
|
328
|
-
var outPut = args[1] || "client-api.ts";
|
|
329
|
-
if (!source) {
|
|
330
|
-
console.error("Please provide a source URL or file path.");
|
|
331
|
-
process.exit(1);
|
|
332
|
-
}
|
|
333
|
-
var isUrl = (str) => {
|
|
334
|
-
try {
|
|
335
|
-
new URL(str);
|
|
336
|
-
return true;
|
|
337
|
-
} catch {
|
|
338
|
-
return false;
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
async function generate() {
|
|
342
|
-
if (!source)
|
|
343
|
-
return;
|
|
344
|
-
if (isUrl(source) === false) {
|
|
345
|
-
source = resolve(process.cwd(), source);
|
|
346
|
-
}
|
|
347
|
-
console.log(`Generating API client from ${source}...`);
|
|
348
|
-
const ast = await openapiTS(source);
|
|
349
|
-
const contents = astToString(ast);
|
|
350
|
-
const project = new tsMorph.Project;
|
|
351
|
-
const sourceFile = project.createSourceFile(resolve(process.cwd(), outPut), contents, {
|
|
352
|
-
overwrite: true
|
|
353
|
-
});
|
|
354
|
-
sourceFile.addTypeAlias({
|
|
355
|
-
name: "RestMethod",
|
|
356
|
-
isExported: true,
|
|
357
|
-
type: '"get" | "post" | "put" | "delete" | "patch"'
|
|
358
|
-
});
|
|
359
|
-
sourceFile.addTypeAlias({
|
|
360
|
-
name: "KeyPaths",
|
|
361
|
-
isExported: true,
|
|
362
|
-
type: "keyof paths"
|
|
363
|
-
});
|
|
364
|
-
sourceFile.addTypeAlias({
|
|
365
|
-
name: "ExtractPathParams",
|
|
366
|
-
isExported: true,
|
|
367
|
-
typeParameters: ["T extends KeyPaths", "K extends RestMethod"],
|
|
368
|
-
type: "paths[T][K] extends { parameters: { path?: infer P } } ? P : never"
|
|
369
|
-
});
|
|
370
|
-
sourceFile.addTypeAlias({
|
|
371
|
-
name: "ExtractQueryParams",
|
|
372
|
-
isExported: true,
|
|
373
|
-
typeParameters: ["T extends KeyPaths", "K extends RestMethod"],
|
|
374
|
-
type: "paths[T][K] extends { parameters: { query?: infer Q } } ? Q : never"
|
|
375
|
-
});
|
|
376
|
-
sourceFile.addTypeAlias({
|
|
377
|
-
name: "ExtractHeaderParams",
|
|
378
|
-
isExported: true,
|
|
379
|
-
typeParameters: ["T extends KeyPaths", "K extends RestMethod"],
|
|
380
|
-
type: "paths[T][K] extends { parameters: { header?: infer H } } ? H : never"
|
|
381
|
-
});
|
|
382
|
-
sourceFile.addTypeAlias({
|
|
383
|
-
name: "ExtractBody",
|
|
384
|
-
isExported: true,
|
|
385
|
-
typeParameters: ["T extends KeyPaths", "K extends RestMethod"],
|
|
386
|
-
type: `paths[T][K] extends {
|
|
1
|
+
import y,{astToString as m}from"openapi-typescript";import h from"ora";import{resolve as r}from"path";import*as e from"ts-morph";var o=process.argv.slice(2),a=o[0],p=o[1]||"client-api.ts";if(!a)console.error("Please provide a source URL or file path."),process.exit(1);var u=(s)=>{try{return new URL(s),!0}catch{return!1}};async function c(){if(!a)return;if(u(a)===!1)a=r(process.cwd(),a);let s=h(`Generating API client from ${a}...`).start(),i=await y(a),d=m(i),n=new e.Project,t=n.createSourceFile(r(process.cwd(),p),d,{overwrite:!0});t.addTypeAlias({name:"RestMethod",isExported:!0,type:'"get" | "post" | "put" | "delete" | "patch"'}),t.addTypeAlias({name:"KeyPaths",isExported:!0,type:"keyof paths"}),t.addTypeAlias({name:"ExtractPathParams",isExported:!0,typeParameters:["T extends KeyPaths","K extends RestMethod"],type:"paths[T][K] extends { parameters: { path?: infer P } } ? P : never"}),t.addTypeAlias({name:"ExtractQueryParams",isExported:!0,typeParameters:["T extends KeyPaths","K extends RestMethod"],type:"paths[T][K] extends { parameters: { query?: infer Q } } ? Q : never"}),t.addTypeAlias({name:"ExtractHeaderParams",isExported:!0,typeParameters:["T extends KeyPaths","K extends RestMethod"],type:"paths[T][K] extends { parameters: { header?: infer H } } ? H : never"}),t.addTypeAlias({name:"ExtractBody",isExported:!0,typeParameters:["T extends KeyPaths","K extends RestMethod"],type:`paths[T][K] extends {
|
|
387
2
|
requestBody: { content: { "application/json": infer B } };
|
|
388
3
|
}
|
|
389
4
|
? B
|
|
390
|
-
: never`
|
|
391
|
-
});
|
|
392
|
-
sourceFile.addTypeAlias({
|
|
393
|
-
name: "APIResponse",
|
|
394
|
-
isExported: true,
|
|
395
|
-
typeParameters: ["T extends KeyPaths", "K extends RestMethod"],
|
|
396
|
-
type: `paths[T][K] extends {
|
|
5
|
+
: never`}),t.addTypeAlias({name:"APIResponse",isExported:!0,typeParameters:["T extends KeyPaths","K extends RestMethod"],type:`paths[T][K] extends {
|
|
397
6
|
responses:
|
|
398
7
|
| { content: { "application/json": infer R } }
|
|
399
8
|
| { [code: number]: { content: { "application/json": infer R } } };
|
|
400
9
|
}
|
|
401
10
|
? R
|
|
402
|
-
: unknown`
|
|
403
|
-
});
|
|
404
|
-
sourceFile.addTypeAlias({
|
|
405
|
-
name: "ApiPayload",
|
|
406
|
-
isExported: true,
|
|
407
|
-
typeParameters: ["T extends KeyPaths", "K extends RestMethod"],
|
|
408
|
-
type: `{
|
|
11
|
+
: unknown`}),t.addTypeAlias({name:"ApiPayload",isExported:!0,typeParameters:["T extends KeyPaths","K extends RestMethod"],type:`{
|
|
409
12
|
path?: ExtractPathParams<T, K>;
|
|
410
13
|
query?: ExtractQueryParams<T, K>;
|
|
411
14
|
body?: K extends "post" | "put" | "patch" ? ExtractBody<T, K> : never;
|
|
412
15
|
headers?: ExtractHeaderParams<T, K>;
|
|
413
|
-
}`
|
|
414
|
-
});
|
|
415
|
-
sourceFile.addTypeAlias({
|
|
416
|
-
name: "ApiClientType",
|
|
417
|
-
isExported: true,
|
|
418
|
-
type: `{
|
|
16
|
+
}`}),t.addTypeAlias({name:"ApiClientType",isExported:!0,type:`{
|
|
419
17
|
[K in RestMethod]: <T extends KeyPaths>(
|
|
420
18
|
path: T,
|
|
421
19
|
payload?: ApiPayload<T, K>,
|
|
422
20
|
) => Promise<APIResponse<T, K>>;
|
|
423
|
-
}`
|
|
424
|
-
});
|
|
425
|
-
sourceFile.addTypeAlias({
|
|
426
|
-
name: "TypePaths",
|
|
427
|
-
typeParameters: ["T extends RestMethod"],
|
|
428
|
-
type: `{
|
|
21
|
+
}`}),t.addTypeAlias({name:"TypePaths",typeParameters:["T extends RestMethod"],type:`{
|
|
429
22
|
[K in KeyPaths]: paths[K] extends { [M in T]: unknown } ? K : never;
|
|
430
|
-
}[KeyPaths]`
|
|
431
|
-
});
|
|
432
|
-
sourceFile.addClass({
|
|
433
|
-
name: "RestApiClient",
|
|
434
|
-
isExported: true,
|
|
435
|
-
ctors: [
|
|
436
|
-
{
|
|
437
|
-
parameters: [
|
|
438
|
-
{ name: "basePath", type: "string", scope: tsMorph.Scope.Private },
|
|
439
|
-
{
|
|
440
|
-
name: "option",
|
|
441
|
-
type: "RequestInit",
|
|
442
|
-
hasQuestionToken: true,
|
|
443
|
-
scope: tsMorph.Scope.Private
|
|
444
|
-
}
|
|
445
|
-
]
|
|
446
|
-
}
|
|
447
|
-
],
|
|
448
|
-
methods: [
|
|
449
|
-
{
|
|
450
|
-
name: "fetcher",
|
|
451
|
-
scope: tsMorph.Scope.Public,
|
|
452
|
-
isAsync: true,
|
|
453
|
-
parameters: [
|
|
454
|
-
{ name: "input", type: "RequestInfo" },
|
|
455
|
-
{ name: "init", type: "RequestInit", hasQuestionToken: true }
|
|
456
|
-
],
|
|
457
|
-
statements: `const headers = {
|
|
23
|
+
}[KeyPaths]`}),t.addClass({name:"RestApiClient",isExported:!0,ctors:[{parameters:[{name:"basePath",type:"string",scope:e.Scope.Private},{name:"option",type:"RequestInit",hasQuestionToken:!0,scope:e.Scope.Private}]}],methods:[{name:"fetcher",scope:e.Scope.Public,isAsync:!0,parameters:[{name:"input",type:"RequestInfo"},{name:"init",type:"RequestInit",hasQuestionToken:!0}],statements:`const headers = {
|
|
458
24
|
"Content-Type": "application/json",
|
|
459
25
|
...init?.headers,
|
|
460
26
|
};
|
|
@@ -466,22 +32,7 @@ async function generate() {
|
|
|
466
32
|
\`API request failed: \${response.status} \${response.statusText} - \${errorBody}\`,
|
|
467
33
|
);
|
|
468
34
|
}
|
|
469
|
-
return response.json();`
|
|
470
|
-
},
|
|
471
|
-
{
|
|
472
|
-
name: "request",
|
|
473
|
-
typeParameters: ["M extends RestMethod", "P extends TypePaths<M>"],
|
|
474
|
-
parameters: [
|
|
475
|
-
{ name: "method", type: "M" },
|
|
476
|
-
{ name: "path", type: "P" },
|
|
477
|
-
{
|
|
478
|
-
name: "init",
|
|
479
|
-
type: "ApiPayload<P, M>",
|
|
480
|
-
initializer: "{} as ApiPayload<P, M>"
|
|
481
|
-
}
|
|
482
|
-
],
|
|
483
|
-
returnType: "Promise<APIResponse<P, M>>",
|
|
484
|
-
statements: `const url = new URL(this.basePath + String(path));
|
|
35
|
+
return response.json();`},{name:"request",typeParameters:["M extends RestMethod","P extends TypePaths<M>"],parameters:[{name:"method",type:"M"},{name:"path",type:"P"},{name:"init",type:"ApiPayload<P, M>",initializer:"{} as ApiPayload<P, M>"}],returnType:"Promise<APIResponse<P, M>>",statements:`const url = new URL(this.basePath + String(path));
|
|
485
36
|
|
|
486
37
|
url.pathname = this.buildPathUrl(url.pathname, init.path);
|
|
487
38
|
this.appendQueryParams(url, init.query);
|
|
@@ -498,134 +49,21 @@ async function generate() {
|
|
|
498
49
|
|
|
499
50
|
return this.fetcher(url.toString(), requestInit) as Promise<
|
|
500
51
|
APIResponse<P, M>
|
|
501
|
-
>;`
|
|
502
|
-
},
|
|
503
|
-
{
|
|
504
|
-
name: "get",
|
|
505
|
-
scope: tsMorph.Scope.Public,
|
|
506
|
-
typeParameters: ['T extends TypePaths<"get">'],
|
|
507
|
-
parameters: [
|
|
508
|
-
{ name: "path", type: "T" },
|
|
509
|
-
{
|
|
510
|
-
name: "payload",
|
|
511
|
-
type: 'ApiPayload<T, "get">',
|
|
512
|
-
hasQuestionToken: true
|
|
513
|
-
}
|
|
514
|
-
],
|
|
515
|
-
returnType: 'Promise<APIResponse<T, "get">>',
|
|
516
|
-
statements: 'return this.request("get", path, payload);'
|
|
517
|
-
},
|
|
518
|
-
{
|
|
519
|
-
name: "post",
|
|
520
|
-
scope: tsMorph.Scope.Public,
|
|
521
|
-
typeParameters: ['T extends TypePaths<"post">'],
|
|
522
|
-
parameters: [
|
|
523
|
-
{ name: "path", type: "T" },
|
|
524
|
-
{
|
|
525
|
-
name: "payload",
|
|
526
|
-
type: 'ApiPayload<T, "post">',
|
|
527
|
-
hasQuestionToken: true
|
|
528
|
-
}
|
|
529
|
-
],
|
|
530
|
-
returnType: 'Promise<APIResponse<T, "post">>',
|
|
531
|
-
statements: 'return this.request("post", path, payload);'
|
|
532
|
-
},
|
|
533
|
-
{
|
|
534
|
-
name: "put",
|
|
535
|
-
scope: tsMorph.Scope.Public,
|
|
536
|
-
typeParameters: ['T extends TypePaths<"put">'],
|
|
537
|
-
parameters: [
|
|
538
|
-
{ name: "path", type: "T" },
|
|
539
|
-
{
|
|
540
|
-
name: "payload",
|
|
541
|
-
type: 'ApiPayload<T, "put">',
|
|
542
|
-
hasQuestionToken: true
|
|
543
|
-
}
|
|
544
|
-
],
|
|
545
|
-
returnType: 'Promise<APIResponse<T, "put">>',
|
|
546
|
-
statements: 'return this.request("put", path, payload);'
|
|
547
|
-
},
|
|
548
|
-
{
|
|
549
|
-
name: "delete",
|
|
550
|
-
scope: tsMorph.Scope.Public,
|
|
551
|
-
typeParameters: ['T extends TypePaths<"delete">'],
|
|
552
|
-
parameters: [
|
|
553
|
-
{ name: "path", type: "T" },
|
|
554
|
-
{
|
|
555
|
-
name: "payload",
|
|
556
|
-
type: 'ApiPayload<T, "delete">',
|
|
557
|
-
hasQuestionToken: true
|
|
558
|
-
}
|
|
559
|
-
],
|
|
560
|
-
returnType: 'Promise<APIResponse<T, "delete">>',
|
|
561
|
-
statements: 'return this.request("delete", path, payload);'
|
|
562
|
-
},
|
|
563
|
-
{
|
|
564
|
-
name: "patch",
|
|
565
|
-
scope: tsMorph.Scope.Public,
|
|
566
|
-
typeParameters: ['T extends TypePaths<"patch">'],
|
|
567
|
-
parameters: [
|
|
568
|
-
{ name: "path", type: "T" },
|
|
569
|
-
{
|
|
570
|
-
name: "payload",
|
|
571
|
-
type: 'ApiPayload<T, "patch">',
|
|
572
|
-
hasQuestionToken: true
|
|
573
|
-
}
|
|
574
|
-
],
|
|
575
|
-
returnType: 'Promise<APIResponse<T, "patch">>',
|
|
576
|
-
statements: 'return this.request("patch", path, payload);'
|
|
577
|
-
},
|
|
578
|
-
{
|
|
579
|
-
name: "buildPathUrl",
|
|
580
|
-
scope: tsMorph.Scope.Private,
|
|
581
|
-
parameters: [
|
|
582
|
-
{ name: "basePath", type: "string" },
|
|
583
|
-
{ name: "pathParams", type: "unknown", hasQuestionToken: true }
|
|
584
|
-
],
|
|
585
|
-
returnType: "string",
|
|
586
|
-
statements: `let pathname = basePath;
|
|
52
|
+
>;`},{name:"get",scope:e.Scope.Public,typeParameters:['T extends TypePaths<"get">'],parameters:[{name:"path",type:"T"},{name:"payload",type:'ApiPayload<T, "get">',hasQuestionToken:!0}],returnType:'Promise<APIResponse<T, "get">>',statements:'return this.request("get", path, payload);'},{name:"post",scope:e.Scope.Public,typeParameters:['T extends TypePaths<"post">'],parameters:[{name:"path",type:"T"},{name:"payload",type:'ApiPayload<T, "post">',hasQuestionToken:!0}],returnType:'Promise<APIResponse<T, "post">>',statements:'return this.request("post", path, payload);'},{name:"put",scope:e.Scope.Public,typeParameters:['T extends TypePaths<"put">'],parameters:[{name:"path",type:"T"},{name:"payload",type:'ApiPayload<T, "put">',hasQuestionToken:!0}],returnType:'Promise<APIResponse<T, "put">>',statements:'return this.request("put", path, payload);'},{name:"delete",scope:e.Scope.Public,typeParameters:['T extends TypePaths<"delete">'],parameters:[{name:"path",type:"T"},{name:"payload",type:'ApiPayload<T, "delete">',hasQuestionToken:!0}],returnType:'Promise<APIResponse<T, "delete">>',statements:'return this.request("delete", path, payload);'},{name:"patch",scope:e.Scope.Public,typeParameters:['T extends TypePaths<"patch">'],parameters:[{name:"path",type:"T"},{name:"payload",type:'ApiPayload<T, "patch">',hasQuestionToken:!0}],returnType:'Promise<APIResponse<T, "patch">>',statements:'return this.request("patch", path, payload);'},{name:"buildPathUrl",scope:e.Scope.Private,parameters:[{name:"basePath",type:"string"},{name:"pathParams",type:"unknown",hasQuestionToken:!0}],returnType:"string",statements:`let pathname = basePath;
|
|
587
53
|
if (pathParams != null) {
|
|
588
54
|
const params = pathParams as Record<string, unknown>;
|
|
589
55
|
pathname = decodeURIComponent(pathname).replace(/{(w+)}/g, (_, key) =>
|
|
590
56
|
encodeURIComponent(String(params[key])),
|
|
591
57
|
);
|
|
592
58
|
}
|
|
593
|
-
return pathname;`
|
|
594
|
-
},
|
|
595
|
-
{
|
|
596
|
-
name: "prepareBody",
|
|
597
|
-
scope: tsMorph.Scope.Private,
|
|
598
|
-
parameters: [
|
|
599
|
-
{ name: "method", type: "RestMethod" },
|
|
600
|
-
{ name: "body", type: "unknown", hasQuestionToken: true }
|
|
601
|
-
],
|
|
602
|
-
returnType: "string | undefined",
|
|
603
|
-
statements: `if (body && ["post", "put", "patch"].includes(method)) {
|
|
59
|
+
return pathname;`},{name:"prepareBody",scope:e.Scope.Private,parameters:[{name:"method",type:"RestMethod"},{name:"body",type:"unknown",hasQuestionToken:!0}],returnType:"string | undefined",statements:`if (body && ["post", "put", "patch"].includes(method)) {
|
|
604
60
|
return JSON.stringify(body);
|
|
605
61
|
}
|
|
606
|
-
return undefined;`
|
|
607
|
-
},
|
|
608
|
-
{
|
|
609
|
-
name: "appendQueryParams",
|
|
610
|
-
scope: tsMorph.Scope.Private,
|
|
611
|
-
parameters: [
|
|
612
|
-
{ name: "url", type: "URL" },
|
|
613
|
-
{ name: "queryParams", type: "unknown", hasQuestionToken: true }
|
|
614
|
-
],
|
|
615
|
-
returnType: "void",
|
|
616
|
-
statements: `if (queryParams != null) {
|
|
62
|
+
return undefined;`},{name:"appendQueryParams",scope:e.Scope.Private,parameters:[{name:"url",type:"URL"},{name:"queryParams",type:"unknown",hasQuestionToken:!0}],returnType:"void",statements:`if (queryParams != null) {
|
|
617
63
|
const params = queryParams as Record<string, unknown>;
|
|
618
64
|
for (const [key, value] of Object.entries(params)) {
|
|
619
65
|
if (value !== undefined && value !== null) {
|
|
620
66
|
url.searchParams.append(key, String(value));
|
|
621
67
|
}
|
|
622
68
|
}
|
|
623
|
-
}`
|
|
624
|
-
}
|
|
625
|
-
]
|
|
626
|
-
});
|
|
627
|
-
await sourceFile.formatText();
|
|
628
|
-
await project.save();
|
|
629
|
-
console.log(`API client generated at ${outPut}`);
|
|
630
|
-
}
|
|
631
|
-
generate();
|
|
69
|
+
}`}]}),await t.formatText(),await n.save(),s.stopAndPersist({symbol:"✔",text:`API client generated at ${r(process.cwd(),p)}`})}c();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-swagger-client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Generate fully type-safe REST API clients from OpenAPI/Swagger specifications",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"dist"
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
|
-
"build": "bun build index.ts --outdir dist --external openapi-typescript --external ts-morph",
|
|
15
|
+
"build": "bun build index.ts --minify --outdir dist --target=node --external openapi-typescript --external ts-morph --external ora",
|
|
16
16
|
"typecheck": "tsc --noEmit",
|
|
17
17
|
"prepublishOnly": "bun run build"
|
|
18
18
|
},
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
50
|
"openapi-typescript": "^7.10.1",
|
|
51
|
+
"ora": "^9.1.0",
|
|
51
52
|
"ts-morph": "^27.0.2"
|
|
52
53
|
}
|
|
53
54
|
}
|