@geekmidas/cli 10.0.0-alpha.72 → 10.0.0-alpha.74

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.
Files changed (197) hide show
  1. package/dist/{OpenApiTsGenerator-BlP53kf2.cjs → EndpointGenerator-CP6sBvQV.cjs} +4 -510
  2. package/dist/EndpointGenerator-CP6sBvQV.cjs.map +1 -0
  3. package/dist/{OpenApiTsGenerator-Dv0gT2DL.mjs → EndpointGenerator-DftalLYg.mjs} +3 -509
  4. package/dist/EndpointGenerator-DftalLYg.mjs.map +1 -0
  5. package/dist/{LegacyStateStore-NSHEinQi.mjs → LegacyStateStore-DTo7z924.mjs} +2 -2
  6. package/dist/{LegacyStateStore-NSHEinQi.mjs.map → LegacyStateStore-DTo7z924.mjs.map} +1 -1
  7. package/dist/{LegacyStateStore-Dd5IwiyC.cjs → LegacyStateStore-D_78eaHM.cjs} +2 -2
  8. package/dist/{LegacyStateStore-Dd5IwiyC.cjs.map → LegacyStateStore-D_78eaHM.cjs.map} +1 -1
  9. package/dist/{LocalStateStore-DTylG4T4.cjs → LocalStateStore-BhrlQIXD.cjs} +2 -2
  10. package/dist/{LocalStateStore-DTylG4T4.cjs.map → LocalStateStore-BhrlQIXD.cjs.map} +1 -1
  11. package/dist/{LocalStateStore-DUoG2wA_.mjs → LocalStateStore-CNjgkRk4.mjs} +2 -2
  12. package/dist/{LocalStateStore-DUoG2wA_.mjs.map → LocalStateStore-CNjgkRk4.mjs.map} +1 -1
  13. package/dist/OpenApiTsGenerator-CKBCckKz.cjs +514 -0
  14. package/dist/OpenApiTsGenerator-CKBCckKz.cjs.map +1 -0
  15. package/dist/OpenApiTsGenerator-nu1r1NgB.mjs +509 -0
  16. package/dist/OpenApiTsGenerator-nu1r1NgB.mjs.map +1 -0
  17. package/dist/{S3StateStore-Dxob3PNA.mjs → S3StateStore-g2P7T_Mo.mjs} +2 -2
  18. package/dist/{S3StateStore-Dxob3PNA.mjs.map → S3StateStore-g2P7T_Mo.mjs.map} +1 -1
  19. package/dist/{S3StateStore-D7hrU-sy.cjs → S3StateStore-oCxRs6HM.cjs} +2 -2
  20. package/dist/{S3StateStore-D7hrU-sy.cjs.map → S3StateStore-oCxRs6HM.cjs.map} +1 -1
  21. package/dist/{SSMStateStore-Dvl4A8Up.mjs → SSMStateStore-CYenunmK.mjs} +2 -2
  22. package/dist/{SSMStateStore-Dvl4A8Up.mjs.map → SSMStateStore-CYenunmK.mjs.map} +1 -1
  23. package/dist/{SSMStateStore-DGIKJ4NN.cjs → SSMStateStore-DXp0m7XI.cjs} +2 -2
  24. package/dist/{SSMStateStore-DGIKJ4NN.cjs.map → SSMStateStore-DXp0m7XI.cjs.map} +1 -1
  25. package/dist/SubscriberGenerator-5looQ3gB.mjs +448 -0
  26. package/dist/SubscriberGenerator-5looQ3gB.mjs.map +1 -0
  27. package/dist/SubscriberGenerator-CajwOa5W.cjs +489 -0
  28. package/dist/SubscriberGenerator-CajwOa5W.cjs.map +1 -0
  29. package/dist/{add-XTLU19_E.mjs → add-BTH7WaH3.mjs} +4 -4
  30. package/dist/{add-XTLU19_E.mjs.map → add-BTH7WaH3.mjs.map} +1 -1
  31. package/dist/{add-DeC2Kyyv.cjs → add-Djrr12Xc.cjs} +4 -4
  32. package/dist/{add-DeC2Kyyv.cjs.map → add-Djrr12Xc.cjs.map} +1 -1
  33. package/dist/{bundler-CNTVLCCA.mjs → bundler-BUojOkof.mjs} +6 -6
  34. package/dist/bundler-BUojOkof.mjs.map +1 -0
  35. package/dist/{bundler-CEaR6Dpb.cjs → bundler-utHuESvL.cjs} +6 -6
  36. package/dist/bundler-utHuESvL.cjs.map +1 -0
  37. package/dist/{cli-MMgBrHx7.cjs → cli-Bx0sUzxH.cjs} +4 -4
  38. package/dist/{cli-MMgBrHx7.cjs.map → cli-Bx0sUzxH.cjs.map} +1 -1
  39. package/dist/{cli-D1arS0p1.mjs → cli-CyYceKTS.mjs} +4 -4
  40. package/dist/{cli-D1arS0p1.mjs.map → cli-CyYceKTS.mjs.map} +1 -1
  41. package/dist/{compose-T3hnnjKZ.mjs → compose-DZp8DJ0A.mjs} +419 -70
  42. package/dist/compose-DZp8DJ0A.mjs.map +1 -0
  43. package/dist/{compose-B-MME-4C.cjs → compose-iuw8wfHk.cjs} +420 -71
  44. package/dist/compose-iuw8wfHk.cjs.map +1 -0
  45. package/dist/{config-j9zBKaEG.d.cts → config-B38YWicj.d.cts} +3 -3
  46. package/dist/{config-BN6iXvyR.d.mts.map → config-B38YWicj.d.cts.map} +1 -1
  47. package/dist/{config-BN6iXvyR.d.mts → config-DA0kRTQe.d.mts} +3 -3
  48. package/dist/{config-j9zBKaEG.d.cts.map → config-DA0kRTQe.d.mts.map} +1 -1
  49. package/dist/config.cjs +4 -1
  50. package/dist/config.cjs.map +1 -1
  51. package/dist/config.d.cts +3 -3
  52. package/dist/config.d.mts +3 -3
  53. package/dist/config.mjs +4 -1
  54. package/dist/config.mjs.map +1 -1
  55. package/dist/{credentialSchemas-BmYxnEz_.mjs → credentialSchemas-BJqRJNK4.mjs} +2 -2
  56. package/dist/{credentialSchemas-BmYxnEz_.mjs.map → credentialSchemas-BJqRJNK4.mjs.map} +1 -1
  57. package/dist/{credentialSchemas-BcNL1N5R.cjs → credentialSchemas-DCR4Wd1W.cjs} +2 -2
  58. package/dist/{credentialSchemas-BcNL1N5R.cjs.map → credentialSchemas-DCR4Wd1W.cjs.map} +1 -1
  59. package/dist/deploy/public.cjs +7 -7
  60. package/dist/deploy/public.d.cts +4 -4
  61. package/dist/deploy/public.d.cts.map +1 -1
  62. package/dist/deploy/public.d.mts +4 -4
  63. package/dist/deploy/public.d.mts.map +1 -1
  64. package/dist/deploy/public.mjs +7 -7
  65. package/dist/deploy/sniffer-routes-worker.cjs +2 -2
  66. package/dist/deploy/sniffer-routes-worker.mjs +2 -2
  67. package/dist/{deploy-ClC53rc6.mjs → deploy-C17K7Imy.mjs} +12 -6
  68. package/dist/deploy-C17K7Imy.mjs.map +1 -0
  69. package/dist/{deploy-CZE0m6jd.cjs → deploy-eWorhvQp.cjs} +12 -6
  70. package/dist/deploy-eWorhvQp.cjs.map +1 -0
  71. package/dist/{discover-Buwf1z4P.mjs → discover-BPelzeGW.mjs} +21 -2
  72. package/dist/discover-BPelzeGW.mjs.map +1 -0
  73. package/dist/{discover-B_IkPukx.d.cts → discover-CU0paUyH.d.cts} +10 -1
  74. package/dist/discover-CU0paUyH.d.cts.map +1 -0
  75. package/dist/{discover-B4VjaFJk.cjs → discover-D1It5r_h.cjs} +21 -2
  76. package/dist/discover-D1It5r_h.cjs.map +1 -0
  77. package/dist/{discover-B6yPpvRV.d.mts → discover-DFiJxwfv.d.mts} +10 -1
  78. package/dist/discover-DFiJxwfv.d.mts.map +1 -0
  79. package/dist/{dokploy-D1UwQKm3.mjs → dokploy-DKa49Nqm.mjs} +2 -2
  80. package/dist/{dokploy-D1UwQKm3.mjs.map → dokploy-DKa49Nqm.mjs.map} +1 -1
  81. package/dist/{dokploy-lwmH05zr.cjs → dokploy-DKzcI-RL.cjs} +2 -2
  82. package/dist/{dokploy-lwmH05zr.cjs.map → dokploy-DKzcI-RL.cjs.map} +1 -1
  83. package/dist/drivers-BdvtCKc7.cjs +200 -0
  84. package/dist/drivers-BdvtCKc7.cjs.map +1 -0
  85. package/dist/drivers-Ch1rJitn.mjs +177 -0
  86. package/dist/drivers-Ch1rJitn.mjs.map +1 -0
  87. package/dist/{encryption-D05sNwED.cjs → encryption-DSkJdoyk.cjs} +2 -2
  88. package/dist/{encryption-D05sNwED.cjs.map → encryption-DSkJdoyk.cjs.map} +1 -1
  89. package/dist/{encryption-DcrxWl1s.mjs → encryption-sTMz3aWi.mjs} +2 -2
  90. package/dist/{encryption-DcrxWl1s.mjs.map → encryption-sTMz3aWi.mjs.map} +1 -1
  91. package/dist/{engine-DmQS3XHX.mjs → engine-B1b4I34Z.mjs} +117 -17
  92. package/dist/engine-B1b4I34Z.mjs.map +1 -0
  93. package/dist/{engine-Cry1vwMz.cjs → engine-Bh76sAHy.cjs} +117 -17
  94. package/dist/engine-Bh76sAHy.cjs.map +1 -0
  95. package/dist/{github-BchWoiVx.cjs → github-BvN3CfxM.cjs} +2 -2
  96. package/dist/{github-BchWoiVx.cjs.map → github-BvN3CfxM.cjs.map} +1 -1
  97. package/dist/{github-CqYOP8cI.mjs → github-C9ODoyZU.mjs} +2 -2
  98. package/dist/{github-CqYOP8cI.mjs.map → github-C9ODoyZU.mjs.map} +1 -1
  99. package/dist/{index-DvoxuTqR.d.mts → index-B-1lLGzy.d.mts} +2 -2
  100. package/dist/{index-Bk3NY6DN.d.cts.map → index-B-1lLGzy.d.mts.map} +1 -1
  101. package/dist/{index-Bk3NY6DN.d.cts → index-vMidfqhU.d.cts} +2 -2
  102. package/dist/{index-DvoxuTqR.d.mts.map → index-vMidfqhU.d.cts.map} +1 -1
  103. package/dist/index.cjs +130 -473
  104. package/dist/index.cjs.map +1 -1
  105. package/dist/index.mjs +122 -465
  106. package/dist/index.mjs.map +1 -1
  107. package/dist/{migrate-qKeGYq21.cjs → migrate-B0FCZNkp.cjs} +3 -3
  108. package/dist/{migrate-qKeGYq21.cjs.map → migrate-B0FCZNkp.cjs.map} +1 -1
  109. package/dist/{migrate-guck0NJK.mjs → migrate-CTtJhGV9.mjs} +3 -3
  110. package/dist/{migrate-guck0NJK.mjs.map → migrate-CTtJhGV9.mjs.map} +1 -1
  111. package/dist/openapi.cjs +3 -2
  112. package/dist/openapi.cjs.map +1 -1
  113. package/dist/openapi.d.cts +1 -1
  114. package/dist/openapi.d.mts +1 -1
  115. package/dist/openapi.mjs +2 -1
  116. package/dist/openapi.mjs.map +1 -1
  117. package/dist/ready-BB9xS4S9.cjs +402 -0
  118. package/dist/ready-BB9xS4S9.cjs.map +1 -0
  119. package/dist/ready-ZZoNskrr.mjs +373 -0
  120. package/dist/ready-ZZoNskrr.mjs.map +1 -0
  121. package/dist/reconcile/public.cjs +1 -1
  122. package/dist/reconcile/public.d.cts +2 -2
  123. package/dist/reconcile/public.d.mts +2 -2
  124. package/dist/reconcile/public.mjs +1 -1
  125. package/dist/{resolve-BsXEXAUz.mjs → resolve-DSAXj_47.mjs} +3 -3
  126. package/dist/{resolve-BsXEXAUz.mjs.map → resolve-DSAXj_47.mjs.map} +1 -1
  127. package/dist/{resolve-wEjEvbJ5.cjs → resolve-D_BU-wKA.cjs} +3 -3
  128. package/dist/{resolve-wEjEvbJ5.cjs.map → resolve-D_BU-wKA.cjs.map} +1 -1
  129. package/dist/{rollback-Bk91csFg.mjs → rollback-CWYTUhfW.mjs} +4 -4
  130. package/dist/{rollback-Bk91csFg.mjs.map → rollback-CWYTUhfW.mjs.map} +1 -1
  131. package/dist/{rollback-DmcU-efZ.cjs → rollback-DJy3t696.cjs} +4 -4
  132. package/dist/{rollback-DmcU-efZ.cjs.map → rollback-DJy3t696.cjs.map} +1 -1
  133. package/dist/{runtime-DHJhe4QI.d.mts → runtime-BzZD5HHi.d.cts} +2 -2
  134. package/dist/{runtime-CYAO4iZG.d.cts.map → runtime-BzZD5HHi.d.cts.map} +1 -1
  135. package/dist/{runtime-CYAO4iZG.d.cts → runtime-Cm6J6L7n.d.mts} +2 -2
  136. package/dist/{runtime-DHJhe4QI.d.mts.map → runtime-Cm6J6L7n.d.mts.map} +1 -1
  137. package/dist/sandbox/credentials-worker.cjs +2 -2
  138. package/dist/sandbox/credentials-worker.mjs +2 -2
  139. package/dist/sandbox/discover-worker.cjs +6 -3
  140. package/dist/sandbox/discover-worker.cjs.map +1 -1
  141. package/dist/sandbox/discover-worker.mjs +6 -3
  142. package/dist/sandbox/discover-worker.mjs.map +1 -1
  143. package/dist/sandbox/migrate-worker.cjs +1 -1
  144. package/dist/sandbox/migrate-worker.mjs +1 -1
  145. package/dist/{sniffer-vAXsU_4G.mjs → sniffer-BFmdZpZ2.mjs} +6 -6
  146. package/dist/{sniffer-vAXsU_4G.mjs.map → sniffer-BFmdZpZ2.mjs.map} +1 -1
  147. package/dist/{sniffer-DpHpFZBD.cjs → sniffer-C-T7dSMN.cjs} +6 -6
  148. package/dist/{sniffer-DpHpFZBD.cjs.map → sniffer-C-T7dSMN.cjs.map} +1 -1
  149. package/dist/{state-CCuTJNRH.cjs → state-DCwRWyh-.cjs} +954 -29
  150. package/dist/state-DCwRWyh-.cjs.map +1 -0
  151. package/dist/{state-BJFherj1.mjs → state-DpkxSwzI.mjs} +889 -24
  152. package/dist/state-DpkxSwzI.mjs.map +1 -0
  153. package/dist/target/public.cjs +1 -1
  154. package/dist/target/public.d.cts +2 -2
  155. package/dist/target/public.d.mts +2 -2
  156. package/dist/target/public.mjs +1 -1
  157. package/dist/{terminal-CFO3xWoF.cjs → terminal-BL5E0xbR.cjs} +2 -2
  158. package/dist/{terminal-CFO3xWoF.cjs.map → terminal-BL5E0xbR.cjs.map} +1 -1
  159. package/dist/{terminal-C6TBo_SA.mjs → terminal-BdvrmkaC.mjs} +2 -2
  160. package/dist/{terminal-C6TBo_SA.mjs.map → terminal-BdvrmkaC.mjs.map} +1 -1
  161. package/dist/{types-DkG5WW8l.d.mts → types-Dp9lgx_S.d.mts} +22 -2
  162. package/dist/types-Dp9lgx_S.d.mts.map +1 -0
  163. package/dist/{types-BD1jgA85.d.cts → types-TzCChNrA.d.cts} +22 -2
  164. package/dist/types-TzCChNrA.d.cts.map +1 -0
  165. package/dist/vitest.cjs +1 -1
  166. package/dist/vitest.mjs +1 -1
  167. package/dist/workspace/index.d.cts +2 -2
  168. package/dist/workspace/index.d.mts +2 -2
  169. package/dist/workspace-C7NqCsQF.mjs.map +1 -1
  170. package/dist/workspace-vdrcRI-m.cjs.map +1 -1
  171. package/package.json +15 -15
  172. package/dist/OpenApiTsGenerator-BlP53kf2.cjs.map +0 -1
  173. package/dist/OpenApiTsGenerator-Dv0gT2DL.mjs.map +0 -1
  174. package/dist/bundler-CEaR6Dpb.cjs.map +0 -1
  175. package/dist/bundler-CNTVLCCA.mjs.map +0 -1
  176. package/dist/compose-B-MME-4C.cjs.map +0 -1
  177. package/dist/compose-T3hnnjKZ.mjs.map +0 -1
  178. package/dist/deploy-CZE0m6jd.cjs.map +0 -1
  179. package/dist/deploy-ClC53rc6.mjs.map +0 -1
  180. package/dist/discover-B4VjaFJk.cjs.map +0 -1
  181. package/dist/discover-B6yPpvRV.d.mts.map +0 -1
  182. package/dist/discover-B_IkPukx.d.cts.map +0 -1
  183. package/dist/discover-Buwf1z4P.mjs.map +0 -1
  184. package/dist/engine-Cry1vwMz.cjs.map +0 -1
  185. package/dist/engine-DmQS3XHX.mjs.map +0 -1
  186. package/dist/fakes-C9RiT6XG.mjs +0 -125
  187. package/dist/fakes-C9RiT6XG.mjs.map +0 -1
  188. package/dist/fakes-zW-jNAbQ.cjs +0 -148
  189. package/dist/fakes-zW-jNAbQ.cjs.map +0 -1
  190. package/dist/ready-B-7LayMF.cjs +0 -872
  191. package/dist/ready-B-7LayMF.cjs.map +0 -1
  192. package/dist/ready-ULc5BTOb.mjs +0 -819
  193. package/dist/ready-ULc5BTOb.mjs.map +0 -1
  194. package/dist/state-BJFherj1.mjs.map +0 -1
  195. package/dist/state-CCuTJNRH.cjs.map +0 -1
  196. package/dist/types-BD1jgA85.d.cts.map +0 -1
  197. package/dist/types-DkG5WW8l.d.mts.map +0 -1
@@ -0,0 +1,509 @@
1
+ import { StandardSchemaJsonSchema, getRegisteredZodJsonSchemas, getSchemaMetadata } from "@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 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 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 StandardSchemaJsonSchema)) return unknownType(name);
192
+ const toJsonSchema = 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
+ export { OpenApiTsGenerator as t };
508
+
509
+ //# sourceMappingURL=OpenApiTsGenerator-nu1r1NgB.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenApiTsGenerator-nu1r1NgB.mjs","names":[],"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":";;;;;;;;;;AAiFA,IAAa,qBAAb,MAAgC;CAC/B,MAAM,SACL,WACA,UAA4B,CAAC,GACX;EAClB,MAAM,EAAE,QAAQ,OAAO,UAAU,SAAS,gBAAgB;EAG1D,MAAM,gBAAgB,MAAM,KAAK,qBAAqB,SAAS;EAG/D,MAAM,kBAAkB,KAAK,uBAAuB,aAAa;EAGjE,MAAM,eAAe,KAAK,qBAAqB,aAAa;EAG5D,MAAM,mBAAmB,MAAM,KAAK,yBAAyB,aAAa;EAG1E,MAAM,iBAAiB,MAAM,KAAK,uBAAuB,aAAa;EAGtE,OAAO,KAAK,YAAY;GACvB;GACA;GACA;GACA;GACA;GACA;GACA;EACD,CAAC;CACF;CAEA,MAAc,qBACb,WAC0B;EAC1B,OAAO,UAAU,KAAK,OAAO;GAC5B,MAAM,QAAQ,GAAG,MAAM,QAAQ,WAAW,MAAM;GAChD,MAAM,SAAS,GAAG,OAAO,YAAY;GAIrC,MAAM,iBAAiB,GAAG,YAAY;GAItC,OAAO;IACN,UAAU,GAAG,OAAO,GAAG;IACvB;IACA;IACA,gBAAgB,GAAG,YAAY,QAAQ;IACvC,gBAAgB,GAAG,YAAY,QAAQ;IACvC,gBAAgB,kBAAkB;IAClC,OAAO,GAAG;IACV,QAAQ,GAAG;IACX,aAAa,GAAG;IAChB,MAAM,GAAG;IACT,aAAa,GAAG;IAChB,cAAc,GAAG,gBAAgB;GAClC;EACD,CAAC;CACF;CAEA,uBACC,eACuB;EACvB,MAAM,0BAAU,IAAI,IAAgC;EAEpD,KAAK,MAAM,QAAQ,eAClB,IAAI,KAAK,kBAAkB,CAAC,QAAQ,IAAI,KAAK,cAAc,GAAG;GAG7D,MAAM,SACL,KAAK,mBACJ,KAAK,iBACH,KAAK,8BACL,KAAK,gBACL,KAAK,cACN,IACC;GAEJ,IAAI,QACH,QAAQ,IAAI,KAAK,gBAAgB;IAChC,MAAM,KAAK;IACX,MAAM,OAAO;IACb;GACD,CAAC;EAEH;EAGD,OAAO,MAAM,KAAK,QAAQ,OAAO,CAAC;CACnC;CAEA,8BACC,MACA,OACuB;EACvB,QAAQ,KAAK,YAAY,GAAzB;GACC,KAAK;GACL,KAAK,UACJ,OAAO;IACN,MAAM;IACN,QAAQ;IACR,cAAc;GACf;GACD,KAAK;GACL,KAAK;GACL,KAAK,SACJ,OAAO;IACN,MAAM;IACN,IAAI;IACJ,MAAM;IACN,gCAAgC;GACjC;GACD,KAAK;GACL,KAAK,WACJ,OAAO;IACN,MAAM;IACN,IAAI;IACJ,MAAM;GACP;GACD,KAAK,UACJ,OAAO;IACN,MAAM;IACN,OAAO,CAAC;GACT;GACD,KAAK;GACL,KAAK,iBACJ,OAAO;IACN,MAAM;IACN,kBAAkB;GACnB;GACD,SACC,OAAO;IACN,MAAM;IACN,QAAQ;GACT;EACF;CACD;CAEA,qBACC,eACgC;EAChC,MAAM,UAAyC,CAAC;EAEhD,KAAK,MAAM,QAAQ,eAClB,QAAQ,KAAK,YAAY,KAAK;EAG/B,OAAO;CACR;CAEA,MAAc,yBACb,eACkB;EAClB,MAAM,aAAuB,CAAC;EAC9B,MAAM,iCAAiB,IAAI,IAAY;EAEvC,MAAM,gCAAgB,IAAI,IAAwB;EAElD,KAAK,MAAM,QAAQ,eAAe;GACjC,MAAM,WAAW,KAAK,kBAAkB,IAAI;GAG5C,IAAI,KAAK,OAAO,MAAM;IACrB,MAAM,OAAO,MAAM,KAAK,cACvB,KAAK,MAAM,MACX,GAAG,SAAS,MACb;IACA,IAAI,CAAC,eAAe,IAAI,IAAI,GAAG;KAC9B,MAAM,SAAS,MAAM,KAAK,0BACzB,KAAK,MAAM,MACX,MACA,aACD;KACA,IAAI,QAAQ;MACX,WAAW,KAAK,MAAM;MACtB,eAAe,IAAI,IAAI;KACxB;IACD;GACD;GAGA,IAAI,KAAK,OAAO,QAAQ;IACvB,MAAM,OAAO,MAAM,KAAK,cACvB,KAAK,MAAM,QACX,GAAG,SAAS,OACb;IACA,IAAI,CAAC,eAAe,IAAI,IAAI,GAAG;KAC9B,MAAM,SAAS,MAAM,KAAK,0BACzB,KAAK,MAAM,QACX,MACA,aACD;KACA,IAAI,QAAQ;MACX,WAAW,KAAK,MAAM;MACtB,eAAe,IAAI,IAAI;KACxB;IACD;GACD;GAGA,IAAI,KAAK,OAAO,OAAO;IACtB,MAAM,OAAO,MAAM,KAAK,cACvB,KAAK,MAAM,OACX,GAAG,SAAS,MACb;IACA,IAAI,CAAC,eAAe,IAAI,IAAI,GAAG;KAC9B,MAAM,SAAS,MAAM,KAAK,0BACzB,KAAK,MAAM,OACX,MACA,aACD;KACA,IAAI,QAAQ;MACX,WAAW,KAAK,MAAM;MACtB,eAAe,IAAI,IAAI;KACxB;IACD;GACD;GAGA,IAAI,KAAK,QAAQ;IAChB,MAAM,OAAO,MAAM,KAAK,cAAc,KAAK,QAAQ,GAAG,SAAS,OAAO;IACtE,IAAI,CAAC,eAAe,IAAI,IAAI,GAAG;KAC9B,MAAM,SAAS,MAAM,KAAK,0BACzB,KAAK,QACL,MACA,aACD;KACA,IAAI,QAAQ;MACX,WAAW,KAAK,MAAM;MACtB,eAAe,IAAI,IAAI;KACxB;IACD;GACD;EACD;EAOA,MAAM,kBAAkB,MAAM,4BAA4B;EAC1D,KAAK,MAAM,CAAC,SAAS,cAAc,OAAO,QAAQ,eAAe,GAAG;GACnE,MAAM,UAAU,KAAK,WAAW,OAAO;GACvC,IAAI,cAAc,IAAI,OAAO,KAAK,eAAe,IAAI,OAAO,GAC3D;GAED,MAAM,EACL,IAAI,KACJ,OAAO,OACP,GAAG,SACA;GAGJ,cAAc,IAAI,SAAS,IAAkB;EAC9C;EAGA,KAAK,MAAM,CAAC,SAAS,cAAc,eAClC,IAAI,CAAC,eAAe,IAAI,OAAO,GAAG;GACjC,MAAM,eAAe,KAAK,sBAAsB,WAAW,OAAO;GAClE,WAAW,KAAK,YAAY;GAC5B,eAAe,IAAI,OAAO;EAC3B;EAGD,OAAO,WAAW,KAAK,MAAM;CAC9B;;;;;CAMA,MAAc,cACb,QACA,aACkB;EAClB,IAAI;GACH,MAAM,WAAW,MAAM,kBAAkB,MAAM;GAC/C,IAAI,UAAU,IACb,OAAO,KAAK,WAAW,SAAS,EAAE;EAEpC,QAAQ,CAER;EACA,OAAO;CACR;CAEA,kBAA0B,MAA4B;EACrD,IAAI,KAAK,aACR,OAAO,KAAK,WAAW,KAAK,WAAW;EAIxC,MAAM,aAAa,KAAK,MACtB,QAAQ,SAAS,EAAE,CAAC,CACpB,MAAM,GAAG,CAAC,CACV,OAAO,OAAO,CAAC,CACf,KAAK,SAAS,KAAK,WAAW,IAAI,CAAC;EAErC,OAAO,GAAG,KAAK,WAAW,KAAK,OAAO,YAAY,CAAC,IAAI,WAAW,KAAK,EAAE;CAC1E;CAEA,WAAmB,KAAqB;EACvC,OAAO,IACL,QAAQ,aAAa,GAAG,MAAM,EAAE,YAAY,CAAC,CAAC,CAC9C,QAAQ,OAAO,MAAM,EAAE,YAAY,CAAC;CACvC;;;;;CAMA,MAAc,0BACb,QACA,MACA,eACyB;EACzB,IAAI;GAGH,MAAM,SAAS,OAAO,YAAY,EAAE;GACpC,IAAI,CAAC,UAAU,EAAE,UAAU,2BAC1B,OAAO,YAAY,IAAI;GAGxB,MAAM,eACL,yBACC;GAEF,MAAM,aAAa,MAAM,aAAa,MAAM;GAC5C,IAAI,CAAC,YAAY,OAAO,YAAY,IAAI;GAGxC,IAAI,WAAW,SAAS,OAAO,WAAW,UAAU,UAC9C;SAAA,MAAM,CAAC,SAAS,cAAc,OAAO,QAAQ,WAAW,KAAK,GACjE,IAAI,CAAC,cAAc,IAAI,OAAO,GAAG;KAEhC,MAAM,EAAE,IAAI,GAAG,oBAAoB;KAGnC,cAAc,IAAI,SAAS,eAA6B;IACzD;;GAKF,MAAM,EAAE,OAAO,GAAG,sBAAsB;GASxC,MAAM,MAAO,kBAAwC;GACrD,IACC,OACA,OAAO,KAAK,iBAAiB,CAAC,CAAC,OAC7B,MAAM,MAAM,UAAU,MAAM,SAC9B,GACC;IACD,MAAM,SAAS,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI;IAGlC,OAAO,WAAW,OAAO,OAAO,eAAe,KAAK,KAAK,OAAO;GACjE;GAEA,OAAO,KAAK,sBAAsB,mBAAmB,IAAI;EAC1D,QAAQ;GACP,OAAO,YAAY,IAAI;EACxB;CACD;CAEA,sBAA8B,QAAoB,MAAsB;EACvE,IAAI,OAAO,SAAS,YAAY,CAAC,OAAO,YAGvC,OAAO,eAAe,KAAK,KADX,KAAK,mBAAmB,MACF,EAAE;EAGzC,MAAM,QAAkB,CAAC;EACzB,MAAM,WAAW,IAAI,IAAI,OAAO,YAAY,CAAC,CAAC;EAE9C,KAAK,MAAM,CAAC,UAAU,eAAe,OAAO,QAAQ,OAAO,UAAU,GAAG;GACvE,MAAM,aAAa,SAAS,IAAI,QAAQ;GACxC,MAAM,UAAU,KAAK,mBAAmB,UAAwB;GAChE,MAAM,eAAe,aAAa,KAAK;GACvC,MAAM,KAAK,KAAK,WAAW,aAAa,IAAI,QAAQ,EAAE;EACvD;EAEA,OAAO,oBAAoB,KAAK,MAAM,MAAM,KAAK,IAAI,EAAE;CACxD;CAEA,mBAA2B,QAA4B;EACtD,IAAI,CAAC,QAAQ,OAAO;EAEpB,IAAI,OAAO,MAGV,OADgB,OAAO,KAAK,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK;EAMjD,IAAI,OAAO,UAAU,KAAA,GACpB,OAAO,OAAO,OAAO,UAAU,WAC5B,IAAI,OAAO,MAAM,KACjB,OAAO,OAAO,KAAK;EAGvB,IAAI,OAAO,OACV,OAAO,OAAO,MACZ,KAAK,MAAkB,KAAK,mBAAmB,CAAC,CAAC,CAAC,CAClD,KAAK,KAAK;EAGb,IAAI,OAAO,OACV,OAAO,OAAO,MACZ,KAAK,MAAkB,KAAK,mBAAmB,CAAC,CAAC,CAAC,CAClD,KAAK,KAAK;EAGb,IAAI,OAAO,OACV,OAAO,OAAO,MACZ,KAAK,MAAkB,KAAK,mBAAmB,CAAC,CAAC,CAAC,CAClD,KAAK,KAAK;EAGb,IAAI,MAAM,QAAQ,OAAO,IAAI,GAC5B,OAAO,OAAO,KACZ,KAAK,SAAS,KAAK,mBAAmB;GAAE,GAAG;GAAQ;EAAK,CAAC,CAAC,CAAC,CAC3D,KAAK,KAAK;EAGb,QAAQ,OAAO,MAAf;GACC,KAAK;IACJ,IAAI,OAAO,MACV,OAAO,OAAO,KAAK,KAAK,MAAc,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,KAAK;IAE3D,OAAO;GACR,KAAK;GACL,KAAK,WACJ,OAAO;GACR,KAAK,WACJ,OAAO;GACR,KAAK,QACJ,OAAO;GACR,KAAK;IACJ,IAAI,OAAO,OACV,OAAO,SAAS,KAAK,mBAAmB,OAAO,KAAmB,EAAE;IAErE,OAAO;GACR,KAAK;IACJ,IAAI,OAAO,YAAY;KACtB,MAAM,QAAkB,CAAC;KACzB,MAAM,WAAW,IAAI,IAAI,OAAO,YAAY,CAAC,CAAC;KAC9C,KAAK,MAAM,CAAC,UAAU,eAAe,OAAO,QAC3C,OAAO,UACR,GAAG;MACF,MAAM,aAAa,SAAS,IAAI,QAAQ;MACxC,MAAM,UAAU,KAAK,mBAAmB,UAAwB;MAChE,MAAM,eAAe,aAAa,KAAK;MACvC,MAAM,KAAK,GAAG,WAAW,aAAa,IAAI,SAAS;KACpD;KACA,OAAO,KAAK,MAAM,KAAK,IAAI,EAAE;IAC9B;IACA,IAAI,OAAO,sBAIV,OAAO,kBAHW,KAAK,mBACtB,OAAO,oBAEyB,EAAE;IAEpC,OAAO;GACR,SACC,OAAO;EACT;CACD;CAEA,MAAc,uBACb,eACkB;EAClB,MAAM,6BAAa,IAAI,IAA4B;EAGnD,KAAK,MAAM,QAAQ,eAAe;GACjC,MAAM,WAAW,WAAW,IAAI,KAAK,KAAK,KAAK,CAAC;GAChD,SAAS,KAAK,IAAI;GAClB,WAAW,IAAI,KAAK,OAAO,QAAQ;EACpC;EAEA,MAAM,cAAwB,CAAC;EAE/B,KAAK,MAAM,CAAC,OAAO,UAAU,YAAY;GACxC,MAAM,gBAA0B,CAAC;GAEjC,KAAK,MAAM,QAAQ,OAAO;IACzB,MAAM,YAAY,MAAM,KAAK,yBAAyB,IAAI;IAC1D,cAAc,KAAK,OAAO,KAAK,OAAO,YAAY,EAAE,IAAI,UAAU,EAAE;GACrE;GAGA,MAAM,kBAAkB,MAAM,MAAM,MAAM,EAAE,OAAO,MAAM;GACzD,IAAI,cAAc;GAClB,IAAI,iBAAiB,OAAO,QAK3B,cAAc,oCAAoC,MAJzB,KAAK,cAC7B,gBAAgB,MAAM,QACtB,GAAG,KAAK,kBAAkB,eAAe,EAAE,OAC5C,EAC6D;GAG9D,YAAY,KACX,MAAM,MAAM,MAAM,YAAY,IAAI,cAAc,KAAK,IAAI,EAAE,OAC5D;EACD;EAEA,OAAO,6BAA6B,YAAY,KAAK,IAAI,EAAE;CAC5D;CAEA,MAAc,yBAAyB,MAAqC;EAC3E,MAAM,QAAkB,CAAC;EACzB,MAAM,WAAW,KAAK,kBAAkB,IAAI;EAG5C,IAAI,KAAK,OAAO,MAAM;GACrB,MAAM,WAAW,MAAM,KAAK,cAC3B,KAAK,MAAM,MACX,GAAG,SAAS,MACb;GACA,MAAM,KAAK;;gCAEkB,SAAS;;QAEjC;EACN;EAGA,IAAI,KAAK,OAAO,OAAO;GACtB,MAAM,YAAY,MAAM,KAAK,cAC5B,KAAK,MAAM,OACX,GAAG,SAAS,MACb;GACA,MAAM,KAAK;iBACG,UAAU;QACnB;EACN;EAGA,MAAM,aAAa,KAAK,SACrB,MAAM,KAAK,cAAc,KAAK,QAAQ,GAAG,SAAS,OAAO,IACzD;EACH,MAAM,KAAK;;;eAGE,KAAK,aAAa,KAAK,WAAW;;;QAGzC;EAEN,OAAO,YAAY,MAAM,KAAK,WAAW,EAAE;CAC5C;CAEA,YAAoB,QAQT;EACV,MAAM,EACL,OACA,SACA,aACA,iBACA,cACA,kBACA,mBACG;EAEJ,MAAM,qBAAqB,gBAAgB,QACzC,KAAK,MAAM;GACX,IAAI,EAAE,QAAQ,EAAE;GAChB,OAAO;EACR,GACA,CAAC,CACF;EAEA,MAAM,cAAc,gBAAgB,KAAK,MAAM,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,KAAK;EAKxE,MAAM,mBAFqB,YAAY,SAAS,IAG7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA+DA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6CH,OAAO;;;;;;;;;;;;;;;;;;;;;;;YAuBG,MAAM;cACJ,QAAQ,IAAI,cAAc,qBAAqB,YAAY,QAAQ,MAAM,KAAK,EAAE,MAAM,GAAG;;;;;;;;;;;iCAWtE,KAAK,UAAU,oBAAoB,MAAM,CAAC,CAAC,CAAC,QAAQ,kCAAkC,KAAK,EAAE;;iCAE7F,eAAe,QAAQ;;;;;;;;;;8BAU1B,KAAK,UAAU,cAAc,MAAM,CAAC,CAAC,CAAC,QAAQ,eAAe,OAAO,EAAE;;;;;;;;;;;;;;;;EAgBlG,iBAAiB;;;;;;EAMjB,eAAe;EACf,iBAAiB;;CAElB;AACD;;;;;;AAOA,SAAS,YAAY,MAAsB;CAC1C,OAAO,eAAe,KAAK;AAC5B"}
@@ -1,5 +1,5 @@
1
1
  import { n as __require } from "./rolldown-runtime-BhDjJH2R.mjs";
2
- import { d as StateLocked, l as DocumentStateStore, m as StateVersionConflict } from "./sniffer-vAXsU_4G.mjs";
2
+ import { d as StateLocked, l as DocumentStateStore, m as StateVersionConflict } from "./sniffer-BFmdZpZ2.mjs";
3
3
  import { DeleteObjectCommand, GetObjectCommand, PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
4
4
  //#region src/deploy/S3StateStore.ts
5
5
  /**
@@ -158,4 +158,4 @@ var S3StateStore = class S3StateStore extends DocumentStateStore {
158
158
  //#endregion
159
159
  export { S3StateStore };
160
160
 
161
- //# sourceMappingURL=S3StateStore-Dxob3PNA.mjs.map
161
+ //# sourceMappingURL=S3StateStore-g2P7T_Mo.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"S3StateStore-Dxob3PNA.mjs","names":[],"sources":["../src/deploy/S3StateStore.ts"],"sourcesContent":["/**\n * Amazon S3 state store.\n *\n * - `<prefix>/<workspace>/<stage>/state.json`: the state.\n * - `<prefix>/<workspace>/<stage>/lock.json`: the lock.\n * - `<prefix>/<workspace>/<stage>/state.v1.json`: the v1 state, kept on\n * migration.\n *\n * Every write is conditional on the server: `If-None-Match: *` to create,\n * `If-Match: <etag>` to replace. S3 answers a lost race with 412 (or 409 when\n * two conditional writes are in flight at once), so there is no window\n * between a check and a write for another run to slip into.\n */\n\nimport {\n\tDeleteObjectCommand,\n\tGetObjectCommand,\n\tPutObjectCommand,\n\tS3Client,\n\ttype S3ClientConfig,\n} from '@aws-sdk/client-s3';\nimport type { AwsRegion } from './StateProvider';\nimport {\n\tDocumentStateStore,\n\ttype LockHolder,\n\ttype RawState,\n\tStateLocked,\n\ttype StateVersion,\n\tStateVersionConflict,\n} from './StateStore';\n\nexport interface S3StateStoreOptions {\n\tworkspaceName: string;\n\tbucket: string;\n\t/** Key prefix inside the bucket; `gkm` by default. */\n\tprefix?: string;\n\tregion?: AwsRegion;\n\t/** Uses the default credential chain when omitted. */\n\tprofile?: string;\n\tcredentials?: S3ClientConfig['credentials'];\n\t/** For the local AWS emulator. */\n\tendpoint?: string;\n}\n\ninterface S3Failure {\n\tname?: string;\n\t$metadata?: { httpStatusCode?: number };\n}\n\n/** A conditional write that lost: the object is not what the write assumed. */\nfunction lostRace(error: unknown): boolean {\n\tconst { name, $metadata } = (error ?? {}) as S3Failure;\n\treturn (\n\t\tname === 'PreconditionFailed' ||\n\t\tname === 'ConditionalRequestConflict' ||\n\t\t$metadata?.httpStatusCode === 412 ||\n\t\t$metadata?.httpStatusCode === 409\n\t);\n}\n\nfunction notFound(error: unknown): boolean {\n\tconst { name, $metadata } = (error ?? {}) as S3Failure;\n\treturn (\n\t\tname === 'NoSuchKey' ||\n\t\tname === 'NotFound' ||\n\t\t$metadata?.httpStatusCode === 404\n\t);\n}\n\nexport class S3StateStore extends DocumentStateStore {\n\tprivate readonly prefix: string;\n\n\tconstructor(\n\t\treadonly workspaceName: string,\n\t\treadonly bucket: string,\n\t\tprivate readonly client: S3Client,\n\t\tprefix = 'gkm',\n\t) {\n\t\tsuper();\n\t\tthis.prefix = prefix.replace(/\\/+$/, '');\n\t}\n\n\tstatic create(options: S3StateStoreOptions): S3StateStore {\n\t\tconst config: S3ClientConfig = {\n\t\t\tregion: options.region,\n\t\t\tendpoint: options.endpoint,\n\t\t\t// The emulator serves buckets by path, not by subdomain.\n\t\t\tforcePathStyle: options.endpoint ? true : undefined,\n\t\t};\n\t\tif (options.profile) {\n\t\t\t// Required lazily: only a profile needs the credential providers.\n\t\t\tconst { fromIni } = require('@aws-sdk/credential-providers');\n\t\t\tconfig.credentials = fromIni({ profile: options.profile });\n\t\t} else if (options.credentials) {\n\t\t\tconfig.credentials = options.credentials;\n\t\t}\n\t\treturn new S3StateStore(\n\t\t\toptions.workspaceName,\n\t\t\toptions.bucket,\n\t\t\tnew S3Client(config),\n\t\t\toptions.prefix,\n\t\t);\n\t}\n\n\tprivate key(stage: string, leaf: string): string {\n\t\tconst path = `${this.workspaceName}/${stage}/${leaf}`;\n\t\treturn this.prefix ? `${this.prefix}/${path}` : path;\n\t}\n\n\tprotected location(stage: string): string {\n\t\treturn `s3://${this.bucket}/${this.key(stage, 'state.json')}`;\n\t}\n\n\tprotected async readRaw(stage: string): Promise<RawState | null> {\n\t\tconst object = await this.get(this.key(stage, 'state.json'));\n\t\tif (!object) return null;\n\t\treturn { body: object.body, version: object.etag };\n\t}\n\n\tprotected async writeRaw(\n\t\tstage: string,\n\t\tbody: string,\n\t\texpectedVersion: StateVersion | null,\n\t): Promise<StateVersion> {\n\t\tconst Key = this.key(stage, 'state.json');\n\t\ttry {\n\t\t\tconst { ETag } = await this.client.send(\n\t\t\t\tnew PutObjectCommand({\n\t\t\t\t\tBucket: this.bucket,\n\t\t\t\t\tKey,\n\t\t\t\t\tBody: body,\n\t\t\t\t\tContentType: 'application/json',\n\t\t\t\t\t...(expectedVersion === null\n\t\t\t\t\t\t? { IfNoneMatch: '*' }\n\t\t\t\t\t\t: { IfMatch: expectedVersion }),\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (ETag) return ETag;\n\t\t\t// Some S3-compatible servers omit the ETag on a conditional put.\n\t\t\treturn (await this.get(Key))?.etag ?? '';\n\t\t} catch (error) {\n\t\t\tif (lostRace(error)) {\n\t\t\t\tconst current = await this.get(Key);\n\t\t\t\tthrow new StateVersionConflict(\n\t\t\t\t\tstage,\n\t\t\t\t\texpectedVersion,\n\t\t\t\t\tcurrent?.etag ?? null,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprotected async writeV1Backup(stage: string, body: string): Promise<void> {\n\t\ttry {\n\t\t\tawait this.client.send(\n\t\t\t\tnew PutObjectCommand({\n\t\t\t\t\tBucket: this.bucket,\n\t\t\t\t\tKey: this.key(stage, 'state.v1.json'),\n\t\t\t\t\tBody: body,\n\t\t\t\t\tContentType: 'application/json',\n\t\t\t\t\tIfNoneMatch: '*',\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// The first migration's backup is the one worth keeping.\n\t\t\tif (!lostRace(error)) throw error;\n\t\t}\n\t}\n\n\tprotected async createLock(stage: string, holder: LockHolder): Promise<void> {\n\t\tconst Key = this.key(stage, 'lock.json');\n\t\ttry {\n\t\t\tawait this.client.send(\n\t\t\t\tnew PutObjectCommand({\n\t\t\t\t\tBucket: this.bucket,\n\t\t\t\t\tKey,\n\t\t\t\t\tBody: JSON.stringify(holder),\n\t\t\t\t\tContentType: 'application/json',\n\t\t\t\t\tIfNoneMatch: '*',\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (lostRace(error)) {\n\t\t\t\tthrow new StateLocked(\n\t\t\t\t\tstage,\n\t\t\t\t\tawait this.readLock(stage),\n\t\t\t\t\t`s3://${this.bucket}/${Key}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprotected async readLock(stage: string): Promise<LockHolder | null> {\n\t\tconst object = await this.get(this.key(stage, 'lock.json'));\n\t\tif (!object) return null;\n\t\ttry {\n\t\t\treturn JSON.parse(object.body) as LockHolder;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprotected async removeLock(\n\t\tstage: string,\n\t\tholder: LockHolder | null,\n\t): Promise<void> {\n\t\tconst Key = this.key(stage, 'lock.json');\n\t\tconst object = await this.get(Key);\n\t\tif (!object) return;\n\t\tif (holder) {\n\t\t\ttry {\n\t\t\t\tif ((JSON.parse(object.body) as LockHolder).id !== holder.id) return;\n\t\t\t} catch {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\t// Conditional on the lock read above, so a lock taken by another\n\t\t\t// run in the meantime survives.\n\t\t\tawait this.client.send(\n\t\t\t\tnew DeleteObjectCommand({\n\t\t\t\t\tBucket: this.bucket,\n\t\t\t\t\tKey,\n\t\t\t\t\tIfMatch: object.etag,\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (!lostRace(error) && !notFound(error)) throw error;\n\t\t}\n\t}\n\n\tprivate async get(\n\t\tKey: string,\n\t): Promise<{ body: string; etag: string } | null> {\n\t\ttry {\n\t\t\tconst response = await this.client.send(\n\t\t\t\tnew GetObjectCommand({ Bucket: this.bucket, Key }),\n\t\t\t);\n\t\t\tconst body = (await response.Body?.transformToString('utf-8')) ?? '';\n\t\t\treturn { body, etag: response.ETag ?? '' };\n\t\t} catch (error) {\n\t\t\tif (notFound(error)) return null;\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"S3StateStore-g2P7T_Mo.mjs","names":[],"sources":["../src/deploy/S3StateStore.ts"],"sourcesContent":["/**\n * Amazon S3 state store.\n *\n * - `<prefix>/<workspace>/<stage>/state.json`: the state.\n * - `<prefix>/<workspace>/<stage>/lock.json`: the lock.\n * - `<prefix>/<workspace>/<stage>/state.v1.json`: the v1 state, kept on\n * migration.\n *\n * Every write is conditional on the server: `If-None-Match: *` to create,\n * `If-Match: <etag>` to replace. S3 answers a lost race with 412 (or 409 when\n * two conditional writes are in flight at once), so there is no window\n * between a check and a write for another run to slip into.\n */\n\nimport {\n\tDeleteObjectCommand,\n\tGetObjectCommand,\n\tPutObjectCommand,\n\tS3Client,\n\ttype S3ClientConfig,\n} from '@aws-sdk/client-s3';\nimport type { AwsRegion } from './StateProvider';\nimport {\n\tDocumentStateStore,\n\ttype LockHolder,\n\ttype RawState,\n\tStateLocked,\n\ttype StateVersion,\n\tStateVersionConflict,\n} from './StateStore';\n\nexport interface S3StateStoreOptions {\n\tworkspaceName: string;\n\tbucket: string;\n\t/** Key prefix inside the bucket; `gkm` by default. */\n\tprefix?: string;\n\tregion?: AwsRegion;\n\t/** Uses the default credential chain when omitted. */\n\tprofile?: string;\n\tcredentials?: S3ClientConfig['credentials'];\n\t/** For the local AWS emulator. */\n\tendpoint?: string;\n}\n\ninterface S3Failure {\n\tname?: string;\n\t$metadata?: { httpStatusCode?: number };\n}\n\n/** A conditional write that lost: the object is not what the write assumed. */\nfunction lostRace(error: unknown): boolean {\n\tconst { name, $metadata } = (error ?? {}) as S3Failure;\n\treturn (\n\t\tname === 'PreconditionFailed' ||\n\t\tname === 'ConditionalRequestConflict' ||\n\t\t$metadata?.httpStatusCode === 412 ||\n\t\t$metadata?.httpStatusCode === 409\n\t);\n}\n\nfunction notFound(error: unknown): boolean {\n\tconst { name, $metadata } = (error ?? {}) as S3Failure;\n\treturn (\n\t\tname === 'NoSuchKey' ||\n\t\tname === 'NotFound' ||\n\t\t$metadata?.httpStatusCode === 404\n\t);\n}\n\nexport class S3StateStore extends DocumentStateStore {\n\tprivate readonly prefix: string;\n\n\tconstructor(\n\t\treadonly workspaceName: string,\n\t\treadonly bucket: string,\n\t\tprivate readonly client: S3Client,\n\t\tprefix = 'gkm',\n\t) {\n\t\tsuper();\n\t\tthis.prefix = prefix.replace(/\\/+$/, '');\n\t}\n\n\tstatic create(options: S3StateStoreOptions): S3StateStore {\n\t\tconst config: S3ClientConfig = {\n\t\t\tregion: options.region,\n\t\t\tendpoint: options.endpoint,\n\t\t\t// The emulator serves buckets by path, not by subdomain.\n\t\t\tforcePathStyle: options.endpoint ? true : undefined,\n\t\t};\n\t\tif (options.profile) {\n\t\t\t// Required lazily: only a profile needs the credential providers.\n\t\t\tconst { fromIni } = require('@aws-sdk/credential-providers');\n\t\t\tconfig.credentials = fromIni({ profile: options.profile });\n\t\t} else if (options.credentials) {\n\t\t\tconfig.credentials = options.credentials;\n\t\t}\n\t\treturn new S3StateStore(\n\t\t\toptions.workspaceName,\n\t\t\toptions.bucket,\n\t\t\tnew S3Client(config),\n\t\t\toptions.prefix,\n\t\t);\n\t}\n\n\tprivate key(stage: string, leaf: string): string {\n\t\tconst path = `${this.workspaceName}/${stage}/${leaf}`;\n\t\treturn this.prefix ? `${this.prefix}/${path}` : path;\n\t}\n\n\tprotected location(stage: string): string {\n\t\treturn `s3://${this.bucket}/${this.key(stage, 'state.json')}`;\n\t}\n\n\tprotected async readRaw(stage: string): Promise<RawState | null> {\n\t\tconst object = await this.get(this.key(stage, 'state.json'));\n\t\tif (!object) return null;\n\t\treturn { body: object.body, version: object.etag };\n\t}\n\n\tprotected async writeRaw(\n\t\tstage: string,\n\t\tbody: string,\n\t\texpectedVersion: StateVersion | null,\n\t): Promise<StateVersion> {\n\t\tconst Key = this.key(stage, 'state.json');\n\t\ttry {\n\t\t\tconst { ETag } = await this.client.send(\n\t\t\t\tnew PutObjectCommand({\n\t\t\t\t\tBucket: this.bucket,\n\t\t\t\t\tKey,\n\t\t\t\t\tBody: body,\n\t\t\t\t\tContentType: 'application/json',\n\t\t\t\t\t...(expectedVersion === null\n\t\t\t\t\t\t? { IfNoneMatch: '*' }\n\t\t\t\t\t\t: { IfMatch: expectedVersion }),\n\t\t\t\t}),\n\t\t\t);\n\t\t\tif (ETag) return ETag;\n\t\t\t// Some S3-compatible servers omit the ETag on a conditional put.\n\t\t\treturn (await this.get(Key))?.etag ?? '';\n\t\t} catch (error) {\n\t\t\tif (lostRace(error)) {\n\t\t\t\tconst current = await this.get(Key);\n\t\t\t\tthrow new StateVersionConflict(\n\t\t\t\t\tstage,\n\t\t\t\t\texpectedVersion,\n\t\t\t\t\tcurrent?.etag ?? null,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprotected async writeV1Backup(stage: string, body: string): Promise<void> {\n\t\ttry {\n\t\t\tawait this.client.send(\n\t\t\t\tnew PutObjectCommand({\n\t\t\t\t\tBucket: this.bucket,\n\t\t\t\t\tKey: this.key(stage, 'state.v1.json'),\n\t\t\t\t\tBody: body,\n\t\t\t\t\tContentType: 'application/json',\n\t\t\t\t\tIfNoneMatch: '*',\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\t// The first migration's backup is the one worth keeping.\n\t\t\tif (!lostRace(error)) throw error;\n\t\t}\n\t}\n\n\tprotected async createLock(stage: string, holder: LockHolder): Promise<void> {\n\t\tconst Key = this.key(stage, 'lock.json');\n\t\ttry {\n\t\t\tawait this.client.send(\n\t\t\t\tnew PutObjectCommand({\n\t\t\t\t\tBucket: this.bucket,\n\t\t\t\t\tKey,\n\t\t\t\t\tBody: JSON.stringify(holder),\n\t\t\t\t\tContentType: 'application/json',\n\t\t\t\t\tIfNoneMatch: '*',\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (lostRace(error)) {\n\t\t\t\tthrow new StateLocked(\n\t\t\t\t\tstage,\n\t\t\t\t\tawait this.readLock(stage),\n\t\t\t\t\t`s3://${this.bucket}/${Key}`,\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tprotected async readLock(stage: string): Promise<LockHolder | null> {\n\t\tconst object = await this.get(this.key(stage, 'lock.json'));\n\t\tif (!object) return null;\n\t\ttry {\n\t\t\treturn JSON.parse(object.body) as LockHolder;\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\tprotected async removeLock(\n\t\tstage: string,\n\t\tholder: LockHolder | null,\n\t): Promise<void> {\n\t\tconst Key = this.key(stage, 'lock.json');\n\t\tconst object = await this.get(Key);\n\t\tif (!object) return;\n\t\tif (holder) {\n\t\t\ttry {\n\t\t\t\tif ((JSON.parse(object.body) as LockHolder).id !== holder.id) return;\n\t\t\t} catch {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\t// Conditional on the lock read above, so a lock taken by another\n\t\t\t// run in the meantime survives.\n\t\t\tawait this.client.send(\n\t\t\t\tnew DeleteObjectCommand({\n\t\t\t\t\tBucket: this.bucket,\n\t\t\t\t\tKey,\n\t\t\t\t\tIfMatch: object.etag,\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tif (!lostRace(error) && !notFound(error)) throw error;\n\t\t}\n\t}\n\n\tprivate async get(\n\t\tKey: string,\n\t): Promise<{ body: string; etag: string } | null> {\n\t\ttry {\n\t\t\tconst response = await this.client.send(\n\t\t\t\tnew GetObjectCommand({ Bucket: this.bucket, Key }),\n\t\t\t);\n\t\t\tconst body = (await response.Body?.transformToString('utf-8')) ?? '';\n\t\t\treturn { body, etag: response.ETag ?? '' };\n\t\t} catch (error) {\n\t\t\tif (notFound(error)) return null;\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"],"mappings":"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"}