@geekmidas/constructs 0.0.20 → 0.0.21

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 (204) hide show
  1. package/dist/{AWSLambdaFunction-B-Oxr8qt.d.cts → AWSLambdaFunction-gpqm7UBb.d.cts} +3 -3
  2. package/dist/{AWSLambdaFunction-CAm9r5ZX.d.mts → AWSLambdaFunction-qWpalqfr.d.mts} +3 -3
  3. package/dist/{AWSLambdaSubscriberAdaptor-Cknp_nn1.d.cts → AWSLambdaSubscriberAdaptor-CWbBNRz3.d.mts} +4 -4
  4. package/dist/{AWSLambdaSubscriberAdaptor-DpHzp-AM.d.mts → AWSLambdaSubscriberAdaptor-DT8icDRf.d.cts} +4 -4
  5. package/dist/{AmazonApiGatewayEndpointAdaptor-4hPy5vty.d.mts → AmazonApiGatewayEndpointAdaptor-BQ0IJdaI.d.mts} +3 -2
  6. package/dist/{AmazonApiGatewayEndpointAdaptor-C6Jk5HSy.mjs → AmazonApiGatewayEndpointAdaptor-CacGag6F.mjs} +16 -5
  7. package/dist/AmazonApiGatewayEndpointAdaptor-CacGag6F.mjs.map +1 -0
  8. package/dist/{AmazonApiGatewayEndpointAdaptor-CI9L7Ucn.cjs → AmazonApiGatewayEndpointAdaptor-DXssXsJi.cjs} +16 -5
  9. package/dist/AmazonApiGatewayEndpointAdaptor-DXssXsJi.cjs.map +1 -0
  10. package/dist/{AmazonApiGatewayEndpointAdaptor-ro0RMLzr.d.cts → AmazonApiGatewayEndpointAdaptor-Da9BR5On.d.cts} +3 -2
  11. package/dist/{AmazonApiGatewayV1EndpointAdaptor-BMy8DdNJ.mjs → AmazonApiGatewayV1EndpointAdaptor-BpnG55R7.mjs} +2 -2
  12. package/dist/{AmazonApiGatewayV1EndpointAdaptor-BMy8DdNJ.mjs.map → AmazonApiGatewayV1EndpointAdaptor-BpnG55R7.mjs.map} +1 -1
  13. package/dist/{AmazonApiGatewayV1EndpointAdaptor-hyR-WwyP.d.mts → AmazonApiGatewayV1EndpointAdaptor-C4_AZ1ek.d.mts} +3 -3
  14. package/dist/{AmazonApiGatewayV1EndpointAdaptor-BWJWKqQT.d.cts → AmazonApiGatewayV1EndpointAdaptor-CSm3NsWz.d.cts} +3 -3
  15. package/dist/{AmazonApiGatewayV1EndpointAdaptor-DYL1bCBS.cjs → AmazonApiGatewayV1EndpointAdaptor-Df4kszio.cjs} +2 -2
  16. package/dist/{AmazonApiGatewayV1EndpointAdaptor-DYL1bCBS.cjs.map → AmazonApiGatewayV1EndpointAdaptor-Df4kszio.cjs.map} +1 -1
  17. package/dist/{AmazonApiGatewayV2EndpointAdaptor-CPLCMeaN.cjs → AmazonApiGatewayV2EndpointAdaptor-5SIvqPby.cjs} +2 -2
  18. package/dist/{AmazonApiGatewayV2EndpointAdaptor-CPLCMeaN.cjs.map → AmazonApiGatewayV2EndpointAdaptor-5SIvqPby.cjs.map} +1 -1
  19. package/dist/{AmazonApiGatewayV2EndpointAdaptor-D1Irdggp.d.cts → AmazonApiGatewayV2EndpointAdaptor-6hsBFVLf.d.cts} +3 -3
  20. package/dist/{AmazonApiGatewayV2EndpointAdaptor-DX3SuI5S.d.mts → AmazonApiGatewayV2EndpointAdaptor-DdM8Tr1X.d.mts} +3 -3
  21. package/dist/{AmazonApiGatewayV2EndpointAdaptor-BU5wQMOe.mjs → AmazonApiGatewayV2EndpointAdaptor-ZORzMEET.mjs} +2 -2
  22. package/dist/{AmazonApiGatewayV2EndpointAdaptor-BU5wQMOe.mjs.map → AmazonApiGatewayV2EndpointAdaptor-ZORzMEET.mjs.map} +1 -1
  23. package/dist/{BaseFunctionBuilder-CbDnPZpD.d.mts → BaseFunctionBuilder-Ct6zY6Jq.d.mts} +2 -2
  24. package/dist/{BaseFunctionBuilder-DUZMbEr3.d.cts → BaseFunctionBuilder-DaQA0uKE.d.cts} +2 -2
  25. package/dist/{Construct-ZPqE0vhn.d.mts → Construct-DDR0295I.d.mts} +7 -7
  26. package/dist/{Construct-dI_rgdSp.d.cts → Construct-Dkd8Kvc9.d.cts} +7 -7
  27. package/dist/Construct.d.cts +1 -1
  28. package/dist/Construct.d.mts +1 -1
  29. package/dist/{Cron-COdfP0Jd.d.cts → Cron-7VPR2cNR.d.cts} +6 -5
  30. package/dist/Cron-Bi3QOge_.cjs.map +1 -1
  31. package/dist/{Cron-D8cn_ahj.d.mts → Cron-DnMRWPFR.d.mts} +6 -5
  32. package/dist/Cron-Dy_HW2Vv.mjs.map +1 -1
  33. package/dist/{CronBuilder-DntF6H3A.d.cts → CronBuilder-290th4zF.d.cts} +4 -4
  34. package/dist/{CronBuilder-DoMnSs_0.d.mts → CronBuilder-RLDitFmP.d.mts} +4 -4
  35. package/dist/{Endpoint-DDpF7NO1.cjs → Endpoint-CA-byrDr.cjs} +1 -3
  36. package/dist/Endpoint-CA-byrDr.cjs.map +1 -0
  37. package/dist/{Endpoint-Bu8Phz6y.d.cts → Endpoint-D2Imgihs.d.cts} +31 -7
  38. package/dist/{Endpoint-S6Yh2_PN.mjs → Endpoint-DbPsw13b.mjs} +1 -3
  39. package/dist/Endpoint-DbPsw13b.mjs.map +1 -0
  40. package/dist/{Endpoint-Bbs_sFvg.d.mts → Endpoint-PtQ-wLIS.d.mts} +31 -7
  41. package/dist/{EndpointBuilder-D47py-H1.mjs → EndpointBuilder-B5QPf5Wd.mjs} +2 -2
  42. package/dist/EndpointBuilder-B5QPf5Wd.mjs.map +1 -0
  43. package/dist/{EndpointBuilder-D02Qo4Ha.d.mts → EndpointBuilder-BPHpUekp.d.mts} +4 -4
  44. package/dist/{EndpointBuilder-vxy3s960.cjs → EndpointBuilder-DrJbIf3Z.cjs} +2 -2
  45. package/dist/EndpointBuilder-DrJbIf3Z.cjs.map +1 -0
  46. package/dist/{EndpointBuilder-DHPOWw0B.d.cts → EndpointBuilder-TApJQhtG.d.cts} +4 -4
  47. package/dist/{EndpointFactory-DSTXeokM.cjs → EndpointFactory-CSeDcWYn.cjs} +2 -2
  48. package/dist/EndpointFactory-CSeDcWYn.cjs.map +1 -0
  49. package/dist/{EndpointFactory-DFFXRU-l.d.cts → EndpointFactory-D94AFjIc.d.cts} +5 -5
  50. package/dist/{EndpointFactory-HOCnoBNT.mjs → EndpointFactory-DNwMexc7.mjs} +2 -2
  51. package/dist/EndpointFactory-DNwMexc7.mjs.map +1 -0
  52. package/dist/{EndpointFactory-g84YJjGf.d.mts → EndpointFactory-TJ6gtM0W.d.mts} +5 -5
  53. package/dist/{Function-V9M9UVHp.d.mts → Function-CD3rXWfa.d.mts} +5 -5
  54. package/dist/{Function-VI1TB3Mh.d.cts → Function-DHD1V9QW.d.cts} +5 -5
  55. package/dist/{FunctionBuilder-CjVEFTYC.d.cts → FunctionBuilder-FV6r3I7X.d.cts} +4 -4
  56. package/dist/{FunctionBuilder-D1ofSeMd.d.mts → FunctionBuilder-j2VkwuGf.d.mts} +4 -4
  57. package/dist/{FunctionExecutionWrapper-CwtwYozd.d.cts → FunctionExecutionWrapper-B0WP-Vec.d.mts} +4 -4
  58. package/dist/{FunctionExecutionWrapper-rhbIYT0Q.d.mts → FunctionExecutionWrapper-DYt3C8b9.d.cts} +4 -4
  59. package/dist/{HonoEndpointAdaptor-CdWWj3EJ.cjs → HonoEndpointAdaptor-B_gJPWGD.cjs} +6 -5
  60. package/dist/HonoEndpointAdaptor-B_gJPWGD.cjs.map +1 -0
  61. package/dist/{HonoEndpointAdaptor-BI0tA0Fg.mjs → HonoEndpointAdaptor-Bg_vTyA5.mjs} +6 -5
  62. package/dist/HonoEndpointAdaptor-Bg_vTyA5.mjs.map +1 -0
  63. package/dist/{HonoEndpointAdaptor-BTwjymKt.d.mts → HonoEndpointAdaptor-D99d4b-Z.d.mts} +5 -5
  64. package/dist/{HonoEndpointAdaptor-CDL4pkMO.d.cts → HonoEndpointAdaptor-DB_DdiJr.d.cts} +5 -5
  65. package/dist/{Subscriber-CJOWwaw1.mjs → Subscriber-CGb8LjZa.mjs} +1 -1
  66. package/dist/{Subscriber-CJOWwaw1.mjs.map → Subscriber-CGb8LjZa.mjs.map} +1 -1
  67. package/dist/{Subscriber-Bdh8rMSL.cjs → Subscriber-D-FPWts6.cjs} +1 -1
  68. package/dist/{Subscriber-Bdh8rMSL.cjs.map → Subscriber-D-FPWts6.cjs.map} +1 -1
  69. package/dist/{Subscriber-BhzqUzs-.d.cts → Subscriber-DMSzvO_J.d.cts} +6 -6
  70. package/dist/{Subscriber-s6yfjeOc.d.mts → Subscriber-itwm7ugy.d.mts} +6 -6
  71. package/dist/{SubscriberBuilder-BCVkp-ga.d.cts → SubscriberBuilder-9j3JCu8-.d.mts} +3 -3
  72. package/dist/{SubscriberBuilder-BWQmiYd8.mjs → SubscriberBuilder-BcAspHv9.mjs} +2 -2
  73. package/dist/{SubscriberBuilder-BWQmiYd8.mjs.map → SubscriberBuilder-BcAspHv9.mjs.map} +1 -1
  74. package/dist/{SubscriberBuilder-DieD_60p.cjs → SubscriberBuilder-BfE2cL1q.cjs} +2 -2
  75. package/dist/{SubscriberBuilder-DieD_60p.cjs.map → SubscriberBuilder-BfE2cL1q.cjs.map} +1 -1
  76. package/dist/{SubscriberBuilder-aCua5_wA.d.mts → SubscriberBuilder-BxJM3Hz_.d.cts} +3 -3
  77. package/dist/{TestEndpointAdaptor-ByXqQufk.d.cts → TestEndpointAdaptor-BYCwwiYk.d.cts} +2 -2
  78. package/dist/{TestEndpointAdaptor-C5qwQSnQ.cjs → TestEndpointAdaptor-Bew9lWsx.cjs} +5 -4
  79. package/dist/TestEndpointAdaptor-Bew9lWsx.cjs.map +1 -0
  80. package/dist/{TestEndpointAdaptor-Bl2ic-yr.d.mts → TestEndpointAdaptor-C-c8v7VI.d.mts} +2 -2
  81. package/dist/{TestEndpointAdaptor-DFDT9m8q.mjs → TestEndpointAdaptor-JONQJeXc.mjs} +5 -4
  82. package/dist/TestEndpointAdaptor-JONQJeXc.mjs.map +1 -0
  83. package/dist/adaptors/aws.cjs +4 -4
  84. package/dist/adaptors/aws.d.cts +13 -13
  85. package/dist/adaptors/aws.d.mts +13 -13
  86. package/dist/adaptors/aws.mjs +4 -4
  87. package/dist/adaptors/hono.cjs +3 -3
  88. package/dist/adaptors/hono.d.cts +7 -7
  89. package/dist/adaptors/hono.d.mts +7 -7
  90. package/dist/adaptors/hono.mjs +3 -3
  91. package/dist/adaptors/testing.cjs +2 -2
  92. package/dist/adaptors/testing.d.cts +7 -7
  93. package/dist/adaptors/testing.d.mts +7 -7
  94. package/dist/adaptors/testing.mjs +2 -2
  95. package/dist/crons/Cron.d.cts +6 -6
  96. package/dist/crons/Cron.d.mts +6 -6
  97. package/dist/crons/CronBuilder.d.cts +7 -7
  98. package/dist/crons/CronBuilder.d.mts +7 -7
  99. package/dist/crons/index.d.cts +11 -11
  100. package/dist/crons/index.d.mts +11 -11
  101. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.cjs +2 -2
  102. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.cts +7 -7
  103. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.mts +7 -7
  104. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.mjs +2 -2
  105. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.cjs +3 -3
  106. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.cts +8 -8
  107. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.mts +8 -8
  108. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.mjs +3 -3
  109. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.cjs +3 -3
  110. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.cts +8 -8
  111. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.mts +8 -8
  112. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.mjs +3 -3
  113. package/dist/endpoints/Endpoint.cjs +1 -1
  114. package/dist/endpoints/Endpoint.d.cts +6 -6
  115. package/dist/endpoints/Endpoint.d.mts +6 -6
  116. package/dist/endpoints/Endpoint.mjs +1 -1
  117. package/dist/endpoints/EndpointBuilder.cjs +2 -2
  118. package/dist/endpoints/EndpointBuilder.d.cts +7 -7
  119. package/dist/endpoints/EndpointBuilder.d.mts +7 -7
  120. package/dist/endpoints/EndpointBuilder.mjs +2 -2
  121. package/dist/endpoints/EndpointFactory.cjs +3 -3
  122. package/dist/endpoints/EndpointFactory.d.cts +8 -8
  123. package/dist/endpoints/EndpointFactory.d.mts +8 -8
  124. package/dist/endpoints/EndpointFactory.mjs +3 -3
  125. package/dist/endpoints/HonoEndpointAdaptor.cjs +3 -3
  126. package/dist/endpoints/HonoEndpointAdaptor.d.cts +7 -7
  127. package/dist/endpoints/HonoEndpointAdaptor.d.mts +7 -7
  128. package/dist/endpoints/HonoEndpointAdaptor.mjs +3 -3
  129. package/dist/endpoints/TestEndpointAdaptor.cjs +2 -2
  130. package/dist/endpoints/TestEndpointAdaptor.d.cts +7 -7
  131. package/dist/endpoints/TestEndpointAdaptor.d.mts +7 -7
  132. package/dist/endpoints/TestEndpointAdaptor.mjs +2 -2
  133. package/dist/endpoints/audit.d.cts +6 -6
  134. package/dist/endpoints/audit.d.mts +6 -6
  135. package/dist/endpoints/helpers.cjs +2 -2
  136. package/dist/endpoints/helpers.d.cts +6 -6
  137. package/dist/endpoints/helpers.d.mts +6 -6
  138. package/dist/endpoints/helpers.mjs +2 -2
  139. package/dist/endpoints/index.cjs +3 -3
  140. package/dist/endpoints/index.d.cts +10 -10
  141. package/dist/endpoints/index.d.mts +10 -10
  142. package/dist/endpoints/index.mjs +3 -3
  143. package/dist/endpoints/processAudits.d.cts +6 -6
  144. package/dist/endpoints/processAudits.d.mts +6 -6
  145. package/dist/functions/AWSLambdaFunction.d.cts +4 -4
  146. package/dist/functions/AWSLambdaFunction.d.mts +4 -4
  147. package/dist/functions/BaseFunctionBuilder.d.cts +2 -2
  148. package/dist/functions/BaseFunctionBuilder.d.mts +2 -2
  149. package/dist/functions/Function.d.cts +2 -2
  150. package/dist/functions/Function.d.mts +2 -2
  151. package/dist/functions/FunctionBuilder.d.cts +4 -4
  152. package/dist/functions/FunctionBuilder.d.mts +4 -4
  153. package/dist/functions/FunctionExecutionWrapper.d.cts +3 -3
  154. package/dist/functions/FunctionExecutionWrapper.d.mts +3 -3
  155. package/dist/functions/TestFunctionAdaptor.d.cts +2 -2
  156. package/dist/functions/TestFunctionAdaptor.d.mts +2 -2
  157. package/dist/functions/index.d.cts +5 -5
  158. package/dist/functions/index.d.mts +5 -5
  159. package/dist/{helpers-2CLKTnRm.mjs → helpers-CrrdyA04.mjs} +2 -2
  160. package/dist/{helpers-2CLKTnRm.mjs.map → helpers-CrrdyA04.mjs.map} +1 -1
  161. package/dist/{helpers-Khuhi_Qx.cjs → helpers-DiPZVJQC.cjs} +2 -2
  162. package/dist/{helpers-Khuhi_Qx.cjs.map → helpers-DiPZVJQC.cjs.map} +1 -1
  163. package/dist/{index-Sxtb_Pzw.d.mts → index-C6vCFivC.d.cts} +2 -2
  164. package/dist/index-IoTEI3As.d.mts +10 -0
  165. package/dist/index.d.cts +1 -1
  166. package/dist/index.d.mts +1 -1
  167. package/dist/publisher.d.cts +2 -2
  168. package/dist/publisher.d.mts +2 -2
  169. package/dist/subscribers/AWSLambdaSubscriberAdaptor.d.cts +3 -3
  170. package/dist/subscribers/AWSLambdaSubscriberAdaptor.d.mts +3 -3
  171. package/dist/subscribers/Subscriber.cjs +1 -1
  172. package/dist/subscribers/Subscriber.d.cts +2 -2
  173. package/dist/subscribers/Subscriber.d.mts +2 -2
  174. package/dist/subscribers/Subscriber.mjs +1 -1
  175. package/dist/subscribers/SubscriberBuilder.cjs +2 -2
  176. package/dist/subscribers/SubscriberBuilder.d.cts +3 -3
  177. package/dist/subscribers/SubscriberBuilder.d.mts +3 -3
  178. package/dist/subscribers/SubscriberBuilder.mjs +2 -2
  179. package/dist/subscribers/index.cjs +2 -2
  180. package/dist/subscribers/index.d.cts +5 -5
  181. package/dist/subscribers/index.d.mts +3 -3
  182. package/dist/subscribers/index.mjs +2 -2
  183. package/package.json +6 -6
  184. package/src/crons/Cron.ts +7 -6
  185. package/src/endpoints/AmazonApiGatewayEndpointAdaptor.ts +31 -10
  186. package/src/endpoints/Endpoint.ts +41 -6
  187. package/src/endpoints/EndpointBuilder.ts +2 -1
  188. package/src/endpoints/EndpointFactory.ts +13 -4
  189. package/src/endpoints/HonoEndpointAdaptor.ts +12 -11
  190. package/src/endpoints/TestEndpointAdaptor.ts +11 -6
  191. package/src/endpoints/__tests__/TestEndpointAdaptor.audits.spec.ts +30 -42
  192. package/dist/AmazonApiGatewayEndpointAdaptor-C6Jk5HSy.mjs.map +0 -1
  193. package/dist/AmazonApiGatewayEndpointAdaptor-CI9L7Ucn.cjs.map +0 -1
  194. package/dist/Endpoint-DDpF7NO1.cjs.map +0 -1
  195. package/dist/Endpoint-S6Yh2_PN.mjs.map +0 -1
  196. package/dist/EndpointBuilder-D47py-H1.mjs.map +0 -1
  197. package/dist/EndpointBuilder-vxy3s960.cjs.map +0 -1
  198. package/dist/EndpointFactory-DSTXeokM.cjs.map +0 -1
  199. package/dist/EndpointFactory-HOCnoBNT.mjs.map +0 -1
  200. package/dist/HonoEndpointAdaptor-BI0tA0Fg.mjs.map +0 -1
  201. package/dist/HonoEndpointAdaptor-CdWWj3EJ.cjs.map +0 -1
  202. package/dist/TestEndpointAdaptor-C5qwQSnQ.cjs.map +0 -1
  203. package/dist/TestEndpointAdaptor-DFDT9m8q.mjs.map +0 -1
  204. package/dist/index-CkBMFqhI.d.cts +0 -10
@@ -191,17 +191,44 @@ export abstract class AmazonApiGatewayEndpoint<
191
191
  };
192
192
  }
193
193
 
194
+ private database(): Middleware<TEvent, TInput, TServices, TLogger> {
195
+ return {
196
+ before: async (req) => {
197
+ if (!this.endpoint.databaseService) {
198
+ return;
199
+ }
200
+
201
+ const logger = req.event.logger as TLogger;
202
+ const serviceDiscovery = ServiceDiscovery.getInstance<
203
+ ServiceRecord<TServices>,
204
+ TLogger
205
+ >(logger, this.envParser);
206
+
207
+ const db = await serviceDiscovery
208
+ .register([this.endpoint.databaseService])
209
+ .then(
210
+ (s) =>
211
+ s[this.endpoint.databaseService!.serviceName as keyof typeof s],
212
+ );
213
+
214
+ (req.event as any).db = db;
215
+ },
216
+ };
217
+ }
218
+
194
219
  private session(): Middleware<TEvent, TInput, TServices, TLogger> {
195
220
  return {
196
221
  before: async (req) => {
197
222
  const logger = req.event.logger as TLogger;
198
223
  const services = req.event.services;
224
+ const db = (req.event as any).db;
199
225
  req.event.session = (await this.endpoint.getSession({
200
226
  logger,
201
227
  services,
202
228
  header: req.event.header,
203
229
  cookie: req.event.cookie,
204
- })) as TSession;
230
+ ...(db !== undefined && { db }),
231
+ } as any)) as TSession;
205
232
  },
206
233
  };
207
234
  }
@@ -267,15 +294,8 @@ export abstract class AmazonApiGatewayEndpoint<
267
294
  logger.warn('No auditor storage service available');
268
295
  }
269
296
 
270
- // Resolve database service if configured
271
- const rawDb = this.endpoint.databaseService
272
- ? await serviceDiscovery
273
- .register([this.endpoint.databaseService])
274
- .then(
275
- (s) =>
276
- s[this.endpoint.databaseService!.serviceName as keyof typeof s],
277
- )
278
- : undefined;
297
+ // Get pre-resolved database from middleware
298
+ const rawDb = (event as any).db;
279
299
 
280
300
  // Execute handler with automatic audit transaction support
281
301
  const result = await executeWithAuditTransaction(
@@ -382,6 +402,7 @@ export abstract class AmazonApiGatewayEndpoint<
382
402
  .use(this.error())
383
403
  .use(this.services())
384
404
  .use(this.input())
405
+ .use(this.database())
385
406
  .use(this.session())
386
407
  .use(this.authorize())
387
408
  .use(this.events()) as unknown as THandler;
@@ -109,7 +109,7 @@ export class Endpoint<
109
109
  /** Default headers to apply to all responses */
110
110
  public readonly defaultHeaders: Record<string, string> = {};
111
111
  /** Function to extract session data from the request context */
112
- public getSession: SessionFn<TServices, TLogger, TSession> = () =>
112
+ public getSession: SessionFn<TServices, TLogger, TSession, TDatabase> = () =>
113
113
  ({}) as TSession;
114
114
  /** Function to determine if the request is authorized */
115
115
  public authorize: AuthorizeFn<TServices, TLogger, TSession> = () => true;
@@ -122,7 +122,7 @@ export class Endpoint<
122
122
  /** Declarative audit definitions */
123
123
  public audits: MappedAudit<TAuditAction, OutSchema>[] = [];
124
124
  /** Database service for this endpoint */
125
- public databaseService?: Service<TDatabaseServiceName, TDatabase>;
125
+ public declare databaseService?: Service<TDatabaseServiceName, TDatabase>;
126
126
  /** The endpoint handler function */
127
127
  private endpointFn!: EndpointHandler<
128
128
  TInput,
@@ -752,7 +752,7 @@ export interface EndpointOptions<
752
752
  /** Logger instance */
753
753
  logger: TLogger;
754
754
  /** Optional session extraction function */
755
- getSession: SessionFn<TServices, TLogger, TSession> | undefined;
755
+ getSession: SessionFn<TServices, TLogger, TSession, TDatabase> | undefined;
756
756
  /** Optional rate limiting configuration */
757
757
  rateLimit?: RateLimitConfig;
758
758
  /** Success HTTP status code */
@@ -826,7 +826,10 @@ export type AuthorizeFn<
826
826
  ctx: AuthorizeContext<TServices, TLogger, TSession>,
827
827
  ) => Promise<boolean> | boolean;
828
828
 
829
- export type SessionContext<
829
+ /**
830
+ * Base session context without database
831
+ */
832
+ type BaseSessionContext<
830
833
  TServices extends Service[] = [],
831
834
  TLogger extends Logger = Logger,
832
835
  > = {
@@ -835,29 +838,61 @@ export type SessionContext<
835
838
  header: HeaderFn;
836
839
  cookie: CookieFn;
837
840
  };
841
+
842
+ /**
843
+ * Conditional database context for session - only present when database service is configured
844
+ */
845
+ type SessionDatabaseContext<TDatabase = undefined> = TDatabase extends undefined
846
+ ? {}
847
+ : {
848
+ /**
849
+ * Database instance for session extraction.
850
+ * Available when a database service is configured via `.database()`.
851
+ * Useful for looking up user data from the database based on auth tokens.
852
+ */
853
+ db: TDatabase;
854
+ };
855
+
856
+ export type SessionContext<
857
+ TServices extends Service[] = [],
858
+ TLogger extends Logger = Logger,
859
+ TDatabase = undefined,
860
+ > = BaseSessionContext<TServices, TLogger> & SessionDatabaseContext<TDatabase>;
838
861
  /**
839
862
  * Function type for extracting session data from a request.
840
863
  *
841
864
  * @template TServices - Available service dependencies
842
865
  * @template TLogger - Logger type
843
866
  * @template TSession - Session data type to extract
867
+ * @template TDatabase - Database type (when database service is configured)
844
868
  *
845
- * @param ctx - Context containing services, logger, and headers
869
+ * @param ctx - Context containing services, logger, headers, and optionally database
846
870
  * @returns The extracted session data
847
871
  *
848
872
  * @example
849
873
  * ```typescript
874
+ * // Without database
850
875
  * const getSession: SessionFn<Services, Logger, UserSession> = async ({ header, services }) => {
851
876
  * const token = header('authorization');
852
877
  * return await services.auth.verifyToken(token);
853
878
  * };
879
+ *
880
+ * // With database
881
+ * const getSession: SessionFn<Services, Logger, UserSession, Database> = async ({ header, db }) => {
882
+ * const token = header('authorization');
883
+ * const user = await db.selectFrom('users').where('token', '=', token).executeTakeFirst();
884
+ * return { userId: user?.id };
885
+ * };
854
886
  * ```
855
887
  */
856
888
  export type SessionFn<
857
889
  TServices extends Service[] = [],
858
890
  TLogger extends Logger = Logger,
859
891
  TSession = unknown,
860
- > = (ctx: SessionContext<TServices, TLogger>) => Promise<TSession> | TSession;
892
+ TDatabase = undefined,
893
+ > = (
894
+ ctx: SessionContext<TServices, TLogger, TDatabase>,
895
+ ) => Promise<TSession> | TSession;
861
896
 
862
897
  /**
863
898
  * Utility type that converts Express-style route parameters to OpenAPI format.
@@ -58,7 +58,8 @@ export class EndpointBuilder<
58
58
  protected _status?: SuccessStatus;
59
59
  protected _tags?: string[];
60
60
  protected _memorySize?: number;
61
- _getSession: SessionFn<TServices, TLogger, TSession> = () => ({}) as TSession;
61
+ _getSession: SessionFn<TServices, TLogger, TSession, TDatabase> = () =>
62
+ ({}) as TSession;
62
63
  _authorize: AuthorizeFn<TServices, TLogger, TSession> = () => true;
63
64
  _rateLimit?: RateLimitConfig;
64
65
  _availableAuthorizers: Authorizer[] = [];
@@ -40,7 +40,12 @@ export class EndpointFactory<
40
40
  private defaultEventPublisher:
41
41
  | Service<TEventPublisherServiceName, TEventPublisher>
42
42
  | undefined;
43
- private defaultSessionExtractor?: SessionFn<TServices, TLogger, TSession>;
43
+ private defaultSessionExtractor?: SessionFn<
44
+ TServices,
45
+ TLogger,
46
+ TSession,
47
+ TDatabase
48
+ >;
44
49
  private defaultLogger: TLogger = DEFAULT_LOGGER;
45
50
  private availableAuthorizers: Authorizer[] = [];
46
51
  private defaultAuthorizerName?: TAuthorizers[number];
@@ -423,7 +428,7 @@ export class EndpointFactory<
423
428
  }
424
429
 
425
430
  session<T>(
426
- session: SessionFn<TServices, TLogger, T>,
431
+ session: SessionFn<TServices, TLogger, T, TDatabase>,
427
432
  ): EndpointFactory<
428
433
  TServices,
429
434
  TBasePath,
@@ -513,7 +518,11 @@ export class EndpointFactory<
513
518
  basePath: this.basePath,
514
519
  defaultAuthorizeFn: this.defaultAuthorizeFn,
515
520
  defaultLogger: this.defaultLogger,
516
- defaultSessionExtractor: this.defaultSessionExtractor,
521
+ // Reset session extractor when database changes - user should call .session() after .database()
522
+ // to get proper type inference for the new database type
523
+ defaultSessionExtractor: this.defaultSessionExtractor as unknown as
524
+ | SessionFn<TServices, TLogger, TSession, T>
525
+ | undefined,
517
526
  defaultEventPublisher: this.defaultEventPublisher,
518
527
  availableAuthorizers: this.availableAuthorizers,
519
528
  defaultAuthorizerName: this.defaultAuthorizerName,
@@ -781,7 +790,7 @@ export interface EndpointFactoryOptions<
781
790
  basePath?: TBasePath;
782
791
  defaultAuthorizeFn?: AuthorizeFn<TServices, TLogger, TSession>;
783
792
  defaultLogger?: TLogger;
784
- defaultSessionExtractor?: SessionFn<TServices, TLogger, TSession>;
793
+ defaultSessionExtractor?: SessionFn<TServices, TLogger, TSession, TDatabase>;
785
794
  defaultEventPublisher?: Service<TEventPublisherServiceName, TEventPublisher>;
786
795
  defaultEvents?: MappedEvent<TEventPublisher, undefined>[];
787
796
  availableAuthorizers?: Authorizer[];
@@ -298,12 +298,23 @@ export class HonoEndpoint<
298
298
 
299
299
  const services = await serviceDiscovery.register(endpoint.services);
300
300
 
301
+ // Resolve database service early so it's available for session extraction
302
+ const rawDb = endpoint.databaseService
303
+ ? await serviceDiscovery
304
+ .register([endpoint.databaseService])
305
+ .then(
306
+ (s) =>
307
+ s[endpoint.databaseService!.serviceName as keyof typeof s],
308
+ )
309
+ : undefined;
310
+
301
311
  const session = await endpoint.getSession({
302
312
  services,
303
313
  logger,
304
314
  header,
305
315
  cookie,
306
- });
316
+ ...(rawDb !== undefined && { db: rawDb }),
317
+ } as any);
307
318
 
308
319
  const isAuthorized = await endpoint.authorize({
309
320
  header,
@@ -363,16 +374,6 @@ export class HonoEndpoint<
363
374
  logger.warn('No auditor storage service available');
364
375
  }
365
376
 
366
- // Resolve database service if configured
367
- const rawDb = endpoint.databaseService
368
- ? await serviceDiscovery
369
- .register([endpoint.databaseService])
370
- .then(
371
- (s) =>
372
- s[endpoint.databaseService!.serviceName as keyof typeof s],
373
- )
374
- : undefined;
375
-
376
377
  // Execute handler with automatic audit transaction support
377
378
  const result = await executeWithAuditTransaction(
378
379
  auditContext,
@@ -1,4 +1,8 @@
1
- import type { AuditActor, AuditStorage, AuditableAction } from '@geekmidas/audit';
1
+ import type {
2
+ AuditActor,
3
+ AuditStorage,
4
+ AuditableAction,
5
+ } from '@geekmidas/audit';
2
6
  import { DefaultAuditor } from '@geekmidas/audit';
3
7
  import { EnvironmentParser } from '@geekmidas/envkit';
4
8
  import type { EventPublisher } from '@geekmidas/events';
@@ -179,12 +183,17 @@ export class TestEndpointAdaptor<
179
183
  host: ctx.headers.host,
180
184
  method: this.endpoint.method,
181
185
  }) as TLogger;
186
+
187
+ // Get database from context for session extraction
188
+ const rawDb = (ctx as any).database as TDatabase;
189
+
182
190
  const session = await this.endpoint.getSession({
183
191
  logger,
184
192
  services: ctx.services,
185
193
  header,
186
194
  cookie,
187
- });
195
+ ...(rawDb !== undefined && { db: rawDb }),
196
+ } as any);
188
197
 
189
198
  // Create audit context if audit storage is provided
190
199
  // The auditorStorage instance is required when endpoint uses .auditor()
@@ -229,10 +238,6 @@ export class TestEndpointAdaptor<
229
238
  logger.warn('No auditor storage service available');
230
239
  }
231
240
 
232
- // Use database instance directly from context
233
- // The database instance is required when endpoint uses .database()
234
- const rawDb = (ctx as any).database as TDatabase;
235
-
236
241
  // Execute handler with automatic audit transaction support
237
242
  const result = await executeWithAuditTransaction(
238
243
  auditContext,
@@ -71,13 +71,11 @@ describe('TestEndpointAdaptor with auditorStorage and database', () => {
71
71
  it('should process declarative audits when auditorStorage is provided', async () => {
72
72
  const auditStorage = new InMemoryAuditStorage();
73
73
 
74
- const auditStorageService: Service<
75
- 'auditStorage',
76
- InMemoryAuditStorage
77
- > = {
78
- serviceName: 'auditStorage' as const,
79
- register: vi.fn().mockResolvedValue(auditStorage),
80
- };
74
+ const auditStorageService: Service<'auditStorage', InMemoryAuditStorage> =
75
+ {
76
+ serviceName: 'auditStorage' as const,
77
+ register: vi.fn().mockResolvedValue(auditStorage),
78
+ };
81
79
 
82
80
  const outputSchema = z.object({ id: z.string(), email: z.string() });
83
81
 
@@ -123,13 +121,11 @@ describe('TestEndpointAdaptor with auditorStorage and database', () => {
123
121
  it('should allow manual auditing via auditor in handler context', async () => {
124
122
  const auditStorage = new InMemoryAuditStorage();
125
123
 
126
- const auditStorageService: Service<
127
- 'auditStorage',
128
- InMemoryAuditStorage
129
- > = {
130
- serviceName: 'auditStorage' as const,
131
- register: vi.fn().mockResolvedValue(auditStorage),
132
- };
124
+ const auditStorageService: Service<'auditStorage', InMemoryAuditStorage> =
125
+ {
126
+ serviceName: 'auditStorage' as const,
127
+ register: vi.fn().mockResolvedValue(auditStorage),
128
+ };
133
129
 
134
130
  const endpoint = e
135
131
  .post('/users')
@@ -168,13 +164,11 @@ describe('TestEndpointAdaptor with auditorStorage and database', () => {
168
164
  it('should extract actor from session when actorExtractor is configured', async () => {
169
165
  const auditStorage = new InMemoryAuditStorage();
170
166
 
171
- const auditStorageService: Service<
172
- 'auditStorage',
173
- InMemoryAuditStorage
174
- > = {
175
- serviceName: 'auditStorage' as const,
176
- register: vi.fn().mockResolvedValue(auditStorage),
177
- };
167
+ const auditStorageService: Service<'auditStorage', InMemoryAuditStorage> =
168
+ {
169
+ serviceName: 'auditStorage' as const,
170
+ register: vi.fn().mockResolvedValue(auditStorage),
171
+ };
178
172
 
179
173
  const outputSchema = z.object({ id: z.string(), email: z.string() });
180
174
 
@@ -349,13 +343,11 @@ describe('TestEndpointAdaptor with auditorStorage and database', () => {
349
343
  { id: 'db-user-1', email: 'dbuser@example.com' },
350
344
  ]);
351
345
 
352
- const auditStorageService: Service<
353
- 'auditStorage',
354
- InMemoryAuditStorage
355
- > = {
356
- serviceName: 'auditStorage' as const,
357
- register: vi.fn().mockResolvedValue(auditStorage),
358
- };
346
+ const auditStorageService: Service<'auditStorage', InMemoryAuditStorage> =
347
+ {
348
+ serviceName: 'auditStorage' as const,
349
+ register: vi.fn().mockResolvedValue(auditStorage),
350
+ };
359
351
 
360
352
  const databaseService: Service<'database', MockDatabase> = {
361
353
  serviceName: 'database' as const,
@@ -438,13 +430,11 @@ describe('TestEndpointAdaptor with auditorStorage and database', () => {
438
430
  const mockDb = createMockDatabase();
439
431
  (mockDb.query as any).mockResolvedValue([]);
440
432
 
441
- const auditStorageService: Service<
442
- 'auditStorage',
443
- InMemoryAuditStorage
444
- > = {
445
- serviceName: 'auditStorage' as const,
446
- register: vi.fn().mockResolvedValue(auditStorage),
447
- };
433
+ const auditStorageService: Service<'auditStorage', InMemoryAuditStorage> =
434
+ {
435
+ serviceName: 'auditStorage' as const,
436
+ register: vi.fn().mockResolvedValue(auditStorage),
437
+ };
448
438
 
449
439
  const databaseService: Service<'database', MockDatabase> = {
450
440
  serviceName: 'database' as const,
@@ -508,13 +498,11 @@ describe('TestEndpointAdaptor with auditorStorage and database', () => {
508
498
  it('should require auditorStorage when endpoint uses .auditor()', async () => {
509
499
  const auditStorage = new InMemoryAuditStorage();
510
500
 
511
- const auditStorageService: Service<
512
- 'auditStorage',
513
- InMemoryAuditStorage
514
- > = {
515
- serviceName: 'auditStorage' as const,
516
- register: vi.fn().mockResolvedValue(auditStorage),
517
- };
501
+ const auditStorageService: Service<'auditStorage', InMemoryAuditStorage> =
502
+ {
503
+ serviceName: 'auditStorage' as const,
504
+ register: vi.fn().mockResolvedValue(auditStorage),
505
+ };
518
506
 
519
507
  const endpoint = e
520
508
  .post('/users')
@@ -1 +0,0 @@
1
- {"version":3,"file":"AmazonApiGatewayEndpointAdaptor-C6Jk5HSy.mjs","names":["envParser: EnvironmentParser<{}>","endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >","event: Event<TEvent, TInput, TServices, TLogger, TSession>","metadata","output","result","lambdaResponse: AmazonApiGatewayEndpointHandlerResponse","setCookieHeaders: string[]"],"sources":["../src/endpoints/AmazonApiGatewayEndpointAdaptor.ts"],"sourcesContent":["import type { AuditStorage, AuditableAction } from '@geekmidas/audit';\nimport type { Logger } from '@geekmidas/logger';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { HttpMethod } from '../types';\nimport { Endpoint, type EndpointSchemas, ResponseBuilder } from './Endpoint';\n\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport middy, { type MiddlewareObj } from '@middy/core';\nimport type {\n APIGatewayProxyEvent,\n APIGatewayProxyEventV2,\n Context,\n} from 'aws-lambda';\nimport set from 'lodash.set';\n\nimport {\n UnauthorizedError,\n UnprocessableEntityError,\n wrapError,\n} from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport {\n type Service,\n ServiceDiscovery,\n type ServiceRecord,\n} from '@geekmidas/services';\n\nimport type {\n InferComposableStandardSchema,\n InferStandardSchema,\n} from '@geekmidas/schema';\nimport { publishConstructEvents } from '../publisher';\nimport type { CookieFn, HeaderFn } from './Endpoint';\nimport type { MappedAudit } from './audit';\nimport {\n createAuditContext,\n executeWithAuditTransaction,\n} from './processAudits';\n\n// Helper function to publish events\n\nexport abstract class AmazonApiGatewayEndpoint<\n THandler extends\n | AmazonApiGatewayV1EndpointHandler\n | AmazonApiGatewayV2EndpointHandler,\n TEvent extends HandlerEvent<THandler>,\n TRoute extends string,\n TMethod extends HttpMethod,\n TInput extends EndpointSchemas = {},\n TOutSchema extends StandardSchemaV1 | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n TAuditStorage extends AuditStorage | undefined = undefined,\n TAuditStorageServiceName extends string = string,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n> {\n constructor(\n protected envParser: EnvironmentParser<{}>,\n protected readonly endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >,\n ) {}\n\n private error(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n onError: (req) => {\n (req.event.logger || this.endpoint.logger).error(\n req.error || {},\n 'Error processing request',\n );\n const wrappedError = wrapError(req.error);\n\n // Set the response with the proper status code from the HttpError\n req.response = {\n statusCode: wrappedError.statusCode,\n body: wrappedError.body,\n };\n },\n };\n }\n abstract getInput(e: TEvent): GetInputResponse;\n\n private input(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n try {\n const { body, query, params } = this.getInput(req.event);\n const headers = req.event.headers as Record<string, string>;\n const header = Endpoint.createHeaders(headers);\n const cookie = Endpoint.createCookies(headers.cookie);\n\n set(req.event, 'body', await this.endpoint.parseInput(body, 'body'));\n\n set(\n req.event,\n 'query',\n await this.endpoint.parseInput(query, 'query'),\n );\n set(\n req.event,\n 'params',\n await this.endpoint.parseInput(params, 'params'),\n );\n set(req.event, 'header', header);\n set(req.event, 'cookie', cookie);\n } catch (error) {\n // Convert validation errors to 422 Unprocessable Entity\n if (error && typeof error === 'object' && Array.isArray(error)) {\n throw new UnprocessableEntityError('Validation failed', error);\n }\n throw error;\n }\n },\n };\n }\n\n abstract getLoggerContext(data: TEvent, context: Context): LoggerContext;\n\n private logger(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: (req) => {\n req.event.logger = this.endpoint.logger.child({\n route: this.endpoint.route,\n host: req.event.headers?.host,\n method: this.endpoint.method,\n ...this.getLoggerContext(req.event, req.context),\n }) as TLogger;\n },\n };\n }\n private services(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n const logger = req.event.logger as TLogger;\n const serviceDiscovery = ServiceDiscovery.getInstance<\n ServiceRecord<TServices>,\n TLogger\n >(logger, this.envParser);\n\n const services = await serviceDiscovery.register(\n this.endpoint.services,\n );\n\n req.event.services = services;\n },\n };\n }\n\n private authorize(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n const logger = req.event.logger as TLogger;\n const services = req.event.services;\n const header = req.event.header;\n const cookie = req.event.cookie;\n const session = req.event.session as TSession;\n\n const isAuthorized = await this.endpoint.authorize({\n header,\n cookie,\n services,\n logger,\n session,\n });\n\n if (!isAuthorized) {\n logger.warn('Unauthorized access attempt');\n throw new UnauthorizedError(\n 'Unauthorized access to the endpoint',\n 'You do not have permission to access this resource.',\n );\n }\n },\n };\n }\n\n private session(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n const logger = req.event.logger as TLogger;\n const services = req.event.services;\n req.event.session = (await this.endpoint.getSession({\n logger,\n services,\n header: req.event.header,\n cookie: req.event.cookie,\n })) as TSession;\n },\n };\n }\n\n private events(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n after: async (req) => {\n const event = req.event;\n const response = (event as any)\n .__response as InferStandardSchema<TOutSchema>;\n const statusCode = req.response?.statusCode ?? this.endpoint.status;\n\n // Only publish events on successful responses (2xx status codes)\n // Note: Audits are processed inside the handler's transaction\n if (Endpoint.isSuccessStatus(statusCode)) {\n const logger = event.logger as TLogger;\n const serviceDiscovery = ServiceDiscovery.getInstance<\n ServiceRecord<TServices>,\n TLogger\n >(logger, this.envParser);\n\n // Publish events\n await publishConstructEvents(\n this.endpoint,\n response,\n serviceDiscovery,\n logger,\n );\n }\n },\n };\n }\n\n private async _handler(\n event: Event<TEvent, TInput, TServices, TLogger, TSession>,\n ) {\n const input = this.endpoint.refineInput(event);\n const logger = event.logger as TLogger;\n const serviceDiscovery = ServiceDiscovery.getInstance<\n ServiceRecord<TServices>,\n TLogger\n >(logger, this.envParser);\n\n // Create audit context if audit storage is configured\n const auditContext = await createAuditContext(\n this.endpoint,\n serviceDiscovery,\n logger,\n {\n session: event.session,\n header: event.header,\n cookie: event.cookie,\n services: event.services as Record<string, unknown>,\n },\n );\n\n // Warn if declarative audits are configured but no audit storage\n const audits = this.endpoint.audits as MappedAudit<\n TAuditAction,\n TOutSchema\n >[];\n if (!auditContext && audits?.length) {\n logger.warn('No auditor storage service available');\n }\n\n // Resolve database service if configured\n const rawDb = this.endpoint.databaseService\n ? await serviceDiscovery\n .register([this.endpoint.databaseService])\n .then(\n (s) =>\n s[this.endpoint.databaseService!.serviceName as keyof typeof s],\n )\n : undefined;\n\n // Execute handler with automatic audit transaction support\n const result = await executeWithAuditTransaction(\n auditContext,\n async (auditor) => {\n // Use audit transaction as db only if the storage uses the same database service\n const sameDatabase =\n auditContext?.storage?.databaseServiceName &&\n auditContext.storage.databaseServiceName ===\n this.endpoint.databaseService?.serviceName;\n const db = sameDatabase\n ? (auditor?.getTransaction?.() ?? rawDb)\n : rawDb;\n\n const responseBuilder = new ResponseBuilder();\n const response = await this.endpoint.handler(\n {\n header: event.header,\n cookie: event.cookie,\n logger: event.logger,\n services: event.services,\n session: event.session,\n auditor,\n db,\n ...input,\n } as any,\n responseBuilder,\n );\n\n // Check if response has metadata\n let data = response;\n let metadata = responseBuilder.getMetadata();\n\n if (Endpoint.hasMetadata(response)) {\n data = response.data;\n metadata = response.metadata;\n }\n\n const output = this.endpoint.outputSchema\n ? await this.endpoint.parseOutput(data)\n : undefined;\n\n return { output, metadata, responseBuilder };\n },\n // Process declarative audits after handler (inside transaction)\n async (result, auditor) => {\n if (!audits?.length) return;\n\n for (const audit of audits) {\n if (audit.when && !audit.when(result.output as any)) {\n continue;\n }\n const payload = audit.payload(result.output as any);\n const entityId = audit.entityId?.(result.output as any);\n auditor.audit(audit.type as any, payload as any, {\n table: audit.table,\n entityId,\n });\n }\n },\n );\n\n const { output, metadata } = result;\n const body = output !== undefined ? JSON.stringify(output) : undefined;\n\n // Store response for middleware access\n (event as any).__response = output;\n\n // Build response with metadata\n const lambdaResponse: AmazonApiGatewayEndpointHandlerResponse = {\n statusCode: metadata.status ?? this.endpoint.status,\n body,\n };\n\n // Add custom headers\n if (metadata.headers && Object.keys(metadata.headers).length > 0) {\n lambdaResponse.headers = { ...metadata.headers };\n }\n\n // Format cookies as Set-Cookie headers\n if (metadata.cookies && metadata.cookies.size > 0) {\n const setCookieHeaders: string[] = [];\n for (const [name, { value, options }] of metadata.cookies) {\n setCookieHeaders.push(\n Endpoint.formatCookieHeader(name, value, options),\n );\n }\n\n if (setCookieHeaders.length > 0) {\n lambdaResponse.multiValueHeaders = {\n ...lambdaResponse.multiValueHeaders,\n 'Set-Cookie': setCookieHeaders,\n };\n }\n }\n\n return lambdaResponse;\n }\n\n get handler() {\n const handler = this._handler.bind(this);\n return middy(handler)\n .use(this.logger())\n .use(this.error())\n .use(this.services())\n .use(this.input())\n .use(this.session())\n .use(this.authorize())\n .use(this.events()) as unknown as THandler;\n }\n}\n\nexport type Event<\n TEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n TInput extends EndpointSchemas = {},\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n> = {\n services: ServiceRecord<TServices>;\n logger: TLogger;\n header: HeaderFn;\n cookie: CookieFn;\n session: TSession;\n} & TEvent &\n InferComposableStandardSchema<TInput>;\n\ntype Middleware<\n TEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n TInput extends EndpointSchemas = {},\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n> = MiddlewareObj<Event<TEvent, TInput, TServices, TLogger, TSession>>;\n\nexport type AmazonApiGatewayEndpointHandlerResponse = {\n statusCode: number;\n body: string | undefined;\n headers?: Record<string, string>;\n multiValueHeaders?: Record<string, string[]>;\n};\n\nexport type LoggerContext = {\n fn: {\n name: string;\n version: string;\n };\n req: {\n id: string | undefined;\n awsRequestId: string;\n path: string;\n ip: string | undefined;\n userAgent: string | undefined;\n };\n};\n\nexport type GetInputResponse = {\n body: any;\n query: any;\n params: any;\n};\n\nexport type AmazonApiGatewayV1EndpointHandler = (\n event: APIGatewayProxyEvent,\n context: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type AmazonApiGatewayV2EndpointHandler = (\n event: APIGatewayProxyEventV2,\n context: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type HandlerEvent<T extends Function> = T extends (\n event: infer E,\n context: Context,\n) => any\n ? E\n : never;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"AmazonApiGatewayEndpointAdaptor-CI9L7Ucn.cjs","names":["envParser: EnvironmentParser<{}>","endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >","UnprocessableEntityError","UnauthorizedError","event: Event<TEvent, TInput, TServices, TLogger, TSession>","ResponseBuilder","metadata","output","result","lambdaResponse: AmazonApiGatewayEndpointHandlerResponse","setCookieHeaders: string[]"],"sources":["../src/endpoints/AmazonApiGatewayEndpointAdaptor.ts"],"sourcesContent":["import type { AuditStorage, AuditableAction } from '@geekmidas/audit';\nimport type { Logger } from '@geekmidas/logger';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { HttpMethod } from '../types';\nimport { Endpoint, type EndpointSchemas, ResponseBuilder } from './Endpoint';\n\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport middy, { type MiddlewareObj } from '@middy/core';\nimport type {\n APIGatewayProxyEvent,\n APIGatewayProxyEventV2,\n Context,\n} from 'aws-lambda';\nimport set from 'lodash.set';\n\nimport {\n UnauthorizedError,\n UnprocessableEntityError,\n wrapError,\n} from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport {\n type Service,\n ServiceDiscovery,\n type ServiceRecord,\n} from '@geekmidas/services';\n\nimport type {\n InferComposableStandardSchema,\n InferStandardSchema,\n} from '@geekmidas/schema';\nimport { publishConstructEvents } from '../publisher';\nimport type { CookieFn, HeaderFn } from './Endpoint';\nimport type { MappedAudit } from './audit';\nimport {\n createAuditContext,\n executeWithAuditTransaction,\n} from './processAudits';\n\n// Helper function to publish events\n\nexport abstract class AmazonApiGatewayEndpoint<\n THandler extends\n | AmazonApiGatewayV1EndpointHandler\n | AmazonApiGatewayV2EndpointHandler,\n TEvent extends HandlerEvent<THandler>,\n TRoute extends string,\n TMethod extends HttpMethod,\n TInput extends EndpointSchemas = {},\n TOutSchema extends StandardSchemaV1 | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n TAuditStorage extends AuditStorage | undefined = undefined,\n TAuditStorageServiceName extends string = string,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n> {\n constructor(\n protected envParser: EnvironmentParser<{}>,\n protected readonly endpoint: Endpoint<\n TRoute,\n TMethod,\n TInput,\n TOutSchema,\n TServices,\n TLogger,\n TSession,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction\n >,\n ) {}\n\n private error(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n onError: (req) => {\n (req.event.logger || this.endpoint.logger).error(\n req.error || {},\n 'Error processing request',\n );\n const wrappedError = wrapError(req.error);\n\n // Set the response with the proper status code from the HttpError\n req.response = {\n statusCode: wrappedError.statusCode,\n body: wrappedError.body,\n };\n },\n };\n }\n abstract getInput(e: TEvent): GetInputResponse;\n\n private input(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n try {\n const { body, query, params } = this.getInput(req.event);\n const headers = req.event.headers as Record<string, string>;\n const header = Endpoint.createHeaders(headers);\n const cookie = Endpoint.createCookies(headers.cookie);\n\n set(req.event, 'body', await this.endpoint.parseInput(body, 'body'));\n\n set(\n req.event,\n 'query',\n await this.endpoint.parseInput(query, 'query'),\n );\n set(\n req.event,\n 'params',\n await this.endpoint.parseInput(params, 'params'),\n );\n set(req.event, 'header', header);\n set(req.event, 'cookie', cookie);\n } catch (error) {\n // Convert validation errors to 422 Unprocessable Entity\n if (error && typeof error === 'object' && Array.isArray(error)) {\n throw new UnprocessableEntityError('Validation failed', error);\n }\n throw error;\n }\n },\n };\n }\n\n abstract getLoggerContext(data: TEvent, context: Context): LoggerContext;\n\n private logger(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: (req) => {\n req.event.logger = this.endpoint.logger.child({\n route: this.endpoint.route,\n host: req.event.headers?.host,\n method: this.endpoint.method,\n ...this.getLoggerContext(req.event, req.context),\n }) as TLogger;\n },\n };\n }\n private services(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n const logger = req.event.logger as TLogger;\n const serviceDiscovery = ServiceDiscovery.getInstance<\n ServiceRecord<TServices>,\n TLogger\n >(logger, this.envParser);\n\n const services = await serviceDiscovery.register(\n this.endpoint.services,\n );\n\n req.event.services = services;\n },\n };\n }\n\n private authorize(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n const logger = req.event.logger as TLogger;\n const services = req.event.services;\n const header = req.event.header;\n const cookie = req.event.cookie;\n const session = req.event.session as TSession;\n\n const isAuthorized = await this.endpoint.authorize({\n header,\n cookie,\n services,\n logger,\n session,\n });\n\n if (!isAuthorized) {\n logger.warn('Unauthorized access attempt');\n throw new UnauthorizedError(\n 'Unauthorized access to the endpoint',\n 'You do not have permission to access this resource.',\n );\n }\n },\n };\n }\n\n private session(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n const logger = req.event.logger as TLogger;\n const services = req.event.services;\n req.event.session = (await this.endpoint.getSession({\n logger,\n services,\n header: req.event.header,\n cookie: req.event.cookie,\n })) as TSession;\n },\n };\n }\n\n private events(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n after: async (req) => {\n const event = req.event;\n const response = (event as any)\n .__response as InferStandardSchema<TOutSchema>;\n const statusCode = req.response?.statusCode ?? this.endpoint.status;\n\n // Only publish events on successful responses (2xx status codes)\n // Note: Audits are processed inside the handler's transaction\n if (Endpoint.isSuccessStatus(statusCode)) {\n const logger = event.logger as TLogger;\n const serviceDiscovery = ServiceDiscovery.getInstance<\n ServiceRecord<TServices>,\n TLogger\n >(logger, this.envParser);\n\n // Publish events\n await publishConstructEvents(\n this.endpoint,\n response,\n serviceDiscovery,\n logger,\n );\n }\n },\n };\n }\n\n private async _handler(\n event: Event<TEvent, TInput, TServices, TLogger, TSession>,\n ) {\n const input = this.endpoint.refineInput(event);\n const logger = event.logger as TLogger;\n const serviceDiscovery = ServiceDiscovery.getInstance<\n ServiceRecord<TServices>,\n TLogger\n >(logger, this.envParser);\n\n // Create audit context if audit storage is configured\n const auditContext = await createAuditContext(\n this.endpoint,\n serviceDiscovery,\n logger,\n {\n session: event.session,\n header: event.header,\n cookie: event.cookie,\n services: event.services as Record<string, unknown>,\n },\n );\n\n // Warn if declarative audits are configured but no audit storage\n const audits = this.endpoint.audits as MappedAudit<\n TAuditAction,\n TOutSchema\n >[];\n if (!auditContext && audits?.length) {\n logger.warn('No auditor storage service available');\n }\n\n // Resolve database service if configured\n const rawDb = this.endpoint.databaseService\n ? await serviceDiscovery\n .register([this.endpoint.databaseService])\n .then(\n (s) =>\n s[this.endpoint.databaseService!.serviceName as keyof typeof s],\n )\n : undefined;\n\n // Execute handler with automatic audit transaction support\n const result = await executeWithAuditTransaction(\n auditContext,\n async (auditor) => {\n // Use audit transaction as db only if the storage uses the same database service\n const sameDatabase =\n auditContext?.storage?.databaseServiceName &&\n auditContext.storage.databaseServiceName ===\n this.endpoint.databaseService?.serviceName;\n const db = sameDatabase\n ? (auditor?.getTransaction?.() ?? rawDb)\n : rawDb;\n\n const responseBuilder = new ResponseBuilder();\n const response = await this.endpoint.handler(\n {\n header: event.header,\n cookie: event.cookie,\n logger: event.logger,\n services: event.services,\n session: event.session,\n auditor,\n db,\n ...input,\n } as any,\n responseBuilder,\n );\n\n // Check if response has metadata\n let data = response;\n let metadata = responseBuilder.getMetadata();\n\n if (Endpoint.hasMetadata(response)) {\n data = response.data;\n metadata = response.metadata;\n }\n\n const output = this.endpoint.outputSchema\n ? await this.endpoint.parseOutput(data)\n : undefined;\n\n return { output, metadata, responseBuilder };\n },\n // Process declarative audits after handler (inside transaction)\n async (result, auditor) => {\n if (!audits?.length) return;\n\n for (const audit of audits) {\n if (audit.when && !audit.when(result.output as any)) {\n continue;\n }\n const payload = audit.payload(result.output as any);\n const entityId = audit.entityId?.(result.output as any);\n auditor.audit(audit.type as any, payload as any, {\n table: audit.table,\n entityId,\n });\n }\n },\n );\n\n const { output, metadata } = result;\n const body = output !== undefined ? JSON.stringify(output) : undefined;\n\n // Store response for middleware access\n (event as any).__response = output;\n\n // Build response with metadata\n const lambdaResponse: AmazonApiGatewayEndpointHandlerResponse = {\n statusCode: metadata.status ?? this.endpoint.status,\n body,\n };\n\n // Add custom headers\n if (metadata.headers && Object.keys(metadata.headers).length > 0) {\n lambdaResponse.headers = { ...metadata.headers };\n }\n\n // Format cookies as Set-Cookie headers\n if (metadata.cookies && metadata.cookies.size > 0) {\n const setCookieHeaders: string[] = [];\n for (const [name, { value, options }] of metadata.cookies) {\n setCookieHeaders.push(\n Endpoint.formatCookieHeader(name, value, options),\n );\n }\n\n if (setCookieHeaders.length > 0) {\n lambdaResponse.multiValueHeaders = {\n ...lambdaResponse.multiValueHeaders,\n 'Set-Cookie': setCookieHeaders,\n };\n }\n }\n\n return lambdaResponse;\n }\n\n get handler() {\n const handler = this._handler.bind(this);\n return middy(handler)\n .use(this.logger())\n .use(this.error())\n .use(this.services())\n .use(this.input())\n .use(this.session())\n .use(this.authorize())\n .use(this.events()) as unknown as THandler;\n }\n}\n\nexport type Event<\n TEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n TInput extends EndpointSchemas = {},\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n> = {\n services: ServiceRecord<TServices>;\n logger: TLogger;\n header: HeaderFn;\n cookie: CookieFn;\n session: TSession;\n} & TEvent &\n InferComposableStandardSchema<TInput>;\n\ntype Middleware<\n TEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n TInput extends EndpointSchemas = {},\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n> = MiddlewareObj<Event<TEvent, TInput, TServices, TLogger, TSession>>;\n\nexport type AmazonApiGatewayEndpointHandlerResponse = {\n statusCode: number;\n body: string | undefined;\n headers?: Record<string, string>;\n multiValueHeaders?: Record<string, string[]>;\n};\n\nexport type LoggerContext = {\n fn: {\n name: string;\n version: string;\n };\n req: {\n id: string | undefined;\n awsRequestId: string;\n path: string;\n ip: string | undefined;\n userAgent: string | undefined;\n };\n};\n\nexport type GetInputResponse = {\n body: any;\n query: any;\n params: any;\n};\n\nexport type AmazonApiGatewayV1EndpointHandler = (\n event: APIGatewayProxyEvent,\n context: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type AmazonApiGatewayV2EndpointHandler = (\n event: APIGatewayProxyEventV2,\n context: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type HandlerEvent<T extends Function> = T extends (\n event: infer E,\n context: Context,\n) => any\n ? E\n : never;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Endpoint-DDpF7NO1.cjs","names":["Function","endpoints: Endpoint<any, any, any, any, any, any>[]","options?: OpenApiSchemaOptions","input: unknown","key: K","body: unknown","status: number","headers: Record<string, string>","key?: string","cookieHeader: string | undefined","name?: string","name: string","value: string","options?: CookieOptions","ctx: EndpointContext<TInput, TServices, TLogger, TSession>","ctx: EndpointContext<\n TInput,\n TServices,\n TLogger,\n TSession,\n TAuditAction,\n TDatabase,\n TAuditStorage\n >","response: ResponseBuilder","obj: any","ConstructType","response: T | ResponseWithMetadata<T>","componentCollector?: ComponentCollector","operation: OpenAPIV3_1.OperationObject","pathParameters: OpenAPIV3_1.ParameterObject[]","queryParameters: OpenAPIV3_1.ParameterObject[]","routeObject: any","key: string","options?: Pick<CookieOptions, 'domain' | 'path'>","code: SuccessStatus","data: T"],"sources":["../src/endpoints/Endpoint.ts"],"sourcesContent":["import type { AuditStorage, AuditableAction, Auditor } from '@geekmidas/audit';\nimport type {\n EventPublisher,\n ExtractPublisherMessage,\n MappedEvent,\n} from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { RateLimitConfig } from '@geekmidas/rate-limit';\nimport type {\n InferComposableStandardSchema,\n InferStandardSchema,\n} from '@geekmidas/schema';\nimport {\n convertSchemaWithComponents,\n convertStandardSchemaToJsonSchema,\n} from '@geekmidas/schema/conversion';\nimport {\n type ComponentCollector,\n type OpenApiSchemaOptions,\n buildOpenApiSchema,\n} from '@geekmidas/schema/openapi';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport pick from 'lodash.pick';\nimport set from 'lodash.set';\nimport type { OpenAPIV3_1 } from 'openapi-types';\nimport { ConstructType } from '../Construct';\nimport { Function, type FunctionHandler } from '../functions';\nimport type { HttpMethod, LowerHttpMethod, RemoveUndefined } from '../types';\nimport type { Authorizer } from './Authorizer';\nimport type { ActorExtractor, MappedAudit } from './audit';\n\n/**\n * Represents an HTTP endpoint that can handle requests with type-safe input/output validation,\n * dependency injection, session management, and authorization.\n *\n * @template TRoute - The route path string with parameter placeholders (e.g., '/users/:id')\n * @template TMethod - The HTTP method (GET, POST, PUT, DELETE, PATCH)\n * @template TInput - The input schema definition for body, query, and path parameters\n * @template OutSchema - The output schema for response validation\n * @template TServices - Array of service dependencies to inject\n * @template TLogger - The logger instance type\n * @template TSession - The session data type\n *\n * @extends Function - Base function construct for handler execution\n *\n * @example\n * ```typescript\n * const endpoint = new Endpoint({\n * route: '/users/:id',\n * method: 'GET',\n * input: { params: userIdSchema },\n * output: userSchema,\n * fn: async ({ params }) => getUserById(params.id)\n * });\n * ```\n */\nexport class Endpoint<\n TRoute extends string,\n TMethod extends HttpMethod,\n TInput extends EndpointSchemas = {},\n OutSchema extends StandardSchemaV1 | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n TAuditStorage extends AuditStorage | undefined = undefined,\n TAuditStorageServiceName extends string = string,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n TDatabase = undefined,\n TDatabaseServiceName extends string = string,\n> extends Function<\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TDatabase,\n TDatabaseServiceName,\n TAuditAction,\n FunctionHandler<\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TDatabase,\n TAuditStorage,\n TAuditAction\n >\n> {\n operationId?: string;\n /** The route path pattern with parameter placeholders */\n route: TRoute;\n /** The HTTP method for this endpoint */\n method: TMethod;\n /** Optional description for OpenAPI documentation */\n description?: string;\n /** Optional tags for OpenAPI documentation */\n tags?: string[];\n /** The HTTP success status code to return (default: 200) */\n public readonly status: SuccessStatus;\n /** Default headers to apply to all responses */\n public readonly defaultHeaders: Record<string, string> = {};\n /** Function to extract session data from the request context */\n public getSession: SessionFn<TServices, TLogger, TSession> = () =>\n ({}) as TSession;\n /** Function to determine if the request is authorized */\n public authorize: AuthorizeFn<TServices, TLogger, TSession> = () => true;\n /** Optional rate limiting configuration */\n public rateLimit?: RateLimitConfig;\n /** Optional authorizer for this endpoint */\n public authorizer?: Authorizer;\n /** Optional actor extractor for audit records */\n public actorExtractor?: ActorExtractor<TServices, TSession, TLogger>;\n /** Declarative audit definitions */\n public audits: MappedAudit<TAuditAction, OutSchema>[] = [];\n /** Database service for this endpoint */\n public databaseService?: Service<TDatabaseServiceName, TDatabase>;\n /** The endpoint handler function */\n private endpointFn!: EndpointHandler<\n TInput,\n TServices,\n TLogger,\n OutSchema,\n TSession,\n TDatabase,\n TAuditStorage,\n TAuditAction\n >;\n\n /**\n * Builds a complete OpenAPI 3.1 schema from an array of endpoints.\n *\n * @param endpoints - Array of endpoint instances to document\n * @param options - Optional configuration for OpenAPI generation\n * @returns OpenAPI 3.1 specification object\n *\n * @example\n * ```typescript\n * const schema = await Endpoint.buildOpenApiSchema([\n * getUserEndpoint,\n * createUserEndpoint\n * ], {\n * title: 'User API',\n * version: '1.0.0'\n * });\n * ```\n */\n static async buildOpenApiSchema(\n endpoints: Endpoint<any, any, any, any, any, any>[],\n options?: OpenApiSchemaOptions,\n ) {\n return buildOpenApiSchema(endpoints, options);\n }\n\n /**\n * Gets the full path including HTTP method and route.\n * @returns Formatted string like 'GET /users/{id}'\n */\n get fullPath() {\n return `${this.method} ${this._path}` as const;\n }\n\n /**\n * Parses and validates input data for a specific input type (body, query, params).\n *\n * @param input - The raw input data to validate\n * @param key - The input type key ('body', 'query', or 'params')\n * @returns The validated input data for the specified key\n * @throws {UnprocessableEntityError} When validation fails\n */\n async parseInput<K extends keyof TInput>(\n input: unknown,\n key: K,\n ): Promise<InferComposableStandardSchema<TInput[K]>> {\n const schema = this.input?.[key];\n return Endpoint.parseSchema(schema as StandardSchemaV1, input) as Promise<\n InferComposableStandardSchema<TInput[K]>\n >;\n }\n\n /**\n * Parses and validates the request body against the body schema.\n *\n * @param body - The raw request body to validate\n * @returns The validated body data\n * @throws {UnprocessableEntityError} When body validation fails\n */\n async parseBody(body: unknown): Promise<InferStandardSchema<TInput['body']>> {\n return this.parseInput(body, 'body') as Promise<\n InferStandardSchema<TInput['body']>\n >;\n }\n\n static isSuccessStatus(status: number): boolean {\n return status >= 200 && status < 300;\n }\n\n /**\n * Creates a case-insensitive header lookup function from a headers object.\n *\n * @param headers - Object containing header key-value pairs\n * @returns Function to retrieve header values by case-insensitive key, or all headers\n *\n * @example\n * ```typescript\n * const headerFn = Endpoint.createHeaders({ 'Content-Type': 'application/json' });\n * headerFn('content-type'); // Returns 'application/json'\n * headerFn(); // Returns { 'content-type': 'application/json' }\n * ```\n */\n static createHeaders(headers: Record<string, string>): HeaderFn {\n const headerMap = new Map<string, string>();\n for (const [k, v] of Object.entries(headers)) {\n const key = k.toLowerCase();\n headerMap.set(key, v);\n }\n\n function get(): Record<string, string>;\n function get(key: string): string | undefined;\n function get(key?: string): string | undefined | Record<string, string> {\n if (key === undefined) {\n // Return all headers as plain object\n return Object.fromEntries(headerMap.entries());\n }\n return headerMap.get(key.toLowerCase());\n }\n\n return get;\n }\n\n /**\n * Parses cookie string and creates a cookie lookup function.\n *\n * @param cookieHeader - The Cookie header value\n * @returns Function to retrieve cookie values by name, or all cookies\n *\n * @example\n * ```typescript\n * const cookieFn = Endpoint.createCookies('session=abc123; theme=dark');\n * cookieFn('session'); // Returns 'abc123'\n * cookieFn(); // Returns { session: 'abc123', theme: 'dark' }\n * ```\n */\n static createCookies(cookieHeader: string | undefined): CookieFn {\n const cookieMap = new Map<string, string>();\n\n if (cookieHeader) {\n // Parse cookie string: \"name1=value1; name2=value2\"\n const cookies = cookieHeader.split(';');\n for (const cookie of cookies) {\n const [name, ...valueParts] = cookie.trim().split('=');\n if (name) {\n const value = valueParts.join('='); // Handle values with = in them\n cookieMap.set(name, decodeURIComponent(value));\n }\n }\n }\n\n function get(): Record<string, string>;\n function get(name: string): string | undefined;\n function get(name?: string): string | undefined | Record<string, string> {\n if (name === undefined) {\n // Return all cookies as plain object\n return Object.fromEntries(cookieMap.entries());\n }\n return cookieMap.get(name);\n }\n\n return get;\n }\n\n /**\n * Formats a cookie as a Set-Cookie header string.\n *\n * @param name - Cookie name\n * @param value - Cookie value\n * @param options - Cookie options (httpOnly, secure, sameSite, etc.)\n * @returns Formatted Set-Cookie header string\n *\n * @example\n * ```typescript\n * const header = Endpoint.formatCookieHeader('session', 'abc123', {\n * httpOnly: true,\n * secure: true,\n * sameSite: 'strict',\n * maxAge: 3600\n * });\n * // Returns: \"session=abc123; Max-Age=3600; HttpOnly; Secure; SameSite=Strict\"\n * ```\n */\n static formatCookieHeader(\n name: string,\n value: string,\n options?: CookieOptions,\n ): string {\n let cookie = `${name}=${value}`;\n\n if (options) {\n if (options.domain) cookie += `; Domain=${options.domain}`;\n if (options.path) cookie += `; Path=${options.path}`;\n if (options.expires)\n cookie += `; Expires=${options.expires.toUTCString()}`;\n if (options.maxAge !== undefined) cookie += `; Max-Age=${options.maxAge}`;\n if (options.httpOnly) cookie += '; HttpOnly';\n if (options.secure) cookie += '; Secure';\n if (options.sameSite) {\n cookie += `; SameSite=${options.sameSite.charAt(0).toUpperCase() + options.sameSite.slice(1)}`;\n }\n }\n\n return cookie;\n }\n\n /**\n * Extracts and refines input data from the endpoint context.\n *\n * @param ctx - The endpoint execution context\n * @returns Object containing only the input data (body, query, params)\n * @internal\n */\n refineInput(\n ctx: EndpointContext<TInput, TServices, TLogger, TSession>,\n ): InferComposableStandardSchema<TInput> {\n const input = pick(ctx, [\n 'body',\n 'query',\n 'params',\n ]) as InferComposableStandardSchema<TInput>;\n\n return input;\n }\n\n handler = (\n ctx: EndpointContext<\n TInput,\n TServices,\n TLogger,\n TSession,\n TAuditAction,\n TDatabase,\n TAuditStorage\n >,\n response: ResponseBuilder,\n ): OutSchema extends StandardSchemaV1\n ?\n | InferStandardSchema<OutSchema>\n | ResponseWithMetadata<InferStandardSchema<OutSchema>>\n | Promise<InferStandardSchema<OutSchema>>\n | Promise<ResponseWithMetadata<InferStandardSchema<OutSchema>>>\n :\n | any\n | ResponseWithMetadata<any>\n | Promise<any>\n | Promise<ResponseWithMetadata<any>> => {\n // Apply default headers to response builder\n for (const [key, value] of Object.entries(this.defaultHeaders)) {\n response.header(key, value);\n }\n\n // Build context object, conditionally including auditor and db\n const handlerCtx = {\n ...this.refineInput(ctx),\n services: ctx.services,\n logger: ctx.logger,\n header: ctx.header,\n cookie: ctx.cookie,\n session: ctx.session,\n // These are conditionally present based on configuration\n ...('auditor' in ctx && { auditor: ctx.auditor }),\n ...('db' in ctx && { db: ctx.db }),\n } as EndpointContext<\n TInput,\n TServices,\n TLogger,\n TSession,\n TAuditAction,\n TDatabase,\n TAuditStorage\n >;\n\n return this.endpointFn(handlerCtx, response);\n };\n\n /**\n * Type guard to check if an object is an Endpoint instance.\n *\n * @param obj - The object to check\n * @returns True if the object is an Endpoint\n */\n static isEndpoint(obj: any): obj is Endpoint<any, any, any, any> {\n return Boolean(\n obj &&\n (obj as Function).__IS_FUNCTION__ === true &&\n obj.type === ConstructType.Endpoint,\n );\n }\n\n /**\n * Helper to check if response has metadata\n */\n static hasMetadata<T>(\n response: T | ResponseWithMetadata<T>,\n ): response is ResponseWithMetadata<T> {\n return (\n response !== null &&\n typeof response === 'object' &&\n 'data' in response &&\n 'metadata' in response\n );\n }\n\n /**\n * Converts Express-style route params to OpenAPI format.\n * @returns Route with ':param' converted to '{param}'\n * @internal\n */\n get _path() {\n return this.route.replace(/:(\\w+)/g, '{$1}') as ConvertRouteParams<TRoute>;\n }\n\n /**\n * Generates OpenAPI 3.1 schema for this endpoint.\n *\n * @returns OpenAPI route definition with operation details\n */\n async toOpenApi3Route(\n componentCollector?: ComponentCollector,\n ): Promise<EndpointOpenApiSchema<TRoute, TMethod>> {\n const operation: OpenAPIV3_1.OperationObject = {\n operationId: this.operationId,\n ...(this.description && { description: this.description }),\n ...(this.tags && this.tags.length > 0 && { tags: this.tags }),\n responses: {\n '200': {\n description: 'Successful response',\n } as OpenAPIV3_1.ResponseObject,\n },\n };\n\n // Add response schema\n if (this.outputSchema) {\n const responseSchema = await convertSchemaWithComponents(\n this.outputSchema,\n componentCollector,\n );\n if (responseSchema) {\n set(\n operation,\n ['responses', '200', 'content', 'application/json', 'schema'],\n responseSchema,\n );\n }\n }\n\n // Separate path and query parameters\n const pathParameters: OpenAPIV3_1.ParameterObject[] = [];\n const queryParameters: OpenAPIV3_1.ParameterObject[] = [];\n\n // Since the EndpointBuilder doesn't have body/search/params methods yet,\n // and the input is a composite type, we need to check if input exists\n // and has the expected shape\n if (this.input && typeof this.input === 'object') {\n // Add request body for methods that support it\n if (\n ['POST', 'PUT', 'PATCH'].includes(this.method) &&\n 'body' in this.input &&\n this.input.body\n ) {\n const bodySchema = await convertSchemaWithComponents(\n this.input.body as StandardSchemaV1,\n componentCollector,\n );\n if (bodySchema) {\n set(operation, ['requestBody'], {\n required: true,\n content: {\n 'application/json': {\n schema: bodySchema,\n },\n },\n });\n }\n }\n\n // Add path parameters\n if ('params' in this.input && this.input.params) {\n const paramsSchema = await convertStandardSchemaToJsonSchema(\n this.input.params as StandardSchemaV1,\n );\n if (\n paramsSchema &&\n paramsSchema.type === 'object' &&\n paramsSchema.properties\n ) {\n for (const [name, schema] of Object.entries(\n paramsSchema.properties,\n )) {\n pathParameters.push({\n name,\n in: 'path',\n required: paramsSchema.required?.includes(name) ?? true,\n schema: schema as any,\n });\n }\n }\n }\n\n // Add query parameters\n if ('query' in this.input && this.input.query) {\n const querySchema = await convertStandardSchemaToJsonSchema(\n this.input.query,\n );\n if (\n querySchema &&\n querySchema.type === 'object' &&\n querySchema.properties\n ) {\n for (const [name, schema] of Object.entries(querySchema.properties)) {\n queryParameters.push({\n name,\n in: 'query',\n required: querySchema.required?.includes(name) ?? false,\n schema: schema as any,\n });\n }\n }\n }\n }\n\n // Only add query parameters to the operation\n if (queryParameters.length > 0) {\n operation.parameters = queryParameters;\n }\n\n // Build the route object with path parameters at the route level\n const routeObject: any = {};\n if (pathParameters.length > 0) {\n routeObject.parameters = pathParameters;\n }\n routeObject[this.method.toLowerCase()] = operation;\n\n return {\n [this._path]: routeObject,\n } as EndpointOpenApiSchema<TRoute, TMethod>;\n }\n\n /**\n * Creates a new Endpoint instance.\n *\n * @param options - Configuration options for the endpoint\n * @param options.fn - The handler function to execute\n * @param options.method - HTTP method\n * @param options.route - Route path with parameter placeholders\n * @param options.description - Optional description for documentation\n * @param options.input - Input schemas for validation\n * @param options.logger - Logger instance\n * @param options.output - Output schema for response validation\n * @param options.services - Service dependencies\n * @param options.timeout - Execution timeout in milliseconds\n * @param options.getSession - Session extraction function\n * @param options.authorize - Authorization check function\n * @param options.status - Success HTTP status code (default: 200)\n * @param options.authorizer - Optional authorizer configuration\n */\n constructor({\n fn,\n method,\n route,\n description,\n tags,\n input,\n logger,\n output: outputSchema,\n services,\n timeout,\n memorySize,\n getSession,\n authorize,\n rateLimit,\n status = SuccessStatus.OK,\n publisherService,\n events,\n authorizer,\n auditorStorageService,\n actorExtractor,\n audits,\n databaseService,\n }: EndpointOptions<\n TRoute,\n TMethod,\n TInput,\n OutSchema,\n TServices,\n TLogger,\n TSession,\n OutSchema,\n TEventPublisher,\n TEventPublisherServiceName,\n TAuditStorage,\n TAuditStorageServiceName,\n TAuditAction,\n TDatabase,\n TDatabaseServiceName\n >) {\n super(\n fn as unknown as FunctionHandler<TInput, TServices, TLogger, OutSchema>,\n timeout,\n ConstructType.Endpoint,\n input,\n outputSchema,\n services,\n logger,\n publisherService,\n events,\n memorySize,\n auditorStorageService,\n );\n\n this.route = route;\n this.method = method;\n this.description = description;\n this.tags = tags;\n this.status = status;\n this.endpointFn = fn;\n\n if (getSession) {\n this.getSession = getSession;\n }\n\n if (authorize) {\n this.authorize = authorize;\n }\n\n if (rateLimit) {\n this.rateLimit = rateLimit;\n }\n\n if (authorizer) {\n this.authorizer = authorizer;\n }\n\n if (actorExtractor) {\n this.actorExtractor = actorExtractor;\n }\n\n if (audits) {\n this.audits = audits;\n }\n\n if (databaseService) {\n this.databaseService = databaseService;\n }\n }\n}\n\n/**\n * Defines the input schema structure for an endpoint.\n *\n * @template TBody - Schema for request body validation\n * @template TSearch - Schema for query string validation\n * @template TParams - Schema for URL path parameters validation\n *\n * @example\n * ```typescript\n * type UserInput = EndpointInput<\n * typeof createUserBodySchema,\n * typeof userQuerySchema,\n * typeof userParamsSchema\n * >;\n * ```\n */\nexport type EndpointInput<\n TBody extends StandardSchemaV1 | undefined = undefined,\n TSearch extends StandardSchemaV1 | undefined = undefined,\n TParams extends StandardSchemaV1 | undefined = undefined,\n> = RemoveUndefined<{\n body: TBody;\n search: TSearch;\n params: TParams;\n}>;\n\n/**\n * Configuration options for creating an Endpoint instance.\n *\n * @template TRoute - The route path string\n * @template TMethod - The HTTP method\n * @template TInput - Input schema definitions\n * @template TOutput - Output schema definition\n * @template TServices - Service dependencies array\n * @template TLogger - Logger type\n * @template TSession - Session data type\n */\nexport interface EndpointOptions<\n TRoute extends string,\n TMethod extends HttpMethod,\n TInput extends EndpointSchemas = {},\n TOutput extends StandardSchemaV1 | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n OutSchema extends StandardSchemaV1 | undefined = undefined,\n TEventPublisher extends EventPublisher<any> | undefined = undefined,\n TEventPublisherServiceName extends string = string,\n TAuditStorage extends AuditStorage | undefined = undefined,\n TAuditStorageServiceName extends string = string,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n TDatabase = undefined,\n TDatabaseServiceName extends string = string,\n> {\n /** The route path with parameter placeholders */\n route: TRoute;\n /** The HTTP method for this endpoint */\n method: TMethod;\n /** The handler function that implements the endpoint logic */\n fn: EndpointHandler<\n TInput,\n TServices,\n TLogger,\n TOutput,\n TSession,\n TDatabase,\n TAuditStorage,\n TAuditAction\n >;\n /** Optional authorization check function */\n authorize: AuthorizeFn<TServices, TLogger, TSession> | undefined;\n /** Optional description for documentation */\n description: string | undefined;\n /** Optional tags for OpenAPI documentation */\n tags?: string[];\n /** Optional execution timeout in milliseconds */\n timeout: number | undefined;\n /** Optional memory size in MB for serverless deployments */\n memorySize: number | undefined;\n /** Input validation schemas */\n input: TInput | undefined;\n /** Output validation schema */\n output: TOutput | undefined;\n /** Service dependencies to inject */\n services: TServices;\n /** Logger instance */\n logger: TLogger;\n /** Optional session extraction function */\n getSession: SessionFn<TServices, TLogger, TSession> | undefined;\n /** Optional rate limiting configuration */\n rateLimit?: RateLimitConfig;\n /** Success HTTP status code */\n status: SuccessStatus | undefined;\n /**\n * Event publisher service for publishing events from this endpoint\n */\n publisherService?: Service<TEventPublisherServiceName, TEventPublisher>;\n\n events?: MappedEvent<TEventPublisher, OutSchema>[];\n /** Optional authorizer configuration */\n authorizer?: Authorizer;\n /**\n * Auditor storage service for persisting audit records from this endpoint\n */\n auditorStorageService?: Service<TAuditStorageServiceName, TAuditStorage>;\n /** Optional actor extractor function for audit records */\n actorExtractor?: ActorExtractor<TServices, TSession, TLogger>;\n /** Declarative audit definitions */\n audits?: MappedAudit<TAuditAction, OutSchema>[];\n /** Database service for this endpoint */\n databaseService?: Service<TDatabaseServiceName, TDatabase>;\n}\n\n/**\n * Defines the possible input schema types for an endpoint.\n * Each property represents a different part of the HTTP request.\n */\nexport type EndpointSchemas = Partial<{\n /** Schema for URL path parameters (e.g., /users/:id) */\n params: StandardSchemaV1;\n /** Schema for query string parameters */\n query: StandardSchemaV1;\n /** Schema for request body (POST, PUT, PATCH) */\n body: StandardSchemaV1;\n}>;\n\nexport type AuthorizeContext<\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n> = {\n services: ServiceRecord<TServices>;\n logger: TLogger;\n header: HeaderFn;\n cookie: CookieFn;\n session: TSession;\n};\n/**\n * Function type for endpoint authorization checks.\n *\n * @template TServices - Available service dependencies\n * @template TLogger - Logger type\n * @template TSession - Session data type\n *\n * @param ctx - Context containing services, logger, headers, and session\n * @returns Boolean indicating if the request is authorized\n *\n * @example\n * ```typescript\n * const authorize: AuthorizeFn = ({ session }) => {\n * return session.userId !== undefined;\n * };\n * ```\n */\nexport type AuthorizeFn<\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n> = (\n ctx: AuthorizeContext<TServices, TLogger, TSession>,\n) => Promise<boolean> | boolean;\n\nexport type SessionContext<\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n> = {\n services: ServiceRecord<TServices>;\n logger: TLogger;\n header: HeaderFn;\n cookie: CookieFn;\n};\n/**\n * Function type for extracting session data from a request.\n *\n * @template TServices - Available service dependencies\n * @template TLogger - Logger type\n * @template TSession - Session data type to extract\n *\n * @param ctx - Context containing services, logger, and headers\n * @returns The extracted session data\n *\n * @example\n * ```typescript\n * const getSession: SessionFn<Services, Logger, UserSession> = async ({ header, services }) => {\n * const token = header('authorization');\n * return await services.auth.verifyToken(token);\n * };\n * ```\n */\nexport type SessionFn<\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n> = (ctx: SessionContext<TServices, TLogger>) => Promise<TSession> | TSession;\n\n/**\n * Utility type that converts Express-style route parameters to OpenAPI format.\n * Transforms ':param' syntax to '{param}' syntax.\n *\n * @template T - The route string to convert\n *\n * @example\n * ```typescript\n * type Route1 = ConvertRouteParams<'/users/:id'>; // '/users/{id}'\n * type Route2 = ConvertRouteParams<'/users/:userId/posts/:postId'>; // '/users/{userId}/posts/{postId}'\n * ```\n */\nexport type ConvertRouteParams<T extends string> =\n T extends `${infer Start}:${infer Param}/${infer Rest}`\n ? `${Start}{${Param}}/${ConvertRouteParams<Rest>}`\n : T extends `${infer Start}:${infer Param}`\n ? `${Start}{${Param}}`\n : T;\n\n/**\n * Type representing the OpenAPI schema structure for an endpoint.\n *\n * @template TRoute - The route path\n * @template TMethod - The HTTP method\n *\n * @example\n * ```typescript\n * type Schema = EndpointOpenApiSchema<'/users/:id', 'GET'>;\n * // Results in: { '/users/{id}': { get: OperationObject, parameters?: ParameterObject[] } }\n * ```\n */\nexport type EndpointOpenApiSchema<\n TRoute extends string,\n TMethod extends HttpMethod,\n> = {\n [key in ConvertRouteParams<TRoute>]: {\n [key in LowerHttpMethod<TMethod>]: OpenAPIV3_1.OperationObject<{}>;\n } & {\n parameters?: OpenAPIV3_1.ParameterObject[];\n };\n};\n\nexport type SingleHeaderFn = (key: string) => string | undefined;\nexport type MultiHeaderFn = () => EndpointHeaders;\n/**\n * Type representing HTTP headers as a Map.\n */\nexport type EndpointHeaders = Map<string, string>;\n\n/**\n * Function type for retrieving HTTP header values.\n * Supports two calling patterns:\n * - `header(key)` - Get a single header value (case-insensitive)\n * - `header()` - Get all headers as a plain object\n *\n * @example\n * ```typescript\n * // Get single header\n * const contentType = header('content-type');\n *\n * // Get all headers\n * const allHeaders = header();\n * // { 'content-type': 'application/json', 'host': 'example.com', ... }\n * ```\n */\nexport interface HeaderFn {\n (): Record<string, string>;\n (key: string): string | undefined;\n}\n\n/**\n * Function type for retrieving cookie values.\n * Supports two calling patterns:\n * - `cookie(name)` - Get a single cookie value\n * - `cookie()` - Get all cookies as a plain object\n *\n * @example\n * ```typescript\n * // Get single cookie\n * const sessionId = cookie('session');\n *\n * // Get all cookies\n * const allCookies = cookie();\n * // { session: 'abc123', theme: 'dark', ... }\n * ```\n */\nexport interface CookieFn {\n (): Record<string, string>;\n (name: string): string | undefined;\n}\n\n/**\n * Cookie options matching standard Set-Cookie attributes\n */\nexport interface CookieOptions {\n domain?: string;\n path?: string;\n expires?: Date;\n maxAge?: number;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: 'strict' | 'lax' | 'none';\n}\n\n/**\n * Response metadata that handlers can set\n */\nexport interface ResponseMetadata {\n headers?: Record<string, string>;\n cookies?: Map<string, { value: string; options?: CookieOptions }>;\n status?: SuccessStatus;\n}\n\n/**\n * Return type for handlers that want to set response metadata\n */\nexport interface ResponseWithMetadata<T> {\n data: T;\n metadata: ResponseMetadata;\n}\n\n/**\n * Response builder for fluent API in handlers\n */\nexport class ResponseBuilder {\n private metadata: ResponseMetadata = {\n headers: {},\n cookies: new Map(),\n };\n\n header(key: string, value: string): this {\n this.metadata.headers![key] = value;\n return this;\n }\n\n cookie(name: string, value: string, options?: CookieOptions): this {\n this.metadata.cookies!.set(name, { value, options });\n return this;\n }\n\n deleteCookie(\n name: string,\n options?: Pick<CookieOptions, 'domain' | 'path'>,\n ): this {\n this.metadata.cookies!.set(name, {\n value: '',\n options: { ...options, maxAge: 0, expires: new Date(0) },\n });\n return this;\n }\n\n status(code: SuccessStatus): this {\n this.metadata.status = code;\n return this;\n }\n\n send<T>(data: T): ResponseWithMetadata<T> {\n return { data, metadata: this.metadata };\n }\n\n getMetadata(): ResponseMetadata {\n return this.metadata;\n }\n}\n\n/**\n * Base context properties that are always available\n */\ntype BaseEndpointContext<\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n> = {\n /** Injected service instances */\n services: ServiceRecord<TServices>;\n /** Logger instance for this request */\n logger: TLogger;\n /** Function to retrieve request headers */\n header: HeaderFn;\n /** Function to retrieve request cookies */\n cookie: CookieFn;\n /** Session data extracted by getSession */\n session: TSession;\n};\n\n/**\n * Conditional auditor context - only present when audit storage is configured\n */\ntype AuditorContext<\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n TAuditStorage = undefined,\n> = TAuditStorage extends undefined\n ? {}\n : {\n /**\n * Auditor instance for recording audit events.\n * Only present when audit storage is configured on the endpoint.\n * When a transactional database is used for audit storage,\n * the auditor is pre-configured with the transaction context.\n */\n auditor: Auditor<TAuditAction>;\n };\n\n/**\n * Conditional database context - only present when database service is configured\n */\ntype DatabaseContext<TDatabase = undefined> = TDatabase extends undefined\n ? {}\n : {\n /**\n * Database instance for this request.\n * When audit storage is configured and uses the same database,\n * this will be the transaction for ACID compliance.\n * Otherwise, it's the raw database connection.\n */\n db: TDatabase;\n };\n\n/**\n * The execution context provided to endpoint handlers.\n * Contains all parsed input data, services, logger, headers, cookies, and session.\n *\n * @template Input - The input schemas (body, query, params)\n * @template TServices - Available service dependencies\n * @template TLogger - Logger type\n * @template TSession - Session data type\n * @template TAuditAction - Audit action types (when auditor is configured)\n * @template TDatabase - Database type (when database service is configured)\n * @template TAuditStorage - Audit storage type (determines if auditor is present)\n */\nexport type EndpointContext<\n Input extends EndpointSchemas | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n TSession = unknown,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n TDatabase = undefined,\n TAuditStorage = undefined,\n> = BaseEndpointContext<TServices, TLogger, TSession> &\n InferComposableStandardSchema<Input> &\n AuditorContext<TAuditAction, TAuditStorage> &\n DatabaseContext<TDatabase>;\n\n/**\n * Handler function type for endpoint implementations.\n *\n * @template TInput - Input schemas for validation\n * @template TServices - Available service dependencies\n * @template TLogger - Logger type\n * @template OutSchema - Output schema for response validation\n * @template TSession - Session data type\n *\n * @param ctx - The endpoint execution context\n * @param response - Response builder for setting cookies, headers, and status\n * @returns The response data (validated if OutSchema is provided) or ResponseWithMetadata\n *\n * @example\n * ```typescript\n * // Simple response\n * const handler: EndpointHandler<Input, [UserService], Logger, UserSchema> =\n * async ({ params, services }) => {\n * return await services.users.findById(params.id);\n * };\n *\n * // With response builder\n * const handler: EndpointHandler<Input, [UserService], Logger, UserSchema> =\n * async ({ params, services }, response) => {\n * const user = await services.users.findById(params.id);\n * return response.header('X-User-Id', user.id).send(user);\n * };\n * ```\n */\nexport type EndpointHandler<\n TInput extends EndpointSchemas | undefined = undefined,\n TServices extends Service[] = [],\n TLogger extends Logger = Logger,\n OutSchema extends StandardSchemaV1 | undefined = undefined,\n TSession = unknown,\n TDatabase = undefined,\n TAuditStorage = undefined,\n TAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n string,\n unknown\n >,\n> = (\n ctx: EndpointContext<\n TInput,\n TServices,\n TLogger,\n TSession,\n TAuditAction,\n TDatabase,\n TAuditStorage\n >,\n response: ResponseBuilder,\n) => OutSchema extends StandardSchemaV1\n ?\n | InferStandardSchema<OutSchema>\n | ResponseWithMetadata<InferStandardSchema<OutSchema>>\n | Promise<InferStandardSchema<OutSchema>>\n | Promise<ResponseWithMetadata<InferStandardSchema<OutSchema>>>\n :\n | unknown\n | ResponseWithMetadata<unknown>\n | Promise<unknown>\n | Promise<ResponseWithMetadata<unknown>>;\n\n/**\n * HTTP success status codes that can be returned by endpoints.\n */\nexport enum SuccessStatus {\n /** Standard response for successful HTTP requests */\n OK = 200,\n /** Request has been fulfilled and resulted in a new resource being created */\n Created = 201,\n /** Request has been accepted for processing, but processing is not complete */\n Accepted = 202,\n /** Server successfully processed the request but is not returning any content */\n NoContent = 204,\n /** Server successfully processed the request and is not returning any content, client should reset the document view */\n ResetContent = 205,\n /** Server is delivering only part of the resource due to a range header */\n PartialContent = 206,\n}\n\nexport type EndpointOutput<T> = T extends Endpoint<\n any,\n any,\n any,\n infer OutSchema,\n any,\n any,\n any,\n any\n>\n ? InferStandardSchema<OutSchema>\n : never;\n\nexport type EndpointEvent<T> = T extends Endpoint<\n any,\n any,\n any,\n any,\n any,\n any,\n any,\n infer TEventPublisher\n>\n ? ExtractPublisherMessage<TEventPublisher>\n : never;\n"],"mappings":"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"}