@geekmidas/constructs 7.0.1 → 10.0.0-alpha.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/README.md +71 -44
- package/dist/{AWSScheduledFunction-ysaCsdWx.d.mts → AWSScheduledFunction-BvFvBsBN.d.cts} +10 -5
- package/dist/{AWSScheduledFunction-ysaCsdWx.d.mts.map → AWSScheduledFunction-BvFvBsBN.d.cts.map} +1 -1
- package/dist/{AWSScheduledFunction-CTIa90EH.d.cts → AWSScheduledFunction-CVccZO-L.d.mts} +10 -5
- package/dist/{AWSScheduledFunction-CTIa90EH.d.cts.map → AWSScheduledFunction-CVccZO-L.d.mts.map} +1 -1
- package/dist/{AWSScheduledFunction-CufMMhGB.mjs → AWSScheduledFunction-Db1lttJH.mjs} +3 -3
- package/dist/{AWSScheduledFunction-CufMMhGB.mjs.map → AWSScheduledFunction-Db1lttJH.mjs.map} +1 -1
- package/dist/{AWSScheduledFunction-DbkDr8CA.cjs → AWSScheduledFunction-qu4ieRZR.cjs} +9 -9
- package/dist/{AWSScheduledFunction-DbkDr8CA.cjs.map → AWSScheduledFunction-qu4ieRZR.cjs.map} +1 -1
- package/dist/{Construct-_1wX7p_Y.d.cts → Construct-B-xc0SE9.d.mts} +27 -5
- package/dist/Construct-B-xc0SE9.d.mts.map +1 -0
- package/dist/{Construct-r0U2zBwW.mjs → Construct-HmWM6YYu.mjs} +4 -3
- package/dist/Construct-HmWM6YYu.mjs.map +1 -0
- package/dist/{Construct-DCMuYOox.d.mts → Construct-WhCXIOPV.d.cts} +29 -7
- package/dist/Construct-WhCXIOPV.d.cts.map +1 -0
- package/dist/{Construct-vXMZJgRp.cjs → Construct-roId57cU.cjs} +7 -43
- package/dist/Construct-roId57cU.cjs.map +1 -0
- package/dist/{lazyAccessors-DmTG8sQH.cjs → Endpoint-BBkV6l0k.cjs} +869 -1079
- package/dist/Endpoint-BBkV6l0k.cjs.map +1 -0
- package/dist/{lazyAccessors-DfqZR6C4.mjs → Endpoint-BGwpNEX4.mjs} +840 -1003
- package/dist/Endpoint-BGwpNEX4.mjs.map +1 -0
- package/dist/{Endpoint-CAzNbDEt.d.cts → Endpoint-BnxZqIX-.d.cts} +53 -4
- package/dist/Endpoint-BnxZqIX-.d.cts.map +1 -0
- package/dist/{Endpoint-CLPSIl6S.d.mts → Endpoint-ROcXU-eH.d.mts} +55 -6
- package/dist/Endpoint-ROcXU-eH.d.mts.map +1 -0
- package/dist/EndpointFactory-DYoGLaIT.cjs +850 -0
- package/dist/EndpointFactory-DYoGLaIT.cjs.map +1 -0
- package/dist/EndpointFactory-Di0X9AWp.mjs +808 -0
- package/dist/EndpointFactory-Di0X9AWp.mjs.map +1 -0
- package/dist/{HonoEndpointAdaptor-DJDT3PMx.mjs → HonoEndpointAdaptor-DFKIIG2o.mjs} +5 -4
- package/dist/HonoEndpointAdaptor-DFKIIG2o.mjs.map +1 -0
- package/dist/{HonoEndpointAdaptor-CkJENANP.cjs → HonoEndpointAdaptor-wMsCyMgt.cjs} +24 -23
- package/dist/HonoEndpointAdaptor-wMsCyMgt.cjs.map +1 -0
- package/dist/{Queue-DaxjwmOQ.d.cts → Queue-D6WeziRD.d.cts} +43 -4
- package/dist/Queue-D6WeziRD.d.cts.map +1 -0
- package/dist/{Queue-HBDf0fqz.d.mts → Queue-DpUeqdC8.d.mts} +43 -4
- package/dist/Queue-DpUeqdC8.d.mts.map +1 -0
- package/dist/{Subscriber-B69ngPwl.d.cts → Subscriber-4rBJgDKI.d.mts} +9 -4
- package/dist/{Subscriber-B69ngPwl.d.cts.map → Subscriber-4rBJgDKI.d.mts.map} +1 -1
- package/dist/{Subscriber-D8Xm-86W.d.mts → Subscriber-DVQowdyj.d.cts} +11 -6
- package/dist/Subscriber-DVQowdyj.d.cts.map +1 -0
- package/dist/{Topic-C5ZMfveW.d.cts → Topic-Ohx9dvWr.d.cts} +33 -2
- package/dist/Topic-Ohx9dvWr.d.cts.map +1 -0
- package/dist/{Topic-DT10AqHk.d.mts → Topic-cmy2jOUy.d.mts} +33 -2
- package/dist/Topic-cmy2jOUy.d.mts.map +1 -0
- package/dist/adaptors/aws.cjs +39 -26
- package/dist/adaptors/aws.cjs.map +1 -1
- package/dist/adaptors/aws.d.cts +24 -16
- package/dist/adaptors/aws.d.cts.map +1 -1
- package/dist/adaptors/aws.d.mts +25 -17
- package/dist/adaptors/aws.d.mts.map +1 -1
- package/dist/adaptors/aws.mjs +26 -14
- package/dist/adaptors/aws.mjs.map +1 -1
- package/dist/adaptors/hono.cjs +9 -6
- package/dist/adaptors/hono.d.cts +7 -6
- package/dist/adaptors/hono.d.cts.map +1 -1
- package/dist/adaptors/hono.d.mts +8 -7
- package/dist/adaptors/hono.d.mts.map +1 -1
- package/dist/adaptors/hono.mjs +9 -6
- package/dist/adaptors/testing.cjs +18 -14
- package/dist/adaptors/testing.cjs.map +1 -1
- package/dist/adaptors/testing.d.cts +7 -6
- package/dist/adaptors/testing.d.cts.map +1 -1
- package/dist/adaptors/testing.d.mts +11 -10
- package/dist/adaptors/testing.d.mts.map +1 -1
- package/dist/adaptors/testing.mjs +10 -7
- package/dist/adaptors/testing.mjs.map +1 -1
- package/dist/auth.cjs +165 -0
- package/dist/auth.cjs.map +1 -0
- package/dist/auth.d.cts +108 -0
- package/dist/auth.d.cts.map +1 -0
- package/dist/auth.d.mts +108 -0
- package/dist/auth.d.mts.map +1 -0
- package/dist/auth.mjs +164 -0
- package/dist/auth.mjs.map +1 -0
- package/dist/cache-0ANvRQnD.mjs +51 -0
- package/dist/cache-0ANvRQnD.mjs.map +1 -0
- package/dist/cache-3WSvAulx.cjs +57 -0
- package/dist/cache-3WSvAulx.cjs.map +1 -0
- package/dist/cache-CdQ7OLpR.d.cts +47 -0
- package/dist/cache-CdQ7OLpR.d.cts.map +1 -0
- package/dist/cache-DYoJFcfd.d.mts +47 -0
- package/dist/cache-DYoJFcfd.d.mts.map +1 -0
- package/dist/cache.cjs +3 -0
- package/dist/cache.d.cts +3 -0
- package/dist/cache.d.mts +3 -0
- package/dist/cache.mjs +3 -0
- package/dist/chunk-DWy1uDak.cjs +39 -0
- package/dist/clone-DblgEZZa.mjs +39 -0
- package/dist/clone-DblgEZZa.mjs.map +1 -0
- package/dist/clone-Dy0cR2SZ.cjs +45 -0
- package/dist/clone-Dy0cR2SZ.cjs.map +1 -0
- package/dist/construct-interface-BfjcOD_E.cjs +117 -0
- package/dist/construct-interface-BfjcOD_E.cjs.map +1 -0
- package/dist/construct-interface-BqwRNYA2.d.mts +131 -0
- package/dist/construct-interface-BqwRNYA2.d.mts.map +1 -0
- package/dist/construct-interface-D2nNkHUN.d.cts +131 -0
- package/dist/construct-interface-D2nNkHUN.d.cts.map +1 -0
- package/dist/construct-interface-Z4CpS8tK.mjs +81 -0
- package/dist/construct-interface-Z4CpS8tK.mjs.map +1 -0
- package/dist/construct-interface.cjs +8 -0
- package/dist/construct-interface.d.cts +2 -0
- package/dist/construct-interface.d.mts +2 -0
- package/dist/construct-interface.mjs +3 -0
- package/dist/credential.cjs +96 -0
- package/dist/credential.cjs.map +1 -0
- package/dist/credential.d.cts +61 -0
- package/dist/credential.d.cts.map +1 -0
- package/dist/credential.d.mts +61 -0
- package/dist/credential.d.mts.map +1 -0
- package/dist/credential.mjs +94 -0
- package/dist/credential.mjs.map +1 -0
- package/dist/crons/index.cjs +39 -37
- package/dist/crons/index.cjs.map +1 -1
- package/dist/crons/index.d.cts +21 -8
- package/dist/crons/index.d.cts.map +1 -1
- package/dist/crons/index.d.mts +29 -13
- package/dist/crons/index.d.mts.map +1 -1
- package/dist/crons/index.mjs +37 -36
- package/dist/crons/index.mjs.map +1 -1
- package/dist/database/kysely.cjs +181 -0
- package/dist/database/kysely.cjs.map +1 -0
- package/dist/database/kysely.d.cts +152 -0
- package/dist/database/kysely.d.cts.map +1 -0
- package/dist/database/kysely.d.mts +152 -0
- package/dist/database/kysely.d.mts.map +1 -0
- package/dist/database/kysely.mjs +180 -0
- package/dist/database/kysely.mjs.map +1 -0
- package/dist/email.cjs +59 -0
- package/dist/email.cjs.map +1 -0
- package/dist/email.d.cts +50 -0
- package/dist/email.d.cts.map +1 -0
- package/dist/email.d.mts +50 -0
- package/dist/email.d.mts.map +1 -0
- package/dist/email.mjs +58 -0
- package/dist/email.mjs.map +1 -0
- package/dist/endpoints/index.cjs +21 -747
- package/dist/endpoints/index.d.cts +7 -343
- package/dist/endpoints/index.d.mts +7 -342
- package/dist/endpoints/index.mjs +11 -738
- package/dist/file-server.cjs +154 -0
- package/dist/file-server.cjs.map +1 -0
- package/dist/file-server.d.cts +156 -0
- package/dist/file-server.d.cts.map +1 -0
- package/dist/file-server.d.mts +156 -0
- package/dist/file-server.d.mts.map +1 -0
- package/dist/file-server.mjs +152 -0
- package/dist/file-server.mjs.map +1 -0
- package/dist/functions/index.cjs +4 -2
- package/dist/functions/index.d.cts +3 -2
- package/dist/functions/index.d.mts +3 -2
- package/dist/functions/index.mjs +4 -2
- package/dist/{functions-B-qt91O7.mjs → functions-CvT_q7Y4.mjs} +55 -51
- package/dist/functions-CvT_q7Y4.mjs.map +1 -0
- package/dist/{functions-C8i1kCMM.cjs → functions-DukjG8ov.cjs} +62 -57
- package/dist/functions-DukjG8ov.cjs.map +1 -0
- package/dist/index-7OcOWe75.d.cts +419 -0
- package/dist/index-7OcOWe75.d.cts.map +1 -0
- package/dist/index-Bt-F7u8L.d.mts +419 -0
- package/dist/index-Bt-F7u8L.d.mts.map +1 -0
- package/dist/{index-DP6fqv0I.d.mts → index-CPeqtKgq.d.mts} +48 -19
- package/dist/index-CPeqtKgq.d.mts.map +1 -0
- package/dist/{index-BGeTScmi.d.cts → index-Dadljnh_.d.cts} +36 -9
- package/dist/index-Dadljnh_.d.cts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +1 -1
- package/dist/lazyAccessors-DM6HcXQk.mjs +175 -0
- package/dist/lazyAccessors-DM6HcXQk.mjs.map +1 -0
- package/dist/lazyAccessors-DrJj8NpA.cjs +223 -0
- package/dist/lazyAccessors-DrJj8NpA.cjs.map +1 -0
- package/dist/object-storage.cjs +48 -0
- package/dist/object-storage.cjs.map +1 -0
- package/dist/object-storage.d.cts +36 -0
- package/dist/object-storage.d.cts.map +1 -0
- package/dist/object-storage.d.mts +36 -0
- package/dist/object-storage.d.mts.map +1 -0
- package/dist/object-storage.mjs +47 -0
- package/dist/object-storage.mjs.map +1 -0
- package/dist/{processAudits-CKjjivyz.cjs → processAudits-Bc8rz6Ev.cjs} +3 -3
- package/dist/{processAudits-CKjjivyz.cjs.map → processAudits-Bc8rz6Ev.cjs.map} +1 -1
- package/dist/{processAudits-ySnizdMG.mjs → processAudits-D89tICM4.mjs} +1 -1
- package/dist/{processAudits-ySnizdMG.mjs.map → processAudits-D89tICM4.mjs.map} +1 -1
- package/dist/{publisher-BrFOF847.mjs → publisher-CGEo8UKD.mjs} +1 -1
- package/dist/{publisher-BrFOF847.mjs.map → publisher-CGEo8UKD.mjs.map} +1 -1
- package/dist/{publisher-lFQleddL.cjs → publisher-CqGsXB2X.cjs} +1 -1
- package/dist/{publisher-lFQleddL.cjs.map → publisher-CqGsXB2X.cjs.map} +1 -1
- package/dist/queue/index.cjs +92 -30
- package/dist/queue/index.cjs.map +1 -1
- package/dist/queue/index.d.cts +19 -4
- package/dist/queue/index.d.cts.map +1 -1
- package/dist/queue/index.d.mts +22 -6
- package/dist/queue/index.d.mts.map +1 -1
- package/dist/queue/index.mjs +90 -29
- package/dist/queue/index.mjs.map +1 -1
- package/dist/rest-api.cjs +187 -0
- package/dist/rest-api.cjs.map +1 -0
- package/dist/rest-api.d.cts +221 -0
- package/dist/rest-api.d.cts.map +1 -0
- package/dist/rest-api.d.mts +221 -0
- package/dist/rest-api.d.mts.map +1 -0
- package/dist/rest-api.mjs +186 -0
- package/dist/rest-api.mjs.map +1 -0
- package/dist/site.cjs +48 -0
- package/dist/site.cjs.map +1 -0
- package/dist/site.d.cts +101 -0
- package/dist/site.d.cts.map +1 -0
- package/dist/site.d.mts +101 -0
- package/dist/site.d.mts.map +1 -0
- package/dist/site.mjs +47 -0
- package/dist/site.mjs.map +1 -0
- package/dist/subscribers/index.cjs +35 -27
- package/dist/subscribers/index.cjs.map +1 -1
- package/dist/subscribers/index.d.cts +20 -5
- package/dist/subscribers/index.d.cts.map +1 -1
- package/dist/subscribers/index.d.mts +23 -7
- package/dist/subscribers/index.d.mts.map +1 -1
- package/dist/subscribers/index.mjs +34 -27
- package/dist/subscribers/index.mjs.map +1 -1
- package/dist/surfaceEnv-BFXEms2f.cjs +39 -0
- package/dist/surfaceEnv-BFXEms2f.cjs.map +1 -0
- package/dist/surfaceEnv-C3Ktahea.mjs +27 -0
- package/dist/surfaceEnv-C3Ktahea.mjs.map +1 -0
- package/dist/{telemetry-3vdxGn4q.d.mts → telemetry-C3L0iS28.d.cts} +2 -2
- package/dist/{telemetry-3vdxGn4q.d.mts.map → telemetry-C3L0iS28.d.cts.map} +1 -1
- package/dist/{telemetry-Dqx-D3F7.d.cts → telemetry-D7bVFLGi.d.mts} +2 -2
- package/dist/{telemetry-Dqx-D3F7.d.cts.map → telemetry-D7bVFLGi.d.mts.map} +1 -1
- package/dist/topic/index.cjs +56 -13
- package/dist/topic/index.cjs.map +1 -1
- package/dist/topic/index.d.cts +2 -2
- package/dist/topic/index.d.cts.map +1 -1
- package/dist/topic/index.d.mts +2 -2
- package/dist/topic/index.d.mts.map +1 -1
- package/dist/topic/index.mjs +54 -12
- package/dist/topic/index.mjs.map +1 -1
- package/dist/{types-BDNGr7pv.d.mts → types-BlAkSuGI.d.cts} +1 -1
- package/dist/{types-BDNGr7pv.d.mts.map → types-BlAkSuGI.d.cts.map} +1 -1
- package/dist/{types-BdAaYDvd.d.cts → types-aKksMEWL.d.mts} +1 -1
- package/dist/{types-BdAaYDvd.d.cts.map → types-aKksMEWL.d.mts.map} +1 -1
- package/dist/types.d.cts +1 -1
- package/dist/types.d.mts +1 -1
- package/package.json +155 -23
- package/CHANGELOG.md +0 -366
- package/dist/Construct-DCMuYOox.d.mts.map +0 -1
- package/dist/Construct-_1wX7p_Y.d.cts.map +0 -1
- package/dist/Construct-r0U2zBwW.mjs.map +0 -1
- package/dist/Construct-vXMZJgRp.cjs.map +0 -1
- package/dist/Endpoint-CAzNbDEt.d.cts.map +0 -1
- package/dist/Endpoint-CLPSIl6S.d.mts.map +0 -1
- package/dist/HonoEndpointAdaptor-CkJENANP.cjs.map +0 -1
- package/dist/HonoEndpointAdaptor-DJDT3PMx.mjs.map +0 -1
- package/dist/Queue-DaxjwmOQ.d.cts.map +0 -1
- package/dist/Queue-HBDf0fqz.d.mts.map +0 -1
- package/dist/Subscriber-D8Xm-86W.d.mts.map +0 -1
- package/dist/Topic-C5ZMfveW.d.cts.map +0 -1
- package/dist/Topic-DT10AqHk.d.mts.map +0 -1
- package/dist/endpoints/index.cjs.map +0 -1
- package/dist/endpoints/index.d.cts.map +0 -1
- package/dist/endpoints/index.d.mts.map +0 -1
- package/dist/endpoints/index.mjs.map +0 -1
- package/dist/functions-B-qt91O7.mjs.map +0 -1
- package/dist/functions-C8i1kCMM.cjs.map +0 -1
- package/dist/index-BGeTScmi.d.cts.map +0 -1
- package/dist/index-DP6fqv0I.d.mts.map +0 -1
- package/dist/lazyAccessors-DfqZR6C4.mjs.map +0 -1
- package/dist/lazyAccessors-DmTG8sQH.cjs.map +0 -1
- package/src/Construct.ts +0 -204
- package/src/__benchmarks__/build-time-optimization.bench.ts +0 -274
- package/src/__benchmarks__/endpoint.bench.ts +0 -494
- package/src/__benchmarks__/fixtures.ts +0 -241
- package/src/__benchmarks__/hono-adaptor.bench.ts +0 -533
- package/src/__benchmarks__/hono-server.bench.ts +0 -249
- package/src/__benchmarks__/response-builder.bench.ts +0 -428
- package/src/__benchmarks__/strategies/strategy-a-lazy-services.ts +0 -319
- package/src/__benchmarks__/strategies/strategy-c-middleware.ts +0 -530
- package/src/__benchmarks__/strategies/strategy-d-opt-in-events.ts +0 -567
- package/src/__tests__/Construct.environment.spec.ts +0 -704
- package/src/__tests__/publisher.setting.spec.ts +0 -508
- package/src/__tests__/publisher.spec.ts +0 -452
- package/src/adaptors/aws.ts +0 -6
- package/src/adaptors/hono.ts +0 -1
- package/src/adaptors/testing.ts +0 -11
- package/src/crons/AWSScheduledFunction.ts +0 -73
- package/src/crons/Cron.ts +0 -149
- package/src/crons/CronBuilder.ts +0 -271
- package/src/crons/__tests__/AWSScheduledFunction.spec.ts +0 -152
- package/src/crons/__tests__/Cron.spec.ts +0 -464
- package/src/crons/__tests__/CronBuilder.state-isolation.spec.ts +0 -227
- package/src/crons/index.ts +0 -12
- package/src/endpoints/AmazonApiGatewayEndpointAdaptor.ts +0 -677
- package/src/endpoints/AmazonApiGatewayV1EndpointAdaptor.ts +0 -105
- package/src/endpoints/AmazonApiGatewayV2EndpointAdaptor.ts +0 -97
- package/src/endpoints/Authorizer.ts +0 -152
- package/src/endpoints/Endpoint.ts +0 -1287
- package/src/endpoints/EndpointBuilder.ts +0 -758
- package/src/endpoints/EndpointFactory.ts +0 -1148
- package/src/endpoints/HonoEndpointAdaptor.ts +0 -677
- package/src/endpoints/MswEndpointAdaptor.ts +0 -226
- package/src/endpoints/TestEndpointAdaptor.ts +0 -422
- package/src/endpoints/__tests__/AmazonApiGatewayV1EndpointAdaptor.audits.spec.ts +0 -499
- package/src/endpoints/__tests__/AmazonApiGatewayV1EndpointAdaptor.events.spec.ts +0 -560
- package/src/endpoints/__tests__/AmazonApiGatewayV1EndpointAdaptor.spec.ts +0 -1304
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.audits.spec.ts +0 -626
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.events.spec.ts +0 -732
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.factory-publisher.spec.ts +0 -296
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.kysely-audit.integration.spec.ts +0 -951
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.responseType.spec.ts +0 -111
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.rls.spec.ts +0 -307
- package/src/endpoints/__tests__/AmazonApiGatewayV2EndpointAdaptor.spec.ts +0 -629
- package/src/endpoints/__tests__/Authorizer.spec.ts +0 -286
- package/src/endpoints/__tests__/Endpoint.cookies.spec.ts +0 -207
- package/src/endpoints/__tests__/Endpoint.headers.spec.ts +0 -187
- package/src/endpoints/__tests__/Endpoint.manifest.spec.ts +0 -175
- package/src/endpoints/__tests__/Endpoint.spec.ts +0 -857
- package/src/endpoints/__tests__/EndpointBuilder.audit.spec.ts +0 -448
- package/src/endpoints/__tests__/EndpointBuilder.responseType.spec.ts +0 -47
- package/src/endpoints/__tests__/EndpointBuilder.spec.ts +0 -523
- package/src/endpoints/__tests__/EndpointFactory.authorizers.spec.ts +0 -492
- package/src/endpoints/__tests__/EndpointFactory.database-auditor.spec.ts +0 -509
- package/src/endpoints/__tests__/EndpointFactory.reference-audit.spec.ts +0 -190
- package/src/endpoints/__tests__/EndpointFactory.spec.ts +0 -479
- package/src/endpoints/__tests__/EndpointFactory.state-isolation.spec.ts +0 -155
- package/src/endpoints/__tests__/HonoEndpointAdaptor.audit-transactions.spec.ts +0 -703
- package/src/endpoints/__tests__/HonoEndpointAdaptor.audits.spec.ts +0 -632
- package/src/endpoints/__tests__/HonoEndpointAdaptor.events.spec.ts +0 -577
- package/src/endpoints/__tests__/HonoEndpointAdaptor.kysely-audit.integration.spec.ts +0 -1067
- package/src/endpoints/__tests__/HonoEndpointAdaptor.openapi.spec.ts +0 -317
- package/src/endpoints/__tests__/HonoEndpointAdaptor.pgboss-publisher.spec.ts +0 -289
- package/src/endpoints/__tests__/HonoEndpointAdaptor.responseType.spec.ts +0 -128
- package/src/endpoints/__tests__/HonoEndpointAdaptor.spec.ts +0 -1207
- package/src/endpoints/__tests__/MswEndpointAdaptor.spec.ts +0 -211
- package/src/endpoints/__tests__/ResponseBuilder.spec.ts +0 -235
- package/src/endpoints/__tests__/TestEndpointAdaptor.audits.spec.ts +0 -602
- package/src/endpoints/__tests__/TestEndpointAdaptor.spec.ts +0 -1044
- package/src/endpoints/__tests__/__snapshots__/HonoEndpointAdaptor.spec.ts.snap +0 -54
- package/src/endpoints/__tests__/endpoint-types.test.ts +0 -88
- package/src/endpoints/__tests__/helpers.spec.ts +0 -37
- package/src/endpoints/__tests__/lazyAccessors.spec.ts +0 -330
- package/src/endpoints/__tests__/processAudits.spec.ts +0 -631
- package/src/endpoints/audit.ts +0 -87
- package/src/endpoints/helpers.ts +0 -98
- package/src/endpoints/index.ts +0 -42
- package/src/endpoints/lazyAccessors.ts +0 -241
- package/src/endpoints/parseHonoQuery.ts +0 -16
- package/src/endpoints/parseQueryParams.ts +0 -32
- package/src/endpoints/processAudits.ts +0 -371
- package/src/endpoints/rls.ts +0 -67
- package/src/functions/AWSLambdaFunction.ts +0 -348
- package/src/functions/BaseFunctionBuilder.ts +0 -201
- package/src/functions/Function.ts +0 -238
- package/src/functions/FunctionBuilder.ts +0 -391
- package/src/functions/FunctionExecutionWrapper.ts +0 -216
- package/src/functions/TestFunctionAdaptor.ts +0 -217
- package/src/functions/__tests__/AWSLambdaFunctionAdaptor.spec.ts +0 -513
- package/src/functions/__tests__/Function.audits.spec.ts +0 -393
- package/src/functions/__tests__/Function.spec.ts +0 -477
- package/src/functions/__tests__/FunctionBuilder.state-isolation.spec.ts +0 -207
- package/src/functions/__tests__/TestFunctionAdaptor.spec.ts +0 -480
- package/src/functions/index.ts +0 -12
- package/src/index.ts +0 -23
- package/src/publisher.ts +0 -93
- package/src/queue/AWSLambdaQueueAdaptor.ts +0 -162
- package/src/queue/Queue.ts +0 -128
- package/src/queue/QueueBuilder.ts +0 -115
- package/src/queue/TestQueueAdaptor.ts +0 -63
- package/src/queue/__tests__/QueueBuilder.spec.ts +0 -137
- package/src/queue/index.ts +0 -12
- package/src/subscribers/AWSLambdaSubscriberAdaptor.ts +0 -342
- package/src/subscribers/Subscriber.ts +0 -117
- package/src/subscribers/SubscriberBuilder.ts +0 -186
- package/src/subscribers/TestSubscriberAdaptor.ts +0 -133
- package/src/subscribers/__tests__/AWSLambdaSubscriberAdaptor.spec.ts +0 -1018
- package/src/subscribers/__tests__/Subscriber.spec.ts +0 -430
- package/src/subscribers/__tests__/TestSubscriberAdaptor.spec.ts +0 -652
- package/src/subscribers/index.ts +0 -6
- package/src/telemetry.ts +0 -103
- package/src/topic/Topic.ts +0 -103
- package/src/topic/TopicBuilder.ts +0 -51
- package/src/topic/__tests__/TopicBuilder.spec.ts +0 -82
- package/src/topic/index.ts +0 -11
- package/src/types.ts +0 -13
- package/test.ts +0 -91
- package/tsconfig.json +0 -9
- package/tsdown.config.ts +0 -34
|
@@ -1,1044 +0,0 @@
|
|
|
1
|
-
import { UnprocessableEntityError } from '@geekmidas/errors';
|
|
2
|
-
import { ConsoleLogger } from '@geekmidas/logger/console';
|
|
3
|
-
import { describe, expect, it, vi } from 'vitest';
|
|
4
|
-
import { z } from 'zod';
|
|
5
|
-
import { SuccessStatus } from '../Endpoint';
|
|
6
|
-
import { e } from '../EndpointFactory';
|
|
7
|
-
import { TestEndpointAdaptor } from '../TestEndpointAdaptor';
|
|
8
|
-
|
|
9
|
-
describe('TestEndpointAdaptor', () => {
|
|
10
|
-
const mockServices = {};
|
|
11
|
-
const _logger = new ConsoleLogger();
|
|
12
|
-
|
|
13
|
-
describe('request', () => {
|
|
14
|
-
it('should handle simple endpoint without schemas', async () => {
|
|
15
|
-
const endpoint = e
|
|
16
|
-
.get('/test')
|
|
17
|
-
.output(z.object({ message: z.string() }))
|
|
18
|
-
.handle(() => ({ message: 'Hello World' }));
|
|
19
|
-
|
|
20
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
21
|
-
|
|
22
|
-
const result = await adapter.request({
|
|
23
|
-
services: mockServices,
|
|
24
|
-
headers: { host: 'example.com' },
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
expect(result).toEqual({ message: 'Hello World' });
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('should handle endpoint with body schema', async () => {
|
|
31
|
-
const endpoint = e
|
|
32
|
-
.post('/users')
|
|
33
|
-
.body(z.object({ name: z.string(), email: z.string().email() }))
|
|
34
|
-
.output(z.object({ id: z.string(), name: z.string() }))
|
|
35
|
-
.handle(async ({ body }) => ({
|
|
36
|
-
id: 'user-123',
|
|
37
|
-
name: body.name,
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
41
|
-
|
|
42
|
-
const result = await adapter.request({
|
|
43
|
-
body: { name: 'John Doe', email: 'john@example.com' },
|
|
44
|
-
services: mockServices,
|
|
45
|
-
headers: { host: 'example.com', 'content-type': 'application/json' },
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
expect(result).toEqual({ id: 'user-123', name: 'John Doe' });
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it('should handle endpoint with params schema', async () => {
|
|
52
|
-
const endpoint = e
|
|
53
|
-
.get('/users/:id')
|
|
54
|
-
.params(z.object({ id: z.string() }))
|
|
55
|
-
.output(z.object({ id: z.string(), found: z.boolean() }))
|
|
56
|
-
.handle(async ({ params }) => ({
|
|
57
|
-
id: params.id,
|
|
58
|
-
found: true,
|
|
59
|
-
}));
|
|
60
|
-
|
|
61
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
62
|
-
|
|
63
|
-
const result = await adapter.request({
|
|
64
|
-
params: { id: 'user-456' },
|
|
65
|
-
services: mockServices,
|
|
66
|
-
headers: { host: 'example.com' },
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
expect(result).toEqual({ id: 'user-456', found: true });
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
it('should handle endpoint with query schema', async () => {
|
|
73
|
-
const endpoint = e
|
|
74
|
-
.get('/search')
|
|
75
|
-
.query(z.object({ q: z.string(), page: z.coerce.number().default(1) }))
|
|
76
|
-
.output(z.object({ query: z.string(), page: z.number() }))
|
|
77
|
-
.handle(async ({ query }) => ({
|
|
78
|
-
query: query.q,
|
|
79
|
-
page: query.page,
|
|
80
|
-
}));
|
|
81
|
-
|
|
82
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
83
|
-
|
|
84
|
-
const result = await adapter.request({
|
|
85
|
-
query: { q: 'test search', page: 2 },
|
|
86
|
-
services: mockServices,
|
|
87
|
-
headers: { host: 'example.com' },
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
expect(result).toEqual({ query: 'test search', page: 2 });
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('should handle endpoint with all schemas', async () => {
|
|
94
|
-
const endpoint = e
|
|
95
|
-
.put('/users/:id')
|
|
96
|
-
.params(z.object({ id: z.string() }))
|
|
97
|
-
.body(z.object({ name: z.string(), email: z.string().email() }))
|
|
98
|
-
.query(z.object({ notify: z.coerce.boolean().default(false) }))
|
|
99
|
-
.output(
|
|
100
|
-
z.object({
|
|
101
|
-
id: z.string(),
|
|
102
|
-
updated: z.boolean(),
|
|
103
|
-
notified: z.boolean(),
|
|
104
|
-
}),
|
|
105
|
-
)
|
|
106
|
-
.handle(async ({ params, body, query }) => ({
|
|
107
|
-
id: params.id,
|
|
108
|
-
updated: true,
|
|
109
|
-
notified: query.notify,
|
|
110
|
-
}));
|
|
111
|
-
|
|
112
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
113
|
-
|
|
114
|
-
const result = await adapter.request({
|
|
115
|
-
body: { name: 'Jane Doe', email: 'jane@example.com' },
|
|
116
|
-
query: { notify: true },
|
|
117
|
-
params: { id: 'user-789' },
|
|
118
|
-
services: mockServices,
|
|
119
|
-
headers: { host: 'example.com' },
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
expect(result).toEqual({
|
|
123
|
-
id: 'user-789',
|
|
124
|
-
updated: true,
|
|
125
|
-
notified: true,
|
|
126
|
-
});
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
it('should throw validation error for invalid body', async () => {
|
|
130
|
-
const endpoint = e
|
|
131
|
-
.post('/users')
|
|
132
|
-
.body(z.object({ name: z.string(), age: z.number().min(18) }))
|
|
133
|
-
.handle(async ({ body }) => ({ id: '123' }));
|
|
134
|
-
|
|
135
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
136
|
-
|
|
137
|
-
await expect(
|
|
138
|
-
adapter.request({
|
|
139
|
-
body: { name: 'John', age: 15 },
|
|
140
|
-
services: mockServices,
|
|
141
|
-
headers: { host: 'example.com' },
|
|
142
|
-
}),
|
|
143
|
-
).rejects.toThrow(UnprocessableEntityError);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should handle headers correctly', async () => {
|
|
147
|
-
const endpoint = e
|
|
148
|
-
.get('/headers')
|
|
149
|
-
.output(z.object({ auth: z.string().optional(), host: z.string() }))
|
|
150
|
-
.handle(async ({ header }) => ({
|
|
151
|
-
auth: header('authorization'),
|
|
152
|
-
host: header('host') || 'unknown',
|
|
153
|
-
}));
|
|
154
|
-
|
|
155
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
156
|
-
|
|
157
|
-
const result = await adapter.request({
|
|
158
|
-
services: mockServices,
|
|
159
|
-
headers: {
|
|
160
|
-
host: 'api.example.com',
|
|
161
|
-
authorization: 'Bearer token123',
|
|
162
|
-
'Content-Type': 'application/json',
|
|
163
|
-
},
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
expect(result).toEqual({
|
|
167
|
-
auth: 'Bearer token123',
|
|
168
|
-
host: 'api.example.com',
|
|
169
|
-
});
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it('should handle session correctly', async () => {
|
|
173
|
-
const endpoint = e
|
|
174
|
-
.get('/profile')
|
|
175
|
-
.output(z.object({ userId: z.string() }))
|
|
176
|
-
.handle(async ({ session }) => ({
|
|
177
|
-
userId: (session as any).userId,
|
|
178
|
-
}));
|
|
179
|
-
|
|
180
|
-
// Mock getSession
|
|
181
|
-
endpoint.getSession = vi.fn().mockResolvedValue({ userId: 'user-123' });
|
|
182
|
-
|
|
183
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
184
|
-
|
|
185
|
-
const result = await adapter.request({
|
|
186
|
-
services: mockServices,
|
|
187
|
-
headers: { host: 'example.com' },
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
expect(result).toEqual({ userId: 'user-123' });
|
|
191
|
-
expect(endpoint.getSession).toHaveBeenCalledWith({
|
|
192
|
-
logger: expect.any(ConsoleLogger),
|
|
193
|
-
services: mockServices,
|
|
194
|
-
header: expect.any(Function),
|
|
195
|
-
cookie: expect.any(Function),
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
it('should validate output schema', async () => {
|
|
200
|
-
const endpoint = e
|
|
201
|
-
.get('/invalid')
|
|
202
|
-
.output(z.object({ id: z.string(), count: z.number() }))
|
|
203
|
-
.handle(() => ({ id: '123', count: 'not-a-number' as any }));
|
|
204
|
-
|
|
205
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
206
|
-
|
|
207
|
-
await expect(
|
|
208
|
-
adapter.request({
|
|
209
|
-
services: mockServices,
|
|
210
|
-
headers: { host: 'example.com' },
|
|
211
|
-
}),
|
|
212
|
-
).rejects.toThrow(UnprocessableEntityError);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it('should handle case-insensitive headers', async () => {
|
|
216
|
-
const endpoint = e
|
|
217
|
-
.get('/headers-case')
|
|
218
|
-
.output(z.object({ contentType: z.string().optional() }))
|
|
219
|
-
.handle(async ({ header }) => ({
|
|
220
|
-
contentType: header('CONTENT-TYPE'),
|
|
221
|
-
}));
|
|
222
|
-
|
|
223
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
224
|
-
|
|
225
|
-
const result = await adapter.request({
|
|
226
|
-
services: mockServices,
|
|
227
|
-
headers: {
|
|
228
|
-
host: 'example.com',
|
|
229
|
-
'content-type': 'application/json',
|
|
230
|
-
},
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
expect(result).toEqual({
|
|
234
|
-
contentType: 'application/json',
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it('should read cookies from request', async () => {
|
|
239
|
-
const endpoint = e
|
|
240
|
-
.get('/cookies')
|
|
241
|
-
.output(
|
|
242
|
-
z.object({
|
|
243
|
-
session: z.string().optional(),
|
|
244
|
-
theme: z.string().optional(),
|
|
245
|
-
}),
|
|
246
|
-
)
|
|
247
|
-
.handle(async ({ cookie }) => ({
|
|
248
|
-
session: cookie('session'),
|
|
249
|
-
theme: cookie('theme'),
|
|
250
|
-
}));
|
|
251
|
-
|
|
252
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
253
|
-
|
|
254
|
-
const result = await adapter.request({
|
|
255
|
-
services: mockServices,
|
|
256
|
-
headers: {
|
|
257
|
-
host: 'example.com',
|
|
258
|
-
cookie: 'session=abc123; theme=dark',
|
|
259
|
-
},
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
expect(result).toEqual({
|
|
263
|
-
session: 'abc123',
|
|
264
|
-
theme: 'dark',
|
|
265
|
-
});
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
it('should handle missing cookies gracefully', async () => {
|
|
269
|
-
const endpoint = e
|
|
270
|
-
.get('/cookies-optional')
|
|
271
|
-
.output(
|
|
272
|
-
z.object({
|
|
273
|
-
session: z.string().optional(),
|
|
274
|
-
}),
|
|
275
|
-
)
|
|
276
|
-
.handle(async ({ cookie }) => ({
|
|
277
|
-
session: cookie('session') || 'default',
|
|
278
|
-
}));
|
|
279
|
-
|
|
280
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
281
|
-
|
|
282
|
-
const result = await adapter.request({
|
|
283
|
-
services: mockServices,
|
|
284
|
-
headers: {
|
|
285
|
-
host: 'example.com',
|
|
286
|
-
},
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
expect(result).toEqual({
|
|
290
|
-
session: 'default',
|
|
291
|
-
});
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it('should handle URL encoded cookie values', async () => {
|
|
295
|
-
const endpoint = e
|
|
296
|
-
.get('/cookies-encoded')
|
|
297
|
-
.output(z.object({ user: z.string() }))
|
|
298
|
-
.handle(async ({ cookie }) => ({
|
|
299
|
-
user: cookie('user') || 'unknown',
|
|
300
|
-
}));
|
|
301
|
-
|
|
302
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
303
|
-
|
|
304
|
-
const result = await adapter.request({
|
|
305
|
-
services: mockServices,
|
|
306
|
-
headers: {
|
|
307
|
-
host: 'example.com',
|
|
308
|
-
cookie: 'user=John%20Doe',
|
|
309
|
-
},
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
expect(result).toEqual({
|
|
313
|
-
user: 'John Doe',
|
|
314
|
-
});
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it('should use cookies in session extraction', async () => {
|
|
318
|
-
const endpoint = e
|
|
319
|
-
.get('/profile')
|
|
320
|
-
.output(z.object({ userId: z.string() }))
|
|
321
|
-
.handle(async ({ session }) => ({
|
|
322
|
-
userId: (session as any).userId,
|
|
323
|
-
}));
|
|
324
|
-
|
|
325
|
-
// Mock getSession that uses cookies
|
|
326
|
-
endpoint.getSession = vi.fn().mockImplementation(({ cookie }) => {
|
|
327
|
-
const sessionId = cookie('session');
|
|
328
|
-
if (sessionId === 'valid-session') {
|
|
329
|
-
return { userId: 'user-123' };
|
|
330
|
-
}
|
|
331
|
-
return null;
|
|
332
|
-
});
|
|
333
|
-
|
|
334
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
335
|
-
|
|
336
|
-
const result = await adapter.request({
|
|
337
|
-
services: mockServices,
|
|
338
|
-
headers: {
|
|
339
|
-
host: 'example.com',
|
|
340
|
-
cookie: 'session=valid-session',
|
|
341
|
-
},
|
|
342
|
-
});
|
|
343
|
-
|
|
344
|
-
expect(result).toEqual({ userId: 'user-123' });
|
|
345
|
-
expect(endpoint.getSession).toHaveBeenCalledWith({
|
|
346
|
-
logger: expect.any(ConsoleLogger),
|
|
347
|
-
services: mockServices,
|
|
348
|
-
header: expect.any(Function),
|
|
349
|
-
cookie: expect.any(Function),
|
|
350
|
-
});
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
it('should handle multiple cookies with same name (uses last)', async () => {
|
|
354
|
-
const endpoint = e
|
|
355
|
-
.get('/duplicate-cookies')
|
|
356
|
-
.output(z.object({ value: z.string() }))
|
|
357
|
-
.handle(async ({ cookie }) => ({
|
|
358
|
-
value: cookie('test') || 'none',
|
|
359
|
-
}));
|
|
360
|
-
|
|
361
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
362
|
-
|
|
363
|
-
const result = await adapter.request({
|
|
364
|
-
services: mockServices,
|
|
365
|
-
headers: {
|
|
366
|
-
host: 'example.com',
|
|
367
|
-
cookie: 'test=first; test=second',
|
|
368
|
-
},
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
// When duplicates exist, Map uses the last occurrence
|
|
372
|
-
expect(result).toEqual({
|
|
373
|
-
value: 'second',
|
|
374
|
-
});
|
|
375
|
-
});
|
|
376
|
-
});
|
|
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('Forbidden');
|
|
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
|
-
it('should pass db to authorize when database is configured', async () => {
|
|
517
|
-
const mockDb = {
|
|
518
|
-
query: vi.fn().mockResolvedValue([{ allowed: true }]),
|
|
519
|
-
};
|
|
520
|
-
|
|
521
|
-
const DatabaseService = {
|
|
522
|
-
serviceName: 'database' as const,
|
|
523
|
-
register: vi.fn().mockResolvedValue(mockDb),
|
|
524
|
-
};
|
|
525
|
-
|
|
526
|
-
const authorizeSpy = vi.fn(({ db }) => {
|
|
527
|
-
return db.query !== undefined;
|
|
528
|
-
});
|
|
529
|
-
|
|
530
|
-
const endpoint = e
|
|
531
|
-
.get('/protected')
|
|
532
|
-
.database(DatabaseService)
|
|
533
|
-
.output(z.object({ ok: z.boolean() }))
|
|
534
|
-
.authorize(authorizeSpy)
|
|
535
|
-
.handle(() => ({ ok: true }));
|
|
536
|
-
|
|
537
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
538
|
-
|
|
539
|
-
const result = await adapter.request({
|
|
540
|
-
services: mockServices,
|
|
541
|
-
headers: { host: 'example.com' },
|
|
542
|
-
database: mockDb,
|
|
543
|
-
});
|
|
544
|
-
|
|
545
|
-
expect(result).toEqual({ ok: true });
|
|
546
|
-
expect(authorizeSpy).toHaveBeenCalledTimes(1);
|
|
547
|
-
expect(authorizeSpy.mock.calls[0][0]).toHaveProperty('db', mockDb);
|
|
548
|
-
});
|
|
549
|
-
|
|
550
|
-
it('should not include db in authorize when database is not configured', async () => {
|
|
551
|
-
const authorizeSpy = vi.fn(() => true);
|
|
552
|
-
|
|
553
|
-
const endpoint = e
|
|
554
|
-
.get('/public')
|
|
555
|
-
.output(z.object({ ok: z.boolean() }))
|
|
556
|
-
.authorize(authorizeSpy)
|
|
557
|
-
.handle(() => ({ ok: true }));
|
|
558
|
-
|
|
559
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
560
|
-
|
|
561
|
-
await adapter.request({
|
|
562
|
-
services: mockServices,
|
|
563
|
-
headers: { host: 'example.com' },
|
|
564
|
-
});
|
|
565
|
-
|
|
566
|
-
expect(authorizeSpy).toHaveBeenCalledTimes(1);
|
|
567
|
-
expect(authorizeSpy.mock.calls[0][0]).not.toHaveProperty('db');
|
|
568
|
-
});
|
|
569
|
-
});
|
|
570
|
-
|
|
571
|
-
describe('response handling', () => {
|
|
572
|
-
it('should set response cookies', async () => {
|
|
573
|
-
const endpoint = e
|
|
574
|
-
.post('/auth/login')
|
|
575
|
-
.body(z.object({ email: z.string(), password: z.string() }))
|
|
576
|
-
.output(z.object({ id: z.string(), email: z.string() }))
|
|
577
|
-
.handle(async ({ body }, response) => {
|
|
578
|
-
return response
|
|
579
|
-
.cookie('session', 'abc123', {
|
|
580
|
-
httpOnly: true,
|
|
581
|
-
secure: true,
|
|
582
|
-
sameSite: 'strict',
|
|
583
|
-
maxAge: 3600,
|
|
584
|
-
})
|
|
585
|
-
.send({ id: 'user-1', email: body.email });
|
|
586
|
-
});
|
|
587
|
-
|
|
588
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
589
|
-
const result = await adapter.fullRequest({
|
|
590
|
-
body: { email: 'test@example.com', password: 'pass123' },
|
|
591
|
-
services: mockServices,
|
|
592
|
-
headers: { host: 'example.com' },
|
|
593
|
-
});
|
|
594
|
-
|
|
595
|
-
expect(result.body).toEqual({
|
|
596
|
-
id: 'user-1',
|
|
597
|
-
email: 'test@example.com',
|
|
598
|
-
});
|
|
599
|
-
expect(result.headers['set-cookie']).toEqual([
|
|
600
|
-
'session=abc123; Max-Age=3600; HttpOnly; Secure; SameSite=strict',
|
|
601
|
-
]);
|
|
602
|
-
});
|
|
603
|
-
|
|
604
|
-
it('should set custom response headers', async () => {
|
|
605
|
-
const endpoint = e
|
|
606
|
-
.post('/users')
|
|
607
|
-
.body(z.object({ name: z.string() }))
|
|
608
|
-
.output(z.object({ id: z.string(), name: z.string() }))
|
|
609
|
-
.handle(async ({ body }, response) => {
|
|
610
|
-
const user = { id: 'user-123', name: body.name };
|
|
611
|
-
return response
|
|
612
|
-
.header('Location', `/users/${user.id}`)
|
|
613
|
-
.header('X-User-Id', user.id)
|
|
614
|
-
.send(user);
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
618
|
-
const result = await adapter.fullRequest({
|
|
619
|
-
body: { name: 'John Doe' },
|
|
620
|
-
services: mockServices,
|
|
621
|
-
headers: { host: 'example.com' },
|
|
622
|
-
});
|
|
623
|
-
|
|
624
|
-
expect(result.body).toEqual({
|
|
625
|
-
id: 'user-123',
|
|
626
|
-
name: 'John Doe',
|
|
627
|
-
});
|
|
628
|
-
expect(result.headers).toEqual({
|
|
629
|
-
Location: '/users/user-123',
|
|
630
|
-
'X-User-Id': 'user-123',
|
|
631
|
-
});
|
|
632
|
-
});
|
|
633
|
-
|
|
634
|
-
it('should set custom status code', async () => {
|
|
635
|
-
const endpoint = e
|
|
636
|
-
.post('/resources')
|
|
637
|
-
.body(z.object({ name: z.string() }))
|
|
638
|
-
.output(z.object({ id: z.string() }))
|
|
639
|
-
.handle(async (_ctx, response) => {
|
|
640
|
-
return response.status(SuccessStatus.Created).send({ id: '123' });
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
644
|
-
const result = await adapter.fullRequest({
|
|
645
|
-
body: { name: 'Resource' },
|
|
646
|
-
services: mockServices,
|
|
647
|
-
headers: { host: 'example.com' },
|
|
648
|
-
});
|
|
649
|
-
|
|
650
|
-
expect(result.status).toBe(201);
|
|
651
|
-
});
|
|
652
|
-
|
|
653
|
-
it('should delete cookies', async () => {
|
|
654
|
-
const endpoint = e
|
|
655
|
-
.post('/auth/logout')
|
|
656
|
-
.output(z.object({ success: z.boolean() }))
|
|
657
|
-
.handle(async (_ctx, response) => {
|
|
658
|
-
return response
|
|
659
|
-
.deleteCookie('session', { path: '/' })
|
|
660
|
-
.send({ success: true });
|
|
661
|
-
});
|
|
662
|
-
|
|
663
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
664
|
-
const result = await adapter.fullRequest({
|
|
665
|
-
services: mockServices,
|
|
666
|
-
headers: { host: 'example.com' },
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
expect(result.body.success).toBe(true);
|
|
670
|
-
const setCookieHeader = result.headers['set-cookie'] as string[];
|
|
671
|
-
expect(setCookieHeader).toHaveLength(1);
|
|
672
|
-
expect(setCookieHeader[0]).toContain('session=');
|
|
673
|
-
expect(setCookieHeader[0]).toContain('Max-Age=0');
|
|
674
|
-
expect(setCookieHeader[0]).toContain('Path=/');
|
|
675
|
-
});
|
|
676
|
-
|
|
677
|
-
it('should combine cookies, headers, and status', async () => {
|
|
678
|
-
const endpoint = e
|
|
679
|
-
.post('/complete')
|
|
680
|
-
.body(z.object({ data: z.string() }))
|
|
681
|
-
.output(z.object({ id: z.string(), result: z.string() }))
|
|
682
|
-
.handle(async ({ body }, response) => {
|
|
683
|
-
return response
|
|
684
|
-
.status(SuccessStatus.Created)
|
|
685
|
-
.header('Location', '/complete/123')
|
|
686
|
-
.header('X-Request-Id', 'req-456')
|
|
687
|
-
.cookie('tracking', 'track-789')
|
|
688
|
-
.cookie('preference', 'dark', { maxAge: 86400 })
|
|
689
|
-
.send({ id: '123', result: body.data });
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
693
|
-
const result = await adapter.fullRequest({
|
|
694
|
-
body: { data: 'test' },
|
|
695
|
-
services: mockServices,
|
|
696
|
-
headers: { host: 'example.com' },
|
|
697
|
-
});
|
|
698
|
-
|
|
699
|
-
expect(result.body).toEqual({
|
|
700
|
-
id: '123',
|
|
701
|
-
result: 'test',
|
|
702
|
-
});
|
|
703
|
-
expect(result.status).toBe(201);
|
|
704
|
-
expect(result.headers).toEqual({
|
|
705
|
-
Location: '/complete/123',
|
|
706
|
-
'X-Request-Id': 'req-456',
|
|
707
|
-
'set-cookie': ['tracking=track-789', 'preference=dark; Max-Age=86400'],
|
|
708
|
-
});
|
|
709
|
-
});
|
|
710
|
-
|
|
711
|
-
it('should return simple response without metadata when not using response builder', async () => {
|
|
712
|
-
const endpoint = e
|
|
713
|
-
.get('/simple')
|
|
714
|
-
.output(z.object({ message: z.string() }))
|
|
715
|
-
.handle(async () => {
|
|
716
|
-
// Not using response builder, just returning data
|
|
717
|
-
return { message: 'Hello' };
|
|
718
|
-
});
|
|
719
|
-
|
|
720
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
721
|
-
const result = await adapter.request({
|
|
722
|
-
services: mockServices,
|
|
723
|
-
headers: { host: 'example.com' },
|
|
724
|
-
});
|
|
725
|
-
|
|
726
|
-
// Should return just the data, not wrapped in metadata
|
|
727
|
-
expect(result).toEqual({ message: 'Hello' });
|
|
728
|
-
expect(result).not.toHaveProperty('metadata');
|
|
729
|
-
});
|
|
730
|
-
|
|
731
|
-
it('should combine request cookies and response cookies', async () => {
|
|
732
|
-
const endpoint = e
|
|
733
|
-
.get('/preferences')
|
|
734
|
-
.output(z.object({ theme: z.string(), updated: z.boolean() }))
|
|
735
|
-
.handle(async ({ cookie }, response) => {
|
|
736
|
-
const currentTheme = cookie('theme') || 'light';
|
|
737
|
-
const newTheme = currentTheme === 'light' ? 'dark' : 'light';
|
|
738
|
-
|
|
739
|
-
return response
|
|
740
|
-
.cookie('theme', newTheme, { maxAge: 86400 })
|
|
741
|
-
.send({ theme: newTheme, updated: true });
|
|
742
|
-
});
|
|
743
|
-
|
|
744
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
745
|
-
const result = await adapter.fullRequest({
|
|
746
|
-
services: mockServices,
|
|
747
|
-
headers: {
|
|
748
|
-
host: 'example.com',
|
|
749
|
-
cookie: 'theme=light',
|
|
750
|
-
},
|
|
751
|
-
});
|
|
752
|
-
|
|
753
|
-
expect(result.body).toEqual({
|
|
754
|
-
theme: 'dark',
|
|
755
|
-
updated: true,
|
|
756
|
-
});
|
|
757
|
-
expect(result.headers['set-cookie']).toEqual([
|
|
758
|
-
'theme=dark; Max-Age=86400',
|
|
759
|
-
]);
|
|
760
|
-
});
|
|
761
|
-
});
|
|
762
|
-
|
|
763
|
-
describe('fullRequest', () => {
|
|
764
|
-
it('should return full HTTP response with body, status, and headers', async () => {
|
|
765
|
-
const endpoint = e
|
|
766
|
-
.get('/test')
|
|
767
|
-
.output(z.object({ message: z.string() }))
|
|
768
|
-
.handle(() => ({ message: 'Hello World' }));
|
|
769
|
-
|
|
770
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
771
|
-
|
|
772
|
-
const result = await adapter.fullRequest({
|
|
773
|
-
services: mockServices,
|
|
774
|
-
headers: { host: 'example.com' },
|
|
775
|
-
});
|
|
776
|
-
|
|
777
|
-
expect(result).toEqual({
|
|
778
|
-
body: { message: 'Hello World' },
|
|
779
|
-
status: 200,
|
|
780
|
-
headers: {},
|
|
781
|
-
});
|
|
782
|
-
});
|
|
783
|
-
|
|
784
|
-
it('should return custom status code in HTTP response', async () => {
|
|
785
|
-
const endpoint = e
|
|
786
|
-
.post('/resources')
|
|
787
|
-
.body(z.object({ name: z.string() }))
|
|
788
|
-
.output(z.object({ id: z.string() }))
|
|
789
|
-
.handle(async (_ctx, response) => {
|
|
790
|
-
return response.status(SuccessStatus.Created).send({ id: '123' });
|
|
791
|
-
});
|
|
792
|
-
|
|
793
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
794
|
-
const result = await adapter.fullRequest({
|
|
795
|
-
body: { name: 'Resource' },
|
|
796
|
-
services: mockServices,
|
|
797
|
-
headers: { host: 'example.com' },
|
|
798
|
-
});
|
|
799
|
-
|
|
800
|
-
expect(result.status).toBe(201);
|
|
801
|
-
expect(result.body).toEqual({ id: '123' });
|
|
802
|
-
});
|
|
803
|
-
|
|
804
|
-
it('should include custom headers in HTTP response', async () => {
|
|
805
|
-
const endpoint = e
|
|
806
|
-
.post('/users')
|
|
807
|
-
.body(z.object({ name: z.string() }))
|
|
808
|
-
.output(z.object({ id: z.string(), name: z.string() }))
|
|
809
|
-
.handle(async ({ body }, response) => {
|
|
810
|
-
const user = { id: 'user-123', name: body.name };
|
|
811
|
-
return response
|
|
812
|
-
.header('Location', `/users/${user.id}`)
|
|
813
|
-
.header('X-User-Id', user.id)
|
|
814
|
-
.send(user);
|
|
815
|
-
});
|
|
816
|
-
|
|
817
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
818
|
-
const result = await adapter.fullRequest({
|
|
819
|
-
body: { name: 'John Doe' },
|
|
820
|
-
services: mockServices,
|
|
821
|
-
headers: { host: 'example.com' },
|
|
822
|
-
});
|
|
823
|
-
|
|
824
|
-
expect(result.body).toEqual({
|
|
825
|
-
id: 'user-123',
|
|
826
|
-
name: 'John Doe',
|
|
827
|
-
});
|
|
828
|
-
expect(result.headers).toEqual({
|
|
829
|
-
Location: '/users/user-123',
|
|
830
|
-
'X-User-Id': 'user-123',
|
|
831
|
-
});
|
|
832
|
-
});
|
|
833
|
-
|
|
834
|
-
it('should convert cookies to Set-Cookie headers', async () => {
|
|
835
|
-
const endpoint = e
|
|
836
|
-
.post('/auth/login')
|
|
837
|
-
.body(z.object({ email: z.string(), password: z.string() }))
|
|
838
|
-
.output(z.object({ id: z.string(), email: z.string() }))
|
|
839
|
-
.handle(async ({ body }, response) => {
|
|
840
|
-
return response
|
|
841
|
-
.cookie('session', 'abc123', {
|
|
842
|
-
httpOnly: true,
|
|
843
|
-
secure: true,
|
|
844
|
-
sameSite: 'strict',
|
|
845
|
-
maxAge: 3600,
|
|
846
|
-
})
|
|
847
|
-
.send({ id: 'user-1', email: body.email });
|
|
848
|
-
});
|
|
849
|
-
|
|
850
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
851
|
-
const result = await adapter.fullRequest({
|
|
852
|
-
body: { email: 'test@example.com', password: 'pass123' },
|
|
853
|
-
services: mockServices,
|
|
854
|
-
headers: { host: 'example.com' },
|
|
855
|
-
});
|
|
856
|
-
|
|
857
|
-
expect(result.body).toEqual({
|
|
858
|
-
id: 'user-1',
|
|
859
|
-
email: 'test@example.com',
|
|
860
|
-
});
|
|
861
|
-
expect(result.headers['set-cookie']).toEqual([
|
|
862
|
-
'session=abc123; Max-Age=3600; HttpOnly; Secure; SameSite=strict',
|
|
863
|
-
]);
|
|
864
|
-
});
|
|
865
|
-
|
|
866
|
-
it('should handle multiple cookies as array of Set-Cookie headers', async () => {
|
|
867
|
-
const endpoint = e
|
|
868
|
-
.post('/complete')
|
|
869
|
-
.body(z.object({ data: z.string() }))
|
|
870
|
-
.output(z.object({ id: z.string(), result: z.string() }))
|
|
871
|
-
.handle(async ({ body }, response) => {
|
|
872
|
-
return response
|
|
873
|
-
.cookie('tracking', 'track-789')
|
|
874
|
-
.cookie('preference', 'dark', { maxAge: 86400, path: '/' })
|
|
875
|
-
.send({ id: '123', result: body.data });
|
|
876
|
-
});
|
|
877
|
-
|
|
878
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
879
|
-
const result = await adapter.fullRequest({
|
|
880
|
-
body: { data: 'test' },
|
|
881
|
-
services: mockServices,
|
|
882
|
-
headers: { host: 'example.com' },
|
|
883
|
-
});
|
|
884
|
-
|
|
885
|
-
expect(result.headers['set-cookie']).toEqual([
|
|
886
|
-
'tracking=track-789',
|
|
887
|
-
'preference=dark; Max-Age=86400; Path=/',
|
|
888
|
-
]);
|
|
889
|
-
});
|
|
890
|
-
|
|
891
|
-
it('should serialize all cookie options correctly', async () => {
|
|
892
|
-
const expires = new Date('2025-12-31T23:59:59Z');
|
|
893
|
-
const endpoint = e
|
|
894
|
-
.get('/cookies-full')
|
|
895
|
-
.output(z.object({ success: z.boolean() }))
|
|
896
|
-
.handle(async (_ctx, response) => {
|
|
897
|
-
return response
|
|
898
|
-
.cookie('full-cookie', 'value123', {
|
|
899
|
-
domain: 'example.com',
|
|
900
|
-
path: '/api',
|
|
901
|
-
expires: expires,
|
|
902
|
-
maxAge: 7200,
|
|
903
|
-
httpOnly: true,
|
|
904
|
-
secure: true,
|
|
905
|
-
sameSite: 'lax',
|
|
906
|
-
})
|
|
907
|
-
.send({ success: true });
|
|
908
|
-
});
|
|
909
|
-
|
|
910
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
911
|
-
const result = await adapter.fullRequest({
|
|
912
|
-
services: mockServices,
|
|
913
|
-
headers: { host: 'example.com' },
|
|
914
|
-
});
|
|
915
|
-
|
|
916
|
-
expect(result.headers['set-cookie']).toEqual([
|
|
917
|
-
`full-cookie=value123; Max-Age=7200; Expires=${expires.toUTCString()}; Domain=example.com; Path=/api; HttpOnly; Secure; SameSite=lax`,
|
|
918
|
-
]);
|
|
919
|
-
});
|
|
920
|
-
|
|
921
|
-
it('should handle cookie deletion in Set-Cookie header', async () => {
|
|
922
|
-
const endpoint = e
|
|
923
|
-
.post('/auth/logout')
|
|
924
|
-
.output(z.object({ success: z.boolean() }))
|
|
925
|
-
.handle(async (_ctx, response) => {
|
|
926
|
-
return response
|
|
927
|
-
.deleteCookie('session', { path: '/' })
|
|
928
|
-
.send({ success: true });
|
|
929
|
-
});
|
|
930
|
-
|
|
931
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
932
|
-
const result = await adapter.fullRequest({
|
|
933
|
-
services: mockServices,
|
|
934
|
-
headers: { host: 'example.com' },
|
|
935
|
-
});
|
|
936
|
-
|
|
937
|
-
expect(result.body.success).toBe(true);
|
|
938
|
-
const setCookieHeader = result.headers['set-cookie'] as string[];
|
|
939
|
-
expect(setCookieHeader).toHaveLength(1);
|
|
940
|
-
expect(setCookieHeader[0]).toContain('session=');
|
|
941
|
-
expect(setCookieHeader[0]).toContain('Max-Age=0');
|
|
942
|
-
expect(setCookieHeader[0]).toContain('Path=/');
|
|
943
|
-
expect(setCookieHeader[0]).toContain('Expires=');
|
|
944
|
-
});
|
|
945
|
-
|
|
946
|
-
it('should combine headers and cookies in HTTP response', async () => {
|
|
947
|
-
const endpoint = e
|
|
948
|
-
.post('/complete')
|
|
949
|
-
.body(z.object({ data: z.string() }))
|
|
950
|
-
.output(z.object({ id: z.string(), result: z.string() }))
|
|
951
|
-
.handle(async ({ body }, response) => {
|
|
952
|
-
return response
|
|
953
|
-
.status(SuccessStatus.Created)
|
|
954
|
-
.header('Location', '/complete/123')
|
|
955
|
-
.header('X-Request-Id', 'req-456')
|
|
956
|
-
.cookie('tracking', 'track-789')
|
|
957
|
-
.cookie('preference', 'dark', { maxAge: 86400 })
|
|
958
|
-
.send({ id: '123', result: body.data });
|
|
959
|
-
});
|
|
960
|
-
|
|
961
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
962
|
-
const result = await adapter.fullRequest({
|
|
963
|
-
body: { data: 'test' },
|
|
964
|
-
services: mockServices,
|
|
965
|
-
headers: { host: 'example.com' },
|
|
966
|
-
});
|
|
967
|
-
|
|
968
|
-
expect(result).toEqual({
|
|
969
|
-
body: { id: '123', result: 'test' },
|
|
970
|
-
status: 201,
|
|
971
|
-
headers: {
|
|
972
|
-
Location: '/complete/123',
|
|
973
|
-
'X-Request-Id': 'req-456',
|
|
974
|
-
'set-cookie': [
|
|
975
|
-
'tracking=track-789',
|
|
976
|
-
'preference=dark; Max-Age=86400',
|
|
977
|
-
],
|
|
978
|
-
},
|
|
979
|
-
});
|
|
980
|
-
});
|
|
981
|
-
|
|
982
|
-
it('should handle empty response metadata', async () => {
|
|
983
|
-
const endpoint = e
|
|
984
|
-
.get('/simple')
|
|
985
|
-
.output(z.object({ message: z.string() }))
|
|
986
|
-
.handle(async () => ({ message: 'Hello' }));
|
|
987
|
-
|
|
988
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
989
|
-
const result = await adapter.fullRequest({
|
|
990
|
-
services: mockServices,
|
|
991
|
-
headers: { host: 'example.com' },
|
|
992
|
-
});
|
|
993
|
-
|
|
994
|
-
expect(result).toEqual({
|
|
995
|
-
body: { message: 'Hello' },
|
|
996
|
-
status: 200,
|
|
997
|
-
headers: {},
|
|
998
|
-
});
|
|
999
|
-
});
|
|
1000
|
-
});
|
|
1001
|
-
|
|
1002
|
-
describe('request method delegation', () => {
|
|
1003
|
-
it('should return only body from fullRequest', async () => {
|
|
1004
|
-
const endpoint = e
|
|
1005
|
-
.post('/users')
|
|
1006
|
-
.body(z.object({ name: z.string() }))
|
|
1007
|
-
.output(z.object({ id: z.string(), name: z.string() }))
|
|
1008
|
-
.handle(async ({ body }, response) => {
|
|
1009
|
-
return response
|
|
1010
|
-
.status(SuccessStatus.Created)
|
|
1011
|
-
.header('Location', '/users/123')
|
|
1012
|
-
.cookie('session', 'abc')
|
|
1013
|
-
.send({ id: '123', name: body.name });
|
|
1014
|
-
});
|
|
1015
|
-
|
|
1016
|
-
const adapter = new TestEndpointAdaptor(endpoint);
|
|
1017
|
-
|
|
1018
|
-
// Call request (should only return body)
|
|
1019
|
-
const simpleResult = await adapter.request({
|
|
1020
|
-
body: { name: 'John' },
|
|
1021
|
-
services: mockServices,
|
|
1022
|
-
headers: { host: 'example.com' },
|
|
1023
|
-
});
|
|
1024
|
-
|
|
1025
|
-
// Call fullRequest (should return full HTTP response)
|
|
1026
|
-
const fullResult = await adapter.fullRequest({
|
|
1027
|
-
body: { name: 'John' },
|
|
1028
|
-
services: mockServices,
|
|
1029
|
-
headers: { host: 'example.com' },
|
|
1030
|
-
});
|
|
1031
|
-
|
|
1032
|
-
// request should only return the body
|
|
1033
|
-
expect(simpleResult).toEqual({ id: '123', name: 'John' });
|
|
1034
|
-
expect(simpleResult).not.toHaveProperty('status');
|
|
1035
|
-
expect(simpleResult).not.toHaveProperty('headers');
|
|
1036
|
-
|
|
1037
|
-
// fullRequest should return complete HTTP response
|
|
1038
|
-
expect(fullResult.body).toEqual({ id: '123', name: 'John' });
|
|
1039
|
-
expect(fullResult.status).toBe(201);
|
|
1040
|
-
expect(fullResult.headers).toHaveProperty('Location');
|
|
1041
|
-
expect(fullResult.headers).toHaveProperty('set-cookie');
|
|
1042
|
-
});
|
|
1043
|
-
});
|
|
1044
|
-
});
|