@geekmidas/constructs 3.0.3 → 3.0.5

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 (213) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/{AmazonApiGatewayEndpointAdaptor-B30TqZRX.d.mts → AmazonApiGatewayEndpointAdaptor-CS-m4WZy.d.mts} +11 -2
  3. package/dist/AmazonApiGatewayEndpointAdaptor-CS-m4WZy.d.mts.map +1 -0
  4. package/dist/{AmazonApiGatewayEndpointAdaptor-ciUHVvPX.mjs → AmazonApiGatewayEndpointAdaptor-Cmm9d_Po.mjs} +20 -2
  5. package/dist/AmazonApiGatewayEndpointAdaptor-Cmm9d_Po.mjs.map +1 -0
  6. package/dist/{AmazonApiGatewayEndpointAdaptor-jDYqkgFE.cjs → AmazonApiGatewayEndpointAdaptor-D7mhDtSL.cjs} +20 -2
  7. package/dist/AmazonApiGatewayEndpointAdaptor-D7mhDtSL.cjs.map +1 -0
  8. package/dist/{AmazonApiGatewayEndpointAdaptor-D4lAuXA-.d.cts → AmazonApiGatewayEndpointAdaptor-DisDeEF0.d.cts} +11 -2
  9. package/dist/AmazonApiGatewayEndpointAdaptor-DisDeEF0.d.cts.map +1 -0
  10. package/dist/{AmazonApiGatewayV1EndpointAdaptor-B5xFYauV.d.cts → AmazonApiGatewayV1EndpointAdaptor-D6wNqjth.d.cts} +3 -3
  11. package/dist/AmazonApiGatewayV1EndpointAdaptor-D6wNqjth.d.cts.map +1 -0
  12. package/dist/{AmazonApiGatewayV1EndpointAdaptor-CG1UJoAK.d.mts → AmazonApiGatewayV1EndpointAdaptor-DSMe7dZ4.d.mts} +3 -3
  13. package/dist/AmazonApiGatewayV1EndpointAdaptor-DSMe7dZ4.d.mts.map +1 -0
  14. package/dist/{AmazonApiGatewayV1EndpointAdaptor-DwKlAfnb.cjs → AmazonApiGatewayV1EndpointAdaptor-DstIoQBv.cjs} +3 -3
  15. package/dist/{AmazonApiGatewayV1EndpointAdaptor-DwKlAfnb.cjs.map → AmazonApiGatewayV1EndpointAdaptor-DstIoQBv.cjs.map} +1 -1
  16. package/dist/{AmazonApiGatewayV1EndpointAdaptor-DCfEo-Tu.mjs → AmazonApiGatewayV1EndpointAdaptor-zrlehWUG.mjs} +3 -3
  17. package/dist/{AmazonApiGatewayV1EndpointAdaptor-DCfEo-Tu.mjs.map → AmazonApiGatewayV1EndpointAdaptor-zrlehWUG.mjs.map} +1 -1
  18. package/dist/{AmazonApiGatewayV2EndpointAdaptor-ofjuxcPV.d.mts → AmazonApiGatewayV2EndpointAdaptor-ByljgCnY.d.mts} +3 -3
  19. package/dist/AmazonApiGatewayV2EndpointAdaptor-ByljgCnY.d.mts.map +1 -0
  20. package/dist/{AmazonApiGatewayV2EndpointAdaptor-B126fL6i.cjs → AmazonApiGatewayV2EndpointAdaptor-DaAHSnqs.cjs} +4 -3
  21. package/dist/{AmazonApiGatewayV2EndpointAdaptor-B126fL6i.cjs.map → AmazonApiGatewayV2EndpointAdaptor-DaAHSnqs.cjs.map} +1 -1
  22. package/dist/{AmazonApiGatewayV2EndpointAdaptor-CGMF4lD4.mjs → AmazonApiGatewayV2EndpointAdaptor-Dj5v-I6S.mjs} +4 -3
  23. package/dist/AmazonApiGatewayV2EndpointAdaptor-Dj5v-I6S.mjs.map +1 -0
  24. package/dist/{AmazonApiGatewayV2EndpointAdaptor-OkwjABOz.d.cts → AmazonApiGatewayV2EndpointAdaptor-PcMFUEF9.d.cts} +3 -3
  25. package/dist/AmazonApiGatewayV2EndpointAdaptor-PcMFUEF9.d.cts.map +1 -0
  26. package/dist/{Authorizer-BgjU8-z6.mjs → Authorizer-4unKN3Xn.mjs} +1 -1
  27. package/dist/{Authorizer-BgjU8-z6.mjs.map → Authorizer-4unKN3Xn.mjs.map} +1 -1
  28. package/dist/{Authorizer-BXxBee2P.cjs → Authorizer-Dx57psuM.cjs} +1 -1
  29. package/dist/{Authorizer-BXxBee2P.cjs.map → Authorizer-Dx57psuM.cjs.map} +1 -1
  30. package/dist/{Cron-BUpUS-0f.mjs → Cron-B3vrGuaD.mjs} +1 -1
  31. package/dist/{Cron-BUpUS-0f.mjs.map → Cron-B3vrGuaD.mjs.map} +1 -1
  32. package/dist/{Cron-Bp08dJ4R.cjs → Cron-DEKZg5j4.cjs} +1 -1
  33. package/dist/{Cron-Bp08dJ4R.cjs.map → Cron-DEKZg5j4.cjs.map} +1 -1
  34. package/dist/{CronBuilder-CIxJQ1Ps.cjs → CronBuilder-BHpY6w3b.cjs} +2 -2
  35. package/dist/{CronBuilder-CIxJQ1Ps.cjs.map → CronBuilder-BHpY6w3b.cjs.map} +1 -1
  36. package/dist/{CronBuilder-DUggbCHc.mjs → CronBuilder-VXpyNfp2.mjs} +2 -2
  37. package/dist/{CronBuilder-DUggbCHc.mjs.map → CronBuilder-VXpyNfp2.mjs.map} +1 -1
  38. package/dist/{Endpoint-BiPM0glm.d.mts → Endpoint-BIvS-rKH.d.mts} +6 -6
  39. package/dist/Endpoint-BIvS-rKH.d.mts.map +1 -0
  40. package/dist/{Endpoint-C9N6CmvB.d.cts → Endpoint-BPh52sXZ.d.cts} +6 -6
  41. package/dist/Endpoint-BPh52sXZ.d.cts.map +1 -0
  42. package/dist/Endpoint-BcxvF4F3.cjs.map +1 -1
  43. package/dist/Endpoint-DvY3aqAy.mjs.map +1 -1
  44. package/dist/{EndpointBuilder-B0Aj5jbB.d.mts → EndpointBuilder-3xH8Gllw.d.mts} +4 -3
  45. package/dist/EndpointBuilder-3xH8Gllw.d.mts.map +1 -0
  46. package/dist/{EndpointBuilder-Bel6RS7W.d.cts → EndpointBuilder-BmVTFp1A.d.cts} +4 -3
  47. package/dist/EndpointBuilder-BmVTFp1A.d.cts.map +1 -0
  48. package/dist/{EndpointBuilder-CF-ZWtdu.mjs → EndpointBuilder-CMzbGG2c.mjs} +7 -3
  49. package/dist/{EndpointBuilder-CF-ZWtdu.mjs.map → EndpointBuilder-CMzbGG2c.mjs.map} +1 -1
  50. package/dist/{EndpointBuilder-CyszO0bs.cjs → EndpointBuilder-QdDf3x87.cjs} +7 -3
  51. package/dist/{EndpointBuilder-CyszO0bs.cjs.map → EndpointBuilder-QdDf3x87.cjs.map} +1 -1
  52. package/dist/{EndpointFactory-B0D6d6t9.cjs → EndpointFactory-AsfUsn-v.cjs} +3 -3
  53. package/dist/{EndpointFactory-B0D6d6t9.cjs.map → EndpointFactory-AsfUsn-v.cjs.map} +1 -1
  54. package/dist/{EndpointFactory-Do498RmG.mjs → EndpointFactory-CkPaFZA0.mjs} +3 -3
  55. package/dist/{EndpointFactory-Do498RmG.mjs.map → EndpointFactory-CkPaFZA0.mjs.map} +1 -1
  56. package/dist/{EndpointFactory-CWIeWCRG.d.mts → EndpointFactory-DKHnUYl8.d.mts} +3 -3
  57. package/dist/{EndpointFactory-CXvakOkn.d.cts.map → EndpointFactory-DKHnUYl8.d.mts.map} +1 -1
  58. package/dist/{EndpointFactory-CXvakOkn.d.cts → EndpointFactory-DaDXPRAg.d.cts} +3 -3
  59. package/dist/{EndpointFactory-CWIeWCRG.d.mts.map → EndpointFactory-DaDXPRAg.d.cts.map} +1 -1
  60. package/dist/{HonoEndpointAdaptor-DgoeqUX6.d.mts → HonoEndpointAdaptor-Cb45sqM9.d.mts} +4 -4
  61. package/dist/{HonoEndpointAdaptor-BNHGwpvZ.d.cts.map → HonoEndpointAdaptor-Cb45sqM9.d.mts.map} +1 -1
  62. package/dist/{HonoEndpointAdaptor-BvxQreVM.mjs → HonoEndpointAdaptor-D7N5oiO0.mjs} +5 -2
  63. package/dist/HonoEndpointAdaptor-D7N5oiO0.mjs.map +1 -0
  64. package/dist/{HonoEndpointAdaptor-CQqQPLHH.cjs → HonoEndpointAdaptor-Jbptyuxv.cjs} +5 -2
  65. package/dist/HonoEndpointAdaptor-Jbptyuxv.cjs.map +1 -0
  66. package/dist/{HonoEndpointAdaptor-BNHGwpvZ.d.cts → HonoEndpointAdaptor-VStaYQHr.d.cts} +4 -4
  67. package/dist/{HonoEndpointAdaptor-DgoeqUX6.d.mts.map → HonoEndpointAdaptor-VStaYQHr.d.cts.map} +1 -1
  68. package/dist/{Subscriber-DKQK5gLD.mjs → Subscriber-BEhOdNQi.mjs} +1 -1
  69. package/dist/{Subscriber-DKQK5gLD.mjs.map → Subscriber-BEhOdNQi.mjs.map} +1 -1
  70. package/dist/{Subscriber-ClqSPbIZ.cjs → Subscriber-Scz7hrV6.cjs} +1 -1
  71. package/dist/{Subscriber-ClqSPbIZ.cjs.map → Subscriber-Scz7hrV6.cjs.map} +1 -1
  72. package/dist/{SubscriberBuilder-BS5B_688.cjs → SubscriberBuilder-B82h4v-S.cjs} +2 -2
  73. package/dist/{SubscriberBuilder-BS5B_688.cjs.map → SubscriberBuilder-B82h4v-S.cjs.map} +1 -1
  74. package/dist/{SubscriberBuilder-BswTuvUc.mjs → SubscriberBuilder-DlUaG0Ej.mjs} +2 -2
  75. package/dist/{SubscriberBuilder-BswTuvUc.mjs.map → SubscriberBuilder-DlUaG0Ej.mjs.map} +1 -1
  76. package/dist/{TestEndpointAdaptor-DjQSuxRq.cjs → TestEndpointAdaptor-BKoJpTGT.cjs} +5 -2
  77. package/dist/TestEndpointAdaptor-BKoJpTGT.cjs.map +1 -0
  78. package/dist/{TestEndpointAdaptor-qSWV8dpS.d.mts → TestEndpointAdaptor-Bt-uW6SC.d.mts} +2 -2
  79. package/dist/{TestEndpointAdaptor-CCf3Dg0u.d.cts.map → TestEndpointAdaptor-Bt-uW6SC.d.mts.map} +1 -1
  80. package/dist/{TestEndpointAdaptor-CDOhCmIk.mjs → TestEndpointAdaptor-DHVaHmhw.mjs} +5 -2
  81. package/dist/TestEndpointAdaptor-DHVaHmhw.mjs.map +1 -0
  82. package/dist/{TestEndpointAdaptor-CCf3Dg0u.d.cts → TestEndpointAdaptor-UKhHj1RR.d.cts} +2 -2
  83. package/dist/{TestEndpointAdaptor-qSWV8dpS.d.mts.map → TestEndpointAdaptor-UKhHj1RR.d.cts.map} +1 -1
  84. package/dist/adaptors/aws.cjs +3 -3
  85. package/dist/adaptors/aws.d.cts +5 -5
  86. package/dist/adaptors/aws.d.mts +5 -5
  87. package/dist/adaptors/aws.mjs +3 -3
  88. package/dist/adaptors/hono.cjs +1 -1
  89. package/dist/adaptors/hono.d.cts +3 -3
  90. package/dist/adaptors/hono.d.mts +3 -3
  91. package/dist/adaptors/hono.mjs +1 -1
  92. package/dist/adaptors/testing.cjs +1 -1
  93. package/dist/adaptors/testing.d.cts +3 -3
  94. package/dist/adaptors/testing.d.mts +3 -3
  95. package/dist/adaptors/testing.mjs +1 -1
  96. package/dist/crons/Cron.cjs +1 -1
  97. package/dist/crons/Cron.d.cts +1 -1
  98. package/dist/crons/Cron.d.mts +1 -1
  99. package/dist/crons/Cron.mjs +1 -1
  100. package/dist/crons/CronBuilder.cjs +2 -2
  101. package/dist/crons/CronBuilder.d.cts +1 -1
  102. package/dist/crons/CronBuilder.d.mts +1 -1
  103. package/dist/crons/CronBuilder.mjs +2 -2
  104. package/dist/crons/index.cjs +2 -2
  105. package/dist/crons/index.d.cts +5 -5
  106. package/dist/crons/index.d.cts.map +1 -1
  107. package/dist/crons/index.d.mts +5 -5
  108. package/dist/crons/index.d.mts.map +1 -1
  109. package/dist/crons/index.mjs +2 -2
  110. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.cjs +1 -1
  111. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.cts +3 -3
  112. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.mts +3 -3
  113. package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.mjs +1 -1
  114. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.cjs +2 -2
  115. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.cts +4 -4
  116. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.mts +4 -4
  117. package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.mjs +2 -2
  118. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.cjs +2 -2
  119. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.cts +4 -4
  120. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.mts +4 -4
  121. package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.mjs +2 -2
  122. package/dist/endpoints/Authorizer.cjs +1 -1
  123. package/dist/endpoints/Authorizer.mjs +1 -1
  124. package/dist/endpoints/Endpoint.d.cts +2 -2
  125. package/dist/endpoints/Endpoint.d.mts +2 -2
  126. package/dist/endpoints/EndpointBuilder.cjs +3 -3
  127. package/dist/endpoints/EndpointBuilder.d.cts +3 -3
  128. package/dist/endpoints/EndpointBuilder.d.mts +3 -3
  129. package/dist/endpoints/EndpointBuilder.mjs +3 -3
  130. package/dist/endpoints/EndpointFactory.cjs +4 -4
  131. package/dist/endpoints/EndpointFactory.d.cts +4 -4
  132. package/dist/endpoints/EndpointFactory.d.mts +4 -4
  133. package/dist/endpoints/EndpointFactory.mjs +4 -4
  134. package/dist/endpoints/HonoEndpointAdaptor.cjs +1 -1
  135. package/dist/endpoints/HonoEndpointAdaptor.d.cts +3 -3
  136. package/dist/endpoints/HonoEndpointAdaptor.d.mts +3 -3
  137. package/dist/endpoints/HonoEndpointAdaptor.mjs +1 -1
  138. package/dist/endpoints/TestEndpointAdaptor.cjs +1 -1
  139. package/dist/endpoints/TestEndpointAdaptor.d.cts +3 -3
  140. package/dist/endpoints/TestEndpointAdaptor.d.mts +3 -3
  141. package/dist/endpoints/TestEndpointAdaptor.mjs +1 -1
  142. package/dist/endpoints/audit.d.cts +2 -2
  143. package/dist/endpoints/audit.d.mts +2 -2
  144. package/dist/endpoints/helpers.d.cts +2 -2
  145. package/dist/endpoints/helpers.d.mts +2 -2
  146. package/dist/endpoints/index.cjs +4 -4
  147. package/dist/endpoints/index.d.cts +7 -7
  148. package/dist/endpoints/index.d.mts +5 -5
  149. package/dist/endpoints/index.mjs +4 -4
  150. package/dist/endpoints/lazyAccessors.d.cts +3 -3
  151. package/dist/endpoints/lazyAccessors.d.mts +3 -3
  152. package/dist/endpoints/processAudits.d.cts +2 -2
  153. package/dist/endpoints/processAudits.d.mts +2 -2
  154. package/dist/endpoints/rls.cjs +1 -1
  155. package/dist/endpoints/rls.d.cts +2 -2
  156. package/dist/endpoints/rls.d.mts +2 -2
  157. package/dist/endpoints/rls.mjs +1 -1
  158. package/dist/functions/index.d.cts +1 -1
  159. package/dist/functions/index.d.mts +1 -1
  160. package/dist/index-BfeupgMl.d.cts +12 -0
  161. package/dist/{index-Br-zTYii.d.mts.map → index-BfeupgMl.d.cts.map} +1 -1
  162. package/dist/index-CtMNRkV7.d.mts +12 -0
  163. package/dist/{index-dRNH0dT6.d.cts.map → index-CtMNRkV7.d.mts.map} +1 -1
  164. package/dist/{lazyAccessors-DXkJpnyX.d.mts → lazyAccessors-Ba8HxeIC.d.cts} +2 -2
  165. package/dist/{lazyAccessors-DXkJpnyX.d.mts.map → lazyAccessors-Ba8HxeIC.d.cts.map} +1 -1
  166. package/dist/{lazyAccessors-DdZaA716.d.cts → lazyAccessors-D9tzUZaz.d.mts} +2 -2
  167. package/dist/{lazyAccessors-DdZaA716.d.cts.map → lazyAccessors-D9tzUZaz.d.mts.map} +1 -1
  168. package/dist/{rls-C0cWOnk4.mjs → rls-7XXX7DvY.mjs} +1 -1
  169. package/dist/{rls-C0cWOnk4.mjs.map → rls-7XXX7DvY.mjs.map} +1 -1
  170. package/dist/{rls-BrywnrQb.cjs → rls-DxFqdIA0.cjs} +1 -1
  171. package/dist/{rls-BrywnrQb.cjs.map → rls-DxFqdIA0.cjs.map} +1 -1
  172. package/dist/subscribers/Subscriber.cjs +1 -1
  173. package/dist/subscribers/Subscriber.mjs +1 -1
  174. package/dist/subscribers/SubscriberBuilder.cjs +2 -2
  175. package/dist/subscribers/SubscriberBuilder.mjs +2 -2
  176. package/dist/subscribers/index.cjs +2 -2
  177. package/dist/subscribers/index.d.cts +2 -2
  178. package/dist/subscribers/index.d.mts +2 -2
  179. package/dist/subscribers/index.d.mts.map +1 -1
  180. package/dist/subscribers/index.mjs +2 -2
  181. package/package.json +7 -7
  182. package/src/endpoints/AmazonApiGatewayEndpointAdaptor.ts +32 -1
  183. package/src/endpoints/AmazonApiGatewayV1EndpointAdaptor.ts +5 -1
  184. package/src/endpoints/AmazonApiGatewayV2EndpointAdaptor.ts +7 -1
  185. package/src/endpoints/Endpoint.ts +7 -4
  186. package/src/endpoints/EndpointBuilder.ts +6 -1
  187. package/src/endpoints/EndpointFactory.ts +1 -1
  188. package/src/endpoints/HonoEndpointAdaptor.ts +9 -0
  189. package/src/endpoints/TestEndpointAdaptor.ts +3 -0
  190. package/src/endpoints/__tests__/AmazonApiGatewayV1EndpointAdaptor.spec.ts +112 -0
  191. package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.spec.ts +137 -0
  192. package/src/endpoints/__tests__/EndpointBuilder.spec.ts +35 -0
  193. package/src/endpoints/__tests__/HonoEndpointAdaptor.spec.ts +105 -0
  194. package/src/endpoints/__tests__/TestEndpointAdaptor.spec.ts +139 -0
  195. package/dist/AmazonApiGatewayEndpointAdaptor-B30TqZRX.d.mts.map +0 -1
  196. package/dist/AmazonApiGatewayEndpointAdaptor-D4lAuXA-.d.cts.map +0 -1
  197. package/dist/AmazonApiGatewayEndpointAdaptor-ciUHVvPX.mjs.map +0 -1
  198. package/dist/AmazonApiGatewayEndpointAdaptor-jDYqkgFE.cjs.map +0 -1
  199. package/dist/AmazonApiGatewayV1EndpointAdaptor-B5xFYauV.d.cts.map +0 -1
  200. package/dist/AmazonApiGatewayV1EndpointAdaptor-CG1UJoAK.d.mts.map +0 -1
  201. package/dist/AmazonApiGatewayV2EndpointAdaptor-CGMF4lD4.mjs.map +0 -1
  202. package/dist/AmazonApiGatewayV2EndpointAdaptor-OkwjABOz.d.cts.map +0 -1
  203. package/dist/AmazonApiGatewayV2EndpointAdaptor-ofjuxcPV.d.mts.map +0 -1
  204. package/dist/Endpoint-BiPM0glm.d.mts.map +0 -1
  205. package/dist/Endpoint-C9N6CmvB.d.cts.map +0 -1
  206. package/dist/EndpointBuilder-B0Aj5jbB.d.mts.map +0 -1
  207. package/dist/EndpointBuilder-Bel6RS7W.d.cts.map +0 -1
  208. package/dist/HonoEndpointAdaptor-BvxQreVM.mjs.map +0 -1
  209. package/dist/HonoEndpointAdaptor-CQqQPLHH.cjs.map +0 -1
  210. package/dist/TestEndpointAdaptor-CDOhCmIk.mjs.map +0 -1
  211. package/dist/TestEndpointAdaptor-DjQSuxRq.cjs.map +0 -1
  212. package/dist/index-Br-zTYii.d.mts +0 -12
  213. package/dist/index-dRNH0dT6.d.cts +0 -12
@@ -45,6 +45,118 @@ describe('AmazonApiGatewayV1Endpoint', () => {
45
45
  envParser = new EnvironmentParser({});
46
46
  });
47
47
 
48
+ describe('getInput', () => {
49
+ it('should parse JSON body when content-type is application/json', () => {
50
+ const endpoint = new Endpoint({
51
+ route: '/test',
52
+ method: 'GET',
53
+ fn: async () => ({ success: true }),
54
+ input: {},
55
+ output: z.object({ success: z.boolean() }),
56
+ services: [],
57
+ logger: mockLogger,
58
+ timeout: undefined,
59
+ memorySize: undefined,
60
+ status: undefined,
61
+ getSession: undefined,
62
+ authorize: undefined,
63
+ description: 'Test endpoint',
64
+ });
65
+ const adapter = new AmazonApiGatewayV1Endpoint(envParser, endpoint);
66
+
67
+ const event = createMockV1Event({
68
+ headers: { 'Content-Type': 'application/json' },
69
+ body: JSON.stringify({ name: 'test' }),
70
+ });
71
+
72
+ const result = adapter.getInput(event);
73
+ expect(result.body).toEqual({ name: 'test' });
74
+ });
75
+
76
+ it('should decode base64-encoded JSON body', () => {
77
+ const endpoint = new Endpoint({
78
+ route: '/test',
79
+ method: 'GET',
80
+ fn: async () => ({ success: true }),
81
+ input: {},
82
+ output: z.object({ success: z.boolean() }),
83
+ services: [],
84
+ logger: mockLogger,
85
+ timeout: undefined,
86
+ memorySize: undefined,
87
+ status: undefined,
88
+ getSession: undefined,
89
+ authorize: undefined,
90
+ description: 'Test endpoint',
91
+ });
92
+ const adapter = new AmazonApiGatewayV1Endpoint(envParser, endpoint);
93
+
94
+ const event = createMockV1Event({
95
+ headers: { 'Content-Type': 'application/json' },
96
+ body: Buffer.from(JSON.stringify({ name: 'test' })).toString('base64'),
97
+ isBase64Encoded: true,
98
+ });
99
+
100
+ const result = adapter.getInput(event);
101
+ expect(result.body).toEqual({ name: 'test' });
102
+ });
103
+
104
+ it('should return raw string for non-JSON content-type', () => {
105
+ const endpoint = new Endpoint({
106
+ route: '/test',
107
+ method: 'POST',
108
+ fn: async () => ({ success: true }),
109
+ input: {},
110
+ output: z.object({ success: z.boolean() }),
111
+ services: [],
112
+ logger: mockLogger,
113
+ timeout: undefined,
114
+ memorySize: undefined,
115
+ status: undefined,
116
+ getSession: undefined,
117
+ authorize: undefined,
118
+ description: 'Test endpoint',
119
+ });
120
+ const adapter = new AmazonApiGatewayV1Endpoint(envParser, endpoint);
121
+
122
+ const event = createMockV1Event({
123
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
124
+ body: 'amount=100&currency=ZAR',
125
+ });
126
+
127
+ const result = adapter.getInput(event);
128
+ expect(result.body).toBe('amount=100&currency=ZAR');
129
+ });
130
+
131
+ it('should decode base64 and return string for form-urlencoded content', () => {
132
+ const endpoint = new Endpoint({
133
+ route: '/test',
134
+ method: 'POST',
135
+ fn: async () => ({ success: true }),
136
+ input: {},
137
+ output: z.object({ success: z.boolean() }),
138
+ services: [],
139
+ logger: mockLogger,
140
+ timeout: undefined,
141
+ memorySize: undefined,
142
+ status: undefined,
143
+ getSession: undefined,
144
+ authorize: undefined,
145
+ description: 'Test endpoint',
146
+ });
147
+ const adapter = new AmazonApiGatewayV1Endpoint(envParser, endpoint);
148
+
149
+ const event = createMockV1Event({
150
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
151
+ body: Buffer.from('amount=100&currency=ZAR').toString('base64'),
152
+ isBase64Encoded: true,
153
+ });
154
+
155
+ const result = adapter.getInput(event);
156
+ expect(result.body).toBe('amount=100&currency=ZAR');
157
+ });
158
+ });
159
+
48
160
  describe('handler', () => {
49
161
  it('should handle a simple GET request', async () => {
50
162
  const endpoint = new Endpoint({
@@ -3,6 +3,7 @@ import { createMockContext, createMockV2Event } from '@geekmidas/testkit/aws';
3
3
  import type { Context } from 'aws-lambda';
4
4
  import { beforeEach, describe, expect, it } from 'vitest';
5
5
  import { z } from 'zod';
6
+ import { AmazonApiGatewayEndpoint } from '../AmazonApiGatewayEndpointAdaptor';
6
7
  import { AmazonApiGatewayV2Endpoint } from '../AmazonApiGatewayV2EndpointAdaptor';
7
8
  import { e } from '../EndpointFactory';
8
9
 
@@ -36,6 +37,78 @@ describe('AmazonApiGatewayV2Endpoint', () => {
36
37
  });
37
38
  });
38
39
 
40
+ it('should parse JSON body when content-type is application/json', () => {
41
+ const endpoint = e.get('/test').handle(() => ({ success: true }));
42
+ const adapter = new AmazonApiGatewayV2Endpoint(envParser, endpoint);
43
+
44
+ const event = createMockV2Event({
45
+ headers: { 'content-type': 'application/json' },
46
+ body: JSON.stringify({ name: 'test' }),
47
+ });
48
+
49
+ const result = adapter.getInput(event);
50
+
51
+ expect(result.body).toEqual({ name: 'test' });
52
+ });
53
+
54
+ it('should decode base64-encoded JSON body', () => {
55
+ const endpoint = e.get('/test').handle(() => ({ success: true }));
56
+ const adapter = new AmazonApiGatewayV2Endpoint(envParser, endpoint);
57
+
58
+ const event = createMockV2Event({
59
+ headers: { 'content-type': 'application/json' },
60
+ body: Buffer.from(JSON.stringify({ name: 'test' })).toString('base64'),
61
+ isBase64Encoded: true,
62
+ });
63
+
64
+ const result = adapter.getInput(event);
65
+
66
+ expect(result.body).toEqual({ name: 'test' });
67
+ });
68
+
69
+ it('should return base64-decoded string for non-JSON content-type', () => {
70
+ const endpoint = e.get('/test').handle(() => ({ success: true }));
71
+ const adapter = new AmazonApiGatewayV2Endpoint(envParser, endpoint);
72
+
73
+ const event = createMockV2Event({
74
+ headers: { 'content-type': 'application/x-www-form-urlencoded' },
75
+ body: Buffer.from('amount=100&currency=ZAR').toString('base64'),
76
+ isBase64Encoded: true,
77
+ });
78
+
79
+ const result = adapter.getInput(event);
80
+
81
+ expect(result.body).toBe('amount=100&currency=ZAR');
82
+ });
83
+
84
+ it('should return raw string when content-type is not JSON', () => {
85
+ const endpoint = e.get('/test').handle(() => ({ success: true }));
86
+ const adapter = new AmazonApiGatewayV2Endpoint(envParser, endpoint);
87
+
88
+ const event = createMockV2Event({
89
+ headers: { 'content-type': 'text/plain' },
90
+ body: 'plain-text-body',
91
+ });
92
+
93
+ const result = adapter.getInput(event);
94
+
95
+ expect(result.body).toBe('plain-text-body');
96
+ });
97
+
98
+ it('should default to JSON parsing when no content-type header', () => {
99
+ const endpoint = e.get('/test').handle(() => ({ success: true }));
100
+ const adapter = new AmazonApiGatewayV2Endpoint(envParser, endpoint);
101
+
102
+ const event = createMockV2Event({
103
+ headers: {},
104
+ body: JSON.stringify({ name: 'test' }),
105
+ });
106
+
107
+ const result = adapter.getInput(event);
108
+
109
+ expect(result.body).toEqual({ name: 'test' });
110
+ });
111
+
39
112
  it('should handle missing body, query, and params', () => {
40
113
  const endpoint = e.get('/test').handle(() => ({ success: true }));
41
114
  const adapter = new AmazonApiGatewayV2Endpoint(envParser, endpoint);
@@ -490,3 +563,67 @@ describe('AmazonApiGatewayV2Endpoint', () => {
490
563
  });
491
564
  });
492
565
  });
566
+
567
+ describe('AmazonApiGatewayEndpoint.decodeBody', () => {
568
+ const decodeBody = AmazonApiGatewayEndpoint.decodeBody;
569
+
570
+ it('should return undefined for null/undefined body', () => {
571
+ expect(decodeBody(undefined, false, 'application/json')).toBeUndefined();
572
+ expect(decodeBody(null, false, 'application/json')).toBeUndefined();
573
+ expect(decodeBody('', false, 'application/json')).toBeUndefined();
574
+ });
575
+
576
+ it('should JSON.parse when content-type is application/json', () => {
577
+ const result = decodeBody('{"name":"test"}', false, 'application/json');
578
+ expect(result).toEqual({ name: 'test' });
579
+ });
580
+
581
+ it('should JSON.parse when content-type includes application/json with charset', () => {
582
+ const result = decodeBody(
583
+ '{"name":"test"}',
584
+ false,
585
+ 'application/json; charset=utf-8',
586
+ );
587
+ expect(result).toEqual({ name: 'test' });
588
+ });
589
+
590
+ it('should decode base64 then JSON.parse for base64-encoded JSON', () => {
591
+ const encoded = Buffer.from('{"name":"test"}').toString('base64');
592
+ const result = decodeBody(encoded, true, 'application/json');
593
+ expect(result).toEqual({ name: 'test' });
594
+ });
595
+
596
+ it('should return raw string for non-JSON content-type', () => {
597
+ const result = decodeBody(
598
+ 'amount=100&currency=ZAR',
599
+ false,
600
+ 'application/x-www-form-urlencoded',
601
+ );
602
+ expect(result).toBe('amount=100&currency=ZAR');
603
+ });
604
+
605
+ it('should decode base64 and return string for non-JSON content-type', () => {
606
+ const encoded = Buffer.from('amount=100&currency=ZAR').toString('base64');
607
+ const result = decodeBody(
608
+ encoded,
609
+ true,
610
+ 'application/x-www-form-urlencoded',
611
+ );
612
+ expect(result).toBe('amount=100&currency=ZAR');
613
+ });
614
+
615
+ it('should return raw string for text/plain', () => {
616
+ const result = decodeBody('hello world', false, 'text/plain');
617
+ expect(result).toBe('hello world');
618
+ });
619
+
620
+ it('should default to JSON parsing when content-type is undefined', () => {
621
+ const result = decodeBody('{"name":"test"}', false, undefined);
622
+ expect(result).toEqual({ name: 'test' });
623
+ });
624
+
625
+ it('should not JSON.parse a string that happens to be valid JSON when content-type is not JSON', () => {
626
+ const result = decodeBody('{"looks":"like json"}', false, 'text/plain');
627
+ expect(result).toBe('{"looks":"like json"}');
628
+ });
629
+ });
@@ -379,6 +379,41 @@ describe('EndpointBuilder', () => {
379
379
  expect(endpoint.authorize).toBe(customAuth);
380
380
  });
381
381
 
382
+ it('should set authorize via .authorize() method', () => {
383
+ const authFn = () => true;
384
+ const builder = new EndpointBuilder('/test', 'GET');
385
+ const result = builder.authorize(authFn);
386
+
387
+ expect(result).toBe(builder);
388
+ expect((builder as any)._authorize).toBe(authFn);
389
+ });
390
+
391
+ it('should pass .authorize() function to endpoint', () => {
392
+ const authFn = async () => false;
393
+ const endpoint = new EndpointBuilder('/test', 'POST')
394
+ .authorize(authFn)
395
+ .handle(async () => ({}));
396
+
397
+ expect(endpoint.authorize).toBe(authFn);
398
+ });
399
+
400
+ it('should chain .authorize() with body, query, and params', () => {
401
+ const endpoint = new EndpointBuilder('/users/:id', 'POST')
402
+ .body(z.object({ role: z.string() }))
403
+ .query(z.object({ verbose: z.string() }))
404
+ .params(z.object({ id: z.string() }))
405
+ .authorize(({ body, query, params }) => {
406
+ return (
407
+ body.role === 'admin' &&
408
+ params.id !== '' &&
409
+ query.verbose === 'true'
410
+ );
411
+ })
412
+ .handle(async () => ({}));
413
+
414
+ expect(endpoint.authorize).toBeDefined();
415
+ });
416
+
382
417
  it('should allow setting custom session extractor', () => {
383
418
  const customSession = async () => ({ userId: '123', role: 'admin' });
384
419
  const builder = new EndpointBuilder('/test', 'GET');
@@ -996,6 +996,111 @@ describe('HonoEndpointAdaptor', () => {
996
996
  const response = await app.request('/protected');
997
997
  expect(response.status).toBe(500);
998
998
  });
999
+
1000
+ it('should pass body to authorize function', async () => {
1001
+ const authorizeSpy = vi.fn(() => true);
1002
+ const bodySchema = z.object({ role: z.string() });
1003
+
1004
+ const endpoint = new Endpoint({
1005
+ route: '/protected',
1006
+ method: 'POST',
1007
+ fn: async () => ({ success: true }),
1008
+ input: { body: bodySchema },
1009
+ output: z.object({ success: z.boolean() }),
1010
+ services: [],
1011
+ logger: mockLogger,
1012
+ timeout: undefined,
1013
+ memorySize: undefined,
1014
+ status: undefined,
1015
+ getSession: undefined,
1016
+ authorize: authorizeSpy,
1017
+ description: undefined,
1018
+ });
1019
+
1020
+ const adaptor = new HonoEndpoint(endpoint);
1021
+ const app = new Hono();
1022
+
1023
+ adaptor.addRoute(serviceDiscovery, app);
1024
+
1025
+ const response = await app.request('/protected', {
1026
+ method: 'POST',
1027
+ headers: { 'Content-Type': 'application/json' },
1028
+ body: JSON.stringify({ role: 'admin' }),
1029
+ });
1030
+
1031
+ expect(response.status).toBe(200);
1032
+ expect(authorizeSpy).toHaveBeenCalledTimes(1);
1033
+ expect(authorizeSpy.mock.calls[0][0]).toMatchObject({
1034
+ body: { role: 'admin' },
1035
+ });
1036
+ });
1037
+
1038
+ it('should pass params to authorize function', async () => {
1039
+ const authorizeSpy = vi.fn(() => true);
1040
+ const paramsSchema = z.object({ id: z.string() });
1041
+
1042
+ const endpoint = new Endpoint({
1043
+ route: '/resources/:id',
1044
+ method: 'GET',
1045
+ fn: async () => ({ success: true }),
1046
+ input: { params: paramsSchema },
1047
+ output: z.object({ success: z.boolean() }),
1048
+ services: [],
1049
+ logger: mockLogger,
1050
+ timeout: undefined,
1051
+ memorySize: undefined,
1052
+ status: undefined,
1053
+ getSession: undefined,
1054
+ authorize: authorizeSpy,
1055
+ description: undefined,
1056
+ });
1057
+
1058
+ const adaptor = new HonoEndpoint(endpoint);
1059
+ const app = new Hono();
1060
+
1061
+ adaptor.addRoute(serviceDiscovery, app);
1062
+
1063
+ const response = await app.request('/resources/res-42');
1064
+
1065
+ expect(response.status).toBe(200);
1066
+ expect(authorizeSpy).toHaveBeenCalledTimes(1);
1067
+ expect(authorizeSpy.mock.calls[0][0]).toMatchObject({
1068
+ params: { id: 'res-42' },
1069
+ });
1070
+ });
1071
+
1072
+ it('should deny request when authorize uses body to reject', async () => {
1073
+ const bodySchema = z.object({ role: z.string() });
1074
+
1075
+ const endpoint = new Endpoint({
1076
+ route: '/admin',
1077
+ method: 'POST',
1078
+ fn: async () => ({ success: true }),
1079
+ input: { body: bodySchema },
1080
+ output: z.object({ success: z.boolean() }),
1081
+ services: [],
1082
+ logger: mockLogger,
1083
+ timeout: undefined,
1084
+ memorySize: undefined,
1085
+ status: undefined,
1086
+ getSession: undefined,
1087
+ authorize: ({ body }: any) => body?.role === 'admin',
1088
+ description: undefined,
1089
+ });
1090
+
1091
+ const adaptor = new HonoEndpoint(endpoint);
1092
+ const app = new Hono();
1093
+
1094
+ adaptor.addRoute(serviceDiscovery, app);
1095
+
1096
+ const response = await app.request('/admin', {
1097
+ method: 'POST',
1098
+ headers: { 'Content-Type': 'application/json' },
1099
+ body: JSON.stringify({ role: 'viewer' }),
1100
+ });
1101
+
1102
+ expect(response.status).toBe(401);
1103
+ });
999
1104
  });
1000
1105
 
1001
1106
  describe('output validation', () => {
@@ -375,6 +375,145 @@ describe('TestEndpointAdaptor', () => {
375
375
  });
376
376
  });
377
377
 
378
+ describe('authorization with body, query, and params', () => {
379
+ it('should pass body to authorize function', async () => {
380
+ const authorizeSpy = vi.fn(() => true);
381
+ const endpoint = e
382
+ .post('/resources')
383
+ .body(z.object({ role: z.string() }))
384
+ .output(z.object({ ok: z.boolean() }))
385
+ .authorize(authorizeSpy)
386
+ .handle(() => ({ ok: true }));
387
+
388
+ const adapter = new TestEndpointAdaptor(endpoint);
389
+
390
+ await adapter.request({
391
+ body: { role: 'admin' },
392
+ services: mockServices,
393
+ headers: { host: 'example.com' },
394
+ });
395
+
396
+ expect(authorizeSpy).toHaveBeenCalledTimes(1);
397
+ expect(authorizeSpy.mock.calls[0][0]).toMatchObject({
398
+ body: { role: 'admin' },
399
+ });
400
+ });
401
+
402
+ it('should pass query to authorize function', async () => {
403
+ const authorizeSpy = vi.fn(() => true);
404
+ const endpoint = e
405
+ .get('/resources')
406
+ .query(z.object({ tenant: z.string() }))
407
+ .output(z.object({ ok: z.boolean() }))
408
+ .authorize(authorizeSpy)
409
+ .handle(() => ({ ok: true }));
410
+
411
+ const adapter = new TestEndpointAdaptor(endpoint);
412
+
413
+ await adapter.request({
414
+ query: { tenant: 'acme' },
415
+ services: mockServices,
416
+ headers: { host: 'example.com' },
417
+ });
418
+
419
+ expect(authorizeSpy).toHaveBeenCalledTimes(1);
420
+ expect(authorizeSpy.mock.calls[0][0]).toMatchObject({
421
+ query: { tenant: 'acme' },
422
+ });
423
+ });
424
+
425
+ it('should pass params to authorize function', async () => {
426
+ const authorizeSpy = vi.fn(() => true);
427
+ const endpoint = e
428
+ .get('/resources/:id')
429
+ .params(z.object({ id: z.string() }))
430
+ .output(z.object({ ok: z.boolean() }))
431
+ .authorize(authorizeSpy)
432
+ .handle(() => ({ ok: true }));
433
+
434
+ const adapter = new TestEndpointAdaptor(endpoint);
435
+
436
+ await adapter.request({
437
+ params: { id: 'res-123' },
438
+ services: mockServices,
439
+ headers: { host: 'example.com' },
440
+ });
441
+
442
+ expect(authorizeSpy).toHaveBeenCalledTimes(1);
443
+ expect(authorizeSpy.mock.calls[0][0]).toMatchObject({
444
+ params: { id: 'res-123' },
445
+ });
446
+ });
447
+
448
+ it('should pass body, query, and params together to authorize', async () => {
449
+ const authorizeSpy = vi.fn(() => true);
450
+ const endpoint = e
451
+ .post('/orgs/:orgId/members')
452
+ .params(z.object({ orgId: z.string() }))
453
+ .query(z.object({ notify: z.string() }))
454
+ .body(z.object({ userId: z.string(), role: z.string() }))
455
+ .output(z.object({ ok: z.boolean() }))
456
+ .authorize(authorizeSpy)
457
+ .handle(() => ({ ok: true }));
458
+
459
+ const adapter = new TestEndpointAdaptor(endpoint);
460
+
461
+ await adapter.request({
462
+ params: { orgId: 'org-1' },
463
+ query: { notify: 'true' },
464
+ body: { userId: 'user-1', role: 'editor' },
465
+ services: mockServices,
466
+ headers: { host: 'example.com' },
467
+ });
468
+
469
+ expect(authorizeSpy).toHaveBeenCalledTimes(1);
470
+ const ctx = authorizeSpy.mock.calls[0][0];
471
+ expect(ctx).toMatchObject({
472
+ body: { userId: 'user-1', role: 'editor' },
473
+ query: { notify: 'true' },
474
+ params: { orgId: 'org-1' },
475
+ });
476
+ });
477
+
478
+ it('should reject when authorize uses body to deny', async () => {
479
+ const endpoint = e
480
+ .post('/resources')
481
+ .body(z.object({ role: z.string() }))
482
+ .output(z.object({ ok: z.boolean() }))
483
+ .authorize(({ body }) => body.role === 'admin')
484
+ .handle(() => ({ ok: true }));
485
+
486
+ const adapter = new TestEndpointAdaptor(endpoint);
487
+
488
+ await expect(
489
+ adapter.request({
490
+ body: { role: 'viewer' },
491
+ services: mockServices,
492
+ headers: { host: 'example.com' },
493
+ }),
494
+ ).rejects.toThrow('Unauthorized');
495
+ });
496
+
497
+ it('should allow when authorize uses body to allow', async () => {
498
+ const endpoint = e
499
+ .post('/resources')
500
+ .body(z.object({ role: z.string() }))
501
+ .output(z.object({ ok: z.boolean() }))
502
+ .authorize(({ body }) => body.role === 'admin')
503
+ .handle(() => ({ ok: true }));
504
+
505
+ const adapter = new TestEndpointAdaptor(endpoint);
506
+
507
+ const result = await adapter.request({
508
+ body: { role: 'admin' },
509
+ services: mockServices,
510
+ headers: { host: 'example.com' },
511
+ });
512
+
513
+ expect(result).toEqual({ ok: true });
514
+ });
515
+ });
516
+
378
517
  describe('response handling', () => {
379
518
  it('should set response cookies', async () => {
380
519
  const endpoint = e
@@ -1 +0,0 @@
1
- {"version":3,"file":"AmazonApiGatewayEndpointAdaptor-B30TqZRX.d.mts","names":[],"sources":["../src/endpoints/AmazonApiGatewayEndpointAdaptor.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"AmazonApiGatewayEndpointAdaptor-D4lAuXA-.d.cts","names":[],"sources":["../src/endpoints/AmazonApiGatewayEndpointAdaptor.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"AmazonApiGatewayEndpointAdaptor-ciUHVvPX.mjs","names":["envParser: EnvironmentParser<{}>","endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession,\n\t\t\tTEventPublisher,\n\t\t\tTEventPublisherServiceName,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTAuditAction\n\t\t>","options: AmazonApiGatewayEndpointOptions","e: TEvent","event: Event<TEvent, TInput, TServices, TLogger, TSession>","db: any","metadata","output","trx: any","result","lambdaResponse: AmazonApiGatewayEndpointHandlerResponse","setCookieHeaders: string[]","ctx: any","event: TEvent","context: Context"],"sources":["../src/endpoints/AmazonApiGatewayEndpointAdaptor.ts"],"sourcesContent":["import type { AuditableAction, AuditStorage } from '@geekmidas/audit';\nimport { withRlsContext } from '@geekmidas/db/rls';\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport middy, { type MiddlewareObj } from '@middy/core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type {\n\tAPIGatewayProxyEvent,\n\tAPIGatewayProxyEventV2,\n\tContext,\n} from 'aws-lambda';\nimport set from 'lodash.set';\nimport type { Telemetry } from '../telemetry';\nimport type { HttpMethod } from '../types';\nimport { Endpoint, type EndpointSchemas, ResponseBuilder } from './Endpoint';\n\n/**\n * Telescope integration for request recording.\n * Uses Middy middleware pattern for compatibility with existing telescope package.\n */\nexport interface TelescopeIntegration {\n\tmiddleware: MiddlewareObj<any, any, Error, Context>;\n}\n\nimport {\n\tUnauthorizedError,\n\tUnprocessableEntityError,\n\twrapError,\n} from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type {\n\tInferComposableStandardSchema,\n\tInferStandardSchema,\n} from '@geekmidas/schema';\nimport {\n\trunWithRequestContext,\n\ttype Service,\n\tServiceDiscovery,\n\ttype ServiceRecord,\n} from '@geekmidas/services';\nimport { publishConstructEvents } from '../publisher';\nimport type { MappedAudit } from './audit';\nimport type { CookieFn, HeaderFn } from './Endpoint';\nimport {\n\tcreateAuditContext,\n\texecuteWithAuditTransaction,\n} from './processAudits';\n\n// Helper function to publish events\n\n/**\n * Options for Amazon API Gateway endpoint adaptors\n */\nexport interface AmazonApiGatewayEndpointOptions {\n\t/**\n\t * Telescope integration for request recording and monitoring.\n\t *\n\t * @example\n\t * ```typescript\n\t * import { telescopeMiddleware } from '@geekmidas/telescope/lambda';\n\t *\n\t * const adaptor = new AmazonApiGatewayV2Endpoint(envParser, endpoint, {\n\t * telescope: { middleware: telescopeMiddleware(telescope) },\n\t * });\n\t * ```\n\t */\n\ttelescope?: TelescopeIntegration;\n\n\t/**\n\t * Telemetry integration for distributed tracing.\n\t * Works with any OpenTelemetry-compatible backend.\n\t *\n\t * @example\n\t * ```typescript\n\t * import { OTelTelemetry } from '@geekmidas/telescope/instrumentation';\n\t *\n\t * const adaptor = new AmazonApiGatewayV2Endpoint(envParser, endpoint, {\n\t * telemetry: new OTelTelemetry(),\n\t * });\n\t * ```\n\t */\n\ttelemetry?: Telemetry;\n}\n\nexport abstract class AmazonApiGatewayEndpoint<\n\tTHandler extends\n\t\t| AmazonApiGatewayV1EndpointHandler\n\t\t| AmazonApiGatewayV2EndpointHandler,\n\tTEvent extends HandlerEvent<THandler>,\n\tTRoute extends string,\n\tTMethod extends HttpMethod,\n\tTInput extends EndpointSchemas = {},\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\tTEventPublisherServiceName extends string = string,\n\tTAuditStorage extends AuditStorage | undefined = undefined,\n\tTAuditStorageServiceName extends string = string,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> {\n\tprotected options: AmazonApiGatewayEndpointOptions;\n\n\tconstructor(\n\t\tprotected envParser: EnvironmentParser<{}>,\n\t\tprotected readonly endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession,\n\t\t\tTEventPublisher,\n\t\t\tTEventPublisherServiceName,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTAuditAction\n\t\t>,\n\t\toptions: AmazonApiGatewayEndpointOptions = {},\n\t) {\n\t\tthis.options = options;\n\t}\n\n\tprivate error(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tonError: (req) => {\n\t\t\t\t(req.event.logger || this.endpoint.logger).error(\n\t\t\t\t\treq.error || {},\n\t\t\t\t\t'Error processing request',\n\t\t\t\t);\n\t\t\t\tconst wrappedError = wrapError(req.error);\n\n\t\t\t\t// Set the response with the proper status code from the HttpError\n\t\t\t\treq.response = {\n\t\t\t\t\tstatusCode: wrappedError.statusCode,\n\t\t\t\t\tbody: wrappedError.body,\n\t\t\t\t};\n\t\t\t},\n\t\t};\n\t}\n\tabstract getInput(e: TEvent): GetInputResponse;\n\n\tprotected getCookies(e: TEvent): CookieFn {\n\t\tconst headers = e.headers as Record<string, string>;\n\t\treturn Endpoint.createCookies(headers?.cookie);\n\t}\n\n\tprivate input(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { body, query, params } = this.getInput(req.event);\n\t\t\t\t\tconst headers = req.event.headers as Record<string, string>;\n\t\t\t\t\tconst header = Endpoint.createHeaders(headers);\n\t\t\t\t\tconst cookie = this.getCookies(req.event);\n\n\t\t\t\t\tset(req.event, 'body', await this.endpoint.parseInput(body, 'body'));\n\n\t\t\t\t\tset(\n\t\t\t\t\t\treq.event,\n\t\t\t\t\t\t'query',\n\t\t\t\t\t\tawait this.endpoint.parseInput(query, 'query'),\n\t\t\t\t\t);\n\t\t\t\t\tset(\n\t\t\t\t\t\treq.event,\n\t\t\t\t\t\t'params',\n\t\t\t\t\t\tawait this.endpoint.parseInput(params, 'params'),\n\t\t\t\t\t);\n\t\t\t\t\tset(req.event, 'header', header);\n\t\t\t\t\tset(req.event, 'cookie', cookie);\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Convert validation errors to 422 Unprocessable Entity\n\t\t\t\t\tif (error && typeof error === 'object' && Array.isArray(error)) {\n\t\t\t\t\t\tthrow new UnprocessableEntityError('Validation failed', error);\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tabstract getLoggerContext(data: TEvent, context: Context): LoggerContext;\n\n\tprivate logger(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: (req) => {\n\t\t\t\treq.event.logger = this.endpoint.logger.child({\n\t\t\t\t\troute: this.endpoint.route,\n\t\t\t\t\thost: req.event.headers?.host,\n\t\t\t\t\tmethod: this.endpoint.method,\n\t\t\t\t\t...this.getLoggerContext(req.event, req.context),\n\t\t\t\t}) as TLogger;\n\t\t\t},\n\t\t};\n\t}\n\tprivate services(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst _logger = req.event.logger as TLogger;\n\t\t\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\t\t\tServiceRecord<TServices>\n\t\t\t\t>(this.envParser);\n\n\t\t\t\tconst services = await serviceDiscovery.register(\n\t\t\t\t\tthis.endpoint.services,\n\t\t\t\t);\n\n\t\t\t\treq.event.services = services;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate authorize(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst logger = req.event.logger as TLogger;\n\t\t\t\tconst services = req.event.services;\n\t\t\t\tconst header = req.event.header;\n\t\t\t\tconst cookie = req.event.cookie;\n\t\t\t\tconst session = req.event.session as TSession;\n\n\t\t\t\tconst isAuthorized = await this.endpoint.authorize({\n\t\t\t\t\theader,\n\t\t\t\t\tcookie,\n\t\t\t\t\tservices,\n\t\t\t\t\tlogger,\n\t\t\t\t\tsession,\n\t\t\t\t});\n\n\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\tlogger.warn('Unauthorized access attempt');\n\t\t\t\t\tthrow new UnauthorizedError(\n\t\t\t\t\t\t'Unauthorized access to the endpoint',\n\t\t\t\t\t\t'You do not have permission to access this resource.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate database(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tif (!this.endpoint.databaseService) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst _logger = req.event.logger as TLogger;\n\t\t\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\t\t\tServiceRecord<TServices>\n\t\t\t\t>(this.envParser);\n\n\t\t\t\tconst db = await serviceDiscovery\n\t\t\t\t\t.register([this.endpoint.databaseService])\n\t\t\t\t\t.then(\n\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\ts[this.endpoint.databaseService?.serviceName as keyof typeof s],\n\t\t\t\t\t);\n\n\t\t\t\t(req.event as any).db = db;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate session(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst logger = req.event.logger as TLogger;\n\t\t\t\tconst services = req.event.services;\n\t\t\t\tconst db = (req.event as any).db;\n\t\t\t\treq.event.session = (await this.endpoint.getSession({\n\t\t\t\t\tlogger,\n\t\t\t\t\tservices,\n\t\t\t\t\theader: req.event.header,\n\t\t\t\t\tcookie: req.event.cookie,\n\t\t\t\t\t...(db !== undefined && { db }),\n\t\t\t\t} as any)) as TSession;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate events(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tafter: async (req) => {\n\t\t\t\tconst event = req.event;\n\t\t\t\tconst response = (event as any)\n\t\t\t\t\t.__response as InferStandardSchema<TOutSchema>;\n\t\t\t\tconst statusCode = req.response?.statusCode ?? this.endpoint.status;\n\n\t\t\t\t// Only publish events on successful responses (2xx status codes)\n\t\t\t\t// Note: Audits are processed inside the handler's transaction\n\t\t\t\tif (Endpoint.isSuccessStatus(statusCode)) {\n\t\t\t\t\tconst logger = event.logger as TLogger;\n\t\t\t\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\t\t\t\tServiceRecord<TServices>\n\t\t\t\t\t>(this.envParser);\n\n\t\t\t\t\t// Publish events\n\t\t\t\t\tawait publishConstructEvents(\n\t\t\t\t\t\tthis.endpoint,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t\tserviceDiscovery,\n\t\t\t\t\t\tlogger,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async _handler(\n\t\tevent: Event<TEvent, TInput, TServices, TLogger, TSession>,\n\t) {\n\t\tconst input = this.endpoint.refineInput(event);\n\t\tconst logger = event.logger as TLogger;\n\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\tServiceRecord<TServices>\n\t\t>(this.envParser);\n\n\t\t// Create audit context if audit storage is configured\n\t\tconst auditContext = await createAuditContext(\n\t\t\tthis.endpoint,\n\t\t\tserviceDiscovery,\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\tsession: event.session,\n\t\t\t\theader: event.header,\n\t\t\t\tcookie: event.cookie,\n\t\t\t\tservices: event.services as Record<string, unknown>,\n\t\t\t},\n\t\t);\n\n\t\t// Warn if declarative audits are configured but no audit storage\n\t\tconst audits = this.endpoint.audits as MappedAudit<\n\t\t\tTAuditAction,\n\t\t\tTOutSchema\n\t\t>[];\n\t\tif (!auditContext && audits?.length) {\n\t\t\tlogger.warn('No auditor storage service available');\n\t\t}\n\n\t\t// Get pre-resolved database from middleware\n\t\tconst rawDb = (event as any).db;\n\n\t\t// Extract RLS context if configured and not bypassed\n\t\tconst rlsActive =\n\t\t\tthis.endpoint.rlsConfig &&\n\t\t\t!this.endpoint.rlsBypass &&\n\t\t\trawDb !== undefined;\n\t\tconst rlsContext = rlsActive\n\t\t\t? await this.endpoint.rlsConfig?.extractor({\n\t\t\t\t\tservices: event.services as ServiceRecord<TServices>,\n\t\t\t\t\tsession: event.session,\n\t\t\t\t\theader: event.header,\n\t\t\t\t\tcookie: event.cookie,\n\t\t\t\t\tlogger,\n\t\t\t\t})\n\t\t\t: undefined;\n\n\t\t// Execute handler with automatic audit transaction support\n\t\tconst result = await executeWithAuditTransaction(\n\t\t\tauditContext,\n\t\t\tasync (auditor) => {\n\t\t\t\t// Use audit transaction as db only if the storage uses the same database service\n\t\t\t\tconst sameDatabase =\n\t\t\t\t\tauditContext?.storage?.databaseServiceName &&\n\t\t\t\t\tauditContext.storage.databaseServiceName ===\n\t\t\t\t\t\tthis.endpoint.databaseService?.serviceName;\n\t\t\t\tconst baseDb = sameDatabase\n\t\t\t\t\t? (auditor?.getTransaction?.() ?? rawDb)\n\t\t\t\t\t: rawDb;\n\n\t\t\t\t// Helper to execute handler with given db\n\t\t\t\tconst executeHandler = async (db: any) => {\n\t\t\t\t\tconst responseBuilder = new ResponseBuilder();\n\t\t\t\t\tconst response = await this.endpoint.handler(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\theader: event.header,\n\t\t\t\t\t\t\tcookie: event.cookie,\n\t\t\t\t\t\t\tlogger: event.logger,\n\t\t\t\t\t\t\tservices: event.services,\n\t\t\t\t\t\t\tsession: event.session,\n\t\t\t\t\t\t\tauditor,\n\t\t\t\t\t\t\tdb,\n\t\t\t\t\t\t\t...input,\n\t\t\t\t\t\t} as any,\n\t\t\t\t\t\tresponseBuilder,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Check if response has metadata\n\t\t\t\t\tlet data = response;\n\t\t\t\t\tlet metadata = responseBuilder.getMetadata();\n\n\t\t\t\t\tif (Endpoint.hasMetadata(response)) {\n\t\t\t\t\t\tdata = response.data;\n\t\t\t\t\t\tmetadata = response.metadata;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst output = this.endpoint.outputSchema\n\t\t\t\t\t\t? await this.endpoint.parseOutput(data)\n\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\treturn { output, metadata, responseBuilder };\n\t\t\t\t};\n\n\t\t\t\t// If RLS is active, wrap handler with RLS context\n\t\t\t\tif (rlsActive && rlsContext && baseDb) {\n\t\t\t\t\treturn withRlsContext(\n\t\t\t\t\t\tbaseDb,\n\t\t\t\t\t\trlsContext,\n\t\t\t\t\t\tasync (trx: any) => executeHandler(trx),\n\t\t\t\t\t\t{ prefix: this.endpoint.rlsConfig?.prefix },\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn executeHandler(baseDb);\n\t\t\t},\n\t\t\t// Process declarative audits after handler (inside transaction)\n\t\t\tasync (result, auditor) => {\n\t\t\t\tif (!audits?.length) return;\n\n\t\t\t\tfor (const audit of audits) {\n\t\t\t\t\tif (audit.when && !audit.when(result.output as any)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst payload = audit.payload(result.output as any);\n\t\t\t\t\tconst entityId = audit.entityId?.(result.output as any);\n\t\t\t\t\tauditor.audit(audit.type as any, payload as any, {\n\t\t\t\t\t\ttable: audit.table,\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t// Pass rawDb so storage can reuse existing transactions\n\t\t\t{ db: rawDb },\n\t\t);\n\n\t\tconst { output, metadata } = result;\n\t\tconst body = output !== undefined ? JSON.stringify(output) : undefined;\n\n\t\t// Store response for middleware access\n\t\t(event as any).__response = output;\n\n\t\t// Build response with metadata\n\t\tconst lambdaResponse: AmazonApiGatewayEndpointHandlerResponse = {\n\t\t\tstatusCode: metadata.status ?? this.endpoint.status,\n\t\t\tbody,\n\t\t};\n\n\t\t// Add custom headers\n\t\tif (metadata.headers && Object.keys(metadata.headers).length > 0) {\n\t\t\tlambdaResponse.headers = { ...metadata.headers };\n\t\t}\n\n\t\t// Format cookies as Set-Cookie headers\n\t\tif (metadata.cookies && metadata.cookies.size > 0) {\n\t\t\tconst setCookieHeaders: string[] = [];\n\t\t\tfor (const [name, { value, options }] of metadata.cookies) {\n\t\t\t\tsetCookieHeaders.push(\n\t\t\t\t\tEndpoint.formatCookieHeader(name, value, options),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (setCookieHeaders.length > 0) {\n\t\t\t\tlambdaResponse.multiValueHeaders = {\n\t\t\t\t\t...lambdaResponse.multiValueHeaders,\n\t\t\t\t\t'Set-Cookie': setCookieHeaders,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn lambdaResponse;\n\t}\n\n\t/**\n\t * Convert Telemetry interface to Middy middleware\n\t */\n\tprivate telemetry(): Middleware<TEvent, TInput, TServices, TLogger> | null {\n\t\tif (!this.options.telemetry) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst telemetry = this.options.telemetry;\n\t\tlet ctx: any;\n\n\t\treturn {\n\t\t\tbefore: (request) => {\n\t\t\t\tctx = telemetry.onRequestStart({\n\t\t\t\t\tevent: request.event,\n\t\t\t\t\tcontext: request.context,\n\t\t\t\t});\n\t\t\t},\n\t\t\tafter: (request) => {\n\t\t\t\tif (ctx) {\n\t\t\t\t\ttelemetry.onRequestEnd(ctx, {\n\t\t\t\t\t\tstatusCode: request.response?.statusCode ?? 200,\n\t\t\t\t\t\tbody: request.response?.body,\n\t\t\t\t\t\theaders: request.response?.headers,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tonError: (request) => {\n\t\t\t\tif (ctx && request.error) {\n\t\t\t\t\ttelemetry.onRequestError(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\trequest.error instanceof Error\n\t\t\t\t\t\t\t? request.error\n\t\t\t\t\t\t\t: new Error(String(request.error)),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tget handler() {\n\t\tconst handler = this._handler.bind(this);\n\t\tlet chain = middy(handler)\n\t\t\t.use(this.logger())\n\t\t\t.use(this.error())\n\t\t\t.use(this.services())\n\t\t\t.use(this.input())\n\t\t\t.use(this.database())\n\t\t\t.use(this.session())\n\t\t\t.use(this.authorize())\n\t\t\t.use(this.events());\n\n\t\t// Add telemetry middleware if configured (runs early for span creation)\n\t\tconst telemetryMiddleware = this.telemetry();\n\t\tif (telemetryMiddleware) {\n\t\t\tchain = chain.use(telemetryMiddleware);\n\t\t}\n\n\t\t// Add Telescope middleware if configured (runs first/last in chain)\n\t\tif (this.options.telescope?.middleware) {\n\t\t\tchain = chain.use(this.options.telescope.middleware);\n\t\t}\n\n\t\t// Wrap entire Middy chain in request context for service access\n\t\tconst wrappedHandler = async (event: TEvent, context: Context) => {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = context.awsRequestId;\n\t\t\tconst logger = this.endpoint.logger.child({ requestId }) as TLogger;\n\n\t\t\t// Cast event to any since Middy middlewares enrich the event with\n\t\t\t// services, logger, session, etc. during the middleware chain execution\n\t\t\treturn runWithRequestContext({ logger, requestId, startTime }, () =>\n\t\t\t\tchain(event as unknown as Parameters<typeof chain>[0], context),\n\t\t\t);\n\t\t};\n\n\t\treturn wrappedHandler as unknown as THandler;\n\t}\n}\n\nexport type Event<\n\tTEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n\tTInput extends EndpointSchemas = {},\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = {\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\theader: HeaderFn;\n\tcookie: CookieFn;\n\tsession: TSession;\n} & TEvent &\n\tInferComposableStandardSchema<TInput>;\n\ntype Middleware<\n\tTEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n\tTInput extends EndpointSchemas = {},\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = MiddlewareObj<Event<TEvent, TInput, TServices, TLogger, TSession>>;\n\nexport type AmazonApiGatewayEndpointHandlerResponse = {\n\tstatusCode: number;\n\tbody: string | undefined;\n\theaders?: Record<string, string>;\n\tmultiValueHeaders?: Record<string, string[]>;\n};\n\nexport type LoggerContext = {\n\tfn: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n\treq: {\n\t\tid: string | undefined;\n\t\tawsRequestId: string;\n\t\tpath: string;\n\t\tip: string | undefined;\n\t\tuserAgent: string | undefined;\n\t};\n};\n\nexport type GetInputResponse = {\n\tbody: any;\n\tquery: any;\n\tparams: any;\n};\n\nexport type AmazonApiGatewayV1EndpointHandler = (\n\tevent: APIGatewayProxyEvent,\n\tcontext: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type AmazonApiGatewayV2EndpointHandler = (\n\tevent: APIGatewayProxyEventV2,\n\tcontext: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type HandlerEvent<T extends Function> = T extends (\n\tevent: infer E,\n\tcontext: Context,\n) => any\n\t? E\n\t: never;\n"],"mappings":";;;;;;;;;;AAoFA,IAAsB,2BAAtB,MAoBE;CACD,AAAU;CAEV,YACWA,WACSC,UAcnBC,UAA2C,CAAE,GAC5C;EAhBS;EACS;AAgBnB,OAAK,UAAU;CACf;CAED,AAAQ,QAAwD;AAC/D,SAAO,EACN,SAAS,CAAC,QAAQ;AACjB,IAAC,IAAI,MAAM,UAAU,KAAK,SAAS,QAAQ,MAC1C,IAAI,SAAS,CAAE,GACf,2BACA;GACD,MAAM,eAAe,UAAU,IAAI,MAAM;AAGzC,OAAI,WAAW;IACd,YAAY,aAAa;IACzB,MAAM,aAAa;GACnB;EACD,EACD;CACD;CAGD,AAAU,WAAWC,GAAqB;EACzC,MAAM,UAAU,EAAE;AAClB,SAAO,SAAS,cAAc,SAAS,OAAO;CAC9C;CAED,AAAQ,QAAwD;AAC/D,SAAO,EACN,QAAQ,OAAO,QAAQ;AACtB,OAAI;IACH,MAAM,EAAE,MAAM,OAAO,QAAQ,GAAG,KAAK,SAAS,IAAI,MAAM;IACxD,MAAM,UAAU,IAAI,MAAM;IAC1B,MAAM,SAAS,SAAS,cAAc,QAAQ;IAC9C,MAAM,SAAS,KAAK,WAAW,IAAI,MAAM;AAEzC,QAAI,IAAI,OAAO,QAAQ,MAAM,KAAK,SAAS,WAAW,MAAM,OAAO,CAAC;AAEpE,QACC,IAAI,OACJ,SACA,MAAM,KAAK,SAAS,WAAW,OAAO,QAAQ,CAC9C;AACD,QACC,IAAI,OACJ,UACA,MAAM,KAAK,SAAS,WAAW,QAAQ,SAAS,CAChD;AACD,QAAI,IAAI,OAAO,UAAU,OAAO;AAChC,QAAI,IAAI,OAAO,UAAU,OAAO;GAChC,SAAQ,OAAO;AAEf,QAAI,gBAAgB,UAAU,YAAY,MAAM,QAAQ,MAAM,CAC7D,OAAM,IAAI,yBAAyB,qBAAqB;AAEzD,UAAM;GACN;EACD,EACD;CACD;CAID,AAAQ,SAAyD;AAChE,SAAO,EACN,QAAQ,CAAC,QAAQ;AAChB,OAAI,MAAM,SAAS,KAAK,SAAS,OAAO,MAAM;IAC7C,OAAO,KAAK,SAAS;IACrB,MAAM,IAAI,MAAM,SAAS;IACzB,QAAQ,KAAK,SAAS;IACtB,GAAG,KAAK,iBAAiB,IAAI,OAAO,IAAI,QAAQ;GAChD,EAAC;EACF,EACD;CACD;CACD,AAAQ,WAA2D;AAClE,SAAO,EACN,QAAQ,OAAO,QAAQ;GACtB,MAAM,UAAU,IAAI,MAAM;GAC1B,MAAM,mBAAmB,iBAAiB,YAExC,KAAK,UAAU;GAEjB,MAAM,WAAW,MAAM,iBAAiB,SACvC,KAAK,SAAS,SACd;AAED,OAAI,MAAM,WAAW;EACrB,EACD;CACD;CAED,AAAQ,YAA4D;AACnE,SAAO,EACN,QAAQ,OAAO,QAAQ;GACtB,MAAM,SAAS,IAAI,MAAM;GACzB,MAAM,WAAW,IAAI,MAAM;GAC3B,MAAM,SAAS,IAAI,MAAM;GACzB,MAAM,SAAS,IAAI,MAAM;GACzB,MAAM,UAAU,IAAI,MAAM;GAE1B,MAAM,eAAe,MAAM,KAAK,SAAS,UAAU;IAClD;IACA;IACA;IACA;IACA;GACA,EAAC;AAEF,QAAK,cAAc;AAClB,WAAO,KAAK,8BAA8B;AAC1C,UAAM,IAAI,kBACT,uCACA;GAED;EACD,EACD;CACD;CAED,AAAQ,WAA2D;AAClE,SAAO,EACN,QAAQ,OAAO,QAAQ;AACtB,QAAK,KAAK,SAAS,gBAClB;GAGD,MAAM,UAAU,IAAI,MAAM;GAC1B,MAAM,mBAAmB,iBAAiB,YAExC,KAAK,UAAU;GAEjB,MAAM,KAAK,MAAM,iBACf,SAAS,CAAC,KAAK,SAAS,eAAgB,EAAC,CACzC,KACA,CAAC,MACA,EAAE,KAAK,SAAS,iBAAiB,aAClC;AAEF,GAAC,IAAI,MAAc,KAAK;EACxB,EACD;CACD;CAED,AAAQ,UAA0D;AACjE,SAAO,EACN,QAAQ,OAAO,QAAQ;GACtB,MAAM,SAAS,IAAI,MAAM;GACzB,MAAM,WAAW,IAAI,MAAM;GAC3B,MAAM,KAAM,IAAI,MAAc;AAC9B,OAAI,MAAM,UAAW,MAAM,KAAK,SAAS,WAAW;IACnD;IACA;IACA,QAAQ,IAAI,MAAM;IAClB,QAAQ,IAAI,MAAM;IAClB,GAAI,iBAAoB,EAAE,GAAI;GAC9B,EAAQ;EACT,EACD;CACD;CAED,AAAQ,SAAyD;AAChE,SAAO,EACN,OAAO,OAAO,QAAQ;GACrB,MAAM,QAAQ,IAAI;GAClB,MAAM,WAAY,MAChB;GACF,MAAM,aAAa,IAAI,UAAU,cAAc,KAAK,SAAS;AAI7D,OAAI,SAAS,gBAAgB,WAAW,EAAE;IACzC,MAAM,SAAS,MAAM;IACrB,MAAM,mBAAmB,iBAAiB,YAExC,KAAK,UAAU;AAGjB,UAAM,uBACL,KAAK,UACL,UACA,kBACA,OACA;GACD;EACD,EACD;CACD;CAED,MAAc,SACbC,OACC;EACD,MAAM,QAAQ,KAAK,SAAS,YAAY,MAAM;EAC9C,MAAM,SAAS,MAAM;EACrB,MAAM,mBAAmB,iBAAiB,YAExC,KAAK,UAAU;EAGjB,MAAM,eAAe,MAAM,mBAC1B,KAAK,UACL,kBACA,QACA;GACC,SAAS,MAAM;GACf,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd,UAAU,MAAM;EAChB,EACD;EAGD,MAAM,SAAS,KAAK,SAAS;AAI7B,OAAK,gBAAgB,QAAQ,OAC5B,QAAO,KAAK,uCAAuC;EAIpD,MAAM,QAAS,MAAc;EAG7B,MAAM,YACL,KAAK,SAAS,cACb,KAAK,SAAS,aACf;EACD,MAAM,aAAa,YAChB,MAAM,KAAK,SAAS,WAAW,UAAU;GACzC,UAAU,MAAM;GAChB,SAAS,MAAM;GACf,QAAQ,MAAM;GACd,QAAQ,MAAM;GACd;EACA,EAAC;EAIJ,MAAM,SAAS,MAAM,4BACpB,cACA,OAAO,YAAY;GAElB,MAAM,eACL,cAAc,SAAS,uBACvB,aAAa,QAAQ,wBACpB,KAAK,SAAS,iBAAiB;GACjC,MAAM,SAAS,eACX,SAAS,kBAAkB,IAAI,QAChC;GAGH,MAAM,iBAAiB,OAAOC,OAAY;IACzC,MAAM,kBAAkB,IAAI;IAC5B,MAAM,WAAW,MAAM,KAAK,SAAS,QACpC;KACC,QAAQ,MAAM;KACd,QAAQ,MAAM;KACd,QAAQ,MAAM;KACd,UAAU,MAAM;KAChB,SAAS,MAAM;KACf;KACA;KACA,GAAG;IACH,GACD,gBACA;IAGD,IAAI,OAAO;IACX,IAAIC,aAAW,gBAAgB,aAAa;AAE5C,QAAI,SAAS,YAAY,SAAS,EAAE;AACnC,YAAO,SAAS;AAChB,kBAAW,SAAS;IACpB;IAED,MAAMC,WAAS,KAAK,SAAS,eAC1B,MAAM,KAAK,SAAS,YAAY,KAAK;AAGxC,WAAO;KAAE;KAAQ;KAAU;IAAiB;GAC5C;AAGD,OAAI,aAAa,cAAc,OAC9B,QAAO,eACN,QACA,YACA,OAAOC,QAAa,eAAe,IAAI,EACvC,EAAE,QAAQ,KAAK,SAAS,WAAW,OAAQ,EAC3C;AAGF,UAAO,eAAe,OAAO;EAC7B,GAED,OAAOC,UAAQ,YAAY;AAC1B,QAAK,QAAQ,OAAQ;AAErB,QAAK,MAAM,SAAS,QAAQ;AAC3B,QAAI,MAAM,SAAS,MAAM,KAAKA,SAAO,OAAc,CAClD;IAED,MAAM,UAAU,MAAM,QAAQA,SAAO,OAAc;IACnD,MAAM,WAAW,MAAM,WAAWA,SAAO,OAAc;AACvD,YAAQ,MAAM,MAAM,MAAa,SAAgB;KAChD,OAAO,MAAM;KACb;IACA,EAAC;GACF;EACD,GAED,EAAE,IAAI,MAAO,EACb;EAED,MAAM,EAAE,QAAQ,UAAU,GAAG;EAC7B,MAAM,OAAO,oBAAuB,KAAK,UAAU,OAAO;AAG1D,EAAC,MAAc,aAAa;EAG5B,MAAMC,iBAA0D;GAC/D,YAAY,SAAS,UAAU,KAAK,SAAS;GAC7C;EACA;AAGD,MAAI,SAAS,WAAW,OAAO,KAAK,SAAS,QAAQ,CAAC,SAAS,EAC9D,gBAAe,UAAU,EAAE,GAAG,SAAS,QAAS;AAIjD,MAAI,SAAS,WAAW,SAAS,QAAQ,OAAO,GAAG;GAClD,MAAMC,mBAA6B,CAAE;AACrC,QAAK,MAAM,CAAC,MAAM,EAAE,OAAO,SAAS,CAAC,IAAI,SAAS,QACjD,kBAAiB,KAChB,SAAS,mBAAmB,MAAM,OAAO,QAAQ,CACjD;AAGF,OAAI,iBAAiB,SAAS,EAC7B,gBAAe,oBAAoB;IAClC,GAAG,eAAe;IAClB,cAAc;GACd;EAEF;AAED,SAAO;CACP;;;;CAKD,AAAQ,YAAmE;AAC1E,OAAK,KAAK,QAAQ,UACjB,QAAO;EAGR,MAAM,YAAY,KAAK,QAAQ;EAC/B,IAAIC;AAEJ,SAAO;GACN,QAAQ,CAAC,YAAY;AACpB,UAAM,UAAU,eAAe;KAC9B,OAAO,QAAQ;KACf,SAAS,QAAQ;IACjB,EAAC;GACF;GACD,OAAO,CAAC,YAAY;AACnB,QAAI,IACH,WAAU,aAAa,KAAK;KAC3B,YAAY,QAAQ,UAAU,cAAc;KAC5C,MAAM,QAAQ,UAAU;KACxB,SAAS,QAAQ,UAAU;IAC3B,EAAC;GAEH;GACD,SAAS,CAAC,YAAY;AACrB,QAAI,OAAO,QAAQ,MAClB,WAAU,eACT,KACA,QAAQ,iBAAiB,QACtB,QAAQ,QACR,IAAI,MAAM,OAAO,QAAQ,MAAM,EAClC;GAEF;EACD;CACD;CAED,IAAI,UAAU;EACb,MAAM,UAAU,KAAK,SAAS,KAAK,KAAK;EACxC,IAAI,QAAQ,MAAM,QAAQ,CACxB,IAAI,KAAK,QAAQ,CAAC,CAClB,IAAI,KAAK,OAAO,CAAC,CACjB,IAAI,KAAK,UAAU,CAAC,CACpB,IAAI,KAAK,OAAO,CAAC,CACjB,IAAI,KAAK,UAAU,CAAC,CACpB,IAAI,KAAK,SAAS,CAAC,CACnB,IAAI,KAAK,WAAW,CAAC,CACrB,IAAI,KAAK,QAAQ,CAAC;EAGpB,MAAM,sBAAsB,KAAK,WAAW;AAC5C,MAAI,oBACH,SAAQ,MAAM,IAAI,oBAAoB;AAIvC,MAAI,KAAK,QAAQ,WAAW,WAC3B,SAAQ,MAAM,IAAI,KAAK,QAAQ,UAAU,WAAW;EAIrD,MAAM,iBAAiB,OAAOC,OAAeC,YAAqB;GACjE,MAAM,YAAY,KAAK,KAAK;GAC5B,MAAM,YAAY,QAAQ;GAC1B,MAAM,SAAS,KAAK,SAAS,OAAO,MAAM,EAAE,UAAW,EAAC;AAIxD,UAAO,sBAAsB;IAAE;IAAQ;IAAW;GAAW,GAAE,MAC9D,MAAM,OAAiD,QAAQ,CAC/D;EACD;AAED,SAAO;CACP;AACD"}