@geekmidas/cli 10.0.0-alpha.71 → 10.0.0-alpha.73
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/{OpenApiTsGenerator-DZZwHdDC.cjs → EndpointGenerator-CP6sBvQV.cjs} +7 -513
- package/dist/EndpointGenerator-CP6sBvQV.cjs.map +1 -0
- package/dist/{OpenApiTsGenerator-Bhr_XWWN.mjs → EndpointGenerator-DftalLYg.mjs} +6 -512
- package/dist/EndpointGenerator-DftalLYg.mjs.map +1 -0
- package/dist/{LegacyStateStore-NSHEinQi.mjs → LegacyStateStore-DTo7z924.mjs} +2 -2
- package/dist/{LegacyStateStore-NSHEinQi.mjs.map → LegacyStateStore-DTo7z924.mjs.map} +1 -1
- package/dist/{LegacyStateStore-Dd5IwiyC.cjs → LegacyStateStore-D_78eaHM.cjs} +2 -2
- package/dist/{LegacyStateStore-Dd5IwiyC.cjs.map → LegacyStateStore-D_78eaHM.cjs.map} +1 -1
- package/dist/{LocalStateStore-DTylG4T4.cjs → LocalStateStore-BhrlQIXD.cjs} +2 -2
- package/dist/{LocalStateStore-DTylG4T4.cjs.map → LocalStateStore-BhrlQIXD.cjs.map} +1 -1
- package/dist/{LocalStateStore-DUoG2wA_.mjs → LocalStateStore-CNjgkRk4.mjs} +2 -2
- package/dist/{LocalStateStore-DUoG2wA_.mjs.map → LocalStateStore-CNjgkRk4.mjs.map} +1 -1
- package/dist/OpenApiTsGenerator-CKBCckKz.cjs +514 -0
- package/dist/OpenApiTsGenerator-CKBCckKz.cjs.map +1 -0
- package/dist/OpenApiTsGenerator-nu1r1NgB.mjs +509 -0
- package/dist/OpenApiTsGenerator-nu1r1NgB.mjs.map +1 -0
- package/dist/{S3StateStore-Dxob3PNA.mjs → S3StateStore-g2P7T_Mo.mjs} +2 -2
- package/dist/{S3StateStore-Dxob3PNA.mjs.map → S3StateStore-g2P7T_Mo.mjs.map} +1 -1
- package/dist/{S3StateStore-D7hrU-sy.cjs → S3StateStore-oCxRs6HM.cjs} +2 -2
- package/dist/{S3StateStore-D7hrU-sy.cjs.map → S3StateStore-oCxRs6HM.cjs.map} +1 -1
- package/dist/{SSMStateStore-Dvl4A8Up.mjs → SSMStateStore-CYenunmK.mjs} +2 -2
- package/dist/{SSMStateStore-Dvl4A8Up.mjs.map → SSMStateStore-CYenunmK.mjs.map} +1 -1
- package/dist/{SSMStateStore-DGIKJ4NN.cjs → SSMStateStore-DXp0m7XI.cjs} +2 -2
- package/dist/{SSMStateStore-DGIKJ4NN.cjs.map → SSMStateStore-DXp0m7XI.cjs.map} +1 -1
- package/dist/SubscriberGenerator-Bixm28fN.cjs +461 -0
- package/dist/SubscriberGenerator-Bixm28fN.cjs.map +1 -0
- package/dist/SubscriberGenerator-DZk_pKDh.mjs +432 -0
- package/dist/SubscriberGenerator-DZk_pKDh.mjs.map +1 -0
- package/dist/{add-XTLU19_E.mjs → add-BiPlBUq3.mjs} +4 -4
- package/dist/{add-XTLU19_E.mjs.map → add-BiPlBUq3.mjs.map} +1 -1
- package/dist/{add-DeC2Kyyv.cjs → add-C1ojB2Yy.cjs} +4 -4
- package/dist/{add-DeC2Kyyv.cjs.map → add-C1ojB2Yy.cjs.map} +1 -1
- package/dist/{bundler-CNTVLCCA.mjs → bundler-C2LZoLdP.mjs} +6 -6
- package/dist/bundler-C2LZoLdP.mjs.map +1 -0
- package/dist/{bundler-CEaR6Dpb.cjs → bundler-C35h0WKt.cjs} +6 -6
- package/dist/bundler-C35h0WKt.cjs.map +1 -0
- package/dist/{cli-D1arS0p1.mjs → cli-BfdfyTF6.mjs} +4 -4
- package/dist/{cli-D1arS0p1.mjs.map → cli-BfdfyTF6.mjs.map} +1 -1
- package/dist/{cli-MMgBrHx7.cjs → cli-DJVL2sL9.cjs} +4 -4
- package/dist/{cli-MMgBrHx7.cjs.map → cli-DJVL2sL9.cjs.map} +1 -1
- package/dist/{compose-T3hnnjKZ.mjs → compose-9II-0IsK.mjs} +221 -64
- package/dist/compose-9II-0IsK.mjs.map +1 -0
- package/dist/{compose-B-MME-4C.cjs → compose-CNnw8meq.cjs} +223 -66
- package/dist/compose-CNnw8meq.cjs.map +1 -0
- package/dist/{config-BN6iXvyR.d.mts → config-B8OR_TrO.d.mts} +3 -3
- package/dist/{config-BN6iXvyR.d.mts.map → config-B8OR_TrO.d.mts.map} +1 -1
- package/dist/{config-j9zBKaEG.d.cts → config-RLuR2o9A.d.cts} +3 -3
- package/dist/{config-j9zBKaEG.d.cts.map → config-RLuR2o9A.d.cts.map} +1 -1
- package/dist/config.cjs +4 -1
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts +3 -3
- package/dist/config.d.mts +3 -3
- package/dist/config.mjs +4 -1
- package/dist/config.mjs.map +1 -1
- package/dist/{credentialSchemas-BmYxnEz_.mjs → credentialSchemas-BJqRJNK4.mjs} +2 -2
- package/dist/{credentialSchemas-BmYxnEz_.mjs.map → credentialSchemas-BJqRJNK4.mjs.map} +1 -1
- package/dist/{credentialSchemas-BcNL1N5R.cjs → credentialSchemas-DCR4Wd1W.cjs} +2 -2
- package/dist/{credentialSchemas-BcNL1N5R.cjs.map → credentialSchemas-DCR4Wd1W.cjs.map} +1 -1
- package/dist/deploy/public.cjs +7 -7
- package/dist/deploy/public.d.cts +4 -4
- package/dist/deploy/public.d.cts.map +1 -1
- package/dist/deploy/public.d.mts +4 -4
- package/dist/deploy/public.d.mts.map +1 -1
- package/dist/deploy/public.mjs +7 -7
- package/dist/deploy/sniffer-routes-worker.cjs +2 -2
- package/dist/deploy/sniffer-routes-worker.mjs +2 -2
- package/dist/{deploy-CZE0m6jd.cjs → deploy-BitZLdnY.cjs} +12 -6
- package/dist/deploy-BitZLdnY.cjs.map +1 -0
- package/dist/{deploy-ClC53rc6.mjs → deploy-nmov4j0B.mjs} +12 -6
- package/dist/deploy-nmov4j0B.mjs.map +1 -0
- package/dist/{discover-Buwf1z4P.mjs → discover-BPelzeGW.mjs} +21 -2
- package/dist/discover-BPelzeGW.mjs.map +1 -0
- package/dist/{discover-B_IkPukx.d.cts → discover-CU0paUyH.d.cts} +10 -1
- package/dist/discover-CU0paUyH.d.cts.map +1 -0
- package/dist/{discover-B4VjaFJk.cjs → discover-D1It5r_h.cjs} +21 -2
- package/dist/discover-D1It5r_h.cjs.map +1 -0
- package/dist/{discover-B6yPpvRV.d.mts → discover-DFiJxwfv.d.mts} +10 -1
- package/dist/discover-DFiJxwfv.d.mts.map +1 -0
- package/dist/{dokploy-D1UwQKm3.mjs → dokploy-CZ1vZt21.mjs} +2 -2
- package/dist/{dokploy-D1UwQKm3.mjs.map → dokploy-CZ1vZt21.mjs.map} +1 -1
- package/dist/{dokploy-lwmH05zr.cjs → dokploy-Ce_VTytN.cjs} +2 -2
- package/dist/{dokploy-lwmH05zr.cjs.map → dokploy-Ce_VTytN.cjs.map} +1 -1
- package/dist/{encryption-D05sNwED.cjs → encryption-CDGRdcMr.cjs} +2 -2
- package/dist/{encryption-D05sNwED.cjs.map → encryption-CDGRdcMr.cjs.map} +1 -1
- package/dist/{encryption-DcrxWl1s.mjs → encryption-CmfPICSN.mjs} +2 -2
- package/dist/{encryption-DcrxWl1s.mjs.map → encryption-CmfPICSN.mjs.map} +1 -1
- package/dist/{engine-DmQS3XHX.mjs → engine-B37qBO5W.mjs} +117 -17
- package/dist/engine-B37qBO5W.mjs.map +1 -0
- package/dist/{engine-Cry1vwMz.cjs → engine-DL2-PW6m.cjs} +117 -17
- package/dist/engine-DL2-PW6m.cjs.map +1 -0
- package/dist/{github-BchWoiVx.cjs → github-C6qF8kHg.cjs} +2 -2
- package/dist/{github-BchWoiVx.cjs.map → github-C6qF8kHg.cjs.map} +1 -1
- package/dist/{github-CqYOP8cI.mjs → github-hjHHm7jM.mjs} +2 -2
- package/dist/{github-CqYOP8cI.mjs.map → github-hjHHm7jM.mjs.map} +1 -1
- package/dist/{index-DvoxuTqR.d.mts → index-DHyTqGG3.d.mts} +2 -2
- package/dist/{index-Bk3NY6DN.d.cts.map → index-DHyTqGG3.d.mts.map} +1 -1
- package/dist/{index-Bk3NY6DN.d.cts → index-Dg-UZ4Hm.d.cts} +2 -2
- package/dist/{index-DvoxuTqR.d.mts.map → index-Dg-UZ4Hm.d.cts.map} +1 -1
- package/dist/index.cjs +124 -448
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +118 -442
- package/dist/index.mjs.map +1 -1
- package/dist/{migrate-guck0NJK.mjs → migrate-CFFC3esE.mjs} +3 -3
- package/dist/{migrate-guck0NJK.mjs.map → migrate-CFFC3esE.mjs.map} +1 -1
- package/dist/{migrate-qKeGYq21.cjs → migrate-kA_j1TPK.cjs} +3 -3
- package/dist/{migrate-qKeGYq21.cjs.map → migrate-kA_j1TPK.cjs.map} +1 -1
- package/dist/openapi.cjs +3 -2
- package/dist/openapi.cjs.map +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +2 -1
- package/dist/openapi.mjs.map +1 -1
- package/dist/{ready-Dp6arkI4.cjs → ready-BIuMw6wH.cjs} +66 -289
- package/dist/ready-BIuMw6wH.cjs.map +1 -0
- package/dist/{ready-xpoX11uu.mjs → ready-C0U0NYfB.mjs} +58 -281
- package/dist/ready-C0U0NYfB.mjs.map +1 -0
- package/dist/reconcile/public.cjs +1 -1
- package/dist/reconcile/public.d.cts +2 -2
- package/dist/reconcile/public.d.mts +2 -2
- package/dist/reconcile/public.mjs +1 -1
- package/dist/{resolve-BsXEXAUz.mjs → resolve-CV4eQkDa.mjs} +3 -3
- package/dist/{resolve-BsXEXAUz.mjs.map → resolve-CV4eQkDa.mjs.map} +1 -1
- package/dist/{resolve-wEjEvbJ5.cjs → resolve-E5RfY0bm.cjs} +3 -3
- package/dist/{resolve-wEjEvbJ5.cjs.map → resolve-E5RfY0bm.cjs.map} +1 -1
- package/dist/{rollback-Bk91csFg.mjs → rollback-C-V-Rf4a.mjs} +4 -4
- package/dist/{rollback-Bk91csFg.mjs.map → rollback-C-V-Rf4a.mjs.map} +1 -1
- package/dist/{rollback-DmcU-efZ.cjs → rollback-QGwomD64.cjs} +4 -4
- package/dist/{rollback-DmcU-efZ.cjs.map → rollback-QGwomD64.cjs.map} +1 -1
- package/dist/{runtime-DHJhe4QI.d.mts → runtime-CWYLIeCU.d.mts} +2 -2
- package/dist/{runtime-CYAO4iZG.d.cts.map → runtime-CWYLIeCU.d.mts.map} +1 -1
- package/dist/{runtime-CYAO4iZG.d.cts → runtime-CmuQOT6A.d.cts} +2 -2
- package/dist/{runtime-DHJhe4QI.d.mts.map → runtime-CmuQOT6A.d.cts.map} +1 -1
- package/dist/sandbox/credentials-worker.cjs +2 -2
- package/dist/sandbox/credentials-worker.mjs +2 -2
- package/dist/sandbox/discover-worker.cjs +6 -3
- package/dist/sandbox/discover-worker.cjs.map +1 -1
- package/dist/sandbox/discover-worker.mjs +6 -3
- package/dist/sandbox/discover-worker.mjs.map +1 -1
- package/dist/sandbox/migrate-worker.cjs +1 -1
- package/dist/sandbox/migrate-worker.mjs +1 -1
- package/dist/{sniffer-vAXsU_4G.mjs → sniffer-BFmdZpZ2.mjs} +6 -6
- package/dist/{sniffer-vAXsU_4G.mjs.map → sniffer-BFmdZpZ2.mjs.map} +1 -1
- package/dist/{sniffer-DpHpFZBD.cjs → sniffer-C-T7dSMN.cjs} +6 -6
- package/dist/{sniffer-DpHpFZBD.cjs.map → sniffer-C-T7dSMN.cjs.map} +1 -1
- package/dist/{state-CCuTJNRH.cjs → state-DMjFPOhf.cjs} +942 -22
- package/dist/state-DMjFPOhf.cjs.map +1 -0
- package/dist/{state-BJFherj1.mjs → state-DtS2HEfi.mjs} +877 -17
- package/dist/state-DtS2HEfi.mjs.map +1 -0
- package/dist/target/public.cjs +1 -1
- package/dist/target/public.d.cts +2 -2
- package/dist/target/public.d.mts +2 -2
- package/dist/target/public.mjs +1 -1
- package/dist/{terminal-CFO3xWoF.cjs → terminal-BL5E0xbR.cjs} +2 -2
- package/dist/{terminal-CFO3xWoF.cjs.map → terminal-BL5E0xbR.cjs.map} +1 -1
- package/dist/{terminal-C6TBo_SA.mjs → terminal-BdvrmkaC.mjs} +2 -2
- package/dist/{terminal-C6TBo_SA.mjs.map → terminal-BdvrmkaC.mjs.map} +1 -1
- package/dist/{types-DkG5WW8l.d.mts → types-BLdCL4fB.d.mts} +17 -1
- package/dist/types-BLdCL4fB.d.mts.map +1 -0
- package/dist/{types-BD1jgA85.d.cts → types-DwCQCkC-.d.cts} +17 -1
- package/dist/types-DwCQCkC-.d.cts.map +1 -0
- package/dist/vitest.cjs +1 -1
- package/dist/vitest.mjs +1 -1
- package/dist/workspace/index.d.cts +2 -2
- package/dist/workspace/index.d.mts +2 -2
- package/dist/workspace-C7NqCsQF.mjs.map +1 -1
- package/dist/workspace-vdrcRI-m.cjs.map +1 -1
- package/package.json +15 -15
- package/dist/OpenApiTsGenerator-Bhr_XWWN.mjs.map +0 -1
- package/dist/OpenApiTsGenerator-DZZwHdDC.cjs.map +0 -1
- package/dist/bundler-CEaR6Dpb.cjs.map +0 -1
- package/dist/bundler-CNTVLCCA.mjs.map +0 -1
- package/dist/compose-B-MME-4C.cjs.map +0 -1
- package/dist/compose-T3hnnjKZ.mjs.map +0 -1
- package/dist/deploy-CZE0m6jd.cjs.map +0 -1
- package/dist/deploy-ClC53rc6.mjs.map +0 -1
- package/dist/discover-B4VjaFJk.cjs.map +0 -1
- package/dist/discover-B6yPpvRV.d.mts.map +0 -1
- package/dist/discover-B_IkPukx.d.cts.map +0 -1
- package/dist/discover-Buwf1z4P.mjs.map +0 -1
- package/dist/engine-Cry1vwMz.cjs.map +0 -1
- package/dist/engine-DmQS3XHX.mjs.map +0 -1
- package/dist/fakes-C9RiT6XG.mjs +0 -125
- package/dist/fakes-C9RiT6XG.mjs.map +0 -1
- package/dist/fakes-zW-jNAbQ.cjs +0 -148
- package/dist/fakes-zW-jNAbQ.cjs.map +0 -1
- package/dist/ready-Dp6arkI4.cjs.map +0 -1
- package/dist/ready-xpoX11uu.mjs.map +0 -1
- package/dist/state-BJFherj1.mjs.map +0 -1
- package/dist/state-CCuTJNRH.cjs.map +0 -1
- package/dist/types-BD1jgA85.d.cts.map +0 -1
- package/dist/types-DkG5WW8l.d.mts.map +0 -1
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
let _geekmidas_schema_conversion = require("@geekmidas/schema/conversion");
|
|
2
|
+
//#region src/generators/OpenApiTsGenerator.ts
|
|
3
|
+
/**
|
|
4
|
+
* Generates TypeScript OpenAPI module from endpoints.
|
|
5
|
+
* Outputs:
|
|
6
|
+
* - securitySchemes: typed security scheme definitions
|
|
7
|
+
* - endpointAuth: runtime map of endpoints to auth requirements
|
|
8
|
+
* - paths: TypeScript interface for type-safe fetcher
|
|
9
|
+
* - schema interfaces: reusable TypeScript types from Zod/Valibot schemas
|
|
10
|
+
*/
|
|
11
|
+
var OpenApiTsGenerator = class {
|
|
12
|
+
async generate(endpoints, options = {}) {
|
|
13
|
+
const { title = "API", version = "1.0.0", description } = options;
|
|
14
|
+
const endpointInfos = await this.extractEndpointInfos(endpoints);
|
|
15
|
+
const securitySchemes = this.collectSecuritySchemes(endpointInfos);
|
|
16
|
+
const endpointAuth = this.buildEndpointAuthMap(endpointInfos);
|
|
17
|
+
const schemaInterfaces = await this.generateSchemaInterfaces(endpointInfos);
|
|
18
|
+
const pathsInterface = await this.generatePathsInterface(endpointInfos);
|
|
19
|
+
return this.buildModule({
|
|
20
|
+
title,
|
|
21
|
+
version,
|
|
22
|
+
description,
|
|
23
|
+
securitySchemes,
|
|
24
|
+
endpointAuth,
|
|
25
|
+
schemaInterfaces,
|
|
26
|
+
pathsInterface
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async extractEndpointInfos(endpoints) {
|
|
30
|
+
return endpoints.map((ep) => {
|
|
31
|
+
const route = ep.route.replace(/:(\w+)/g, "{$1}");
|
|
32
|
+
const method = ep.method.toUpperCase();
|
|
33
|
+
const securityScheme = ep.authorizer?.securityScheme;
|
|
34
|
+
return {
|
|
35
|
+
endpoint: `${method} ${route}`,
|
|
36
|
+
route,
|
|
37
|
+
method,
|
|
38
|
+
authorizerName: ep.authorizer?.name ?? null,
|
|
39
|
+
authorizerType: ep.authorizer?.type ?? null,
|
|
40
|
+
securityScheme: securityScheme ?? null,
|
|
41
|
+
input: ep.input,
|
|
42
|
+
output: ep.outputSchema,
|
|
43
|
+
description: ep.description,
|
|
44
|
+
tags: ep.tags,
|
|
45
|
+
operationId: ep.operationId,
|
|
46
|
+
responseType: ep.responseType ?? "application/json"
|
|
47
|
+
};
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
collectSecuritySchemes(endpointInfos) {
|
|
51
|
+
const schemes = /* @__PURE__ */ new Map();
|
|
52
|
+
for (const info of endpointInfos) if (info.authorizerName && !schemes.has(info.authorizerName)) {
|
|
53
|
+
const scheme = info.securityScheme ?? (info.authorizerType ? this.mapAuthorizerToSecurityScheme(info.authorizerType, info.authorizerName) : null);
|
|
54
|
+
if (scheme) schemes.set(info.authorizerName, {
|
|
55
|
+
name: info.authorizerName,
|
|
56
|
+
type: scheme.type,
|
|
57
|
+
scheme
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
return Array.from(schemes.values());
|
|
61
|
+
}
|
|
62
|
+
mapAuthorizerToSecurityScheme(type, _name) {
|
|
63
|
+
switch (type.toLowerCase()) {
|
|
64
|
+
case "jwt":
|
|
65
|
+
case "bearer": return {
|
|
66
|
+
type: "http",
|
|
67
|
+
scheme: "bearer",
|
|
68
|
+
bearerFormat: "JWT"
|
|
69
|
+
};
|
|
70
|
+
case "iam":
|
|
71
|
+
case "aws-sigv4":
|
|
72
|
+
case "sigv4": return {
|
|
73
|
+
type: "apiKey",
|
|
74
|
+
in: "header",
|
|
75
|
+
name: "Authorization",
|
|
76
|
+
"x-amazon-apigateway-authtype": "awsSigv4"
|
|
77
|
+
};
|
|
78
|
+
case "apikey":
|
|
79
|
+
case "api-key": return {
|
|
80
|
+
type: "apiKey",
|
|
81
|
+
in: "header",
|
|
82
|
+
name: "X-API-Key"
|
|
83
|
+
};
|
|
84
|
+
case "oauth2": return {
|
|
85
|
+
type: "oauth2",
|
|
86
|
+
flows: {}
|
|
87
|
+
};
|
|
88
|
+
case "oidc":
|
|
89
|
+
case "openidconnect": return {
|
|
90
|
+
type: "openIdConnect",
|
|
91
|
+
openIdConnectUrl: ""
|
|
92
|
+
};
|
|
93
|
+
default: return {
|
|
94
|
+
type: "http",
|
|
95
|
+
scheme: "bearer"
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
buildEndpointAuthMap(endpointInfos) {
|
|
100
|
+
const authMap = {};
|
|
101
|
+
for (const info of endpointInfos) authMap[info.endpoint] = info.authorizerName;
|
|
102
|
+
return authMap;
|
|
103
|
+
}
|
|
104
|
+
async generateSchemaInterfaces(endpointInfos) {
|
|
105
|
+
const interfaces = [];
|
|
106
|
+
const generatedNames = /* @__PURE__ */ new Set();
|
|
107
|
+
const collectedDefs = /* @__PURE__ */ new Map();
|
|
108
|
+
for (const info of endpointInfos) {
|
|
109
|
+
const baseName = this.getSchemaBaseName(info);
|
|
110
|
+
if (info.input?.body) {
|
|
111
|
+
const name = await this.getSchemaName(info.input.body, `${baseName}Input`);
|
|
112
|
+
if (!generatedNames.has(name)) {
|
|
113
|
+
const schema = await this.schemaToInterfaceWithDefs(info.input.body, name, collectedDefs);
|
|
114
|
+
if (schema) {
|
|
115
|
+
interfaces.push(schema);
|
|
116
|
+
generatedNames.add(name);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (info.input?.params) {
|
|
121
|
+
const name = await this.getSchemaName(info.input.params, `${baseName}Params`);
|
|
122
|
+
if (!generatedNames.has(name)) {
|
|
123
|
+
const schema = await this.schemaToInterfaceWithDefs(info.input.params, name, collectedDefs);
|
|
124
|
+
if (schema) {
|
|
125
|
+
interfaces.push(schema);
|
|
126
|
+
generatedNames.add(name);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (info.input?.query) {
|
|
131
|
+
const name = await this.getSchemaName(info.input.query, `${baseName}Query`);
|
|
132
|
+
if (!generatedNames.has(name)) {
|
|
133
|
+
const schema = await this.schemaToInterfaceWithDefs(info.input.query, name, collectedDefs);
|
|
134
|
+
if (schema) {
|
|
135
|
+
interfaces.push(schema);
|
|
136
|
+
generatedNames.add(name);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (info.output) {
|
|
141
|
+
const name = await this.getSchemaName(info.output, `${baseName}Output`);
|
|
142
|
+
if (!generatedNames.has(name)) {
|
|
143
|
+
const schema = await this.schemaToInterfaceWithDefs(info.output, name, collectedDefs);
|
|
144
|
+
if (schema) {
|
|
145
|
+
interfaces.push(schema);
|
|
146
|
+
generatedNames.add(name);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
const registrySchemas = await (0, _geekmidas_schema_conversion.getRegisteredZodJsonSchemas)();
|
|
152
|
+
for (const [rawName, rawSchema] of Object.entries(registrySchemas)) {
|
|
153
|
+
const defName = this.pascalCase(rawName);
|
|
154
|
+
if (collectedDefs.has(defName) || generatedNames.has(defName)) continue;
|
|
155
|
+
const { id: _id, $defs: _defs, ...rest } = rawSchema;
|
|
156
|
+
collectedDefs.set(defName, rest);
|
|
157
|
+
}
|
|
158
|
+
for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
|
|
159
|
+
const interfaceStr = this.jsonSchemaToInterface(defSchema, defName);
|
|
160
|
+
interfaces.push(interfaceStr);
|
|
161
|
+
generatedNames.add(defName);
|
|
162
|
+
}
|
|
163
|
+
return interfaces.join("\n\n");
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get the name for a schema, using metadata `id` if available,
|
|
167
|
+
* otherwise falling back to the provided default name.
|
|
168
|
+
*/
|
|
169
|
+
async getSchemaName(schema, defaultName) {
|
|
170
|
+
try {
|
|
171
|
+
const metadata = await (0, _geekmidas_schema_conversion.getSchemaMetadata)(schema);
|
|
172
|
+
if (metadata?.id) return this.pascalCase(metadata.id);
|
|
173
|
+
} catch {}
|
|
174
|
+
return defaultName;
|
|
175
|
+
}
|
|
176
|
+
getSchemaBaseName(info) {
|
|
177
|
+
if (info.operationId) return this.pascalCase(info.operationId);
|
|
178
|
+
const routeParts = info.route.replace(/[{}]/g, "").split("/").filter(Boolean).map((part) => this.pascalCase(part));
|
|
179
|
+
return `${this.pascalCase(info.method.toLowerCase())}${routeParts.join("")}`;
|
|
180
|
+
}
|
|
181
|
+
pascalCase(str) {
|
|
182
|
+
return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase()).replace(/^./, (c) => c.toUpperCase());
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Convert schema to interface while collecting $defs for nested schemas
|
|
186
|
+
* with .meta({ id: 'X' }).
|
|
187
|
+
*/
|
|
188
|
+
async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
|
|
189
|
+
try {
|
|
190
|
+
const vendor = schema["~standard"]?.vendor;
|
|
191
|
+
if (!vendor || !(vendor in _geekmidas_schema_conversion.StandardSchemaJsonSchema)) return unknownType(name);
|
|
192
|
+
const toJsonSchema = _geekmidas_schema_conversion.StandardSchemaJsonSchema[vendor];
|
|
193
|
+
const jsonSchema = await toJsonSchema(schema);
|
|
194
|
+
if (!jsonSchema) return unknownType(name);
|
|
195
|
+
if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
|
|
196
|
+
for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
|
|
197
|
+
const { id, ...schemaWithoutId } = defSchema;
|
|
198
|
+
collectedDefs.set(defName, schemaWithoutId);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const { $defs, ...schemaWithoutDefs } = jsonSchema;
|
|
202
|
+
const ref = schemaWithoutDefs.$ref;
|
|
203
|
+
if (ref && Object.keys(schemaWithoutDefs).every((k) => k === "$ref" || k === "$schema")) {
|
|
204
|
+
const target = ref.split("/").pop();
|
|
205
|
+
return target === name ? null : `export type ${name} = ${target};`;
|
|
206
|
+
}
|
|
207
|
+
return this.jsonSchemaToInterface(schemaWithoutDefs, name);
|
|
208
|
+
} catch {
|
|
209
|
+
return unknownType(name);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
jsonSchemaToInterface(schema, name) {
|
|
213
|
+
if (schema.type !== "object" || !schema.properties) return `export type ${name} = ${this.jsonSchemaTypeToTs(schema)};`;
|
|
214
|
+
const props = [];
|
|
215
|
+
const required = new Set(schema.required || []);
|
|
216
|
+
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
217
|
+
const isRequired = required.has(propName);
|
|
218
|
+
const typeStr = this.jsonSchemaTypeToTs(propSchema);
|
|
219
|
+
const optionalMark = isRequired ? "" : "?";
|
|
220
|
+
props.push(` ${propName}${optionalMark}: ${typeStr};`);
|
|
221
|
+
}
|
|
222
|
+
return `export interface ${name} {\n${props.join("\n")}\n}`;
|
|
223
|
+
}
|
|
224
|
+
jsonSchemaTypeToTs(schema) {
|
|
225
|
+
if (!schema) return "unknown";
|
|
226
|
+
if (schema.$ref) return schema.$ref.split("/").pop() || "unknown";
|
|
227
|
+
if (schema.const !== void 0) return typeof schema.const === "string" ? `'${schema.const}'` : String(schema.const);
|
|
228
|
+
if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
229
|
+
if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
|
|
230
|
+
if (schema.allOf) return schema.allOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" & ");
|
|
231
|
+
if (Array.isArray(schema.type)) return schema.type.map((type) => this.jsonSchemaTypeToTs({
|
|
232
|
+
...schema,
|
|
233
|
+
type
|
|
234
|
+
})).join(" | ");
|
|
235
|
+
switch (schema.type) {
|
|
236
|
+
case "string":
|
|
237
|
+
if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
|
|
238
|
+
return "string";
|
|
239
|
+
case "number":
|
|
240
|
+
case "integer": return "number";
|
|
241
|
+
case "boolean": return "boolean";
|
|
242
|
+
case "null": return "null";
|
|
243
|
+
case "array":
|
|
244
|
+
if (schema.items) return `Array<${this.jsonSchemaTypeToTs(schema.items)}>`;
|
|
245
|
+
return "Array<unknown>";
|
|
246
|
+
case "object":
|
|
247
|
+
if (schema.properties) {
|
|
248
|
+
const props = [];
|
|
249
|
+
const required = new Set(schema.required || []);
|
|
250
|
+
for (const [propName, propSchema] of Object.entries(schema.properties)) {
|
|
251
|
+
const isRequired = required.has(propName);
|
|
252
|
+
const typeStr = this.jsonSchemaTypeToTs(propSchema);
|
|
253
|
+
const optionalMark = isRequired ? "" : "?";
|
|
254
|
+
props.push(`${propName}${optionalMark}: ${typeStr}`);
|
|
255
|
+
}
|
|
256
|
+
return `{ ${props.join("; ")} }`;
|
|
257
|
+
}
|
|
258
|
+
if (schema.additionalProperties) return `Record<string, ${this.jsonSchemaTypeToTs(schema.additionalProperties)}>`;
|
|
259
|
+
return "Record<string, unknown>";
|
|
260
|
+
default: return "unknown";
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async generatePathsInterface(endpointInfos) {
|
|
264
|
+
const pathGroups = /* @__PURE__ */ new Map();
|
|
265
|
+
for (const info of endpointInfos) {
|
|
266
|
+
const existing = pathGroups.get(info.route) || [];
|
|
267
|
+
existing.push(info);
|
|
268
|
+
pathGroups.set(info.route, existing);
|
|
269
|
+
}
|
|
270
|
+
const pathEntries = [];
|
|
271
|
+
for (const [route, infos] of pathGroups) {
|
|
272
|
+
const methodEntries = [];
|
|
273
|
+
for (const info of infos) {
|
|
274
|
+
const methodDef = await this.generateMethodDefinition(info);
|
|
275
|
+
methodEntries.push(` ${info.method.toLowerCase()}: ${methodDef};`);
|
|
276
|
+
}
|
|
277
|
+
const firstWithParams = infos.find((i) => i.input?.params);
|
|
278
|
+
let paramsEntry = "";
|
|
279
|
+
if (firstWithParams?.input?.params) paramsEntry = `\n parameters: {\n path: ${await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`)};\n };`;
|
|
280
|
+
pathEntries.push(` '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n };`);
|
|
281
|
+
}
|
|
282
|
+
return `export interface paths {\n${pathEntries.join("\n")}\n}`;
|
|
283
|
+
}
|
|
284
|
+
async generateMethodDefinition(info) {
|
|
285
|
+
const parts = [];
|
|
286
|
+
const baseName = this.getSchemaBaseName(info);
|
|
287
|
+
if (info.input?.body) {
|
|
288
|
+
const bodyName = await this.getSchemaName(info.input.body, `${baseName}Input`);
|
|
289
|
+
parts.push(`requestBody: {
|
|
290
|
+
content: {
|
|
291
|
+
'application/json': ${bodyName};
|
|
292
|
+
};
|
|
293
|
+
}`);
|
|
294
|
+
}
|
|
295
|
+
if (info.input?.query) {
|
|
296
|
+
const queryName = await this.getSchemaName(info.input.query, `${baseName}Query`);
|
|
297
|
+
parts.push(`parameters: {
|
|
298
|
+
query: ${queryName};
|
|
299
|
+
}`);
|
|
300
|
+
}
|
|
301
|
+
const outputName = info.output ? await this.getSchemaName(info.output, `${baseName}Output`) : "unknown";
|
|
302
|
+
parts.push(`responses: {
|
|
303
|
+
200: {
|
|
304
|
+
content: {
|
|
305
|
+
'${info.responseType}': ${outputName};
|
|
306
|
+
};
|
|
307
|
+
};
|
|
308
|
+
}`);
|
|
309
|
+
return `{\n ${parts.join(";\n ")};\n }`;
|
|
310
|
+
}
|
|
311
|
+
buildModule(params) {
|
|
312
|
+
const { title, version, description, securitySchemes, endpointAuth, schemaInterfaces, pathsInterface } = params;
|
|
313
|
+
const securitySchemesObj = securitySchemes.reduce((acc, s) => {
|
|
314
|
+
acc[s.name] = s.scheme;
|
|
315
|
+
return acc;
|
|
316
|
+
}, {});
|
|
317
|
+
const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
|
|
318
|
+
const createApiSection = schemeNames.length > 0 ? `
|
|
319
|
+
// ============================================================
|
|
320
|
+
// API Client Factory
|
|
321
|
+
// ============================================================
|
|
322
|
+
|
|
323
|
+
import {
|
|
324
|
+
createAuthAwareFetcher,
|
|
325
|
+
type AuthStrategy,
|
|
326
|
+
} from '@geekmidas/client/auth-fetcher';
|
|
327
|
+
import { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';
|
|
328
|
+
import type { QueryClient } from '@tanstack/react-query';
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Options for creating the API client.
|
|
332
|
+
*/
|
|
333
|
+
export interface CreateApiOptions {
|
|
334
|
+
/** Base URL for all API requests (required) */
|
|
335
|
+
baseURL: string;
|
|
336
|
+
/** Auth strategies for each security scheme used in this API */
|
|
337
|
+
authStrategies: Record<SecuritySchemeId, AuthStrategy>;
|
|
338
|
+
/** Optional React Query client instance */
|
|
339
|
+
queryClient?: QueryClient;
|
|
340
|
+
/** Optional request interceptor */
|
|
341
|
+
onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
|
|
342
|
+
/** The \`fetch\` requests go out on — a test browser's, for one */
|
|
343
|
+
fetch?: typeof fetch;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Create a type-safe API client with authentication and React Query hooks.
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* \`\`\`typescript
|
|
351
|
+
* const api = createApi({
|
|
352
|
+
* baseURL: 'https://api.example.com',
|
|
353
|
+
* authStrategies: {
|
|
354
|
+
* jwt: { type: 'bearer', tokenProvider },
|
|
355
|
+
* },
|
|
356
|
+
* });
|
|
357
|
+
*
|
|
358
|
+
* // Imperative fetch
|
|
359
|
+
* const user = await api('GET /users/{id}', { params: { id: '123' } });
|
|
360
|
+
*
|
|
361
|
+
* // React Query hooks
|
|
362
|
+
* const { data } = api.useQuery('GET /users/{id}', { params: { id: '123' } });
|
|
363
|
+
* const mutation = api.useMutation('POST /users');
|
|
364
|
+
* \`\`\`
|
|
365
|
+
*/
|
|
366
|
+
export function createApi(options: CreateApiOptions) {
|
|
367
|
+
const fetcher = createAuthAwareFetcher<paths, typeof endpointAuth, typeof securitySchemes>({
|
|
368
|
+
baseURL: options.baseURL,
|
|
369
|
+
endpointAuth,
|
|
370
|
+
securitySchemes,
|
|
371
|
+
authStrategies: options.authStrategies,
|
|
372
|
+
onRequest: options.onRequest,
|
|
373
|
+
...(options.fetch ? { fetch: options.fetch } : {}),
|
|
374
|
+
});
|
|
375
|
+
|
|
376
|
+
const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });
|
|
377
|
+
|
|
378
|
+
return Object.assign(fetcher, hooks);
|
|
379
|
+
}
|
|
380
|
+
` : `
|
|
381
|
+
// ============================================================
|
|
382
|
+
// API Client Factory
|
|
383
|
+
// ============================================================
|
|
384
|
+
|
|
385
|
+
import { createTypedFetcher, type FetcherOptions } from '@geekmidas/client/fetcher';
|
|
386
|
+
import { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';
|
|
387
|
+
import type { QueryClient } from '@tanstack/react-query';
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Options for creating the API client.
|
|
391
|
+
*/
|
|
392
|
+
export interface CreateApiOptions extends Omit<FetcherOptions, 'baseURL'> {
|
|
393
|
+
/** Base URL for all API requests (required) */
|
|
394
|
+
baseURL: string;
|
|
395
|
+
/** Optional React Query client instance */
|
|
396
|
+
queryClient?: QueryClient;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Create a type-safe API client with React Query hooks.
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
* \`\`\`typescript
|
|
404
|
+
* const api = createApi({
|
|
405
|
+
* baseURL: 'https://api.example.com',
|
|
406
|
+
* });
|
|
407
|
+
*
|
|
408
|
+
* // Imperative fetch
|
|
409
|
+
* const data = await api('GET /health');
|
|
410
|
+
*
|
|
411
|
+
* // React Query hooks
|
|
412
|
+
* const { data } = api.useQuery('GET /health');
|
|
413
|
+
* \`\`\`
|
|
414
|
+
*/
|
|
415
|
+
export function createApi(options: CreateApiOptions) {
|
|
416
|
+
const { queryClient, ...fetcherOptions } = options;
|
|
417
|
+
const request = createTypedFetcher<paths>(fetcherOptions);
|
|
418
|
+
|
|
419
|
+
const hooks = createEndpointHooks<paths>(request, { queryClient });
|
|
420
|
+
|
|
421
|
+
return Object.assign(request, hooks);
|
|
422
|
+
}
|
|
423
|
+
`;
|
|
424
|
+
return `// Auto-generated by @geekmidas/cli - DO NOT EDIT
|
|
425
|
+
|
|
426
|
+
// ============================================================
|
|
427
|
+
// Security Scheme Type
|
|
428
|
+
// ============================================================
|
|
429
|
+
|
|
430
|
+
interface SecuritySchemeObject {
|
|
431
|
+
type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';
|
|
432
|
+
description?: string;
|
|
433
|
+
name?: string;
|
|
434
|
+
in?: 'query' | 'header' | 'cookie';
|
|
435
|
+
scheme?: string;
|
|
436
|
+
bearerFormat?: string;
|
|
437
|
+
flows?: Record<string, unknown>;
|
|
438
|
+
openIdConnectUrl?: string;
|
|
439
|
+
[key: string]: unknown;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// ============================================================
|
|
443
|
+
// API Info
|
|
444
|
+
// ============================================================
|
|
445
|
+
|
|
446
|
+
export const apiInfo = {
|
|
447
|
+
title: '${title}',
|
|
448
|
+
version: '${version}',${description ? `\n description: '${description.replace(/'/g, "\\'")}',` : ""}
|
|
449
|
+
} as const;
|
|
450
|
+
|
|
451
|
+
// ============================================================
|
|
452
|
+
// Security Schemes
|
|
453
|
+
// ============================================================
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Available security schemes for this API.
|
|
457
|
+
* Maps authorizer names to OpenAPI security scheme definitions.
|
|
458
|
+
*/
|
|
459
|
+
export const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/"([a-zA-Z_$][a-zA-Z0-9_$]*)":/g, "$1:")} as const satisfies Record<string, SecuritySchemeObject>;
|
|
460
|
+
|
|
461
|
+
export type SecuritySchemeId = ${schemeNames || "never"};
|
|
462
|
+
|
|
463
|
+
// ============================================================
|
|
464
|
+
// Endpoint Authentication Map
|
|
465
|
+
// ============================================================
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* Runtime map of endpoints to their required authentication scheme.
|
|
469
|
+
* \`null\` indicates a public endpoint (no auth required).
|
|
470
|
+
*/
|
|
471
|
+
export const endpointAuth = ${JSON.stringify(endpointAuth, null, 2).replace(/"([^"]+)":/g, "'$1':")} as const satisfies Record<string, SecuritySchemeId | null>;
|
|
472
|
+
|
|
473
|
+
export type EndpointString = keyof typeof endpointAuth;
|
|
474
|
+
|
|
475
|
+
export type AuthenticatedEndpoint = {
|
|
476
|
+
[K in EndpointString]: typeof endpointAuth[K] extends null ? never : K;
|
|
477
|
+
}[EndpointString];
|
|
478
|
+
|
|
479
|
+
export type PublicEndpoint = {
|
|
480
|
+
[K in EndpointString]: typeof endpointAuth[K] extends null ? K : never;
|
|
481
|
+
}[EndpointString];
|
|
482
|
+
|
|
483
|
+
// ============================================================
|
|
484
|
+
// Schema Definitions
|
|
485
|
+
// ============================================================
|
|
486
|
+
|
|
487
|
+
${schemaInterfaces}
|
|
488
|
+
|
|
489
|
+
// ============================================================
|
|
490
|
+
// OpenAPI Paths
|
|
491
|
+
// ============================================================
|
|
492
|
+
|
|
493
|
+
${pathsInterface}
|
|
494
|
+
${createApiSection}
|
|
495
|
+
`;
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
/**
|
|
499
|
+
* The declaration for a schema that cannot be converted — a vendor with no
|
|
500
|
+
* converter, or one that fails. The paths interface names it either way, so
|
|
501
|
+
* leaving it undeclared made the generated client fail to compile.
|
|
502
|
+
*/
|
|
503
|
+
function unknownType(name) {
|
|
504
|
+
return `export type ${name} = unknown;`;
|
|
505
|
+
}
|
|
506
|
+
//#endregion
|
|
507
|
+
Object.defineProperty(exports, "OpenApiTsGenerator", {
|
|
508
|
+
enumerable: true,
|
|
509
|
+
get: function() {
|
|
510
|
+
return OpenApiTsGenerator;
|
|
511
|
+
}
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
//# sourceMappingURL=OpenApiTsGenerator-CKBCckKz.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenApiTsGenerator-CKBCckKz.cjs","names":["getRegisteredZodJsonSchemas","getSchemaMetadata","StandardSchemaJsonSchema"],"sources":["../src/generators/OpenApiTsGenerator.ts"],"sourcesContent":["import type { Endpoint } from '@geekmidas/constructs/endpoints';\nimport {\n\tgetRegisteredZodJsonSchemas,\n\tgetSchemaMetadata,\n\tStandardSchemaJsonSchema,\n} from '@geekmidas/schema/conversion';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\n\ninterface OpenApiTsOptions {\n\ttitle?: string;\n\tversion?: string;\n\tdescription?: string;\n}\n\n// JSON Schema type definition\ninterface JsonSchema {\n\t// An array since Zod 4.6, which writes a union of primitives — a nullable\n\t// string among them — as `type: ['string', 'null']` rather than `anyOf`.\n\ttype?: string | string[];\n\t/** A literal — `z.literal('open')` is `{ type: 'string', const: 'open' }`. */\n\tconst?: unknown;\n\tproperties?: Record<string, JsonSchema>;\n\titems?: JsonSchema;\n\trequired?: string[];\n\tenum?: string[];\n\t$ref?: string;\n\tanyOf?: JsonSchema[];\n\toneOf?: JsonSchema[];\n\tallOf?: JsonSchema[];\n\tadditionalProperties?: boolean | JsonSchema;\n\t[key: string]: unknown;\n}\n\n// Security scheme type (OpenAPI 3.1)\ninterface SecuritySchemeObject {\n\ttype: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n\tdescription?: string;\n\tname?: string;\n\tin?: 'query' | 'header' | 'cookie';\n\tscheme?: string;\n\tbearerFormat?: string;\n\tflows?: Record<string, unknown>;\n\topenIdConnectUrl?: string;\n\t[key: string]: unknown;\n}\n\ninterface EndpointInfo {\n\tendpoint: string;\n\troute: string;\n\tmethod: string;\n\tauthorizerName: string | null;\n\t/** @deprecated Use securityScheme instead */\n\tauthorizerType: string | null;\n\t/** The OpenAPI security scheme definition for this endpoint's authorizer */\n\tsecurityScheme: SecuritySchemeObject | null;\n\tinput?: {\n\t\tbody?: StandardSchemaV1;\n\t\tquery?: StandardSchemaV1;\n\t\tparams?: StandardSchemaV1;\n\t};\n\toutput?: StandardSchemaV1;\n\tdescription?: string;\n\ttags?: string[];\n\toperationId?: string;\n\tresponseType: string;\n}\n\ninterface SecuritySchemeInfo {\n\tname: string;\n\ttype: string;\n\tscheme: SecuritySchemeObject;\n}\n\n/**\n * Generates TypeScript OpenAPI module from endpoints.\n * Outputs:\n * - securitySchemes: typed security scheme definitions\n * - endpointAuth: runtime map of endpoints to auth requirements\n * - paths: TypeScript interface for type-safe fetcher\n * - schema interfaces: reusable TypeScript types from Zod/Valibot schemas\n */\nexport class OpenApiTsGenerator {\n\tasync generate(\n\t\tendpoints: Endpoint<any, any, any, any, any, any>[],\n\t\toptions: OpenApiTsOptions = {},\n\t): Promise<string> {\n\t\tconst { title = 'API', version = '1.0.0', description } = options;\n\n\t\t// Extract endpoint info\n\t\tconst endpointInfos = await this.extractEndpointInfos(endpoints);\n\n\t\t// Collect unique security schemes\n\t\tconst securitySchemes = this.collectSecuritySchemes(endpointInfos);\n\n\t\t// Build endpoint auth map\n\t\tconst endpointAuth = this.buildEndpointAuthMap(endpointInfos);\n\n\t\t// Generate schema interfaces\n\t\tconst schemaInterfaces = await this.generateSchemaInterfaces(endpointInfos);\n\n\t\t// Generate paths interface\n\t\tconst pathsInterface = await this.generatePathsInterface(endpointInfos);\n\n\t\t// Build the final TypeScript module\n\t\treturn this.buildModule({\n\t\t\ttitle,\n\t\t\tversion,\n\t\t\tdescription,\n\t\t\tsecuritySchemes,\n\t\t\tendpointAuth,\n\t\t\tschemaInterfaces,\n\t\t\tpathsInterface,\n\t\t});\n\t}\n\n\tprivate async extractEndpointInfos(\n\t\tendpoints: Endpoint<any, any, any, any, any, any>[],\n\t): Promise<EndpointInfo[]> {\n\t\treturn endpoints.map((ep) => {\n\t\t\tconst route = ep.route.replace(/:(\\w+)/g, '{$1}');\n\t\t\tconst method = ep.method.toUpperCase();\n\n\t\t\t// Get security scheme from authorizer (if available)\n\t\t\t// This is the preferred way - the scheme is stored directly on the authorizer\n\t\t\tconst securityScheme = ep.authorizer?.securityScheme as\n\t\t\t\t| SecuritySchemeObject\n\t\t\t\t| undefined;\n\n\t\t\treturn {\n\t\t\t\tendpoint: `${method} ${route}`,\n\t\t\t\troute,\n\t\t\t\tmethod,\n\t\t\t\tauthorizerName: ep.authorizer?.name ?? null,\n\t\t\t\tauthorizerType: ep.authorizer?.type ?? null,\n\t\t\t\tsecurityScheme: securityScheme ?? null,\n\t\t\t\tinput: ep.input,\n\t\t\t\toutput: ep.outputSchema,\n\t\t\t\tdescription: ep.description,\n\t\t\t\ttags: ep.tags,\n\t\t\t\toperationId: ep.operationId,\n\t\t\t\tresponseType: ep.responseType ?? 'application/json',\n\t\t\t};\n\t\t});\n\t}\n\n\tprivate collectSecuritySchemes(\n\t\tendpointInfos: EndpointInfo[],\n\t): SecuritySchemeInfo[] {\n\t\tconst schemes = new Map<string, SecuritySchemeInfo>();\n\n\t\tfor (const info of endpointInfos) {\n\t\t\tif (info.authorizerName && !schemes.has(info.authorizerName)) {\n\t\t\t\t// Prefer the stored security scheme (from .securitySchemes() or built-ins)\n\t\t\t\t// Fall back to inference from authorizerType for backward compatibility\n\t\t\t\tconst scheme =\n\t\t\t\t\tinfo.securityScheme ??\n\t\t\t\t\t(info.authorizerType\n\t\t\t\t\t\t? this.mapAuthorizerToSecurityScheme(\n\t\t\t\t\t\t\t\tinfo.authorizerType,\n\t\t\t\t\t\t\t\tinfo.authorizerName,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t: null);\n\n\t\t\t\tif (scheme) {\n\t\t\t\t\tschemes.set(info.authorizerName, {\n\t\t\t\t\t\tname: info.authorizerName,\n\t\t\t\t\t\ttype: scheme.type,\n\t\t\t\t\t\tscheme,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn Array.from(schemes.values());\n\t}\n\n\tprivate mapAuthorizerToSecurityScheme(\n\t\ttype: string,\n\t\t_name: string,\n\t): SecuritySchemeObject {\n\t\tswitch (type.toLowerCase()) {\n\t\t\tcase 'jwt':\n\t\t\tcase 'bearer':\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'http',\n\t\t\t\t\tscheme: 'bearer',\n\t\t\t\t\tbearerFormat: 'JWT',\n\t\t\t\t};\n\t\t\tcase 'iam':\n\t\t\tcase 'aws-sigv4':\n\t\t\tcase 'sigv4':\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\tin: 'header',\n\t\t\t\t\tname: 'Authorization',\n\t\t\t\t\t'x-amazon-apigateway-authtype': 'awsSigv4',\n\t\t\t\t};\n\t\t\tcase 'apikey':\n\t\t\tcase 'api-key':\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'apiKey',\n\t\t\t\t\tin: 'header',\n\t\t\t\t\tname: 'X-API-Key',\n\t\t\t\t};\n\t\t\tcase 'oauth2':\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'oauth2',\n\t\t\t\t\tflows: {},\n\t\t\t\t};\n\t\t\tcase 'oidc':\n\t\t\tcase 'openidconnect':\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'openIdConnect',\n\t\t\t\t\topenIdConnectUrl: '',\n\t\t\t\t};\n\t\t\tdefault:\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'http',\n\t\t\t\t\tscheme: 'bearer',\n\t\t\t\t};\n\t\t}\n\t}\n\n\tprivate buildEndpointAuthMap(\n\t\tendpointInfos: EndpointInfo[],\n\t): Record<string, string | null> {\n\t\tconst authMap: Record<string, string | null> = {};\n\n\t\tfor (const info of endpointInfos) {\n\t\t\tauthMap[info.endpoint] = info.authorizerName;\n\t\t}\n\n\t\treturn authMap;\n\t}\n\n\tprivate async generateSchemaInterfaces(\n\t\tendpointInfos: EndpointInfo[],\n\t): Promise<string> {\n\t\tconst interfaces: string[] = [];\n\t\tconst generatedNames = new Set<string>();\n\t\t// Collect nested schemas with $defs (from .meta({ id: 'X' }))\n\t\tconst collectedDefs = new Map<string, JsonSchema>();\n\n\t\tfor (const info of endpointInfos) {\n\t\t\tconst baseName = this.getSchemaBaseName(info);\n\n\t\t\t// Input body schema\n\t\t\tif (info.input?.body) {\n\t\t\t\tconst name = await this.getSchemaName(\n\t\t\t\t\tinfo.input.body,\n\t\t\t\t\t`${baseName}Input`,\n\t\t\t\t);\n\t\t\t\tif (!generatedNames.has(name)) {\n\t\t\t\t\tconst schema = await this.schemaToInterfaceWithDefs(\n\t\t\t\t\t\tinfo.input.body,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tcollectedDefs,\n\t\t\t\t\t);\n\t\t\t\t\tif (schema) {\n\t\t\t\t\t\tinterfaces.push(schema);\n\t\t\t\t\t\tgeneratedNames.add(name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Input params schema\n\t\t\tif (info.input?.params) {\n\t\t\t\tconst name = await this.getSchemaName(\n\t\t\t\t\tinfo.input.params,\n\t\t\t\t\t`${baseName}Params`,\n\t\t\t\t);\n\t\t\t\tif (!generatedNames.has(name)) {\n\t\t\t\t\tconst schema = await this.schemaToInterfaceWithDefs(\n\t\t\t\t\t\tinfo.input.params,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tcollectedDefs,\n\t\t\t\t\t);\n\t\t\t\t\tif (schema) {\n\t\t\t\t\t\tinterfaces.push(schema);\n\t\t\t\t\t\tgeneratedNames.add(name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Input query schema\n\t\t\tif (info.input?.query) {\n\t\t\t\tconst name = await this.getSchemaName(\n\t\t\t\t\tinfo.input.query,\n\t\t\t\t\t`${baseName}Query`,\n\t\t\t\t);\n\t\t\t\tif (!generatedNames.has(name)) {\n\t\t\t\t\tconst schema = await this.schemaToInterfaceWithDefs(\n\t\t\t\t\t\tinfo.input.query,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tcollectedDefs,\n\t\t\t\t\t);\n\t\t\t\t\tif (schema) {\n\t\t\t\t\t\tinterfaces.push(schema);\n\t\t\t\t\t\tgeneratedNames.add(name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Output schema\n\t\t\tif (info.output) {\n\t\t\t\tconst name = await this.getSchemaName(info.output, `${baseName}Output`);\n\t\t\t\tif (!generatedNames.has(name)) {\n\t\t\t\t\tconst schema = await this.schemaToInterfaceWithDefs(\n\t\t\t\t\t\tinfo.output,\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tcollectedDefs,\n\t\t\t\t\t);\n\t\t\t\t\tif (schema) {\n\t\t\t\t\t\tinterfaces.push(schema);\n\t\t\t\t\t\tgeneratedNames.add(name);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Pull in every schema registered via `.meta({ id })` in zod's global\n\t\t// registry, even when no endpoint references it directly. This makes\n\t\t// derived schemas like `UserSchema.pick(...)` discoverable through the\n\t\t// named parent type without requiring the parent to be wired into an\n\t\t// endpoint.\n\t\tconst registrySchemas = await getRegisteredZodJsonSchemas();\n\t\tfor (const [rawName, rawSchema] of Object.entries(registrySchemas)) {\n\t\t\tconst defName = this.pascalCase(rawName);\n\t\t\tif (collectedDefs.has(defName) || generatedNames.has(defName)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tconst {\n\t\t\t\tid: _id,\n\t\t\t\t$defs: _defs,\n\t\t\t\t...rest\n\t\t\t} = rawSchema as JsonSchema & {\n\t\t\t\tid?: string;\n\t\t\t};\n\t\t\tcollectedDefs.set(defName, rest as JsonSchema);\n\t\t}\n\n\t\t// Generate interfaces for collected $defs (nested schemas with .meta({ id: 'X' }))\n\t\tfor (const [defName, defSchema] of collectedDefs) {\n\t\t\tif (!generatedNames.has(defName)) {\n\t\t\t\tconst interfaceStr = this.jsonSchemaToInterface(defSchema, defName);\n\t\t\t\tinterfaces.push(interfaceStr);\n\t\t\t\tgeneratedNames.add(defName);\n\t\t\t}\n\t\t}\n\n\t\treturn interfaces.join('\\n\\n');\n\t}\n\n\t/**\n\t * Get the name for a schema, using metadata `id` if available,\n\t * otherwise falling back to the provided default name.\n\t */\n\tprivate async getSchemaName(\n\t\tschema: StandardSchemaV1,\n\t\tdefaultName: string,\n\t): Promise<string> {\n\t\ttry {\n\t\t\tconst metadata = await getSchemaMetadata(schema);\n\t\t\tif (metadata?.id) {\n\t\t\t\treturn this.pascalCase(metadata.id);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore metadata extraction errors\n\t\t}\n\t\treturn defaultName;\n\t}\n\n\tprivate getSchemaBaseName(info: EndpointInfo): string {\n\t\tif (info.operationId) {\n\t\t\treturn this.pascalCase(info.operationId);\n\t\t}\n\n\t\t// Generate name from method + route\n\t\tconst routeParts = info.route\n\t\t\t.replace(/[{}]/g, '')\n\t\t\t.split('/')\n\t\t\t.filter(Boolean)\n\t\t\t.map((part) => this.pascalCase(part));\n\n\t\treturn `${this.pascalCase(info.method.toLowerCase())}${routeParts.join('')}`;\n\t}\n\n\tprivate pascalCase(str: string): string {\n\t\treturn str\n\t\t\t.replace(/[-_](.)/g, (_, c) => c.toUpperCase())\n\t\t\t.replace(/^./, (c) => c.toUpperCase());\n\t}\n\n\t/**\n\t * Convert schema to interface while collecting $defs for nested schemas\n\t * with .meta({ id: 'X' }).\n\t */\n\tprivate async schemaToInterfaceWithDefs(\n\t\tschema: StandardSchemaV1,\n\t\tname: string,\n\t\tcollectedDefs: Map<string, JsonSchema>,\n\t): Promise<string | null> {\n\t\ttry {\n\t\t\t// Get raw JSON schema with $defs intact (don't use convertStandardSchemaToJsonSchema\n\t\t\t// which strips $defs)\n\t\t\tconst vendor = schema['~standard']?.vendor;\n\t\t\tif (!vendor || !(vendor in StandardSchemaJsonSchema)) {\n\t\t\t\treturn unknownType(name);\n\t\t\t}\n\n\t\t\tconst toJsonSchema =\n\t\t\t\tStandardSchemaJsonSchema[\n\t\t\t\t\tvendor as keyof typeof StandardSchemaJsonSchema\n\t\t\t\t];\n\t\t\tconst jsonSchema = await toJsonSchema(schema);\n\t\t\tif (!jsonSchema) return unknownType(name);\n\n\t\t\t// Extract $defs from the JSON schema (these come from .meta({ id: 'X' }))\n\t\t\tif (jsonSchema.$defs && typeof jsonSchema.$defs === 'object') {\n\t\t\t\tfor (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) {\n\t\t\t\t\tif (!collectedDefs.has(defName)) {\n\t\t\t\t\t\t// Remove the 'id' field from the schema as it's just metadata\n\t\t\t\t\t\tconst { id, ...schemaWithoutId } = defSchema as JsonSchema & {\n\t\t\t\t\t\t\tid?: string;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tcollectedDefs.set(defName, schemaWithoutId as JsonSchema);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove $defs from the schema before converting to interface\n\t\t\tconst { $defs, ...schemaWithoutDefs } = jsonSchema;\n\n\t\t\t// A schema that *is* a registered schema converts to nothing but a\n\t\t\t// `$ref` at it, and the def it points at has already been collected\n\t\t\t// above — so emitting a declaration here as well produces\n\t\t\t// `export type User = User`, a circular alias that is not a type.\n\t\t\t//\n\t\t\t// Zod used to inline this case and only started emitting the `$ref` in\n\t\t\t// 4.6, which is how the bug arrived without the generator changing.\n\t\t\tconst ref = (schemaWithoutDefs as { $ref?: string }).$ref;\n\t\t\tif (\n\t\t\t\tref &&\n\t\t\t\tObject.keys(schemaWithoutDefs).every(\n\t\t\t\t\t(k) => k === '$ref' || k === '$schema',\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tconst target = ref.split('/').pop();\n\t\t\t\t// The def's own interface is the declaration. Only alias it when the\n\t\t\t\t// names actually differ, which is when the alias says something.\n\t\t\t\treturn target === name ? null : `export type ${name} = ${target};`;\n\t\t\t}\n\n\t\t\treturn this.jsonSchemaToInterface(schemaWithoutDefs, name);\n\t\t} catch {\n\t\t\treturn unknownType(name);\n\t\t}\n\t}\n\n\tprivate jsonSchemaToInterface(schema: JsonSchema, name: string): string {\n\t\tif (schema.type !== 'object' || !schema.properties) {\n\t\t\t// For non-object types, create a type alias\n\t\t\tconst typeStr = this.jsonSchemaTypeToTs(schema);\n\t\t\treturn `export type ${name} = ${typeStr};`;\n\t\t}\n\n\t\tconst props: string[] = [];\n\t\tconst required = new Set(schema.required || []);\n\n\t\tfor (const [propName, propSchema] of Object.entries(schema.properties)) {\n\t\t\tconst isRequired = required.has(propName);\n\t\t\tconst typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n\t\t\tconst optionalMark = isRequired ? '' : '?';\n\t\t\tprops.push(` ${propName}${optionalMark}: ${typeStr};`);\n\t\t}\n\n\t\treturn `export interface ${name} {\\n${props.join('\\n')}\\n}`;\n\t}\n\n\tprivate jsonSchemaTypeToTs(schema: JsonSchema): string {\n\t\tif (!schema) return 'unknown';\n\n\t\tif (schema.$ref) {\n\t\t\t// Extract name from $ref\n\t\t\tconst refName = schema.$ref.split('/').pop() || 'unknown';\n\t\t\treturn refName;\n\t\t}\n\n\t\t// Before the type: a literal is narrower than the type it belongs to, and\n\t\t// reading only the type turned `'open' | 'closed'` into `string | string`.\n\t\tif (schema.const !== undefined) {\n\t\t\treturn typeof schema.const === 'string'\n\t\t\t\t? `'${schema.const}'`\n\t\t\t\t: String(schema.const);\n\t\t}\n\n\t\tif (schema.anyOf) {\n\t\t\treturn schema.anyOf\n\t\t\t\t.map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n\t\t\t\t.join(' | ');\n\t\t}\n\n\t\tif (schema.oneOf) {\n\t\t\treturn schema.oneOf\n\t\t\t\t.map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n\t\t\t\t.join(' | ');\n\t\t}\n\n\t\tif (schema.allOf) {\n\t\t\treturn schema.allOf\n\t\t\t\t.map((s: JsonSchema) => this.jsonSchemaTypeToTs(s))\n\t\t\t\t.join(' & ');\n\t\t}\n\n\t\tif (Array.isArray(schema.type)) {\n\t\t\treturn schema.type\n\t\t\t\t.map((type) => this.jsonSchemaTypeToTs({ ...schema, type }))\n\t\t\t\t.join(' | ');\n\t\t}\n\n\t\tswitch (schema.type) {\n\t\t\tcase 'string':\n\t\t\t\tif (schema.enum) {\n\t\t\t\t\treturn schema.enum.map((e: string) => `'${e}'`).join(' | ');\n\t\t\t\t}\n\t\t\t\treturn 'string';\n\t\t\tcase 'number':\n\t\t\tcase 'integer':\n\t\t\t\treturn 'number';\n\t\t\tcase 'boolean':\n\t\t\t\treturn 'boolean';\n\t\t\tcase 'null':\n\t\t\t\treturn 'null';\n\t\t\tcase 'array':\n\t\t\t\tif (schema.items) {\n\t\t\t\t\treturn `Array<${this.jsonSchemaTypeToTs(schema.items as JsonSchema)}>`;\n\t\t\t\t}\n\t\t\t\treturn 'Array<unknown>';\n\t\t\tcase 'object':\n\t\t\t\tif (schema.properties) {\n\t\t\t\t\tconst props: string[] = [];\n\t\t\t\t\tconst required = new Set(schema.required || []);\n\t\t\t\t\tfor (const [propName, propSchema] of Object.entries(\n\t\t\t\t\t\tschema.properties,\n\t\t\t\t\t)) {\n\t\t\t\t\t\tconst isRequired = required.has(propName);\n\t\t\t\t\t\tconst typeStr = this.jsonSchemaTypeToTs(propSchema as JsonSchema);\n\t\t\t\t\t\tconst optionalMark = isRequired ? '' : '?';\n\t\t\t\t\t\tprops.push(`${propName}${optionalMark}: ${typeStr}`);\n\t\t\t\t\t}\n\t\t\t\t\treturn `{ ${props.join('; ')} }`;\n\t\t\t\t}\n\t\t\t\tif (schema.additionalProperties) {\n\t\t\t\t\tconst valueType = this.jsonSchemaTypeToTs(\n\t\t\t\t\t\tschema.additionalProperties as JsonSchema,\n\t\t\t\t\t);\n\t\t\t\t\treturn `Record<string, ${valueType}>`;\n\t\t\t\t}\n\t\t\t\treturn 'Record<string, unknown>';\n\t\t\tdefault:\n\t\t\t\treturn 'unknown';\n\t\t}\n\t}\n\n\tprivate async generatePathsInterface(\n\t\tendpointInfos: EndpointInfo[],\n\t): Promise<string> {\n\t\tconst pathGroups = new Map<string, EndpointInfo[]>();\n\n\t\t// Group endpoints by route\n\t\tfor (const info of endpointInfos) {\n\t\t\tconst existing = pathGroups.get(info.route) || [];\n\t\t\texisting.push(info);\n\t\t\tpathGroups.set(info.route, existing);\n\t\t}\n\n\t\tconst pathEntries: string[] = [];\n\n\t\tfor (const [route, infos] of pathGroups) {\n\t\t\tconst methodEntries: string[] = [];\n\n\t\t\tfor (const info of infos) {\n\t\t\t\tconst methodDef = await this.generateMethodDefinition(info);\n\t\t\t\tmethodEntries.push(` ${info.method.toLowerCase()}: ${methodDef};`);\n\t\t\t}\n\n\t\t\t// Add path parameters if present\n\t\t\tconst firstWithParams = infos.find((i) => i.input?.params);\n\t\t\tlet paramsEntry = '';\n\t\t\tif (firstWithParams?.input?.params) {\n\t\t\t\tconst paramsName = await this.getSchemaName(\n\t\t\t\t\tfirstWithParams.input.params,\n\t\t\t\t\t`${this.getSchemaBaseName(firstWithParams)}Params`,\n\t\t\t\t);\n\t\t\t\tparamsEntry = `\\n parameters: {\\n path: ${paramsName};\\n };`;\n\t\t\t}\n\n\t\t\tpathEntries.push(\n\t\t\t\t` '${route}': {${paramsEntry}\\n${methodEntries.join('\\n')}\\n };`,\n\t\t\t);\n\t\t}\n\n\t\treturn `export interface paths {\\n${pathEntries.join('\\n')}\\n}`;\n\t}\n\n\tprivate async generateMethodDefinition(info: EndpointInfo): Promise<string> {\n\t\tconst parts: string[] = [];\n\t\tconst baseName = this.getSchemaBaseName(info);\n\n\t\t// Request body\n\t\tif (info.input?.body) {\n\t\t\tconst bodyName = await this.getSchemaName(\n\t\t\t\tinfo.input.body,\n\t\t\t\t`${baseName}Input`,\n\t\t\t);\n\t\t\tparts.push(`requestBody: {\n content: {\n 'application/json': ${bodyName};\n };\n }`);\n\t\t}\n\n\t\t// Query parameters\n\t\tif (info.input?.query) {\n\t\t\tconst queryName = await this.getSchemaName(\n\t\t\t\tinfo.input.query,\n\t\t\t\t`${baseName}Query`,\n\t\t\t);\n\t\t\tparts.push(`parameters: {\n query: ${queryName};\n }`);\n\t\t}\n\n\t\t// Responses\n\t\tconst outputName = info.output\n\t\t\t? await this.getSchemaName(info.output, `${baseName}Output`)\n\t\t\t: 'unknown';\n\t\tparts.push(`responses: {\n 200: {\n content: {\n '${info.responseType}': ${outputName};\n };\n };\n }`);\n\n\t\treturn `{\\n ${parts.join(';\\n ')};\\n }`;\n\t}\n\n\tprivate buildModule(params: {\n\t\ttitle: string;\n\t\tversion: string;\n\t\tdescription?: string;\n\t\tsecuritySchemes: SecuritySchemeInfo[];\n\t\tendpointAuth: Record<string, string | null>;\n\t\tschemaInterfaces: string;\n\t\tpathsInterface: string;\n\t}): string {\n\t\tconst {\n\t\t\ttitle,\n\t\t\tversion,\n\t\t\tdescription,\n\t\t\tsecuritySchemes,\n\t\t\tendpointAuth,\n\t\t\tschemaInterfaces,\n\t\t\tpathsInterface,\n\t\t} = params;\n\n\t\tconst securitySchemesObj = securitySchemes.reduce(\n\t\t\t(acc, s) => {\n\t\t\t\tacc[s.name] = s.scheme;\n\t\t\t\treturn acc;\n\t\t\t},\n\t\t\t{} as Record<string, SecuritySchemeObject>,\n\t\t);\n\n\t\tconst schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(' | ');\n\n\t\t// Generate createApi only if there are security schemes\n\t\tconst hasSecuritySchemes = schemeNames.length > 0;\n\n\t\tconst createApiSection = hasSecuritySchemes\n\t\t\t? `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport {\n createAuthAwareFetcher,\n type AuthStrategy,\n} from '@geekmidas/client/auth-fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Auth strategies for each security scheme used in this API */\n authStrategies: Record<SecuritySchemeId, AuthStrategy>;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n /** Optional request interceptor */\n onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;\n /** The \\`fetch\\` requests go out on — a test browser's, for one */\n fetch?: typeof fetch;\n}\n\n/**\n * Create a type-safe API client with authentication and React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * authStrategies: {\n * jwt: { type: 'bearer', tokenProvider },\n * },\n * });\n *\n * // Imperative fetch\n * const user = await api('GET /users/{id}', { params: { id: '123' } });\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /users/{id}', { params: { id: '123' } });\n * const mutation = api.useMutation('POST /users');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const fetcher = createAuthAwareFetcher<paths, typeof endpointAuth, typeof securitySchemes>({\n baseURL: options.baseURL,\n endpointAuth,\n securitySchemes,\n authStrategies: options.authStrategies,\n onRequest: options.onRequest,\n ...(options.fetch ? { fetch: options.fetch } : {}),\n });\n\n const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });\n\n return Object.assign(fetcher, hooks);\n}\n`\n\t\t\t: `\n// ============================================================\n// API Client Factory\n// ============================================================\n\nimport { createTypedFetcher, type FetcherOptions } from '@geekmidas/client/fetcher';\nimport { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';\nimport type { QueryClient } from '@tanstack/react-query';\n\n/**\n * Options for creating the API client.\n */\nexport interface CreateApiOptions extends Omit<FetcherOptions, 'baseURL'> {\n /** Base URL for all API requests (required) */\n baseURL: string;\n /** Optional React Query client instance */\n queryClient?: QueryClient;\n}\n\n/**\n * Create a type-safe API client with React Query hooks.\n *\n * @example\n * \\`\\`\\`typescript\n * const api = createApi({\n * baseURL: 'https://api.example.com',\n * });\n *\n * // Imperative fetch\n * const data = await api('GET /health');\n *\n * // React Query hooks\n * const { data } = api.useQuery('GET /health');\n * \\`\\`\\`\n */\nexport function createApi(options: CreateApiOptions) {\n const { queryClient, ...fetcherOptions } = options;\n const request = createTypedFetcher<paths>(fetcherOptions);\n\n const hooks = createEndpointHooks<paths>(request, { queryClient });\n\n return Object.assign(request, hooks);\n}\n`;\n\n\t\treturn `// Auto-generated by @geekmidas/cli - DO NOT EDIT\n\n// ============================================================\n// Security Scheme Type\n// ============================================================\n\ninterface SecuritySchemeObject {\n type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';\n description?: string;\n name?: string;\n in?: 'query' | 'header' | 'cookie';\n scheme?: string;\n bearerFormat?: string;\n flows?: Record<string, unknown>;\n openIdConnectUrl?: string;\n [key: string]: unknown;\n}\n\n// ============================================================\n// API Info\n// ============================================================\n\nexport const apiInfo = {\n title: '${title}',\n version: '${version}',${description ? `\\n description: '${description.replace(/'/g, \"\\\\'\")}',` : ''}\n} as const;\n\n// ============================================================\n// Security Schemes\n// ============================================================\n\n/**\n * Available security schemes for this API.\n * Maps authorizer names to OpenAPI security scheme definitions.\n */\nexport const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/\"([a-zA-Z_$][a-zA-Z0-9_$]*)\":/g, '$1:')} as const satisfies Record<string, SecuritySchemeObject>;\n\nexport type SecuritySchemeId = ${schemeNames || 'never'};\n\n// ============================================================\n// Endpoint Authentication Map\n// ============================================================\n\n/**\n * Runtime map of endpoints to their required authentication scheme.\n * \\`null\\` indicates a public endpoint (no auth required).\n */\nexport const endpointAuth = ${JSON.stringify(endpointAuth, null, 2).replace(/\"([^\"]+)\":/g, \"'$1':\")} as const satisfies Record<string, SecuritySchemeId | null>;\n\nexport type EndpointString = keyof typeof endpointAuth;\n\nexport type AuthenticatedEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? never : K;\n}[EndpointString];\n\nexport type PublicEndpoint = {\n [K in EndpointString]: typeof endpointAuth[K] extends null ? K : never;\n}[EndpointString];\n\n// ============================================================\n// Schema Definitions\n// ============================================================\n\n${schemaInterfaces}\n\n// ============================================================\n// OpenAPI Paths\n// ============================================================\n\n${pathsInterface}\n${createApiSection}\n`;\n\t}\n}\n\n/**\n * The declaration for a schema that cannot be converted — a vendor with no\n * converter, or one that fails. The paths interface names it either way, so\n * leaving it undeclared made the generated client fail to compile.\n */\nfunction unknownType(name: string): string {\n\treturn `export type ${name} = unknown;`;\n}\n"],"mappings":"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"}
|