typedapi-client-helpers 0.1.15 → 0.2.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 +220 -490
- package/dist/index.cjs +274 -47
- package/dist/index.d.cts +79 -95
- package/dist/index.d.ts +79 -95
- package/dist/index.js +267 -47
- package/package.json +54 -12
- package/scripts/generate-api-minimal.mjs +476 -959
- package/scripts/openapi-generator/controller-template.mjs +246 -0
- package/scripts/openapi-generator/http-client-template.mjs +34 -0
- package/scripts/openapi-generator/index.mjs +113 -0
- package/scripts/openapi-generator/method-template.mjs +440 -0
- package/scripts/openapi-generator/names.mjs +145 -0
- package/scripts/openapi-generator/openapi-utils.mjs +147 -0
- package/scripts/openapi-generator/schema.mjs +455 -0
- package/bin/typedapi-generate.js +0 -3
- package/dist/api/generated/Import.d.ts +0 -22
- package/dist/api/generated/Import.d.ts.map +0 -1
- package/dist/api/generated/Import.js +0 -48
- package/dist/api/generated/Import.js.map +0 -1
- package/dist/api/generated/ImportRoute.d.ts +0 -30
- package/dist/api/generated/ImportRoute.d.ts.map +0 -1
- package/dist/api/generated/ImportRoute.js +0 -13
- package/dist/api/generated/ImportRoute.js.map +0 -1
- package/dist/api/generated/Order.d.ts +0 -38
- package/dist/api/generated/Order.d.ts.map +0 -1
- package/dist/api/generated/Order.js +0 -75
- package/dist/api/generated/Order.js.map +0 -1
- package/dist/api/generated/OrderRoute.d.ts +0 -83
- package/dist/api/generated/OrderRoute.d.ts.map +0 -1
- package/dist/api/generated/OrderRoute.js +0 -13
- package/dist/api/generated/OrderRoute.js.map +0 -1
- package/dist/api/generated/Product.d.ts +0 -62
- package/dist/api/generated/Product.d.ts.map +0 -1
- package/dist/api/generated/Product.js +0 -114
- package/dist/api/generated/Product.js.map +0 -1
- package/dist/api/generated/ProductRoute.d.ts +0 -140
- package/dist/api/generated/ProductRoute.d.ts.map +0 -1
- package/dist/api/generated/ProductRoute.js +0 -13
- package/dist/api/generated/ProductRoute.js.map +0 -1
- package/dist/api/generated/Report.d.ts +0 -14
- package/dist/api/generated/Report.d.ts.map +0 -1
- package/dist/api/generated/Report.js +0 -32
- package/dist/api/generated/Report.js.map +0 -1
- package/dist/api/generated/ReportRoute.d.ts +0 -23
- package/dist/api/generated/ReportRoute.d.ts.map +0 -1
- package/dist/api/generated/ReportRoute.js +0 -13
- package/dist/api/generated/ReportRoute.js.map +0 -1
- package/dist/api/generated/Supplier.d.ts +0 -46
- package/dist/api/generated/Supplier.d.ts.map +0 -1
- package/dist/api/generated/Supplier.js +0 -87
- package/dist/api/generated/Supplier.js.map +0 -1
- package/dist/api/generated/SupplierRoute.d.ts +0 -101
- package/dist/api/generated/SupplierRoute.d.ts.map +0 -1
- package/dist/api/generated/SupplierRoute.js +0 -13
- package/dist/api/generated/SupplierRoute.js.map +0 -1
- package/dist/api/generated/data-contracts.d.ts +0 -277
- package/dist/api/generated/data-contracts.d.ts.map +0 -1
- package/dist/api/generated/data-contracts.js +0 -26
- package/dist/api/generated/data-contracts.js.map +0 -1
- package/dist/api/generated/http-client.d.ts +0 -61
- package/dist/api/generated/http-client.d.ts.map +0 -1
- package/dist/api/generated/http-client.js +0 -171
- package/dist/api/generated/http-client.js.map +0 -1
- package/dist/api/index.d.ts +0 -8
- package/dist/api/index.d.ts.map +0 -1
- package/dist/api/index.js +0 -8
- package/dist/api/index.js.map +0 -1
- package/dist/api/methods/Import.api.d.ts +0 -6
- package/dist/api/methods/Import.api.d.ts.map +0 -1
- package/dist/api/methods/Import.api.js +0 -27
- package/dist/api/methods/Import.api.js.map +0 -1
- package/dist/api/methods/Order.api.d.ts +0 -29
- package/dist/api/methods/Order.api.d.ts.map +0 -1
- package/dist/api/methods/Order.api.js +0 -52
- package/dist/api/methods/Order.api.js.map +0 -1
- package/dist/api/methods/Product.api.d.ts +0 -39
- package/dist/api/methods/Product.api.d.ts.map +0 -1
- package/dist/api/methods/Product.api.js +0 -69
- package/dist/api/methods/Product.api.js.map +0 -1
- package/dist/api/methods/Report.api.d.ts +0 -6
- package/dist/api/methods/Report.api.d.ts.map +0 -1
- package/dist/api/methods/Report.api.js +0 -19
- package/dist/api/methods/Report.api.js.map +0 -1
- package/dist/api/methods/Supplier.api.d.ts +0 -35
- package/dist/api/methods/Supplier.api.d.ts.map +0 -1
- package/dist/api/methods/Supplier.api.js +0 -63
- package/dist/api/methods/Supplier.api.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/interfaces/ApiResult.d.ts +0 -17
- package/dist/interfaces/ApiResult.d.ts.map +0 -1
- package/dist/interfaces/ApiResult.js +0 -2
- package/dist/interfaces/ApiResult.js.map +0 -1
- package/dist/interfaces/Filter.d.ts +0 -31
- package/dist/interfaces/Filter.d.ts.map +0 -1
- package/dist/interfaces/Filter.js +0 -2
- package/dist/interfaces/Filter.js.map +0 -1
- package/dist/interfaces/SortType.d.ts +0 -7
- package/dist/interfaces/SortType.d.ts.map +0 -1
- package/dist/interfaces/SortType.js +0 -2
- package/dist/interfaces/SortType.js.map +0 -1
- package/dist/types/ApiCallOptions.d.ts +0 -9
- package/dist/types/ApiCallOptions.d.ts.map +0 -1
- package/dist/types/ApiCallOptions.js +0 -2
- package/dist/types/ApiCallOptions.js.map +0 -1
- package/dist/types/ApiMethodTypes.d.ts +0 -24
- package/dist/types/ApiMethodTypes.d.ts.map +0 -1
- package/dist/types/ApiMethodTypes.js +0 -2
- package/dist/types/ApiMethodTypes.js.map +0 -1
- package/dist/types/HttpResponse.d.ts +0 -16
- package/dist/types/HttpResponse.d.ts.map +0 -1
- package/dist/types/HttpResponse.js +0 -2
- package/dist/types/HttpResponse.js.map +0 -1
- package/dist/utils/SortTypeFromSortDirection.d.ts +0 -22
- package/dist/utils/SortTypeFromSortDirection.d.ts.map +0 -1
- package/dist/utils/SortTypeFromSortDirection.js +0 -45
- package/dist/utils/SortTypeFromSortDirection.js.map +0 -1
- package/dist/utils/buildQuery.d.ts +0 -11
- package/dist/utils/buildQuery.d.ts.map +0 -1
- package/dist/utils/buildQuery.js +0 -94
- package/dist/utils/buildQuery.js.map +0 -1
- package/dist/utils/extractArgsCallbacksAndParams.d.ts +0 -22
- package/dist/utils/extractArgsCallbacksAndParams.d.ts.map +0 -1
- package/dist/utils/extractArgsCallbacksAndParams.js +0 -44
- package/dist/utils/extractArgsCallbacksAndParams.js.map +0 -1
- package/dist/utils/extractArgsToastsAndParams.d.ts +0 -18
- package/dist/utils/extractArgsToastsAndParams.d.ts.map +0 -1
- package/dist/utils/extractArgsToastsAndParams.js +0 -40
- package/dist/utils/extractArgsToastsAndParams.js.map +0 -1
- package/dist/utils/handleApiResponse.d.ts +0 -9
- package/dist/utils/handleApiResponse.d.ts.map +0 -1
- package/dist/utils/handleApiResponse.js +0 -49
- package/dist/utils/handleApiResponse.js.map +0 -1
- package/dist/utils/toFormData.d.ts +0 -8
- package/dist/utils/toFormData.d.ts.map +0 -1
- package/dist/utils/toFormData.js +0 -68
- package/dist/utils/toFormData.js.map +0 -1
|
@@ -1,959 +1,476 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
process.env.
|
|
40
|
-
|
|
41
|
-
config.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
process.env.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
process.env.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
.
|
|
106
|
-
.
|
|
107
|
-
.
|
|
108
|
-
.
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
})}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
const
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
}
|
|
455
|
-
|
|
456
|
-
function
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
.filter(
|
|
478
|
-
(file) =>
|
|
479
|
-
file.endsWith(".ts") &&
|
|
480
|
-
file !== "http-client.ts" &&
|
|
481
|
-
file !== "data-contracts.ts" &&
|
|
482
|
-
!/route\.ts$/i.test(file) &&
|
|
483
|
-
!file.includes(".api"),
|
|
484
|
-
);
|
|
485
|
-
|
|
486
|
-
const methodExports = [];
|
|
487
|
-
|
|
488
|
-
for (const file of generatedFiles) {
|
|
489
|
-
const filePath = path.join(generatedDir, file);
|
|
490
|
-
const source = fs.readFileSync(filePath, "utf8");
|
|
491
|
-
|
|
492
|
-
const baseName = file.replace(".ts", "");
|
|
493
|
-
const className = baseName.split("-").map(pascalCase).join("");
|
|
494
|
-
|
|
495
|
-
const instanceName = `${className.charAt(0).toLowerCase()}${className.slice(1)}Api`;
|
|
496
|
-
|
|
497
|
-
const paginatedMethods = [];
|
|
498
|
-
const simpleQueryMethods = [];
|
|
499
|
-
const nonQueryMethods = [];
|
|
500
|
-
|
|
501
|
-
const generatedMethods = getGeneratedMethods(source);
|
|
502
|
-
|
|
503
|
-
for (const generatedMethod of generatedMethods) {
|
|
504
|
-
const { methodName, methodSource, isFormData } = generatedMethod;
|
|
505
|
-
|
|
506
|
-
const signatureRegex = new RegExp(
|
|
507
|
-
`${methodName}\\s*=\\s*\\(([^)]*)\\)\\s*=>`,
|
|
508
|
-
"m",
|
|
509
|
-
);
|
|
510
|
-
|
|
511
|
-
const signatureMatch = methodSource.match(signatureRegex);
|
|
512
|
-
|
|
513
|
-
if (!signatureMatch) {
|
|
514
|
-
continue;
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
const params = signatureMatch[1].trim();
|
|
518
|
-
const methodArgumentCount = getGeneratedMethodArgumentCount(params);
|
|
519
|
-
|
|
520
|
-
const returnTypeMatch = methodSource.match(/this\.request<([^,>]+)/m);
|
|
521
|
-
const returnType = returnTypeMatch?.[1] ?? "";
|
|
522
|
-
|
|
523
|
-
const isPaginated =
|
|
524
|
-
returnType.includes("ApiPaginationResponse") ||
|
|
525
|
-
returnType.trim().endsWith("[]");
|
|
526
|
-
|
|
527
|
-
if (params.startsWith("query")) {
|
|
528
|
-
if (isPaginated) {
|
|
529
|
-
paginatedMethods.push(methodName);
|
|
530
|
-
} else {
|
|
531
|
-
simpleQueryMethods.push(methodName);
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
continue;
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
nonQueryMethods.push({
|
|
538
|
-
methodName,
|
|
539
|
-
isFormData,
|
|
540
|
-
methodArgumentCount,
|
|
541
|
-
});
|
|
542
|
-
}
|
|
543
|
-
|
|
544
|
-
const queryTypes = [...paginatedMethods, ...simpleQueryMethods]
|
|
545
|
-
.map((methodName) =>
|
|
546
|
-
`
|
|
547
|
-
export type ${toQueryName(methodName)} =
|
|
548
|
-
NonNullable<
|
|
549
|
-
Parameters<${className}["${methodName}"]>[0]
|
|
550
|
-
>;
|
|
551
|
-
`.trim(),
|
|
552
|
-
)
|
|
553
|
-
.join("\n\n");
|
|
554
|
-
|
|
555
|
-
const hasPaginatedMethods = paginatedMethods.length > 0;
|
|
556
|
-
|
|
557
|
-
const hasFormDataMethods = nonQueryMethods.some(
|
|
558
|
-
({ isFormData }) => isFormData,
|
|
559
|
-
);
|
|
560
|
-
|
|
561
|
-
const hasRegularNonQueryMethods = nonQueryMethods.some(
|
|
562
|
-
({ isFormData }) => !isFormData,
|
|
563
|
-
);
|
|
564
|
-
|
|
565
|
-
const paginatedMethodWrappers = paginatedMethods
|
|
566
|
-
.map((methodName) => {
|
|
567
|
-
if (useFilterFormValues) {
|
|
568
|
-
return `
|
|
569
|
-
export async function ${methodName}(
|
|
570
|
-
filters: FilterFormValues<${toQueryName(methodName)}>[] = [],
|
|
571
|
-
page = 1,
|
|
572
|
-
pageSize = 100,
|
|
573
|
-
sortBy: SortableKeys<
|
|
574
|
-
ExtractResponse<ReturnType<${className}["${methodName}"]>>
|
|
575
|
-
> | null = null,
|
|
576
|
-
sortDirection?: SortDirection,
|
|
577
|
-
options: ApiMethodOptions<
|
|
578
|
-
ExtractResponse<ReturnType<${className}["${methodName}"]>>,
|
|
579
|
-
ExtractError<ReturnType<${className}["${methodName}"]>>,
|
|
580
|
-
RequestParams
|
|
581
|
-
> = {}
|
|
582
|
-
): Promise<ApiResult<ExtractResponse<ReturnType<${className}["${methodName}"]>>>> {
|
|
583
|
-
const { onSuccess, onError, params } = options;
|
|
584
|
-
|
|
585
|
-
return handleApiResponse(
|
|
586
|
-
() =>
|
|
587
|
-
${instanceName}.${methodName}(
|
|
588
|
-
buildQuery<
|
|
589
|
-
${toQueryName(methodName)},
|
|
590
|
-
UnwrapArray<
|
|
591
|
-
ExtractDataIfPaginated<
|
|
592
|
-
ExtractResponse<ReturnType<${className}["${methodName}"]>>
|
|
593
|
-
>
|
|
594
|
-
>
|
|
595
|
-
>(filters, page, pageSize, sortBy, sortDirection),
|
|
596
|
-
params ?? {}
|
|
597
|
-
),
|
|
598
|
-
${callbackOptionsExpression(defaultHandlers)}
|
|
599
|
-
);
|
|
600
|
-
}
|
|
601
|
-
`.trim();
|
|
602
|
-
}
|
|
603
|
-
|
|
604
|
-
return `
|
|
605
|
-
export async function ${methodName}(
|
|
606
|
-
query?: ${toQueryName(methodName)},
|
|
607
|
-
options: ApiMethodOptions<
|
|
608
|
-
ExtractResponse<ReturnType<${className}["${methodName}"]>>,
|
|
609
|
-
ExtractError<ReturnType<${className}["${methodName}"]>>,
|
|
610
|
-
RequestParams
|
|
611
|
-
> = {}
|
|
612
|
-
): Promise<ApiResult<ExtractResponse<ReturnType<${className}["${methodName}"]>>>> {
|
|
613
|
-
const { onSuccess, onError, params } = options;
|
|
614
|
-
|
|
615
|
-
return handleApiResponse(
|
|
616
|
-
() =>
|
|
617
|
-
${instanceName}.${methodName}(
|
|
618
|
-
(query ?? {}) as ${toQueryName(methodName)},
|
|
619
|
-
params ?? {}
|
|
620
|
-
),
|
|
621
|
-
${callbackOptionsExpression(defaultHandlers)}
|
|
622
|
-
);
|
|
623
|
-
}
|
|
624
|
-
`.trim();
|
|
625
|
-
})
|
|
626
|
-
.join("\n\n");
|
|
627
|
-
|
|
628
|
-
const simpleQueryMethodWrappers = simpleQueryMethods
|
|
629
|
-
.map((methodName) =>
|
|
630
|
-
`
|
|
631
|
-
export async function ${methodName}(
|
|
632
|
-
query?: ${toQueryName(methodName)},
|
|
633
|
-
options: ApiMethodOptions<
|
|
634
|
-
ExtractResponse<ReturnType<${className}["${methodName}"]>>,
|
|
635
|
-
ExtractError<ReturnType<${className}["${methodName}"]>>,
|
|
636
|
-
RequestParams
|
|
637
|
-
> = {}
|
|
638
|
-
): Promise<
|
|
639
|
-
ApiResult<
|
|
640
|
-
ExtractResponse<
|
|
641
|
-
ReturnType<
|
|
642
|
-
${className}["${methodName}"]
|
|
643
|
-
>
|
|
644
|
-
>
|
|
645
|
-
>
|
|
646
|
-
> {
|
|
647
|
-
const { onSuccess, onError, params } = options;
|
|
648
|
-
|
|
649
|
-
return handleApiResponse(
|
|
650
|
-
() =>
|
|
651
|
-
${instanceName}.${methodName}(
|
|
652
|
-
(query ?? {}) as ${toQueryName(methodName)},
|
|
653
|
-
params ?? {}
|
|
654
|
-
),
|
|
655
|
-
${callbackOptionsExpression(defaultHandlers)}
|
|
656
|
-
);
|
|
657
|
-
}
|
|
658
|
-
`.trim(),
|
|
659
|
-
)
|
|
660
|
-
.join("\n\n");
|
|
661
|
-
|
|
662
|
-
const nonQueryMethodWrappers = nonQueryMethods
|
|
663
|
-
.map(({ methodName, isFormData, methodArgumentCount }) => {
|
|
664
|
-
if (isFormData) {
|
|
665
|
-
return `
|
|
666
|
-
export async function ${methodName}(
|
|
667
|
-
data: Parameters<
|
|
668
|
-
${className}["${methodName}"]
|
|
669
|
-
>[0],
|
|
670
|
-
options: ApiMethodOptions<
|
|
671
|
-
ExtractResponse<ReturnType<${className}["${methodName}"]>>,
|
|
672
|
-
ExtractError<ReturnType<${className}["${methodName}"]>>,
|
|
673
|
-
RequestParams
|
|
674
|
-
> = {}
|
|
675
|
-
): Promise<
|
|
676
|
-
ApiResult<
|
|
677
|
-
ExtractResponse<
|
|
678
|
-
ReturnType<
|
|
679
|
-
${className}["${methodName}"]
|
|
680
|
-
>
|
|
681
|
-
>
|
|
682
|
-
>
|
|
683
|
-
> {
|
|
684
|
-
const { onSuccess, onError, params } = options;
|
|
685
|
-
const formData = toFormData(data);
|
|
686
|
-
|
|
687
|
-
return handleApiResponse(
|
|
688
|
-
() =>
|
|
689
|
-
${instanceName}.${methodName}(
|
|
690
|
-
formData as unknown as Parameters<
|
|
691
|
-
${className}["${methodName}"]
|
|
692
|
-
>[0],
|
|
693
|
-
params ?? {}
|
|
694
|
-
),
|
|
695
|
-
${callbackOptionsExpression(defaultHandlers)}
|
|
696
|
-
);
|
|
697
|
-
}
|
|
698
|
-
`.trim();
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
return `
|
|
702
|
-
export async function ${methodName}(
|
|
703
|
-
...argsWithOptions: [
|
|
704
|
-
...ApiMethodArguments<
|
|
705
|
-
${className}["${methodName}"],
|
|
706
|
-
RequestParams
|
|
707
|
-
>,
|
|
708
|
-
ApiMethodOptions<
|
|
709
|
-
ExtractResponse<ReturnType<${className}["${methodName}"]>>,
|
|
710
|
-
ExtractError<ReturnType<${className}["${methodName}"]>>,
|
|
711
|
-
RequestParams
|
|
712
|
-
>?
|
|
713
|
-
]
|
|
714
|
-
): Promise<
|
|
715
|
-
ApiResult<
|
|
716
|
-
ExtractResponse<
|
|
717
|
-
ReturnType<
|
|
718
|
-
${className}["${methodName}"]
|
|
719
|
-
>
|
|
720
|
-
>
|
|
721
|
-
>
|
|
722
|
-
> {
|
|
723
|
-
const args = [...argsWithOptions] as unknown[];
|
|
724
|
-
|
|
725
|
-
const options =
|
|
726
|
-
args.length > ${methodArgumentCount}
|
|
727
|
-
? (args.pop() as ApiMethodOptions<
|
|
728
|
-
ExtractResponse<ReturnType<${className}["${methodName}"]>>,
|
|
729
|
-
ExtractError<ReturnType<${className}["${methodName}"]>>,
|
|
730
|
-
RequestParams
|
|
731
|
-
>)
|
|
732
|
-
: {};
|
|
733
|
-
|
|
734
|
-
const { onSuccess, onError, params } = options ?? {};
|
|
735
|
-
|
|
736
|
-
const requestArgs = [
|
|
737
|
-
...args,
|
|
738
|
-
params ?? {}
|
|
739
|
-
] as unknown as Parameters<
|
|
740
|
-
${className}["${methodName}"]
|
|
741
|
-
>;
|
|
742
|
-
|
|
743
|
-
return handleApiResponse(
|
|
744
|
-
() =>
|
|
745
|
-
${instanceName}.${methodName}(
|
|
746
|
-
...requestArgs
|
|
747
|
-
),
|
|
748
|
-
${callbackOptionsExpression(defaultHandlers)}
|
|
749
|
-
);
|
|
750
|
-
}
|
|
751
|
-
`.trim();
|
|
752
|
-
})
|
|
753
|
-
.join("\n\n");
|
|
754
|
-
|
|
755
|
-
const runtimeValueImportNames = [
|
|
756
|
-
...(hasPaginatedMethods && useFilterFormValues ? ["buildQuery"] : []),
|
|
757
|
-
...(hasFormDataMethods ? ["toFormData"] : []),
|
|
758
|
-
"handleApiResponse",
|
|
759
|
-
];
|
|
760
|
-
|
|
761
|
-
const runtimeTypeImportNames = [
|
|
762
|
-
"ApiResult",
|
|
763
|
-
"ApiMethodOptions",
|
|
764
|
-
...(hasRegularNonQueryMethods ? ["ApiMethodArguments"] : []),
|
|
765
|
-
"ExtractResponse",
|
|
766
|
-
"ExtractError",
|
|
767
|
-
|
|
768
|
-
...(hasPaginatedMethods && useFilterFormValues
|
|
769
|
-
? [
|
|
770
|
-
"ExtractDataIfPaginated",
|
|
771
|
-
"FilterFormValues",
|
|
772
|
-
"SortableKeys",
|
|
773
|
-
"SortDirection",
|
|
774
|
-
"UnwrapArray",
|
|
775
|
-
]
|
|
776
|
-
: []),
|
|
777
|
-
];
|
|
778
|
-
|
|
779
|
-
const runtimeValueImports = createImportStatement({
|
|
780
|
-
names: runtimeValueImportNames,
|
|
781
|
-
from: runtimePackageName,
|
|
782
|
-
});
|
|
783
|
-
|
|
784
|
-
const defaultFunctionImports = defaultHandlers
|
|
785
|
-
? createAliasedImportStatement({
|
|
786
|
-
imports: [
|
|
787
|
-
{
|
|
788
|
-
name: defaultHandlers.defaultSuccessHandlerName,
|
|
789
|
-
alias: "typedApiDefaultSuccessHandler",
|
|
790
|
-
},
|
|
791
|
-
{
|
|
792
|
-
name: defaultHandlers.defaultErrorHandlerName,
|
|
793
|
-
alias: "typedApiDefaultErrorHandler",
|
|
794
|
-
},
|
|
795
|
-
],
|
|
796
|
-
from: defaultHandlers.defaultFunctionsPath,
|
|
797
|
-
})
|
|
798
|
-
: "";
|
|
799
|
-
|
|
800
|
-
const runtimeTypeImports = createImportStatement({
|
|
801
|
-
names: runtimeTypeImportNames,
|
|
802
|
-
from: runtimePackageName,
|
|
803
|
-
typeOnly: useTypeOnlyImports,
|
|
804
|
-
});
|
|
805
|
-
|
|
806
|
-
const generatedValueImports = createImportStatement({
|
|
807
|
-
names: [className],
|
|
808
|
-
from: `../generated/${baseName}`,
|
|
809
|
-
});
|
|
810
|
-
|
|
811
|
-
const generatedTypeImports =
|
|
812
|
-
generatedMethods.length > 0
|
|
813
|
-
? createImportStatement({
|
|
814
|
-
names: ["RequestParams"],
|
|
815
|
-
from: "../generated/http-client",
|
|
816
|
-
typeOnly: useTypeOnlyImports,
|
|
817
|
-
})
|
|
818
|
-
: "";
|
|
819
|
-
|
|
820
|
-
const content = `
|
|
821
|
-
${runtimeValueImports}
|
|
822
|
-
|
|
823
|
-
${defaultFunctionImports}
|
|
824
|
-
|
|
825
|
-
${runtimeTypeImports}
|
|
826
|
-
|
|
827
|
-
${generatedValueImports}
|
|
828
|
-
|
|
829
|
-
${generatedTypeImports}
|
|
830
|
-
|
|
831
|
-
/* =======================
|
|
832
|
-
Query Types
|
|
833
|
-
======================= */
|
|
834
|
-
${queryTypes}
|
|
835
|
-
|
|
836
|
-
/* =======================
|
|
837
|
-
API Instance
|
|
838
|
-
======================= */
|
|
839
|
-
const ${instanceName} = new ${className}();
|
|
840
|
-
|
|
841
|
-
/* =======================
|
|
842
|
-
Paginated Query Methods
|
|
843
|
-
======================= */
|
|
844
|
-
${paginatedMethodWrappers}
|
|
845
|
-
|
|
846
|
-
/* =======================
|
|
847
|
-
Simple Query Methods
|
|
848
|
-
======================= */
|
|
849
|
-
${simpleQueryMethodWrappers}
|
|
850
|
-
|
|
851
|
-
/* =======================
|
|
852
|
-
Non-Query Methods
|
|
853
|
-
======================= */
|
|
854
|
-
${nonQueryMethodWrappers}
|
|
855
|
-
`.trim();
|
|
856
|
-
|
|
857
|
-
const outputFile = path.join(methodsDir, `${className}.api.ts`);
|
|
858
|
-
|
|
859
|
-
await writeFormattedFile(outputFile, content);
|
|
860
|
-
|
|
861
|
-
methodExports.push(`export * from "./methods/${className}.api";`);
|
|
862
|
-
}
|
|
863
|
-
|
|
864
|
-
const apiIndexContent = `
|
|
865
|
-
export * from "./generated/data-contracts";
|
|
866
|
-
export * from "./generated/http-client";
|
|
867
|
-
${methodExports.join("\n")}
|
|
868
|
-
`.trim();
|
|
869
|
-
|
|
870
|
-
await writeFormattedFile(path.join(apiRoot, "index.ts"), apiIndexContent);
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
async function fixGeneratedMixedImports(apiDir) {
|
|
874
|
-
const tsFiles = getAllTsFiles(apiDir);
|
|
875
|
-
|
|
876
|
-
for (const filePath of tsFiles) {
|
|
877
|
-
if (
|
|
878
|
-
filePath.endsWith("http-client.ts") ||
|
|
879
|
-
filePath.endsWith("data-contracts.ts")
|
|
880
|
-
) {
|
|
881
|
-
continue;
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
const originalContent = fs.readFileSync(filePath, "utf8");
|
|
885
|
-
let content = originalContent;
|
|
886
|
-
|
|
887
|
-
content = content.replace(
|
|
888
|
-
/import\s*\{([\s\S]*?)\}\s*from\s*["']\.\/http-client["'];/g,
|
|
889
|
-
(_match, importsText) => {
|
|
890
|
-
const importedNames = importsText
|
|
891
|
-
.split(",")
|
|
892
|
-
.map((name) => name.trim())
|
|
893
|
-
.filter(Boolean);
|
|
894
|
-
|
|
895
|
-
const typeNames = importedNames.filter(
|
|
896
|
-
(name) => name === "RequestParams",
|
|
897
|
-
);
|
|
898
|
-
|
|
899
|
-
const valueNames = importedNames.filter(
|
|
900
|
-
(name) => name !== "RequestParams",
|
|
901
|
-
);
|
|
902
|
-
|
|
903
|
-
const statements = [];
|
|
904
|
-
|
|
905
|
-
if (valueNames.length > 0) {
|
|
906
|
-
statements.push(
|
|
907
|
-
`import { ${valueNames.join(", ")} } from "./http-client";`,
|
|
908
|
-
);
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
if (typeNames.length > 0 && useTypeOnlyImports) {
|
|
912
|
-
statements.push(
|
|
913
|
-
`import type { ${typeNames.join(", ")} } from "./http-client";`,
|
|
914
|
-
);
|
|
915
|
-
} else if (typeNames.length > 0) {
|
|
916
|
-
statements.push(
|
|
917
|
-
`import { ${typeNames.join(", ")} } from "./http-client";`,
|
|
918
|
-
);
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
return statements.join("\n");
|
|
922
|
-
},
|
|
923
|
-
);
|
|
924
|
-
|
|
925
|
-
if (useTypeOnlyImports) {
|
|
926
|
-
content = content.replace(
|
|
927
|
-
/import\s*\{([\s\S]*?)\}\s*from\s*["']\.\/data-contracts["'];/g,
|
|
928
|
-
(_match, importsText) =>
|
|
929
|
-
`import type {${importsText}} from "./data-contracts";`,
|
|
930
|
-
);
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
if (content !== originalContent) {
|
|
934
|
-
await writeFormattedFile(filePath, content);
|
|
935
|
-
|
|
936
|
-
console.log(
|
|
937
|
-
`Fixed mixed imports in ${path.relative(process.cwd(), filePath)}`,
|
|
938
|
-
);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
async function main() {
|
|
944
|
-
console.log(`Generating API from: ${swaggerInput}`);
|
|
945
|
-
console.log(`Output folder: ${apiRoot}`);
|
|
946
|
-
|
|
947
|
-
await generateOpenApiClient();
|
|
948
|
-
|
|
949
|
-
await fixGeneratedMixedImports(generatedDir);
|
|
950
|
-
|
|
951
|
-
await createMethodFiles();
|
|
952
|
-
|
|
953
|
-
console.log("API generation completed.");
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
main().catch((error) => {
|
|
957
|
-
console.error(error);
|
|
958
|
-
process.exit(1);
|
|
959
|
-
});
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { generateApi } from "./openapi-generator/index.mjs";
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = path.dirname(__filename);
|
|
9
|
+
|
|
10
|
+
const packageRoot = path.resolve(__dirname, "..");
|
|
11
|
+
const runtimePackageJsonPath = path.join(packageRoot, "package.json");
|
|
12
|
+
const runtimePackageJson = JSON.parse(
|
|
13
|
+
fs.readFileSync(runtimePackageJsonPath, "utf8"),
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
const consumerPackageJsonPath = path.resolve(process.cwd(), "package.json");
|
|
17
|
+
const consumerPackageJson = fs.existsSync(consumerPackageJsonPath)
|
|
18
|
+
? JSON.parse(fs.readFileSync(consumerPackageJsonPath, "utf8"))
|
|
19
|
+
: {};
|
|
20
|
+
|
|
21
|
+
const cwd = process.cwd();
|
|
22
|
+
const config = {
|
|
23
|
+
...(runtimePackageJson.config ?? {}),
|
|
24
|
+
...(consumerPackageJson.config ?? {}),
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const runtimePackageName =
|
|
28
|
+
path.resolve(cwd) === packageRoot ? "../.." : runtimePackageJson.name;
|
|
29
|
+
|
|
30
|
+
const swaggerFile = getStringSetting(
|
|
31
|
+
process.env.SWAGGER_FILE,
|
|
32
|
+
process.env.npm_config_swagger_file,
|
|
33
|
+
config.swaggerFile,
|
|
34
|
+
config.input,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
const swaggerUrl = getStringSetting(
|
|
38
|
+
process.env.SWAGGER_URL,
|
|
39
|
+
process.env.npm_config_swagger_url,
|
|
40
|
+
config.swaggerUrl,
|
|
41
|
+
config.url,
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
const defaultSwaggerUrl = getStringSetting(
|
|
45
|
+
config.defaultSwaggerUrl,
|
|
46
|
+
"https://localhost:7000/swagger/v1/swagger.json",
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
const swaggerBackupPath = path.resolve(
|
|
50
|
+
cwd,
|
|
51
|
+
getStringSetting(
|
|
52
|
+
process.env.TYPED_API_SWAGGER_BACKUP_FILE,
|
|
53
|
+
process.env.npm_config_typed_api_swagger_backup_file,
|
|
54
|
+
config.typedApiSwaggerBackupFile,
|
|
55
|
+
"swagger/swagger.backup.json",
|
|
56
|
+
),
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const apiRoot = path.resolve(
|
|
60
|
+
cwd,
|
|
61
|
+
getStringSetting(
|
|
62
|
+
process.env.API_OUTPUT,
|
|
63
|
+
process.env.npm_config_api_output,
|
|
64
|
+
config.apiOutput,
|
|
65
|
+
config.output,
|
|
66
|
+
"src/api",
|
|
67
|
+
),
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
const methodsDir = path.join(apiRoot, "methods");
|
|
71
|
+
|
|
72
|
+
const defaultFunctionsPathSetting = getStringSetting(
|
|
73
|
+
process.env.TYPED_API_DEFAULT_FUNCTIONS_PATH,
|
|
74
|
+
process.env.npm_config_typed_api_default_functions_path,
|
|
75
|
+
config.typedApiDefaultFunctionsPath,
|
|
76
|
+
"src/defaultApiFunctions",
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const defaultFunctionsFilePath = path.resolve(cwd, defaultFunctionsPathSetting);
|
|
80
|
+
|
|
81
|
+
const defaultSuccessHandlerName = getStringSetting(
|
|
82
|
+
process.env.TYPED_API_DEFAULT_SUCCESS_HANDLER,
|
|
83
|
+
process.env.npm_config_typed_api_default_success_handler,
|
|
84
|
+
config.typedApiDefaultSuccessHandler,
|
|
85
|
+
"handleGoodResult",
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const defaultErrorHandlerName = getStringSetting(
|
|
89
|
+
process.env.TYPED_API_DEFAULT_ERROR_HANDLER,
|
|
90
|
+
process.env.npm_config_typed_api_default_error_handler,
|
|
91
|
+
config.typedApiDefaultErrorHandler,
|
|
92
|
+
"handleErrors",
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
const generatorOptions = {
|
|
96
|
+
cleanOutput: getBooleanSetting(
|
|
97
|
+
process.env.TYPED_API_CLEAN_OUTPUT,
|
|
98
|
+
process.env.npm_config_typed_api_clean_output,
|
|
99
|
+
process.env.npm_config_clean_output,
|
|
100
|
+
config.typedApiCleanOutput,
|
|
101
|
+
config.cleanOutput,
|
|
102
|
+
true,
|
|
103
|
+
),
|
|
104
|
+
moduleNameFirstTag: getBooleanSetting(
|
|
105
|
+
process.env.TYPED_API_MODULE_NAME_FIRST_TAG,
|
|
106
|
+
process.env.npm_config_typed_api_module_name_first_tag,
|
|
107
|
+
process.env.npm_config_module_name_first_tag,
|
|
108
|
+
config.typedApiModuleNameFirstTag,
|
|
109
|
+
config.moduleNameFirstTag,
|
|
110
|
+
true,
|
|
111
|
+
),
|
|
112
|
+
defaultResponseAsSuccess: getBooleanSetting(
|
|
113
|
+
process.env.TYPED_API_DEFAULT_RESPONSE_AS_SUCCESS,
|
|
114
|
+
process.env.npm_config_typed_api_default_response_as_success,
|
|
115
|
+
process.env.npm_config_default_response_as_success,
|
|
116
|
+
config.typedApiDefaultResponseAsSuccess,
|
|
117
|
+
config.defaultResponseAsSuccess,
|
|
118
|
+
false,
|
|
119
|
+
),
|
|
120
|
+
generateUnionEnums: getBooleanSetting(
|
|
121
|
+
process.env.TYPED_API_GENERATE_UNION_ENUMS,
|
|
122
|
+
process.env.npm_config_typed_api_generate_union_enums,
|
|
123
|
+
process.env.npm_config_generate_union_enums,
|
|
124
|
+
config.typedApiGenerateUnionEnums,
|
|
125
|
+
config.generateUnionEnums,
|
|
126
|
+
false,
|
|
127
|
+
),
|
|
128
|
+
enumNamesAsValues: getBooleanSetting(
|
|
129
|
+
process.env.TYPED_API_ENUM_NAMES_AS_VALUES,
|
|
130
|
+
process.env.npm_config_typed_api_enum_names_as_values,
|
|
131
|
+
process.env.npm_config_enum_names_as_values,
|
|
132
|
+
config.typedApiEnumNamesAsValues,
|
|
133
|
+
config.enumNamesAsValues,
|
|
134
|
+
false,
|
|
135
|
+
),
|
|
136
|
+
useTypeOnlyImports: getBooleanSetting(
|
|
137
|
+
process.env.TYPED_API_USE_TYPE_ONLY_IMPORTS,
|
|
138
|
+
process.env.npm_config_typed_api_use_type_only_imports,
|
|
139
|
+
process.env.npm_config_use_type_only_imports,
|
|
140
|
+
config.typedApiUseTypeOnlyImports,
|
|
141
|
+
config.useTypeOnlyImports,
|
|
142
|
+
true,
|
|
143
|
+
),
|
|
144
|
+
useFilterFormValues: getBooleanSetting(
|
|
145
|
+
process.env.TYPED_API_USE_FILTER_FORM_VALUES,
|
|
146
|
+
process.env.npm_config_typed_api_use_filter_form_values,
|
|
147
|
+
config.typedApiUseFilterFormValues,
|
|
148
|
+
true,
|
|
149
|
+
),
|
|
150
|
+
baseUrl: getStringSetting(
|
|
151
|
+
process.env.TYPED_API_BASE_URL,
|
|
152
|
+
process.env.npm_config_typed_api_base_url,
|
|
153
|
+
config.typedApiBaseUrl,
|
|
154
|
+
),
|
|
155
|
+
runtimePackageName,
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
function getStringSetting(...values) {
|
|
159
|
+
for (const value of values) {
|
|
160
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
161
|
+
return value.trim();
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function getBooleanSetting(...values) {
|
|
169
|
+
const fallback = values[values.length - 1];
|
|
170
|
+
|
|
171
|
+
for (const value of values.slice(0, -1)) {
|
|
172
|
+
if (typeof value === "boolean") return value;
|
|
173
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
174
|
+
const normalized = value.trim().toLowerCase();
|
|
175
|
+
if (["1", "true", "yes", "on"].includes(normalized)) return true;
|
|
176
|
+
if (["0", "false", "no", "off"].includes(normalized)) return false;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return Boolean(fallback);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function fileExists(filePath) {
|
|
184
|
+
try {
|
|
185
|
+
return fs.existsSync(filePath) && fs.statSync(filePath).isFile();
|
|
186
|
+
} catch {
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function displayPath(filePath) {
|
|
192
|
+
return path.relative(cwd, filePath) || ".";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function writeSwaggerBackup(content, sourceLabel) {
|
|
196
|
+
fs.mkdirSync(path.dirname(swaggerBackupPath), { recursive: true });
|
|
197
|
+
fs.writeFileSync(swaggerBackupPath, content);
|
|
198
|
+
|
|
199
|
+
console.log(
|
|
200
|
+
`Updated Swagger backup from ${sourceLabel}: ${displayPath(swaggerBackupPath)}`,
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function copySwaggerBackupFromFile(filePath) {
|
|
205
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
206
|
+
JSON.parse(content);
|
|
207
|
+
writeSwaggerBackup(content, path.relative(cwd, filePath));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async function downloadSwaggerBackupFromUrl(url) {
|
|
211
|
+
const response = await fetch(url);
|
|
212
|
+
|
|
213
|
+
if (!response.ok) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
`Swagger URL returned ${response.status} ${response.statusText}: ${url}`,
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const content = await response.text();
|
|
220
|
+
JSON.parse(content);
|
|
221
|
+
writeSwaggerBackup(content, url);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function useBackupSwaggerInput(reason) {
|
|
225
|
+
if (!fileExists(swaggerBackupPath)) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
console.warn(
|
|
230
|
+
`${reason} Using Swagger backup: ${displayPath(swaggerBackupPath)}`,
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
input: swaggerBackupPath,
|
|
235
|
+
label: swaggerBackupPath,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async function resolveSwaggerInput() {
|
|
240
|
+
if (swaggerFile) {
|
|
241
|
+
const swaggerFilePath = path.resolve(cwd, swaggerFile);
|
|
242
|
+
|
|
243
|
+
if (fileExists(swaggerFilePath)) {
|
|
244
|
+
copySwaggerBackupFromFile(swaggerFilePath);
|
|
245
|
+
|
|
246
|
+
return {
|
|
247
|
+
input: swaggerFilePath,
|
|
248
|
+
label: swaggerFilePath,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const backupInput = useBackupSwaggerInput(
|
|
253
|
+
`Swagger file was not found: ${swaggerFilePath}.`,
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
if (backupInput) {
|
|
257
|
+
return backupInput;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
throw new Error(
|
|
261
|
+
`Swagger file was not found and no backup exists: ${swaggerFilePath}`,
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (swaggerUrl) {
|
|
266
|
+
try {
|
|
267
|
+
await downloadSwaggerBackupFromUrl(swaggerUrl);
|
|
268
|
+
|
|
269
|
+
return {
|
|
270
|
+
input: swaggerBackupPath,
|
|
271
|
+
label: swaggerUrl,
|
|
272
|
+
};
|
|
273
|
+
} catch (error) {
|
|
274
|
+
const backupInput = useBackupSwaggerInput(
|
|
275
|
+
`Swagger URL is not available: ${swaggerUrl}.`,
|
|
276
|
+
);
|
|
277
|
+
|
|
278
|
+
if (backupInput) {
|
|
279
|
+
return backupInput;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
throw error;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const defaultSwaggerFile = path.resolve(cwd, "swagger/swagger.json");
|
|
287
|
+
|
|
288
|
+
if (fileExists(defaultSwaggerFile)) {
|
|
289
|
+
copySwaggerBackupFromFile(defaultSwaggerFile);
|
|
290
|
+
|
|
291
|
+
return {
|
|
292
|
+
input: defaultSwaggerFile,
|
|
293
|
+
label: defaultSwaggerFile,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
try {
|
|
298
|
+
await downloadSwaggerBackupFromUrl(defaultSwaggerUrl);
|
|
299
|
+
|
|
300
|
+
return {
|
|
301
|
+
input: swaggerBackupPath,
|
|
302
|
+
label: defaultSwaggerUrl,
|
|
303
|
+
};
|
|
304
|
+
} catch {
|
|
305
|
+
const backupInput = useBackupSwaggerInput(
|
|
306
|
+
"Default Swagger file was not found and default Swagger URL is not available.",
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
if (backupInput) {
|
|
310
|
+
return backupInput;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
throw new Error(
|
|
314
|
+
`No Swagger input found. Add swagger/swagger.json, configure swaggerFile, or configure swaggerUrl.`,
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function createImportStatement({ names, from, typeOnly = false }) {
|
|
320
|
+
const cleanNames = [...new Set(names.filter(Boolean))];
|
|
321
|
+
if (cleanNames.length === 0) return "";
|
|
322
|
+
const importKeyword = typeOnly ? "import type" : "import";
|
|
323
|
+
return `${importKeyword} { ${cleanNames.join(", ")} } from ${JSON.stringify(from)};`;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function createDefaultFunctionsFileIfMissing(filePath) {
|
|
327
|
+
const extension = path.extname(filePath);
|
|
328
|
+
const resolvedFilePath = extension ? filePath : `${filePath}.ts`;
|
|
329
|
+
|
|
330
|
+
if (fs.existsSync(resolvedFilePath)) {
|
|
331
|
+
return resolvedFilePath;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
fs.mkdirSync(path.dirname(resolvedFilePath), { recursive: true });
|
|
335
|
+
|
|
336
|
+
fs.writeFileSync(
|
|
337
|
+
resolvedFilePath,
|
|
338
|
+
`${createImportStatement({
|
|
339
|
+
names: ["ApiErrorResult", "ApiSuccessResult"],
|
|
340
|
+
from: runtimePackageName,
|
|
341
|
+
typeOnly: generatorOptions.useTypeOnlyImports !== false,
|
|
342
|
+
})}
|
|
343
|
+
|
|
344
|
+
export function ${defaultSuccessHandlerName}<T>(
|
|
345
|
+
_response: ApiSuccessResult<T>,
|
|
346
|
+
): void | Promise<void> {
|
|
347
|
+
// Add your default success handling here.
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export function ${defaultErrorHandlerName}<T>(
|
|
351
|
+
_error: ApiErrorResult<T>,
|
|
352
|
+
): void | Promise<void> {
|
|
353
|
+
// Add your default error handling here.
|
|
354
|
+
}
|
|
355
|
+
`,
|
|
356
|
+
);
|
|
357
|
+
|
|
358
|
+
console.log(
|
|
359
|
+
`Created default API handler file: ${path.relative(process.cwd(), resolvedFilePath)}`,
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
return resolvedFilePath;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function toRelativeImportPath(fromDirectory, filePath) {
|
|
366
|
+
let relativePath = path.relative(fromDirectory, filePath);
|
|
367
|
+
|
|
368
|
+
if (!relativePath.startsWith(".")) {
|
|
369
|
+
relativePath = `./${relativePath}`;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return relativePath
|
|
373
|
+
.replaceAll(path.sep, "/")
|
|
374
|
+
.replace(/\.(ts|tsx|js|jsx)$/, "");
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function escapeRegExp(value) {
|
|
378
|
+
return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function fileExportsName(source, exportName) {
|
|
382
|
+
const escapedName = escapeRegExp(exportName);
|
|
383
|
+
|
|
384
|
+
const directExportPattern = new RegExp(
|
|
385
|
+
`export\\s+(?:async\\s+)?(?:function|const|let|var|class)\\s+${escapedName}\\b`,
|
|
386
|
+
"m",
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
if (directExportPattern.test(source)) {
|
|
390
|
+
return true;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
const namedExportBlocks = source.matchAll(/export\s*\{([\s\S]*?)\}/g);
|
|
394
|
+
|
|
395
|
+
for (const match of namedExportBlocks) {
|
|
396
|
+
const exportedNames = match[1]
|
|
397
|
+
.split(",")
|
|
398
|
+
.map((part) => part.trim())
|
|
399
|
+
.filter(Boolean);
|
|
400
|
+
|
|
401
|
+
if (
|
|
402
|
+
exportedNames.some((part) => {
|
|
403
|
+
const [localName, aliasName] = part
|
|
404
|
+
.split(/\s+as\s+/)
|
|
405
|
+
.map((name) => name.trim());
|
|
406
|
+
|
|
407
|
+
return (
|
|
408
|
+
aliasName === exportName || (!aliasName && localName === exportName)
|
|
409
|
+
);
|
|
410
|
+
})
|
|
411
|
+
) {
|
|
412
|
+
return true;
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
function resolveDefaultHandlers() {
|
|
420
|
+
const defaultFunctionsFile = createDefaultFunctionsFileIfMissing(
|
|
421
|
+
defaultFunctionsFilePath,
|
|
422
|
+
);
|
|
423
|
+
const source = fs.readFileSync(defaultFunctionsFile, "utf8");
|
|
424
|
+
const hasSuccessHandler = fileExportsName(source, defaultSuccessHandlerName);
|
|
425
|
+
const hasErrorHandler = fileExportsName(source, defaultErrorHandlerName);
|
|
426
|
+
|
|
427
|
+
if (!hasSuccessHandler || !hasErrorHandler) {
|
|
428
|
+
const missingNames = [
|
|
429
|
+
...(!hasSuccessHandler ? [defaultSuccessHandlerName] : []),
|
|
430
|
+
...(!hasErrorHandler ? [defaultErrorHandlerName] : []),
|
|
431
|
+
];
|
|
432
|
+
|
|
433
|
+
console.warn(
|
|
434
|
+
`Default API handlers were not imported because ${path.relative(
|
|
435
|
+
process.cwd(),
|
|
436
|
+
defaultFunctionsFile,
|
|
437
|
+
)} does not export: ${missingNames.join(", ")}.`,
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
return undefined;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
return {
|
|
444
|
+
path: toRelativeImportPath(methodsDir, defaultFunctionsFile),
|
|
445
|
+
success: defaultSuccessHandlerName,
|
|
446
|
+
error: defaultErrorHandlerName,
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
async function main() {
|
|
451
|
+
const swaggerInput = await resolveSwaggerInput();
|
|
452
|
+
|
|
453
|
+
console.log(`Generating API from: ${swaggerInput.label}`);
|
|
454
|
+
console.log(`Output folder: ${apiRoot}`);
|
|
455
|
+
console.log(
|
|
456
|
+
"Generator: local typedapi OpenAPI generator, function-only methods",
|
|
457
|
+
);
|
|
458
|
+
|
|
459
|
+
const result = await generateApi({
|
|
460
|
+
input: swaggerInput.input,
|
|
461
|
+
output: apiRoot,
|
|
462
|
+
...generatorOptions,
|
|
463
|
+
defaultHandlers: resolveDefaultHandlers(),
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
for (const file of result.files) {
|
|
467
|
+
console.log(`Generated ${path.relative(cwd, file)}`);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
console.log("API generation completed.");
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
main().catch((error) => {
|
|
474
|
+
console.error(error);
|
|
475
|
+
process.exit(1);
|
|
476
|
+
});
|