@geekmidas/cli 0.10.0 → 0.12.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 +525 -0
- package/dist/bundler-DRXCw_YR.mjs +70 -0
- package/dist/bundler-DRXCw_YR.mjs.map +1 -0
- package/dist/bundler-WsEvH_b2.cjs +71 -0
- package/dist/bundler-WsEvH_b2.cjs.map +1 -0
- package/dist/{config-C9aXOHBe.cjs → config-AmInkU7k.cjs} +8 -8
- package/dist/config-AmInkU7k.cjs.map +1 -0
- package/dist/{config-BrkUalUh.mjs → config-DYULeEv8.mjs} +3 -3
- package/dist/config-DYULeEv8.mjs.map +1 -0
- package/dist/config.cjs +1 -1
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +1 -1
- package/dist/encryption-C8H-38Yy.mjs +42 -0
- package/dist/encryption-C8H-38Yy.mjs.map +1 -0
- package/dist/encryption-Dyf_r1h-.cjs +44 -0
- package/dist/encryption-Dyf_r1h-.cjs.map +1 -0
- package/dist/index.cjs +2116 -179
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2134 -192
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-CZLI4QTr.mjs → openapi-BfFlOBCG.mjs} +801 -38
- package/dist/openapi-BfFlOBCG.mjs.map +1 -0
- package/dist/{openapi-BeHLKcwP.cjs → openapi-Bt_1FDpT.cjs} +794 -31
- package/dist/openapi-Bt_1FDpT.cjs.map +1 -0
- package/dist/{openapi-react-query-o5iMi8tz.cjs → openapi-react-query-B-sNWHFU.cjs} +5 -5
- package/dist/openapi-react-query-B-sNWHFU.cjs.map +1 -0
- package/dist/{openapi-react-query-CcciaVu5.mjs → openapi-react-query-B6XTeGqS.mjs} +5 -5
- package/dist/openapi-react-query-B6XTeGqS.mjs.map +1 -0
- package/dist/openapi-react-query.cjs +1 -1
- package/dist/openapi-react-query.d.cts.map +1 -1
- package/dist/openapi-react-query.d.mts.map +1 -1
- package/dist/openapi-react-query.mjs +1 -1
- package/dist/openapi.cjs +2 -2
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.cts.map +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.d.mts.map +1 -1
- package/dist/openapi.mjs +2 -2
- package/dist/storage-BUYQJgz7.cjs +4 -0
- package/dist/storage-BXoJvmv2.cjs +149 -0
- package/dist/storage-BXoJvmv2.cjs.map +1 -0
- package/dist/storage-C9PU_30f.mjs +101 -0
- package/dist/storage-C9PU_30f.mjs.map +1 -0
- package/dist/storage-DLJAYxzJ.mjs +3 -0
- package/dist/{types-b-vwGpqc.d.cts → types-BR0M2v_c.d.mts} +100 -1
- package/dist/types-BR0M2v_c.d.mts.map +1 -0
- package/dist/{types-DXgiA1sF.d.mts → types-BhkZc-vm.d.cts} +100 -1
- package/dist/types-BhkZc-vm.d.cts.map +1 -0
- package/examples/cron-example.ts +27 -27
- package/examples/env.ts +27 -27
- package/examples/function-example.ts +31 -31
- package/examples/gkm.config.json +20 -20
- package/examples/gkm.config.ts +8 -8
- package/examples/gkm.minimal.config.json +5 -5
- package/examples/gkm.production.config.json +25 -25
- package/examples/logger.ts +2 -2
- package/package.json +6 -6
- package/src/__tests__/EndpointGenerator.hooks.spec.ts +191 -191
- package/src/__tests__/config.spec.ts +55 -55
- package/src/__tests__/loadEnvFiles.spec.ts +93 -93
- package/src/__tests__/normalizeHooksConfig.spec.ts +58 -58
- package/src/__tests__/openapi-react-query.spec.ts +497 -497
- package/src/__tests__/openapi.spec.ts +428 -428
- package/src/__tests__/test-helpers.ts +76 -76
- package/src/auth/__tests__/credentials.spec.ts +204 -0
- package/src/auth/__tests__/index.spec.ts +168 -0
- package/src/auth/credentials.ts +187 -0
- package/src/auth/index.ts +226 -0
- package/src/build/__tests__/index-new.spec.ts +474 -474
- package/src/build/__tests__/manifests.spec.ts +333 -333
- package/src/build/bundler.ts +141 -0
- package/src/build/endpoint-analyzer.ts +236 -0
- package/src/build/handler-templates.ts +1253 -0
- package/src/build/index.ts +250 -179
- package/src/build/manifests.ts +52 -52
- package/src/build/providerResolver.ts +145 -145
- package/src/build/types.ts +64 -43
- package/src/config.ts +39 -39
- package/src/deploy/__tests__/docker.spec.ts +111 -0
- package/src/deploy/__tests__/dokploy.spec.ts +245 -0
- package/src/deploy/__tests__/init.spec.ts +662 -0
- package/src/deploy/docker.ts +128 -0
- package/src/deploy/dokploy.ts +204 -0
- package/src/deploy/index.ts +136 -0
- package/src/deploy/init.ts +484 -0
- package/src/deploy/types.ts +48 -0
- package/src/dev/__tests__/index.spec.ts +266 -266
- package/src/dev/index.ts +647 -601
- package/src/docker/__tests__/compose.spec.ts +531 -0
- package/src/docker/__tests__/templates.spec.ts +280 -0
- package/src/docker/compose.ts +273 -0
- package/src/docker/index.ts +230 -0
- package/src/docker/templates.ts +446 -0
- package/src/generators/CronGenerator.ts +72 -72
- package/src/generators/EndpointGenerator.ts +699 -398
- package/src/generators/FunctionGenerator.ts +84 -84
- package/src/generators/Generator.ts +72 -72
- package/src/generators/OpenApiTsGenerator.ts +577 -577
- package/src/generators/SubscriberGenerator.ts +124 -124
- package/src/generators/__tests__/CronGenerator.spec.ts +433 -433
- package/src/generators/__tests__/EndpointGenerator.spec.ts +532 -382
- package/src/generators/__tests__/FunctionGenerator.spec.ts +244 -244
- package/src/generators/__tests__/SubscriberGenerator.spec.ts +397 -382
- package/src/generators/index.ts +4 -4
- package/src/index.ts +623 -201
- package/src/init/__tests__/generators.spec.ts +334 -334
- package/src/init/__tests__/init.spec.ts +332 -332
- package/src/init/__tests__/utils.spec.ts +89 -89
- package/src/init/generators/config.ts +175 -175
- package/src/init/generators/docker.ts +41 -41
- package/src/init/generators/env.ts +72 -72
- package/src/init/generators/index.ts +1 -1
- package/src/init/generators/models.ts +64 -64
- package/src/init/generators/monorepo.ts +161 -161
- package/src/init/generators/package.ts +71 -71
- package/src/init/generators/source.ts +6 -6
- package/src/init/index.ts +203 -208
- package/src/init/templates/api.ts +115 -115
- package/src/init/templates/index.ts +75 -75
- package/src/init/templates/minimal.ts +98 -98
- package/src/init/templates/serverless.ts +89 -89
- package/src/init/templates/worker.ts +98 -98
- package/src/init/utils.ts +54 -56
- package/src/openapi-react-query.ts +194 -194
- package/src/openapi.ts +63 -63
- package/src/secrets/__tests__/encryption.spec.ts +226 -0
- package/src/secrets/__tests__/generator.spec.ts +319 -0
- package/src/secrets/__tests__/index.spec.ts +91 -0
- package/src/secrets/__tests__/storage.spec.ts +403 -0
- package/src/secrets/encryption.ts +91 -0
- package/src/secrets/generator.ts +164 -0
- package/src/secrets/index.ts +383 -0
- package/src/secrets/storage.ts +134 -0
- package/src/secrets/types.ts +53 -0
- package/src/types.ts +295 -176
- package/tsdown.config.ts +11 -8
- package/dist/config-BrkUalUh.mjs.map +0 -1
- package/dist/config-C9aXOHBe.cjs.map +0 -1
- package/dist/openapi-BeHLKcwP.cjs.map +0 -1
- package/dist/openapi-CZLI4QTr.mjs.map +0 -1
- package/dist/openapi-react-query-CcciaVu5.mjs.map +0 -1
- package/dist/openapi-react-query-o5iMi8tz.cjs.map +0 -1
- package/dist/types-DXgiA1sF.d.mts.map +0 -1
- package/dist/types-b-vwGpqc.d.cts.map +0 -1
|
@@ -1,68 +1,68 @@
|
|
|
1
1
|
import type { Endpoint } from '@geekmidas/constructs/endpoints';
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
getSchemaMetadata,
|
|
4
|
+
StandardSchemaJsonSchema,
|
|
5
5
|
} from '@geekmidas/schema/conversion';
|
|
6
6
|
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
7
7
|
|
|
8
8
|
interface OpenApiTsOptions {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
title?: string;
|
|
10
|
+
version?: string;
|
|
11
|
+
description?: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
// JSON Schema type definition
|
|
15
15
|
interface JsonSchema {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
type?: string;
|
|
17
|
+
properties?: Record<string, JsonSchema>;
|
|
18
|
+
items?: JsonSchema;
|
|
19
|
+
required?: string[];
|
|
20
|
+
enum?: string[];
|
|
21
|
+
$ref?: string;
|
|
22
|
+
anyOf?: JsonSchema[];
|
|
23
|
+
oneOf?: JsonSchema[];
|
|
24
|
+
allOf?: JsonSchema[];
|
|
25
|
+
additionalProperties?: boolean | JsonSchema;
|
|
26
|
+
[key: string]: unknown;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// Security scheme type (OpenAPI 3.1)
|
|
30
30
|
interface SecuritySchemeObject {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
31
|
+
type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';
|
|
32
|
+
description?: string;
|
|
33
|
+
name?: string;
|
|
34
|
+
in?: 'query' | 'header' | 'cookie';
|
|
35
|
+
scheme?: string;
|
|
36
|
+
bearerFormat?: string;
|
|
37
|
+
flows?: Record<string, unknown>;
|
|
38
|
+
openIdConnectUrl?: string;
|
|
39
|
+
[key: string]: unknown;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
interface EndpointInfo {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
43
|
+
endpoint: string;
|
|
44
|
+
route: string;
|
|
45
|
+
method: string;
|
|
46
|
+
authorizerName: string | null;
|
|
47
|
+
/** @deprecated Use securityScheme instead */
|
|
48
|
+
authorizerType: string | null;
|
|
49
|
+
/** The OpenAPI security scheme definition for this endpoint's authorizer */
|
|
50
|
+
securityScheme: SecuritySchemeObject | null;
|
|
51
|
+
input?: {
|
|
52
|
+
body?: StandardSchemaV1;
|
|
53
|
+
query?: StandardSchemaV1;
|
|
54
|
+
params?: StandardSchemaV1;
|
|
55
|
+
};
|
|
56
|
+
output?: StandardSchemaV1;
|
|
57
|
+
description?: string;
|
|
58
|
+
tags?: string[];
|
|
59
|
+
operationId?: string;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
interface SecuritySchemeInfo {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
name: string;
|
|
64
|
+
type: string;
|
|
65
|
+
scheme: SecuritySchemeObject;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
/**
|
|
@@ -74,505 +74,505 @@ interface SecuritySchemeInfo {
|
|
|
74
74
|
* - schema interfaces: reusable TypeScript types from Zod/Valibot schemas
|
|
75
75
|
*/
|
|
76
76
|
export class OpenApiTsGenerator {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
77
|
+
async generate(
|
|
78
|
+
endpoints: Endpoint<any, any, any, any, any, any>[],
|
|
79
|
+
options: OpenApiTsOptions = {},
|
|
80
|
+
): Promise<string> {
|
|
81
|
+
const { title = 'API', version = '1.0.0', description } = options;
|
|
82
|
+
|
|
83
|
+
// Extract endpoint info
|
|
84
|
+
const endpointInfos = await this.extractEndpointInfos(endpoints);
|
|
85
|
+
|
|
86
|
+
// Collect unique security schemes
|
|
87
|
+
const securitySchemes = this.collectSecuritySchemes(endpointInfos);
|
|
88
|
+
|
|
89
|
+
// Build endpoint auth map
|
|
90
|
+
const endpointAuth = this.buildEndpointAuthMap(endpointInfos);
|
|
91
|
+
|
|
92
|
+
// Generate schema interfaces
|
|
93
|
+
const schemaInterfaces = await this.generateSchemaInterfaces(endpointInfos);
|
|
94
|
+
|
|
95
|
+
// Generate paths interface
|
|
96
|
+
const pathsInterface = await this.generatePathsInterface(endpointInfos);
|
|
97
|
+
|
|
98
|
+
// Build the final TypeScript module
|
|
99
|
+
return this.buildModule({
|
|
100
|
+
title,
|
|
101
|
+
version,
|
|
102
|
+
description,
|
|
103
|
+
securitySchemes,
|
|
104
|
+
endpointAuth,
|
|
105
|
+
schemaInterfaces,
|
|
106
|
+
pathsInterface,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private async extractEndpointInfos(
|
|
111
|
+
endpoints: Endpoint<any, any, any, any, any, any>[],
|
|
112
|
+
): Promise<EndpointInfo[]> {
|
|
113
|
+
return endpoints.map((ep) => {
|
|
114
|
+
const route = ep.route.replace(/:(\w+)/g, '{$1}');
|
|
115
|
+
const method = ep.method.toUpperCase();
|
|
116
|
+
|
|
117
|
+
// Get security scheme from authorizer (if available)
|
|
118
|
+
// This is the preferred way - the scheme is stored directly on the authorizer
|
|
119
|
+
const securityScheme = ep.authorizer?.securityScheme as
|
|
120
|
+
| SecuritySchemeObject
|
|
121
|
+
| undefined;
|
|
122
|
+
|
|
123
|
+
return {
|
|
124
|
+
endpoint: `${method} ${route}`,
|
|
125
|
+
route,
|
|
126
|
+
method,
|
|
127
|
+
authorizerName: ep.authorizer?.name ?? null,
|
|
128
|
+
authorizerType: ep.authorizer?.type ?? null,
|
|
129
|
+
securityScheme: securityScheme ?? null,
|
|
130
|
+
input: ep.input,
|
|
131
|
+
output: ep.outputSchema,
|
|
132
|
+
description: ep.description,
|
|
133
|
+
tags: ep.tags,
|
|
134
|
+
operationId: ep.operationId,
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
private collectSecuritySchemes(
|
|
140
|
+
endpointInfos: EndpointInfo[],
|
|
141
|
+
): SecuritySchemeInfo[] {
|
|
142
|
+
const schemes = new Map<string, SecuritySchemeInfo>();
|
|
143
|
+
|
|
144
|
+
for (const info of endpointInfos) {
|
|
145
|
+
if (info.authorizerName && !schemes.has(info.authorizerName)) {
|
|
146
|
+
// Prefer the stored security scheme (from .securitySchemes() or built-ins)
|
|
147
|
+
// Fall back to inference from authorizerType for backward compatibility
|
|
148
|
+
const scheme =
|
|
149
|
+
info.securityScheme ??
|
|
150
|
+
(info.authorizerType
|
|
151
|
+
? this.mapAuthorizerToSecurityScheme(
|
|
152
|
+
info.authorizerType,
|
|
153
|
+
info.authorizerName,
|
|
154
|
+
)
|
|
155
|
+
: null);
|
|
156
|
+
|
|
157
|
+
if (scheme) {
|
|
158
|
+
schemes.set(info.authorizerName, {
|
|
159
|
+
name: info.authorizerName,
|
|
160
|
+
type: scheme.type,
|
|
161
|
+
scheme,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return Array.from(schemes.values());
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private mapAuthorizerToSecurityScheme(
|
|
171
|
+
type: string,
|
|
172
|
+
_name: string,
|
|
173
|
+
): SecuritySchemeObject {
|
|
174
|
+
switch (type.toLowerCase()) {
|
|
175
|
+
case 'jwt':
|
|
176
|
+
case 'bearer':
|
|
177
|
+
return {
|
|
178
|
+
type: 'http',
|
|
179
|
+
scheme: 'bearer',
|
|
180
|
+
bearerFormat: 'JWT',
|
|
181
|
+
};
|
|
182
|
+
case 'iam':
|
|
183
|
+
case 'aws-sigv4':
|
|
184
|
+
case 'sigv4':
|
|
185
|
+
return {
|
|
186
|
+
type: 'apiKey',
|
|
187
|
+
in: 'header',
|
|
188
|
+
name: 'Authorization',
|
|
189
|
+
'x-amazon-apigateway-authtype': 'awsSigv4',
|
|
190
|
+
};
|
|
191
|
+
case 'apikey':
|
|
192
|
+
case 'api-key':
|
|
193
|
+
return {
|
|
194
|
+
type: 'apiKey',
|
|
195
|
+
in: 'header',
|
|
196
|
+
name: 'X-API-Key',
|
|
197
|
+
};
|
|
198
|
+
case 'oauth2':
|
|
199
|
+
return {
|
|
200
|
+
type: 'oauth2',
|
|
201
|
+
flows: {},
|
|
202
|
+
};
|
|
203
|
+
case 'oidc':
|
|
204
|
+
case 'openidconnect':
|
|
205
|
+
return {
|
|
206
|
+
type: 'openIdConnect',
|
|
207
|
+
openIdConnectUrl: '',
|
|
208
|
+
};
|
|
209
|
+
default:
|
|
210
|
+
return {
|
|
211
|
+
type: 'http',
|
|
212
|
+
scheme: 'bearer',
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private buildEndpointAuthMap(
|
|
218
|
+
endpointInfos: EndpointInfo[],
|
|
219
|
+
): Record<string, string | null> {
|
|
220
|
+
const authMap: Record<string, string | null> = {};
|
|
221
|
+
|
|
222
|
+
for (const info of endpointInfos) {
|
|
223
|
+
authMap[info.endpoint] = info.authorizerName;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return authMap;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private async generateSchemaInterfaces(
|
|
230
|
+
endpointInfos: EndpointInfo[],
|
|
231
|
+
): Promise<string> {
|
|
232
|
+
const interfaces: string[] = [];
|
|
233
|
+
const generatedNames = new Set<string>();
|
|
234
|
+
// Collect nested schemas with $defs (from .meta({ id: 'X' }))
|
|
235
|
+
const collectedDefs = new Map<string, JsonSchema>();
|
|
236
|
+
|
|
237
|
+
for (const info of endpointInfos) {
|
|
238
|
+
const baseName = this.getSchemaBaseName(info);
|
|
239
|
+
|
|
240
|
+
// Input body schema
|
|
241
|
+
if (info.input?.body) {
|
|
242
|
+
const name = await this.getSchemaName(
|
|
243
|
+
info.input.body,
|
|
244
|
+
`${baseName}Input`,
|
|
245
|
+
);
|
|
246
|
+
if (!generatedNames.has(name)) {
|
|
247
|
+
const schema = await this.schemaToInterfaceWithDefs(
|
|
248
|
+
info.input.body,
|
|
249
|
+
name,
|
|
250
|
+
collectedDefs,
|
|
251
|
+
);
|
|
252
|
+
if (schema) {
|
|
253
|
+
interfaces.push(schema);
|
|
254
|
+
generatedNames.add(name);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// Input params schema
|
|
260
|
+
if (info.input?.params) {
|
|
261
|
+
const name = await this.getSchemaName(
|
|
262
|
+
info.input.params,
|
|
263
|
+
`${baseName}Params`,
|
|
264
|
+
);
|
|
265
|
+
if (!generatedNames.has(name)) {
|
|
266
|
+
const schema = await this.schemaToInterfaceWithDefs(
|
|
267
|
+
info.input.params,
|
|
268
|
+
name,
|
|
269
|
+
collectedDefs,
|
|
270
|
+
);
|
|
271
|
+
if (schema) {
|
|
272
|
+
interfaces.push(schema);
|
|
273
|
+
generatedNames.add(name);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Input query schema
|
|
279
|
+
if (info.input?.query) {
|
|
280
|
+
const name = await this.getSchemaName(
|
|
281
|
+
info.input.query,
|
|
282
|
+
`${baseName}Query`,
|
|
283
|
+
);
|
|
284
|
+
if (!generatedNames.has(name)) {
|
|
285
|
+
const schema = await this.schemaToInterfaceWithDefs(
|
|
286
|
+
info.input.query,
|
|
287
|
+
name,
|
|
288
|
+
collectedDefs,
|
|
289
|
+
);
|
|
290
|
+
if (schema) {
|
|
291
|
+
interfaces.push(schema);
|
|
292
|
+
generatedNames.add(name);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Output schema
|
|
298
|
+
if (info.output) {
|
|
299
|
+
const name = await this.getSchemaName(info.output, `${baseName}Output`);
|
|
300
|
+
if (!generatedNames.has(name)) {
|
|
301
|
+
const schema = await this.schemaToInterfaceWithDefs(
|
|
302
|
+
info.output,
|
|
303
|
+
name,
|
|
304
|
+
collectedDefs,
|
|
305
|
+
);
|
|
306
|
+
if (schema) {
|
|
307
|
+
interfaces.push(schema);
|
|
308
|
+
generatedNames.add(name);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Generate interfaces for collected $defs (nested schemas with .meta({ id: 'X' }))
|
|
315
|
+
for (const [defName, defSchema] of collectedDefs) {
|
|
316
|
+
if (!generatedNames.has(defName)) {
|
|
317
|
+
const interfaceStr = this.jsonSchemaToInterface(defSchema, defName);
|
|
318
|
+
interfaces.push(interfaceStr);
|
|
319
|
+
generatedNames.add(defName);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
return interfaces.join('\n\n');
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get the name for a schema, using metadata `id` if available,
|
|
328
|
+
* otherwise falling back to the provided default name.
|
|
329
|
+
*/
|
|
330
|
+
private async getSchemaName(
|
|
331
|
+
schema: StandardSchemaV1,
|
|
332
|
+
defaultName: string,
|
|
333
|
+
): Promise<string> {
|
|
334
|
+
try {
|
|
335
|
+
const metadata = await getSchemaMetadata(schema);
|
|
336
|
+
if (metadata?.id) {
|
|
337
|
+
return this.pascalCase(metadata.id);
|
|
338
|
+
}
|
|
339
|
+
} catch {
|
|
340
|
+
// Ignore metadata extraction errors
|
|
341
|
+
}
|
|
342
|
+
return defaultName;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
private getSchemaBaseName(info: EndpointInfo): string {
|
|
346
|
+
if (info.operationId) {
|
|
347
|
+
return this.pascalCase(info.operationId);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
// Generate name from method + route
|
|
351
|
+
const routeParts = info.route
|
|
352
|
+
.replace(/[{}]/g, '')
|
|
353
|
+
.split('/')
|
|
354
|
+
.filter(Boolean)
|
|
355
|
+
.map((part) => this.pascalCase(part));
|
|
356
|
+
|
|
357
|
+
return `${this.pascalCase(info.method.toLowerCase())}${routeParts.join('')}`;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
private pascalCase(str: string): string {
|
|
361
|
+
return str
|
|
362
|
+
.replace(/[-_](.)/g, (_, c) => c.toUpperCase())
|
|
363
|
+
.replace(/^./, (c) => c.toUpperCase());
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Convert schema to interface while collecting $defs for nested schemas
|
|
368
|
+
* with .meta({ id: 'X' }).
|
|
369
|
+
*/
|
|
370
|
+
private async schemaToInterfaceWithDefs(
|
|
371
|
+
schema: StandardSchemaV1,
|
|
372
|
+
name: string,
|
|
373
|
+
collectedDefs: Map<string, JsonSchema>,
|
|
374
|
+
): Promise<string | null> {
|
|
375
|
+
try {
|
|
376
|
+
// Get raw JSON schema with $defs intact (don't use convertStandardSchemaToJsonSchema
|
|
377
|
+
// which strips $defs)
|
|
378
|
+
const vendor = schema['~standard']?.vendor;
|
|
379
|
+
if (!vendor || !(vendor in StandardSchemaJsonSchema)) {
|
|
380
|
+
return null;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
const toJsonSchema =
|
|
384
|
+
StandardSchemaJsonSchema[
|
|
385
|
+
vendor as keyof typeof StandardSchemaJsonSchema
|
|
386
|
+
];
|
|
387
|
+
const jsonSchema = await toJsonSchema(schema);
|
|
388
|
+
if (!jsonSchema) return null;
|
|
389
|
+
|
|
390
|
+
// Extract $defs from the JSON schema (these come from .meta({ id: 'X' }))
|
|
391
|
+
if (jsonSchema.$defs && typeof jsonSchema.$defs === 'object') {
|
|
392
|
+
for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) {
|
|
393
|
+
if (!collectedDefs.has(defName)) {
|
|
394
|
+
// Remove the 'id' field from the schema as it's just metadata
|
|
395
|
+
const { id, ...schemaWithoutId } = defSchema as JsonSchema & {
|
|
396
|
+
id?: string;
|
|
397
|
+
};
|
|
398
|
+
collectedDefs.set(defName, schemaWithoutId as JsonSchema);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
// Remove $defs from the schema before converting to interface
|
|
404
|
+
const { $defs, ...schemaWithoutDefs } = jsonSchema;
|
|
405
|
+
return this.jsonSchemaToInterface(schemaWithoutDefs, name);
|
|
406
|
+
} catch {
|
|
407
|
+
return null;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
private jsonSchemaToInterface(schema: JsonSchema, name: string): string {
|
|
412
|
+
if (schema.type !== 'object' || !schema.properties) {
|
|
413
|
+
// For non-object types, create a type alias
|
|
414
|
+
const typeStr = this.jsonSchemaTypeToTs(schema);
|
|
415
|
+
return `export type ${name} = ${typeStr};`;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
const props: string[] = [];
|
|
419
|
+
const required = new Set(schema.required || []);
|
|
420
|
+
|
|
421
|
+
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
422
|
+
const isRequired = required.has(propName);
|
|
423
|
+
const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);
|
|
424
|
+
const optionalMark = isRequired ? '' : '?';
|
|
425
|
+
props.push(` ${propName}${optionalMark}: ${typeStr};`);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
return `export interface ${name} {\n${props.join('\n')}\n}`;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
private jsonSchemaTypeToTs(schema: JsonSchema): string {
|
|
432
|
+
if (!schema) return 'unknown';
|
|
433
|
+
|
|
434
|
+
if (schema.$ref) {
|
|
435
|
+
// Extract name from $ref
|
|
436
|
+
const refName = schema.$ref.split('/').pop() || 'unknown';
|
|
437
|
+
return refName;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
if (schema.anyOf) {
|
|
441
|
+
return schema.anyOf
|
|
442
|
+
.map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))
|
|
443
|
+
.join(' | ');
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
if (schema.oneOf) {
|
|
447
|
+
return schema.oneOf
|
|
448
|
+
.map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))
|
|
449
|
+
.join(' | ');
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
if (schema.allOf) {
|
|
453
|
+
return schema.allOf
|
|
454
|
+
.map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))
|
|
455
|
+
.join(' & ');
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
switch (schema.type) {
|
|
459
|
+
case 'string':
|
|
460
|
+
if (schema.enum) {
|
|
461
|
+
return schema.enum.map((e: string) => `'${e}'`).join(' | ');
|
|
462
|
+
}
|
|
463
|
+
return 'string';
|
|
464
|
+
case 'number':
|
|
465
|
+
case 'integer':
|
|
466
|
+
return 'number';
|
|
467
|
+
case 'boolean':
|
|
468
|
+
return 'boolean';
|
|
469
|
+
case 'null':
|
|
470
|
+
return 'null';
|
|
471
|
+
case 'array':
|
|
472
|
+
if (schema.items) {
|
|
473
|
+
return `Array<${this.jsonSchemaTypeToTs(schema.items as JsonSchema)}>`;
|
|
474
|
+
}
|
|
475
|
+
return 'Array<unknown>';
|
|
476
|
+
case 'object':
|
|
477
|
+
if (schema.properties) {
|
|
478
|
+
const props: string[] = [];
|
|
479
|
+
const required = new Set(schema.required || []);
|
|
480
|
+
for (const [propName, propSchema] of Object.entries(
|
|
481
|
+
schema.properties,
|
|
482
|
+
)) {
|
|
483
|
+
const isRequired = required.has(propName);
|
|
484
|
+
const typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);
|
|
485
|
+
const optionalMark = isRequired ? '' : '?';
|
|
486
|
+
props.push(`${propName}${optionalMark}: ${typeStr}`);
|
|
487
|
+
}
|
|
488
|
+
return `{ ${props.join('; ')} }`;
|
|
489
|
+
}
|
|
490
|
+
if (schema.additionalProperties) {
|
|
491
|
+
const valueType = this.jsonSchemaTypeToTs(
|
|
492
|
+
schema.additionalProperties as JsonSchema,
|
|
493
|
+
);
|
|
494
|
+
return `Record<string, ${valueType}>`;
|
|
495
|
+
}
|
|
496
|
+
return 'Record<string, unknown>';
|
|
497
|
+
default:
|
|
498
|
+
return 'unknown';
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
private async generatePathsInterface(
|
|
503
|
+
endpointInfos: EndpointInfo[],
|
|
504
|
+
): Promise<string> {
|
|
505
|
+
const pathGroups = new Map<string, EndpointInfo[]>();
|
|
506
|
+
|
|
507
|
+
// Group endpoints by route
|
|
508
|
+
for (const info of endpointInfos) {
|
|
509
|
+
const existing = pathGroups.get(info.route) || [];
|
|
510
|
+
existing.push(info);
|
|
511
|
+
pathGroups.set(info.route, existing);
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
const pathEntries: string[] = [];
|
|
515
|
+
|
|
516
|
+
for (const [route, infos] of pathGroups) {
|
|
517
|
+
const methodEntries: string[] = [];
|
|
518
|
+
|
|
519
|
+
for (const info of infos) {
|
|
520
|
+
const methodDef = await this.generateMethodDefinition(info);
|
|
521
|
+
methodEntries.push(` ${info.method.toLowerCase()}: ${methodDef};`);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// Add path parameters if present
|
|
525
|
+
const firstWithParams = infos.find((i) => i.input?.params);
|
|
526
|
+
let paramsEntry = '';
|
|
527
|
+
if (firstWithParams?.input?.params) {
|
|
528
|
+
const paramsName = await this.getSchemaName(
|
|
529
|
+
firstWithParams.input.params,
|
|
530
|
+
`${this.getSchemaBaseName(firstWithParams)}Params`,
|
|
531
|
+
);
|
|
532
|
+
paramsEntry = `\n parameters: {\n path: ${paramsName};\n };`;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
pathEntries.push(
|
|
536
|
+
` '${route}': {${paramsEntry}\n${methodEntries.join('\n')}\n };`,
|
|
537
|
+
);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
return `export interface paths {\n${pathEntries.join('\n')}\n}`;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
private async generateMethodDefinition(info: EndpointInfo): Promise<string> {
|
|
544
|
+
const parts: string[] = [];
|
|
545
|
+
const baseName = this.getSchemaBaseName(info);
|
|
546
|
+
|
|
547
|
+
// Request body
|
|
548
|
+
if (info.input?.body) {
|
|
549
|
+
const bodyName = await this.getSchemaName(
|
|
550
|
+
info.input.body,
|
|
551
|
+
`${baseName}Input`,
|
|
552
|
+
);
|
|
553
|
+
parts.push(`requestBody: {
|
|
554
554
|
content: {
|
|
555
555
|
'application/json': ${bodyName};
|
|
556
556
|
};
|
|
557
557
|
}`);
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
// Query parameters
|
|
561
|
+
if (info.input?.query) {
|
|
562
|
+
const queryName = await this.getSchemaName(
|
|
563
|
+
info.input.query,
|
|
564
|
+
`${baseName}Query`,
|
|
565
|
+
);
|
|
566
|
+
parts.push(`parameters: {
|
|
567
567
|
query: ${queryName};
|
|
568
568
|
}`);
|
|
569
|
-
|
|
569
|
+
}
|
|
570
570
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
571
|
+
// Responses
|
|
572
|
+
const outputName = info.output
|
|
573
|
+
? await this.getSchemaName(info.output, `${baseName}Output`)
|
|
574
|
+
: 'unknown';
|
|
575
|
+
parts.push(`responses: {
|
|
576
576
|
200: {
|
|
577
577
|
content: {
|
|
578
578
|
'application/json': ${outputName};
|
|
@@ -580,43 +580,43 @@ export class OpenApiTsGenerator {
|
|
|
580
580
|
};
|
|
581
581
|
}`);
|
|
582
582
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
583
|
+
return `{\n ${parts.join(';\n ')};\n }`;
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
private buildModule(params: {
|
|
587
|
+
title: string;
|
|
588
|
+
version: string;
|
|
589
|
+
description?: string;
|
|
590
|
+
securitySchemes: SecuritySchemeInfo[];
|
|
591
|
+
endpointAuth: Record<string, string | null>;
|
|
592
|
+
schemaInterfaces: string;
|
|
593
|
+
pathsInterface: string;
|
|
594
|
+
}): string {
|
|
595
|
+
const {
|
|
596
|
+
title,
|
|
597
|
+
version,
|
|
598
|
+
description,
|
|
599
|
+
securitySchemes,
|
|
600
|
+
endpointAuth,
|
|
601
|
+
schemaInterfaces,
|
|
602
|
+
pathsInterface,
|
|
603
|
+
} = params;
|
|
604
|
+
|
|
605
|
+
const securitySchemesObj = securitySchemes.reduce(
|
|
606
|
+
(acc, s) => {
|
|
607
|
+
acc[s.name] = s.scheme;
|
|
608
|
+
return acc;
|
|
609
|
+
},
|
|
610
|
+
{} as Record<string, SecuritySchemeObject>,
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(' | ');
|
|
614
|
+
|
|
615
|
+
// Generate createApi only if there are security schemes
|
|
616
|
+
const hasSecuritySchemes = schemeNames.length > 0;
|
|
617
|
+
|
|
618
|
+
const createApiSection = hasSecuritySchemes
|
|
619
|
+
? `
|
|
620
620
|
// ============================================================
|
|
621
621
|
// API Client Factory
|
|
622
622
|
// ============================================================
|
|
@@ -676,7 +676,7 @@ export function createApi(options: CreateApiOptions) {
|
|
|
676
676
|
return Object.assign(fetcher, hooks);
|
|
677
677
|
}
|
|
678
678
|
`
|
|
679
|
-
|
|
679
|
+
: `
|
|
680
680
|
// ============================================================
|
|
681
681
|
// API Client Factory
|
|
682
682
|
// ============================================================
|
|
@@ -721,7 +721,7 @@ export function createApi(options: CreateApiOptions) {
|
|
|
721
721
|
}
|
|
722
722
|
`;
|
|
723
723
|
|
|
724
|
-
|
|
724
|
+
return `// Auto-generated by @geekmidas/cli - DO NOT EDIT
|
|
725
725
|
// Generated: ${new Date().toISOString()}
|
|
726
726
|
|
|
727
727
|
// ============================================================
|
|
@@ -794,5 +794,5 @@ ${schemaInterfaces}
|
|
|
794
794
|
${pathsInterface}
|
|
795
795
|
${createApiSection}
|
|
796
796
|
`;
|
|
797
|
-
|
|
797
|
+
}
|
|
798
798
|
}
|