@geekmidas/constructs 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{AWSLambdaFunction-DCh1tOhB.d.mts → AWSLambdaFunction-D9RZhm0N.d.mts} +3 -3
- package/dist/{AWSLambdaSubscriberAdaptor-DtNZPMoV.d.mts → AWSLambdaSubscriberAdaptor-C0aZBU64.d.mts} +2 -2
- package/dist/{AmazonApiGatewayEndpointAdaptor-CPqlw2Rx.cjs → AmazonApiGatewayEndpointAdaptor-Bk6ssx3K.cjs} +38 -25
- package/dist/AmazonApiGatewayEndpointAdaptor-Bk6ssx3K.cjs.map +1 -0
- package/dist/{AmazonApiGatewayEndpointAdaptor-TP_hLNAa.d.cts → AmazonApiGatewayEndpointAdaptor-CbJqLU6I.d.cts} +2 -2
- package/dist/{AmazonApiGatewayEndpointAdaptor-BaTM2TNu.d.mts → AmazonApiGatewayEndpointAdaptor-DC3N7zY_.d.mts} +3 -3
- package/dist/{AmazonApiGatewayEndpointAdaptor-Cm4iD199.mjs → AmazonApiGatewayEndpointAdaptor-pEWzF2uY.mjs} +38 -25
- package/dist/AmazonApiGatewayEndpointAdaptor-pEWzF2uY.mjs.map +1 -0
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-B2ZpUFiC.d.mts → AmazonApiGatewayV1EndpointAdaptor-BVxgQ-7J.d.mts} +4 -4
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-CConfCqz.d.cts → AmazonApiGatewayV1EndpointAdaptor-CVwJ5k16.d.cts} +3 -3
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-D38HuQa9.mjs → AmazonApiGatewayV1EndpointAdaptor-MJpRbIaQ.mjs} +2 -2
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-D38HuQa9.mjs.map → AmazonApiGatewayV1EndpointAdaptor-MJpRbIaQ.mjs.map} +1 -1
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-tjpvLBRb.cjs → AmazonApiGatewayV1EndpointAdaptor-uBp_4zLf.cjs} +2 -2
- package/dist/{AmazonApiGatewayV1EndpointAdaptor-tjpvLBRb.cjs.map → AmazonApiGatewayV1EndpointAdaptor-uBp_4zLf.cjs.map} +1 -1
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-DurJvFwa.d.cts → AmazonApiGatewayV2EndpointAdaptor-1oBZdQH3.d.cts} +3 -3
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-BwMQInBi.d.mts → AmazonApiGatewayV2EndpointAdaptor-C3H8Hpv7.d.mts} +4 -4
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-ByYtiJtN.mjs → AmazonApiGatewayV2EndpointAdaptor-ChO8BlDz.mjs} +2 -2
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-ByYtiJtN.mjs.map → AmazonApiGatewayV2EndpointAdaptor-ChO8BlDz.mjs.map} +1 -1
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-DcJ_w3ro.cjs → AmazonApiGatewayV2EndpointAdaptor-I1W23Nvn.cjs} +2 -2
- package/dist/{AmazonApiGatewayV2EndpointAdaptor-DcJ_w3ro.cjs.map → AmazonApiGatewayV2EndpointAdaptor-I1W23Nvn.cjs.map} +1 -1
- package/dist/{Authorizer-D1w7MpK6.d.mts → Authorizer-Cpx59w_q.d.mts} +1 -1
- package/dist/{BaseFunctionBuilder-Oc2xmxmg.d.mts → BaseFunctionBuilder-CoV7J45W.d.mts} +2 -2
- package/dist/{Construct-DCPATqec.d.mts → Construct-jBKqb-Zi.d.mts} +1 -1
- package/dist/Construct.d.mts +1 -1
- package/dist/{Cron-DPEcDCDW.d.mts → Cron-JZkp_fHy.d.mts} +2 -2
- package/dist/{CronBuilder-CxKTiepV.d.mts → CronBuilder-BmFDO0Dm.d.mts} +4 -4
- package/dist/{Endpoint-DbPsw13b.mjs → Endpoint-B70_KKhu.mjs} +8 -2
- package/dist/Endpoint-B70_KKhu.mjs.map +1 -0
- package/dist/{Endpoint-CA-byrDr.cjs → Endpoint-BJo9Hhwm.cjs} +8 -2
- package/dist/Endpoint-BJo9Hhwm.cjs.map +1 -0
- package/dist/{Endpoint-DoY1Owv2.d.mts → Endpoint-C5djXyae.d.mts} +69 -6
- package/dist/{Endpoint-BJPJTGjV.d.cts → Endpoint-CC2RGjkl.d.cts} +66 -3
- package/dist/{EndpointBuilder-BJRkivxQ.d.mts → EndpointBuilder-CD8LkBda.d.mts} +42 -5
- package/dist/{EndpointBuilder-Bhyft7WY.cjs → EndpointBuilder-DeswNQdG.cjs} +55 -3
- package/dist/EndpointBuilder-DeswNQdG.cjs.map +1 -0
- package/dist/{EndpointBuilder-69uVrKZL.mjs → EndpointBuilder-FyyoFTJ5.mjs} +55 -3
- package/dist/{EndpointBuilder-Bhyft7WY.cjs.map → EndpointBuilder-FyyoFTJ5.mjs.map} +1 -1
- package/dist/{EndpointBuilder-CQ-jOXsD.d.cts → EndpointBuilder-vXk6eIJk.d.cts} +39 -2
- package/dist/{EndpointFactory-DgwmAR_8.d.cts → EndpointFactory-3g-7Rznt.d.cts} +30 -8
- package/dist/{EndpointFactory-BKEPcQgE.d.mts → EndpointFactory-DaFR9LQG.d.mts} +31 -9
- package/dist/{EndpointFactory-BcVbkrxf.cjs → EndpointFactory-DcT_g9M_.cjs} +63 -14
- package/dist/EndpointFactory-DcT_g9M_.cjs.map +1 -0
- package/dist/{EndpointFactory-ARUlRlyM.mjs → EndpointFactory-KJAjBWmO.mjs} +63 -14
- package/dist/EndpointFactory-KJAjBWmO.mjs.map +1 -0
- package/dist/{Function-Dthlh2Fb.d.mts → Function-Vh1t-Qjj.d.mts} +2 -2
- package/dist/{FunctionBuilder-CZFBLfdV.d.mts → FunctionBuilder-3jsoFffg.d.mts} +4 -4
- package/dist/{FunctionExecutionWrapper-CfuajSB5.d.mts → FunctionExecutionWrapper-CI3CaoCo.d.mts} +2 -2
- package/dist/{HonoEndpointAdaptor-sSG85VER.d.cts → HonoEndpointAdaptor-BJh4J-J9.d.cts} +2 -2
- package/dist/{HonoEndpointAdaptor-BmB4Sc7L.mjs → HonoEndpointAdaptor-CcvXzoYV.mjs} +41 -28
- package/dist/HonoEndpointAdaptor-CcvXzoYV.mjs.map +1 -0
- package/dist/{HonoEndpointAdaptor-CnqR6PSB.cjs → HonoEndpointAdaptor-DodwLM0-.cjs} +41 -28
- package/dist/HonoEndpointAdaptor-DodwLM0-.cjs.map +1 -0
- package/dist/{HonoEndpointAdaptor-DBjipl6Q.d.mts → HonoEndpointAdaptor-kb1ByjUL.d.mts} +5 -5
- package/dist/{Subscriber-DvOtIyWq.cjs → Subscriber-DOt3svUC.cjs} +1 -1
- package/dist/{Subscriber-DvOtIyWq.cjs.map → Subscriber-DOt3svUC.cjs.map} +1 -1
- package/dist/{Subscriber-BfxLwZpX.d.mts → Subscriber-aNr1qkxR.d.mts} +2 -2
- package/dist/{Subscriber-JzcFFi4p.mjs → Subscriber-kCHbH2fZ.mjs} +1 -1
- package/dist/{Subscriber-JzcFFi4p.mjs.map → Subscriber-kCHbH2fZ.mjs.map} +1 -1
- package/dist/{SubscriberBuilder-lTiTUS1o.d.mts → SubscriberBuilder-CWS4tdbp.d.mts} +2 -2
- package/dist/{SubscriberBuilder-DUuV207i.cjs → SubscriberBuilder-Cj2u9k5Q.cjs} +2 -2
- package/dist/{SubscriberBuilder-DUuV207i.cjs.map → SubscriberBuilder-Cj2u9k5Q.cjs.map} +1 -1
- package/dist/{SubscriberBuilder-tm4oVOt3.mjs → SubscriberBuilder-DmxMU89X.mjs} +2 -2
- package/dist/{SubscriberBuilder-tm4oVOt3.mjs.map → SubscriberBuilder-DmxMU89X.mjs.map} +1 -1
- package/dist/{TestEndpointAdaptor-o7JbNcL-.mjs → TestEndpointAdaptor-1pPixE6y.mjs} +2 -2
- package/dist/{TestEndpointAdaptor-o7JbNcL-.mjs.map → TestEndpointAdaptor-1pPixE6y.mjs.map} +1 -1
- package/dist/{TestEndpointAdaptor-CGQVysE0.d.mts → TestEndpointAdaptor-5-unBV8O.d.mts} +3 -3
- package/dist/{TestEndpointAdaptor-CJO-og9U.d.cts → TestEndpointAdaptor-Bm0UjDtV.d.cts} +2 -2
- package/dist/{TestEndpointAdaptor-BtLcw4JW.cjs → TestEndpointAdaptor-wA-fmq4v.cjs} +2 -2
- package/dist/{TestEndpointAdaptor-BtLcw4JW.cjs.map → TestEndpointAdaptor-wA-fmq4v.cjs.map} +1 -1
- package/dist/adaptors/aws.cjs +4 -4
- package/dist/adaptors/aws.d.cts +4 -4
- package/dist/adaptors/aws.d.mts +15 -15
- package/dist/adaptors/aws.mjs +4 -4
- package/dist/adaptors/hono.cjs +3 -3
- package/dist/adaptors/hono.d.cts +2 -2
- package/dist/adaptors/hono.d.mts +9 -9
- package/dist/adaptors/hono.mjs +3 -3
- package/dist/adaptors/testing.cjs +2 -2
- package/dist/adaptors/testing.d.cts +2 -2
- package/dist/adaptors/testing.d.mts +9 -9
- package/dist/adaptors/testing.mjs +2 -2
- package/dist/crons/Cron.d.mts +6 -6
- package/dist/crons/CronBuilder.d.mts +7 -7
- package/dist/crons/index.d.mts +7 -7
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.cjs +2 -2
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.cts +2 -2
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.d.mts +9 -9
- package/dist/endpoints/AmazonApiGatewayEndpointAdaptor.mjs +2 -2
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.cjs +3 -3
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.cts +3 -3
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.d.mts +10 -10
- package/dist/endpoints/AmazonApiGatewayV1EndpointAdaptor.mjs +3 -3
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.cjs +3 -3
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.cts +3 -3
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.d.mts +10 -10
- package/dist/endpoints/AmazonApiGatewayV2EndpointAdaptor.mjs +3 -3
- package/dist/endpoints/Authorizer.d.mts +1 -1
- package/dist/endpoints/Endpoint.cjs +1 -1
- package/dist/endpoints/Endpoint.d.cts +1 -1
- package/dist/endpoints/Endpoint.d.mts +8 -8
- package/dist/endpoints/Endpoint.mjs +1 -1
- package/dist/endpoints/EndpointBuilder.cjs +3 -2
- package/dist/endpoints/EndpointBuilder.d.cts +2 -2
- package/dist/endpoints/EndpointBuilder.d.mts +9 -9
- package/dist/endpoints/EndpointBuilder.mjs +3 -2
- package/dist/endpoints/EndpointFactory.cjs +4 -3
- package/dist/endpoints/EndpointFactory.d.cts +3 -3
- package/dist/endpoints/EndpointFactory.d.mts +10 -10
- package/dist/endpoints/EndpointFactory.mjs +4 -3
- package/dist/endpoints/HonoEndpointAdaptor.cjs +3 -3
- package/dist/endpoints/HonoEndpointAdaptor.d.cts +2 -2
- package/dist/endpoints/HonoEndpointAdaptor.d.mts +9 -9
- package/dist/endpoints/HonoEndpointAdaptor.mjs +3 -3
- package/dist/endpoints/TestEndpointAdaptor.cjs +2 -2
- package/dist/endpoints/TestEndpointAdaptor.d.cts +2 -2
- package/dist/endpoints/TestEndpointAdaptor.d.mts +9 -9
- package/dist/endpoints/TestEndpointAdaptor.mjs +2 -2
- package/dist/endpoints/audit.d.cts +1 -1
- package/dist/endpoints/audit.d.mts +8 -8
- package/dist/endpoints/helpers.cjs +2 -2
- package/dist/endpoints/helpers.d.cts +1 -1
- package/dist/endpoints/helpers.d.mts +8 -8
- package/dist/endpoints/helpers.mjs +2 -2
- package/dist/endpoints/index.cjs +5 -3
- package/dist/endpoints/index.cjs.map +1 -1
- package/dist/endpoints/index.d.cts +5 -5
- package/dist/endpoints/index.d.mts +13 -13
- package/dist/endpoints/index.mjs +5 -4
- package/dist/endpoints/index.mjs.map +1 -1
- package/dist/endpoints/processAudits.d.cts +1 -1
- package/dist/endpoints/processAudits.d.mts +8 -8
- package/dist/endpoints/rls.cjs +3 -0
- package/dist/endpoints/rls.d.cts +9 -0
- package/dist/endpoints/rls.d.mts +9 -0
- package/dist/endpoints/rls.mjs +3 -0
- package/dist/functions/AWSLambdaFunction.d.mts +4 -4
- package/dist/functions/BaseFunctionBuilder.d.mts +2 -2
- package/dist/functions/Function.d.mts +2 -2
- package/dist/functions/FunctionBuilder.d.mts +4 -4
- package/dist/functions/FunctionExecutionWrapper.d.mts +3 -3
- package/dist/functions/TestFunctionAdaptor.d.mts +2 -2
- package/dist/functions/index.d.mts +5 -5
- package/dist/{helpers-CrrdyA04.mjs → helpers-C3B2lVrM.mjs} +2 -2
- package/dist/{helpers-CrrdyA04.mjs.map → helpers-C3B2lVrM.mjs.map} +1 -1
- package/dist/{helpers-DiPZVJQC.cjs → helpers-DxxSpLfw.cjs} +2 -2
- package/dist/{helpers-DiPZVJQC.cjs.map → helpers-DxxSpLfw.cjs.map} +1 -1
- package/dist/{index-9gJrM7Rw.d.mts → index-CFyaRrck.d.mts} +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/publisher.d.mts +1 -1
- package/dist/rls-Bf3FRwto.mjs +9 -0
- package/dist/rls-Bf3FRwto.mjs.map +1 -0
- package/dist/rls-CmJ7bRsz.cjs +15 -0
- package/dist/rls-CmJ7bRsz.cjs.map +1 -0
- package/dist/subscribers/AWSLambdaSubscriberAdaptor.d.mts +3 -3
- package/dist/subscribers/Subscriber.cjs +1 -1
- package/dist/subscribers/Subscriber.d.mts +2 -2
- package/dist/subscribers/Subscriber.mjs +1 -1
- package/dist/subscribers/SubscriberBuilder.cjs +2 -2
- package/dist/subscribers/SubscriberBuilder.d.mts +3 -3
- package/dist/subscribers/SubscriberBuilder.mjs +2 -2
- package/dist/subscribers/index.cjs +2 -2
- package/dist/subscribers/index.d.mts +3 -3
- package/dist/subscribers/index.mjs +2 -2
- package/dist/{types-Cy1IhmUB.d.mts → types-CScirkHt.d.mts} +1 -1
- package/dist/types.d.mts +1 -1
- package/package.json +6 -5
- package/src/endpoints/AmazonApiGatewayEndpointAdaptor.ts +57 -26
- package/src/endpoints/Endpoint.ts +19 -0
- package/src/endpoints/EndpointBuilder.ts +57 -0
- package/src/endpoints/EndpointFactory.ts +119 -12
- package/src/endpoints/HonoEndpointAdaptor.ts +66 -37
- package/src/endpoints/index.ts +7 -0
- package/src/endpoints/rls.ts +67 -0
- package/dist/AmazonApiGatewayEndpointAdaptor-CPqlw2Rx.cjs.map +0 -1
- package/dist/AmazonApiGatewayEndpointAdaptor-Cm4iD199.mjs.map +0 -1
- package/dist/Endpoint-CA-byrDr.cjs.map +0 -1
- package/dist/Endpoint-DbPsw13b.mjs.map +0 -1
- package/dist/EndpointBuilder-69uVrKZL.mjs.map +0 -1
- package/dist/EndpointFactory-ARUlRlyM.mjs.map +0 -1
- package/dist/EndpointFactory-BcVbkrxf.cjs.map +0 -1
- package/dist/HonoEndpointAdaptor-BmB4Sc7L.mjs.map +0 -1
- package/dist/HonoEndpointAdaptor-CnqR6PSB.cjs.map +0 -1
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
import type { AuthorizeFn, SessionFn } from './Endpoint';
|
|
18
18
|
import { EndpointBuilder } from './EndpointBuilder';
|
|
19
19
|
import type { ActorExtractor } from './audit';
|
|
20
|
+
import type { RlsConfig } from './rls';
|
|
20
21
|
|
|
21
22
|
const DEFAULT_LOGGER = new ConsoleLogger() as any;
|
|
22
23
|
|
|
@@ -40,6 +41,9 @@ export class EndpointFactory<
|
|
|
40
41
|
string,
|
|
41
42
|
SecurityScheme
|
|
42
43
|
>,
|
|
44
|
+
TRlsConfig extends
|
|
45
|
+
| RlsConfig<TServices, TSession, TLogger>
|
|
46
|
+
| undefined = undefined,
|
|
43
47
|
> {
|
|
44
48
|
// @ts-ignore
|
|
45
49
|
private defaultServices: TServices;
|
|
@@ -65,6 +69,7 @@ export class EndpointFactory<
|
|
|
65
69
|
| undefined;
|
|
66
70
|
private defaultActorExtractor?: ActorExtractor<TServices, TSession, TLogger>;
|
|
67
71
|
private customSecuritySchemes: TSecuritySchemes = {} as TSecuritySchemes;
|
|
72
|
+
private defaultRlsConfig?: TRlsConfig;
|
|
68
73
|
|
|
69
74
|
constructor({
|
|
70
75
|
basePath,
|
|
@@ -80,6 +85,7 @@ export class EndpointFactory<
|
|
|
80
85
|
defaultDatabaseService,
|
|
81
86
|
defaultActorExtractor,
|
|
82
87
|
customSecuritySchemes = {} as TSecuritySchemes,
|
|
88
|
+
defaultRlsConfig,
|
|
83
89
|
}: EndpointFactoryOptions<
|
|
84
90
|
TServices,
|
|
85
91
|
TBasePath,
|
|
@@ -92,7 +98,8 @@ export class EndpointFactory<
|
|
|
92
98
|
TAuditStorageServiceName,
|
|
93
99
|
TDatabase,
|
|
94
100
|
TDatabaseServiceName,
|
|
95
|
-
TSecuritySchemes
|
|
101
|
+
TSecuritySchemes,
|
|
102
|
+
TRlsConfig
|
|
96
103
|
> = {}) {
|
|
97
104
|
// Initialize default services
|
|
98
105
|
this.defaultServices = uniqBy(
|
|
@@ -111,6 +118,7 @@ export class EndpointFactory<
|
|
|
111
118
|
this.defaultDatabaseService = defaultDatabaseService;
|
|
112
119
|
this.defaultActorExtractor = defaultActorExtractor;
|
|
113
120
|
this.customSecuritySchemes = customSecuritySchemes;
|
|
121
|
+
this.defaultRlsConfig = defaultRlsConfig;
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
static joinPaths<TBasePath extends string, P extends string>(
|
|
@@ -184,7 +192,8 @@ export class EndpointFactory<
|
|
|
184
192
|
TAuditAction,
|
|
185
193
|
TDatabase,
|
|
186
194
|
TDatabaseServiceName,
|
|
187
|
-
TSecuritySchemes
|
|
195
|
+
TSecuritySchemes,
|
|
196
|
+
TRlsConfig
|
|
188
197
|
>({
|
|
189
198
|
defaultServices: this.defaultServices,
|
|
190
199
|
basePath: this.basePath,
|
|
@@ -198,6 +207,7 @@ export class EndpointFactory<
|
|
|
198
207
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
199
208
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
200
209
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
210
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
201
211
|
});
|
|
202
212
|
}
|
|
203
213
|
|
|
@@ -326,7 +336,8 @@ export class EndpointFactory<
|
|
|
326
336
|
TAuditAction,
|
|
327
337
|
TDatabase,
|
|
328
338
|
TDatabaseServiceName,
|
|
329
|
-
TSecuritySchemes
|
|
339
|
+
TSecuritySchemes,
|
|
340
|
+
TRlsConfig
|
|
330
341
|
>({
|
|
331
342
|
defaultServices: this.defaultServices,
|
|
332
343
|
basePath: this.basePath,
|
|
@@ -341,6 +352,7 @@ export class EndpointFactory<
|
|
|
341
352
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
342
353
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
343
354
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
355
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
344
356
|
});
|
|
345
357
|
}
|
|
346
358
|
|
|
@@ -376,7 +388,8 @@ export class EndpointFactory<
|
|
|
376
388
|
TAuditAction,
|
|
377
389
|
TDatabase,
|
|
378
390
|
TDatabaseServiceName,
|
|
379
|
-
TSecuritySchemes
|
|
391
|
+
TSecuritySchemes,
|
|
392
|
+
TRlsConfig
|
|
380
393
|
>({
|
|
381
394
|
defaultServices: this.defaultServices,
|
|
382
395
|
basePath: newBasePath,
|
|
@@ -390,6 +403,7 @@ export class EndpointFactory<
|
|
|
390
403
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
391
404
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
392
405
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
406
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
393
407
|
});
|
|
394
408
|
}
|
|
395
409
|
|
|
@@ -424,7 +438,8 @@ export class EndpointFactory<
|
|
|
424
438
|
TAuditAction,
|
|
425
439
|
TDatabase,
|
|
426
440
|
TDatabaseServiceName,
|
|
427
|
-
TSecuritySchemes
|
|
441
|
+
TSecuritySchemes,
|
|
442
|
+
TRlsConfig
|
|
428
443
|
>({
|
|
429
444
|
defaultServices: this.defaultServices,
|
|
430
445
|
basePath: this.basePath,
|
|
@@ -438,6 +453,7 @@ export class EndpointFactory<
|
|
|
438
453
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
439
454
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
440
455
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
456
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
441
457
|
});
|
|
442
458
|
}
|
|
443
459
|
|
|
@@ -472,7 +488,8 @@ export class EndpointFactory<
|
|
|
472
488
|
TAuditAction,
|
|
473
489
|
TDatabase,
|
|
474
490
|
TDatabaseServiceName,
|
|
475
|
-
TSecuritySchemes
|
|
491
|
+
TSecuritySchemes,
|
|
492
|
+
TRlsConfig
|
|
476
493
|
>({
|
|
477
494
|
defaultServices: [...services, ...this.defaultServices],
|
|
478
495
|
basePath: this.basePath,
|
|
@@ -486,6 +503,7 @@ export class EndpointFactory<
|
|
|
486
503
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
487
504
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
488
505
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
506
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
489
507
|
});
|
|
490
508
|
}
|
|
491
509
|
|
|
@@ -519,7 +537,8 @@ export class EndpointFactory<
|
|
|
519
537
|
TAuditAction,
|
|
520
538
|
TDatabase,
|
|
521
539
|
TDatabaseServiceName,
|
|
522
|
-
TSecuritySchemes
|
|
540
|
+
TSecuritySchemes,
|
|
541
|
+
TRlsConfig
|
|
523
542
|
>({
|
|
524
543
|
defaultServices: this.defaultServices,
|
|
525
544
|
basePath: this.basePath,
|
|
@@ -547,6 +566,7 @@ export class EndpointFactory<
|
|
|
547
566
|
L
|
|
548
567
|
>,
|
|
549
568
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
569
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
550
570
|
});
|
|
551
571
|
}
|
|
552
572
|
|
|
@@ -583,7 +603,8 @@ export class EndpointFactory<
|
|
|
583
603
|
TAuditAction,
|
|
584
604
|
TDatabase,
|
|
585
605
|
TDatabaseServiceName,
|
|
586
|
-
TSecuritySchemes
|
|
606
|
+
TSecuritySchemes,
|
|
607
|
+
TRlsConfig
|
|
587
608
|
>({
|
|
588
609
|
defaultServices: this.defaultServices,
|
|
589
610
|
basePath: this.basePath,
|
|
@@ -597,6 +618,7 @@ export class EndpointFactory<
|
|
|
597
618
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
598
619
|
defaultActorExtractor: this.defaultActorExtractor,
|
|
599
620
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
621
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
600
622
|
});
|
|
601
623
|
}
|
|
602
624
|
|
|
@@ -630,7 +652,8 @@ export class EndpointFactory<
|
|
|
630
652
|
TAuditAction,
|
|
631
653
|
TDatabase,
|
|
632
654
|
TDatabaseServiceName,
|
|
633
|
-
TSecuritySchemes
|
|
655
|
+
TSecuritySchemes,
|
|
656
|
+
TRlsConfig
|
|
634
657
|
>({
|
|
635
658
|
defaultServices: this.defaultServices,
|
|
636
659
|
basePath: this.basePath,
|
|
@@ -653,6 +676,7 @@ export class EndpointFactory<
|
|
|
653
676
|
TLogger
|
|
654
677
|
>,
|
|
655
678
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
679
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
656
680
|
});
|
|
657
681
|
}
|
|
658
682
|
|
|
@@ -690,7 +714,8 @@ export class EndpointFactory<
|
|
|
690
714
|
TAuditAction,
|
|
691
715
|
T,
|
|
692
716
|
TName,
|
|
693
|
-
TSecuritySchemes
|
|
717
|
+
TSecuritySchemes,
|
|
718
|
+
TRlsConfig
|
|
694
719
|
>({
|
|
695
720
|
defaultServices: this.defaultServices,
|
|
696
721
|
basePath: this.basePath,
|
|
@@ -707,6 +732,7 @@ export class EndpointFactory<
|
|
|
707
732
|
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
708
733
|
defaultDatabaseService: service,
|
|
709
734
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
735
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
710
736
|
});
|
|
711
737
|
}
|
|
712
738
|
|
|
@@ -745,7 +771,8 @@ export class EndpointFactory<
|
|
|
745
771
|
ExtractStorageAuditAction<T>,
|
|
746
772
|
TDatabase,
|
|
747
773
|
TDatabaseServiceName,
|
|
748
|
-
TSecuritySchemes
|
|
774
|
+
TSecuritySchemes,
|
|
775
|
+
TRlsConfig
|
|
749
776
|
>({
|
|
750
777
|
defaultServices: this.defaultServices,
|
|
751
778
|
basePath: this.basePath,
|
|
@@ -764,6 +791,7 @@ export class EndpointFactory<
|
|
|
764
791
|
TLogger
|
|
765
792
|
>,
|
|
766
793
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
794
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
767
795
|
});
|
|
768
796
|
}
|
|
769
797
|
|
|
@@ -801,7 +829,8 @@ export class EndpointFactory<
|
|
|
801
829
|
TAuditAction,
|
|
802
830
|
TDatabase,
|
|
803
831
|
TDatabaseServiceName,
|
|
804
|
-
TSecuritySchemes
|
|
832
|
+
TSecuritySchemes,
|
|
833
|
+
TRlsConfig
|
|
805
834
|
>({
|
|
806
835
|
defaultServices: this.defaultServices,
|
|
807
836
|
basePath: this.basePath,
|
|
@@ -815,6 +844,75 @@ export class EndpointFactory<
|
|
|
815
844
|
defaultDatabaseService: this.defaultDatabaseService,
|
|
816
845
|
defaultActorExtractor: extractor,
|
|
817
846
|
customSecuritySchemes: this.customSecuritySchemes,
|
|
847
|
+
defaultRlsConfig: this.defaultRlsConfig,
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
/**
|
|
852
|
+
* Set the RLS (Row-Level Security) configuration for endpoints created from this factory.
|
|
853
|
+
* This enables automatic PostgreSQL session variable setting for RLS policies.
|
|
854
|
+
*
|
|
855
|
+
* @example
|
|
856
|
+
* ```typescript
|
|
857
|
+
* const api = new EndpointFactory()
|
|
858
|
+
* .database(databaseService)
|
|
859
|
+
* .session(extractSession)
|
|
860
|
+
* .rls({
|
|
861
|
+
* extractor: ({ session }) => ({
|
|
862
|
+
* user_id: session.userId,
|
|
863
|
+
* tenant_id: session.tenantId,
|
|
864
|
+
* }),
|
|
865
|
+
* prefix: 'app',
|
|
866
|
+
* });
|
|
867
|
+
* ```
|
|
868
|
+
*/
|
|
869
|
+
rls<TConfig extends RlsConfig<TServices, TSession, TLogger>>(
|
|
870
|
+
config: TConfig,
|
|
871
|
+
): EndpointFactory<
|
|
872
|
+
TServices,
|
|
873
|
+
TBasePath,
|
|
874
|
+
TLogger,
|
|
875
|
+
TSession,
|
|
876
|
+
TEventPublisher,
|
|
877
|
+
TEventPublisherServiceName,
|
|
878
|
+
TAuthorizers,
|
|
879
|
+
TAuditStorage,
|
|
880
|
+
TAuditStorageServiceName,
|
|
881
|
+
TAuditAction,
|
|
882
|
+
TDatabase,
|
|
883
|
+
TDatabaseServiceName,
|
|
884
|
+
TSecuritySchemes,
|
|
885
|
+
TConfig
|
|
886
|
+
> {
|
|
887
|
+
return new EndpointFactory<
|
|
888
|
+
TServices,
|
|
889
|
+
TBasePath,
|
|
890
|
+
TLogger,
|
|
891
|
+
TSession,
|
|
892
|
+
TEventPublisher,
|
|
893
|
+
TEventPublisherServiceName,
|
|
894
|
+
TAuthorizers,
|
|
895
|
+
TAuditStorage,
|
|
896
|
+
TAuditStorageServiceName,
|
|
897
|
+
TAuditAction,
|
|
898
|
+
TDatabase,
|
|
899
|
+
TDatabaseServiceName,
|
|
900
|
+
TSecuritySchemes,
|
|
901
|
+
TConfig
|
|
902
|
+
>({
|
|
903
|
+
defaultServices: this.defaultServices,
|
|
904
|
+
basePath: this.basePath,
|
|
905
|
+
defaultAuthorizeFn: this.defaultAuthorizeFn,
|
|
906
|
+
defaultLogger: this.defaultLogger,
|
|
907
|
+
defaultSessionExtractor: this.defaultSessionExtractor,
|
|
908
|
+
defaultEventPublisher: this.defaultEventPublisher,
|
|
909
|
+
availableAuthorizers: this.availableAuthorizers,
|
|
910
|
+
defaultAuthorizerName: this.defaultAuthorizerName,
|
|
911
|
+
defaultAuditorStorage: this.defaultAuditorStorage,
|
|
912
|
+
defaultDatabaseService: this.defaultDatabaseService,
|
|
913
|
+
defaultActorExtractor: this.defaultActorExtractor,
|
|
914
|
+
customSecuritySchemes: this.customSecuritySchemes,
|
|
915
|
+
defaultRlsConfig: config,
|
|
818
916
|
});
|
|
819
917
|
}
|
|
820
918
|
|
|
@@ -906,6 +1004,11 @@ export class EndpointFactory<
|
|
|
906
1004
|
// Set custom security schemes
|
|
907
1005
|
builder._customSecuritySchemes = this.customSecuritySchemes;
|
|
908
1006
|
|
|
1007
|
+
// Set RLS config if configured
|
|
1008
|
+
if (this.defaultRlsConfig) {
|
|
1009
|
+
builder._rlsConfig = this.defaultRlsConfig as any;
|
|
1010
|
+
}
|
|
1011
|
+
|
|
909
1012
|
return builder;
|
|
910
1013
|
}
|
|
911
1014
|
|
|
@@ -977,6 +1080,9 @@ export interface EndpointFactoryOptions<
|
|
|
977
1080
|
string,
|
|
978
1081
|
SecurityScheme
|
|
979
1082
|
>,
|
|
1083
|
+
TRlsConfig extends
|
|
1084
|
+
| RlsConfig<TServices, TSession, TLogger>
|
|
1085
|
+
| undefined = undefined,
|
|
980
1086
|
> {
|
|
981
1087
|
defaultServices?: TServices;
|
|
982
1088
|
basePath?: TBasePath;
|
|
@@ -991,6 +1097,7 @@ export interface EndpointFactoryOptions<
|
|
|
991
1097
|
defaultDatabaseService?: Service<TDatabaseServiceName, TDatabase>;
|
|
992
1098
|
defaultActorExtractor?: ActorExtractor<TServices, TSession, TLogger>;
|
|
993
1099
|
customSecuritySchemes?: TSecuritySchemes;
|
|
1100
|
+
defaultRlsConfig?: TRlsConfig;
|
|
994
1101
|
}
|
|
995
1102
|
|
|
996
1103
|
export const e = new EndpointFactory();
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
import { getEndpointsFromRoutes } from './helpers';
|
|
20
20
|
import { parseHonoQuery } from './parseHonoQuery';
|
|
21
21
|
|
|
22
|
+
import { withRlsContext } from '@geekmidas/db/rls';
|
|
22
23
|
import { wrapError } from '@geekmidas/errors';
|
|
23
24
|
import {
|
|
24
25
|
type Service,
|
|
@@ -374,6 +375,19 @@ export class HonoEndpoint<
|
|
|
374
375
|
logger.warn('No auditor storage service available');
|
|
375
376
|
}
|
|
376
377
|
|
|
378
|
+
// Extract RLS context if configured and not bypassed
|
|
379
|
+
const rlsActive =
|
|
380
|
+
endpoint.rlsConfig && !endpoint.rlsBypass && rawDb !== undefined;
|
|
381
|
+
const rlsContext = rlsActive
|
|
382
|
+
? await endpoint.rlsConfig!.extractor({
|
|
383
|
+
services,
|
|
384
|
+
session,
|
|
385
|
+
header,
|
|
386
|
+
cookie,
|
|
387
|
+
logger,
|
|
388
|
+
})
|
|
389
|
+
: undefined;
|
|
390
|
+
|
|
377
391
|
// Execute handler with automatic audit transaction support
|
|
378
392
|
const result = await executeWithAuditTransaction(
|
|
379
393
|
auditContext,
|
|
@@ -383,49 +397,64 @@ export class HonoEndpoint<
|
|
|
383
397
|
auditContext?.storage?.databaseServiceName &&
|
|
384
398
|
auditContext.storage.databaseServiceName ===
|
|
385
399
|
endpoint.databaseService?.serviceName;
|
|
386
|
-
const
|
|
400
|
+
const baseDb = sameDatabase
|
|
387
401
|
? (auditor?.getTransaction?.() ?? rawDb)
|
|
388
402
|
: rawDb;
|
|
389
403
|
|
|
390
|
-
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
404
|
+
// Helper to execute handler with given db
|
|
405
|
+
const executeHandler = async (db: TDatabase | undefined) => {
|
|
406
|
+
const responseBuilder = new ResponseBuilder();
|
|
407
|
+
const response = await endpoint.handler(
|
|
408
|
+
{
|
|
409
|
+
services,
|
|
410
|
+
logger,
|
|
411
|
+
body: c.req.valid('json'),
|
|
412
|
+
query: c.req.valid('query'),
|
|
413
|
+
params: c.req.valid('param'),
|
|
414
|
+
session,
|
|
415
|
+
header,
|
|
416
|
+
cookie,
|
|
417
|
+
auditor,
|
|
418
|
+
db,
|
|
419
|
+
} as unknown as EndpointContext<
|
|
420
|
+
TInput,
|
|
421
|
+
TServices,
|
|
422
|
+
TLogger,
|
|
423
|
+
TSession,
|
|
424
|
+
TAuditAction,
|
|
425
|
+
TDatabase,
|
|
426
|
+
TAuditStorage
|
|
427
|
+
>,
|
|
428
|
+
responseBuilder,
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
// Check if response has metadata
|
|
432
|
+
let data = response;
|
|
433
|
+
let metadata = responseBuilder.getMetadata();
|
|
434
|
+
|
|
435
|
+
if (Endpoint.hasMetadata(response)) {
|
|
436
|
+
data = response.data;
|
|
437
|
+
metadata = response.metadata;
|
|
438
|
+
}
|
|
418
439
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
440
|
+
const output = endpoint.outputSchema
|
|
441
|
+
? await endpoint.parseOutput(data)
|
|
442
|
+
: undefined;
|
|
443
|
+
|
|
444
|
+
return { output, metadata, responseBuilder };
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
// If RLS is active, wrap handler with RLS context
|
|
448
|
+
if (rlsActive && rlsContext && baseDb) {
|
|
449
|
+
return withRlsContext(
|
|
450
|
+
baseDb as any,
|
|
451
|
+
rlsContext,
|
|
452
|
+
async (trx) => executeHandler(trx as TDatabase),
|
|
453
|
+
{ prefix: endpoint.rlsConfig!.prefix },
|
|
454
|
+
);
|
|
422
455
|
}
|
|
423
456
|
|
|
424
|
-
|
|
425
|
-
? await endpoint.parseOutput(data)
|
|
426
|
-
: undefined;
|
|
427
|
-
|
|
428
|
-
return { output, metadata, responseBuilder };
|
|
457
|
+
return executeHandler(baseDb as TDatabase | undefined);
|
|
429
458
|
},
|
|
430
459
|
// Process declarative audits after handler (inside transaction)
|
|
431
460
|
async (result, auditor) => {
|
package/src/endpoints/index.ts
CHANGED
|
@@ -10,5 +10,12 @@ export {
|
|
|
10
10
|
} from './Endpoint';
|
|
11
11
|
export { EndpointBuilder } from './EndpointBuilder';
|
|
12
12
|
export { type MappedAudit, type ActorExtractor } from './audit';
|
|
13
|
+
export {
|
|
14
|
+
type RlsConfig,
|
|
15
|
+
type RlsContext,
|
|
16
|
+
type RlsContextExtractor,
|
|
17
|
+
RLS_BYPASS,
|
|
18
|
+
type RlsBypass,
|
|
19
|
+
} from './rls';
|
|
13
20
|
|
|
14
21
|
export const e = new EndpointFactory();
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Logger } from '@geekmidas/logger';
|
|
2
|
+
import type { Service, ServiceRecord } from '@geekmidas/services';
|
|
3
|
+
import type { CookieFn, HeaderFn } from './Endpoint';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* RLS context - key-value pairs to set as PostgreSQL session variables.
|
|
7
|
+
* Keys become `prefix.key` (e.g., `app.user_id`).
|
|
8
|
+
*/
|
|
9
|
+
export interface RlsContext {
|
|
10
|
+
[key: string]: string | number | boolean | null | undefined;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Function type for extracting RLS context from request context.
|
|
15
|
+
*
|
|
16
|
+
* @template TServices - Available service dependencies
|
|
17
|
+
* @template TSession - Session data type
|
|
18
|
+
* @template TLogger - Logger type
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const extractor: RlsContextExtractor<[], UserSession> = ({ session }) => ({
|
|
23
|
+
* user_id: session.userId,
|
|
24
|
+
* tenant_id: session.tenantId,
|
|
25
|
+
* roles: session.roles.join(','),
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export type RlsContextExtractor<
|
|
30
|
+
TServices extends Service[] = [],
|
|
31
|
+
TSession = unknown,
|
|
32
|
+
TLogger extends Logger = Logger,
|
|
33
|
+
> = (ctx: {
|
|
34
|
+
services: ServiceRecord<TServices>;
|
|
35
|
+
session: TSession;
|
|
36
|
+
header: HeaderFn;
|
|
37
|
+
cookie: CookieFn;
|
|
38
|
+
logger: TLogger;
|
|
39
|
+
}) => RlsContext | Promise<RlsContext>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Configuration for RLS on an endpoint or factory.
|
|
43
|
+
*
|
|
44
|
+
* @template TServices - Available service dependencies
|
|
45
|
+
* @template TSession - Session data type
|
|
46
|
+
* @template TLogger - Logger type
|
|
47
|
+
*/
|
|
48
|
+
export interface RlsConfig<
|
|
49
|
+
TServices extends Service[] = [],
|
|
50
|
+
TSession = unknown,
|
|
51
|
+
TLogger extends Logger = Logger,
|
|
52
|
+
> {
|
|
53
|
+
/** Function to extract RLS context from request */
|
|
54
|
+
extractor: RlsContextExtractor<TServices, TSession, TLogger>;
|
|
55
|
+
/** Prefix for PostgreSQL session variables (default: 'app') */
|
|
56
|
+
prefix?: string;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Symbol used to bypass RLS for an endpoint.
|
|
61
|
+
*/
|
|
62
|
+
export const RLS_BYPASS = Symbol.for('geekmidas.rls.bypass');
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Type for RLS bypass marker.
|
|
66
|
+
*/
|
|
67
|
+
export type RlsBypass = typeof RLS_BYPASS;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AmazonApiGatewayEndpointAdaptor-CPqlw2Rx.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 database(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n if (!this.endpoint.databaseService) {\n return;\n }\n\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 db = await serviceDiscovery\n .register([this.endpoint.databaseService])\n .then(\n (s) =>\n s[this.endpoint.databaseService!.serviceName as keyof typeof s],\n );\n\n (req.event as any).db = db;\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 const db = (req.event as any).db;\n req.event.session = (await this.endpoint.getSession({\n logger,\n services,\n header: req.event.header,\n cookie: req.event.cookie,\n ...(db !== undefined && { db }),\n } as any)) 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 // Get pre-resolved database from middleware\n const rawDb = (event as any).db;\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 // Pass rawDb so storage can reuse existing transactions\n { db: rawDb },\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.database())\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-Cm4iD199.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 database(): Middleware<TEvent, TInput, TServices, TLogger> {\n return {\n before: async (req) => {\n if (!this.endpoint.databaseService) {\n return;\n }\n\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 db = await serviceDiscovery\n .register([this.endpoint.databaseService])\n .then(\n (s) =>\n s[this.endpoint.databaseService!.serviceName as keyof typeof s],\n );\n\n (req.event as any).db = db;\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 const db = (req.event as any).db;\n req.event.session = (await this.endpoint.getSession({\n logger,\n services,\n header: req.event.header,\n cookie: req.event.cookie,\n ...(db !== undefined && { db }),\n } as any)) 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 // Get pre-resolved database from middleware\n const rawDb = (event as any).db;\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 // Pass rawDb so storage can reuse existing transactions\n { db: rawDb },\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.database())\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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"}
|