@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,704 +0,0 @@
|
|
|
1
|
-
import type { EventPublisher, PublishableMessage } from '@geekmidas/events';
|
|
2
|
-
import type { Service, ServiceRegisterOptions } from '@geekmidas/services';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
4
|
-
import { z } from 'zod/v4';
|
|
5
|
-
import { sniffService } from '../Construct';
|
|
6
|
-
import { c } from '../crons';
|
|
7
|
-
import { e } from '../endpoints';
|
|
8
|
-
import { f } from '../functions';
|
|
9
|
-
import { s } from '../subscribers';
|
|
10
|
-
|
|
11
|
-
describe('Construct environment getter', () => {
|
|
12
|
-
describe('Function', () => {
|
|
13
|
-
it('should return empty array when no services are provided', async () => {
|
|
14
|
-
const fn = f.handle(async () => ({ success: true }));
|
|
15
|
-
|
|
16
|
-
expect(await fn.getEnvironment()).toEqual([]);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it('should detect environment variables from a single service', async () => {
|
|
20
|
-
const databaseService = {
|
|
21
|
-
serviceName: 'database' as const,
|
|
22
|
-
register({ envParser }) {
|
|
23
|
-
return envParser.create((get) => ({
|
|
24
|
-
url: get('DATABASE_URL').string(),
|
|
25
|
-
port: get('DATABASE_PORT').string().transform(Number).default(5432),
|
|
26
|
-
}));
|
|
27
|
-
},
|
|
28
|
-
} satisfies Service<'database', any>;
|
|
29
|
-
|
|
30
|
-
const fn = f
|
|
31
|
-
.services([databaseService])
|
|
32
|
-
.handle(async () => ({ success: true }));
|
|
33
|
-
|
|
34
|
-
const envVars = await fn.getEnvironment();
|
|
35
|
-
|
|
36
|
-
expect(envVars).toEqual(['DATABASE_PORT', 'DATABASE_URL']);
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('should detect environment variables from multiple services', async () => {
|
|
40
|
-
const databaseService = {
|
|
41
|
-
serviceName: 'database' as const,
|
|
42
|
-
register({ envParser }) {
|
|
43
|
-
return envParser.create((get) => ({
|
|
44
|
-
url: get('DATABASE_URL').string(),
|
|
45
|
-
}));
|
|
46
|
-
},
|
|
47
|
-
} satisfies Service<'database', any>;
|
|
48
|
-
|
|
49
|
-
const redisService = {
|
|
50
|
-
serviceName: 'redis' as const,
|
|
51
|
-
register({ envParser }) {
|
|
52
|
-
return envParser.create((get) => ({
|
|
53
|
-
url: get('REDIS_URL').string(),
|
|
54
|
-
ttl: get('REDIS_TTL').string().transform(Number).default(3600),
|
|
55
|
-
}));
|
|
56
|
-
},
|
|
57
|
-
} satisfies Service<'redis', any>;
|
|
58
|
-
|
|
59
|
-
const fn = f
|
|
60
|
-
.services([databaseService, redisService])
|
|
61
|
-
.handle(async () => ({ success: true }));
|
|
62
|
-
|
|
63
|
-
const envVars = await fn.getEnvironment();
|
|
64
|
-
|
|
65
|
-
expect(envVars).toEqual(['DATABASE_URL', 'REDIS_TTL', 'REDIS_URL']);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should deduplicate environment variables across services', async () => {
|
|
69
|
-
const service1 = {
|
|
70
|
-
serviceName: 'service1' as const,
|
|
71
|
-
register({ envParser }) {
|
|
72
|
-
return envParser.create((get) => ({
|
|
73
|
-
apiKey: get('SHARED_API_KEY').string(),
|
|
74
|
-
}));
|
|
75
|
-
},
|
|
76
|
-
} satisfies Service<'service1', any>;
|
|
77
|
-
|
|
78
|
-
const service2 = {
|
|
79
|
-
serviceName: 'service2' as const,
|
|
80
|
-
register({ envParser }) {
|
|
81
|
-
return envParser.create((get) => ({
|
|
82
|
-
apiKey: get('SHARED_API_KEY').string(),
|
|
83
|
-
}));
|
|
84
|
-
},
|
|
85
|
-
} satisfies Service<'service2', any>;
|
|
86
|
-
|
|
87
|
-
const fn = f
|
|
88
|
-
.services([service1, service2])
|
|
89
|
-
.handle(async () => ({ success: true }));
|
|
90
|
-
|
|
91
|
-
const envVars = await fn.getEnvironment();
|
|
92
|
-
|
|
93
|
-
// Should only appear once despite being used in both services
|
|
94
|
-
expect(envVars).toEqual(['SHARED_API_KEY']);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
it('should handle services with nested configuration', async () => {
|
|
98
|
-
const configService = {
|
|
99
|
-
serviceName: 'config' as const,
|
|
100
|
-
register({ envParser }) {
|
|
101
|
-
return envParser.create((get) => ({
|
|
102
|
-
database: {
|
|
103
|
-
host: get('DB_HOST').string(),
|
|
104
|
-
port: get('DB_PORT').string().transform(Number),
|
|
105
|
-
},
|
|
106
|
-
api: {
|
|
107
|
-
key: get('API_KEY').string(),
|
|
108
|
-
url: get('API_URL').string().url(),
|
|
109
|
-
},
|
|
110
|
-
}));
|
|
111
|
-
},
|
|
112
|
-
} satisfies Service<'config', any>;
|
|
113
|
-
|
|
114
|
-
const fn = f
|
|
115
|
-
.services([configService])
|
|
116
|
-
.handle(async () => ({ success: true }));
|
|
117
|
-
|
|
118
|
-
const envVars = await fn.getEnvironment();
|
|
119
|
-
|
|
120
|
-
expect(envVars).toEqual(['API_KEY', 'API_URL', 'DB_HOST', 'DB_PORT']);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
it('should handle services that return non-ConfigParser values', async () => {
|
|
124
|
-
const simpleService = {
|
|
125
|
-
serviceName: 'simple' as const,
|
|
126
|
-
register(_options: ServiceRegisterOptions) {
|
|
127
|
-
// This service doesn't use envParser - just returns a plain object
|
|
128
|
-
return { value: 'test' };
|
|
129
|
-
},
|
|
130
|
-
} satisfies Service<'simple', any>;
|
|
131
|
-
|
|
132
|
-
const databaseService = {
|
|
133
|
-
serviceName: 'database' as const,
|
|
134
|
-
register({ envParser }) {
|
|
135
|
-
return envParser.create((get) => ({
|
|
136
|
-
url: get('DATABASE_URL').string(),
|
|
137
|
-
}));
|
|
138
|
-
},
|
|
139
|
-
} satisfies Service<'database', any>;
|
|
140
|
-
|
|
141
|
-
const fn = f
|
|
142
|
-
.services([simpleService, databaseService])
|
|
143
|
-
.handle(async () => ({ success: true }));
|
|
144
|
-
|
|
145
|
-
const envVars = await fn.getEnvironment();
|
|
146
|
-
|
|
147
|
-
// Should only include env vars from databaseService
|
|
148
|
-
expect(envVars).toEqual(['DATABASE_URL']);
|
|
149
|
-
});
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
describe('Endpoint', () => {
|
|
153
|
-
it('should detect environment variables from endpoint services', async () => {
|
|
154
|
-
const authService = {
|
|
155
|
-
serviceName: 'auth' as const,
|
|
156
|
-
register({ envParser }) {
|
|
157
|
-
return envParser.create((get) => ({
|
|
158
|
-
secret: get('JWT_SECRET').string(),
|
|
159
|
-
expiresIn: get('JWT_EXPIRES_IN').string().default('15m'),
|
|
160
|
-
}));
|
|
161
|
-
},
|
|
162
|
-
} satisfies Service<'auth', any>;
|
|
163
|
-
|
|
164
|
-
const endpoint = e
|
|
165
|
-
.services([authService])
|
|
166
|
-
.get('/users')
|
|
167
|
-
.handle(async () => []);
|
|
168
|
-
|
|
169
|
-
const envVars = await endpoint.getEnvironment();
|
|
170
|
-
|
|
171
|
-
expect(envVars).toEqual(['JWT_EXPIRES_IN', 'JWT_SECRET']);
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it('should work with different HTTP methods', async () => {
|
|
175
|
-
const storageService = {
|
|
176
|
-
serviceName: 'storage' as const,
|
|
177
|
-
register({ envParser }) {
|
|
178
|
-
return envParser.create((get) => ({
|
|
179
|
-
bucket: get('S3_BUCKET').string(),
|
|
180
|
-
region: get('AWS_REGION').string().default('us-east-1'),
|
|
181
|
-
}));
|
|
182
|
-
},
|
|
183
|
-
} satisfies Service<'storage', any>;
|
|
184
|
-
|
|
185
|
-
const postEndpoint = e
|
|
186
|
-
.services([storageService])
|
|
187
|
-
.post('/upload')
|
|
188
|
-
.handle(async () => ({ success: true }));
|
|
189
|
-
|
|
190
|
-
const getEndpoint = e
|
|
191
|
-
.services([storageService])
|
|
192
|
-
.get('/files')
|
|
193
|
-
.handle(async () => []);
|
|
194
|
-
|
|
195
|
-
expect(await postEndpoint.getEnvironment()).toEqual([
|
|
196
|
-
'AWS_REGION',
|
|
197
|
-
'S3_BUCKET',
|
|
198
|
-
]);
|
|
199
|
-
expect(await getEndpoint.getEnvironment()).toEqual([
|
|
200
|
-
'AWS_REGION',
|
|
201
|
-
'S3_BUCKET',
|
|
202
|
-
]);
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
describe('Cron', () => {
|
|
207
|
-
it('should detect environment variables from cron services', async () => {
|
|
208
|
-
const emailService = {
|
|
209
|
-
serviceName: 'email' as const,
|
|
210
|
-
register({ envParser }) {
|
|
211
|
-
return envParser.create((get) => ({
|
|
212
|
-
smtpHost: get('SMTP_HOST').string(),
|
|
213
|
-
smtpPort: get('SMTP_PORT').string().transform(Number).default(587),
|
|
214
|
-
smtpUser: get('SMTP_USER').string(),
|
|
215
|
-
smtpPass: get('SMTP_PASS').string(),
|
|
216
|
-
}));
|
|
217
|
-
},
|
|
218
|
-
} satisfies Service<'email', any>;
|
|
219
|
-
|
|
220
|
-
const cronJob = c
|
|
221
|
-
.services([emailService])
|
|
222
|
-
.schedule('rate(1 hour)')
|
|
223
|
-
.handle(async () => {
|
|
224
|
-
// Send daily report email
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
const envVars = await cronJob.getEnvironment();
|
|
228
|
-
|
|
229
|
-
expect(envVars).toEqual([
|
|
230
|
-
'SMTP_HOST',
|
|
231
|
-
'SMTP_PASS',
|
|
232
|
-
'SMTP_PORT',
|
|
233
|
-
'SMTP_USER',
|
|
234
|
-
]);
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
describe('Subscriber', () => {
|
|
239
|
-
it('should detect environment variables from subscriber services', async () => {
|
|
240
|
-
type UserEvents =
|
|
241
|
-
| PublishableMessage<'user.created', { userId: string }>
|
|
242
|
-
| PublishableMessage<'user.updated', { userId: string }>;
|
|
243
|
-
|
|
244
|
-
class UserEventPublisher implements EventPublisher<UserEvents> {
|
|
245
|
-
async publish(_events: UserEvents[]): Promise<void> {}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
const eventPublisherService: Service<'events', UserEventPublisher> = {
|
|
249
|
-
serviceName: 'events' as const,
|
|
250
|
-
register() {
|
|
251
|
-
return new UserEventPublisher();
|
|
252
|
-
},
|
|
253
|
-
};
|
|
254
|
-
|
|
255
|
-
const notificationService = {
|
|
256
|
-
serviceName: 'notification' as const,
|
|
257
|
-
register({ envParser }) {
|
|
258
|
-
return envParser
|
|
259
|
-
.create((get) => ({
|
|
260
|
-
apiKey: get('NOTIFICATION_API_KEY').string(),
|
|
261
|
-
endpoint: get('NOTIFICATION_ENDPOINT')
|
|
262
|
-
.string()
|
|
263
|
-
.url()
|
|
264
|
-
.default('https://api.example.com/notify'),
|
|
265
|
-
}))
|
|
266
|
-
.parse();
|
|
267
|
-
},
|
|
268
|
-
} satisfies Service<'notification', any>;
|
|
269
|
-
|
|
270
|
-
const subscriber = s
|
|
271
|
-
.publisher(eventPublisherService)
|
|
272
|
-
.services([notificationService])
|
|
273
|
-
.subscribe('user.created')
|
|
274
|
-
.handle(async () => {
|
|
275
|
-
// Handle user created events
|
|
276
|
-
});
|
|
277
|
-
|
|
278
|
-
const envVars = await subscriber.getEnvironment();
|
|
279
|
-
|
|
280
|
-
expect(envVars).toEqual([
|
|
281
|
-
'NOTIFICATION_API_KEY',
|
|
282
|
-
'NOTIFICATION_ENDPOINT',
|
|
283
|
-
]);
|
|
284
|
-
});
|
|
285
|
-
});
|
|
286
|
-
|
|
287
|
-
describe('Edge cases', () => {
|
|
288
|
-
it('should return empty array when services array is empty', async () => {
|
|
289
|
-
const fn = f.services([]).handle(async () => ({ success: true }));
|
|
290
|
-
|
|
291
|
-
expect(await fn.getEnvironment()).toEqual([]);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
it('should handle service with optional environment variables', async () => {
|
|
295
|
-
const optionalConfigService = {
|
|
296
|
-
serviceName: 'optionalConfig' as const,
|
|
297
|
-
register({ envParser }) {
|
|
298
|
-
return envParser.create((get) => ({
|
|
299
|
-
required: get('REQUIRED_VAR').string(),
|
|
300
|
-
optional1: get('OPTIONAL_VAR_1').string().optional(),
|
|
301
|
-
optional2: get('OPTIONAL_VAR_2').string().optional(),
|
|
302
|
-
}));
|
|
303
|
-
},
|
|
304
|
-
} satisfies Service<'optionalConfig', any>;
|
|
305
|
-
|
|
306
|
-
const fn = f
|
|
307
|
-
.services([optionalConfigService])
|
|
308
|
-
.handle(async () => ({ success: true }));
|
|
309
|
-
|
|
310
|
-
const envVars = await fn.getEnvironment();
|
|
311
|
-
|
|
312
|
-
// Should include both required and optional variables
|
|
313
|
-
expect(envVars).toEqual([
|
|
314
|
-
'OPTIONAL_VAR_1',
|
|
315
|
-
'OPTIONAL_VAR_2',
|
|
316
|
-
'REQUIRED_VAR',
|
|
317
|
-
]);
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it('should be callable multiple times with consistent results', async () => {
|
|
321
|
-
const service = {
|
|
322
|
-
serviceName: 'testService' as const,
|
|
323
|
-
register({ envParser }) {
|
|
324
|
-
return envParser.create((get) => ({
|
|
325
|
-
var1: get('VAR_1').string(),
|
|
326
|
-
var2: get('VAR_2').string(),
|
|
327
|
-
}));
|
|
328
|
-
},
|
|
329
|
-
} satisfies Service<'testService', any>;
|
|
330
|
-
|
|
331
|
-
const fn = f.services([service]).handle(async () => ({ success: true }));
|
|
332
|
-
|
|
333
|
-
const firstCall = await fn.getEnvironment();
|
|
334
|
-
const secondCall = await fn.getEnvironment();
|
|
335
|
-
const thirdCall = await fn.getEnvironment();
|
|
336
|
-
|
|
337
|
-
expect(firstCall).toEqual(['VAR_1', 'VAR_2']);
|
|
338
|
-
expect(secondCall).toEqual(['VAR_1', 'VAR_2']);
|
|
339
|
-
expect(thirdCall).toEqual(['VAR_1', 'VAR_2']);
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it('should handle services with complex transformations', async () => {
|
|
343
|
-
const complexService = {
|
|
344
|
-
serviceName: 'complex' as const,
|
|
345
|
-
register({ envParser }) {
|
|
346
|
-
return envParser.create((get) => ({
|
|
347
|
-
origins: get('ALLOWED_ORIGINS')
|
|
348
|
-
.string()
|
|
349
|
-
.transform((v) => v.split(',')),
|
|
350
|
-
flags: get('FEATURE_FLAGS')
|
|
351
|
-
.string()
|
|
352
|
-
.transform((v) => v.split(',').map((f) => f.trim())),
|
|
353
|
-
config: get('JSON_CONFIG')
|
|
354
|
-
.string()
|
|
355
|
-
.transform((v) => JSON.parse(v))
|
|
356
|
-
.pipe(z.record(z.string(), z.boolean())),
|
|
357
|
-
}));
|
|
358
|
-
},
|
|
359
|
-
} satisfies Service<'complex', any>;
|
|
360
|
-
|
|
361
|
-
const fn = f
|
|
362
|
-
.services([complexService])
|
|
363
|
-
.handle(async () => ({ success: true }));
|
|
364
|
-
|
|
365
|
-
const envVars = await fn.getEnvironment();
|
|
366
|
-
|
|
367
|
-
expect(envVars).toEqual([
|
|
368
|
-
'ALLOWED_ORIGINS',
|
|
369
|
-
'FEATURE_FLAGS',
|
|
370
|
-
'JSON_CONFIG',
|
|
371
|
-
]);
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
it('should handle services that throw synchronous errors during registration', async () => {
|
|
375
|
-
const throwingService = {
|
|
376
|
-
serviceName: 'throwing' as const,
|
|
377
|
-
register({ envParser }) {
|
|
378
|
-
const config = envParser
|
|
379
|
-
.create((get) => ({
|
|
380
|
-
url: get('SERVICE_URL').string(),
|
|
381
|
-
}))
|
|
382
|
-
.parse();
|
|
383
|
-
|
|
384
|
-
// Simulate a library that validates config immediately
|
|
385
|
-
// Sniffer returns '' for strings, so this will throw
|
|
386
|
-
if (!config.url || config.url === '') {
|
|
387
|
-
throw new Error('Invalid URL provided');
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
return { url: config.url };
|
|
391
|
-
},
|
|
392
|
-
} satisfies Service<'throwing', any>;
|
|
393
|
-
|
|
394
|
-
// Verify env vars are captured even when service throws
|
|
395
|
-
const result = await sniffService(throwingService);
|
|
396
|
-
expect(result.envVars).toEqual(['SERVICE_URL']);
|
|
397
|
-
expect(result.error).toBeDefined();
|
|
398
|
-
expect(result.error?.message).toBe('Invalid URL provided');
|
|
399
|
-
|
|
400
|
-
// Also verify it works in a construct context with multiple services
|
|
401
|
-
const workingService = {
|
|
402
|
-
serviceName: 'working' as const,
|
|
403
|
-
register({ envParser }) {
|
|
404
|
-
return envParser
|
|
405
|
-
.create((get) => ({
|
|
406
|
-
key: get('API_KEY').string(),
|
|
407
|
-
}))
|
|
408
|
-
.parse();
|
|
409
|
-
},
|
|
410
|
-
} satisfies Service<'working', any>;
|
|
411
|
-
|
|
412
|
-
const fn = f
|
|
413
|
-
.services([throwingService, workingService])
|
|
414
|
-
.handle(async () => ({ success: true }));
|
|
415
|
-
|
|
416
|
-
const envVars = await fn.getEnvironment();
|
|
417
|
-
expect(envVars).toEqual(['API_KEY', 'SERVICE_URL']);
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
it('should handle services that return rejecting promises', async () => {
|
|
421
|
-
const asyncThrowingService = {
|
|
422
|
-
serviceName: 'asyncThrowing' as const,
|
|
423
|
-
async register({ envParser }) {
|
|
424
|
-
const config = envParser
|
|
425
|
-
.create((get) => ({
|
|
426
|
-
secret: get('AUTH_SECRET').string(),
|
|
427
|
-
frontendUrl: get('FRONTEND_URL').string(),
|
|
428
|
-
}))
|
|
429
|
-
.parse();
|
|
430
|
-
|
|
431
|
-
// Simulate an async library that validates config
|
|
432
|
-
await Promise.resolve();
|
|
433
|
-
if (!config.frontendUrl) {
|
|
434
|
-
throw new Error('Frontend URL is required');
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
return { config };
|
|
438
|
-
},
|
|
439
|
-
} satisfies Service<'asyncThrowing', any>;
|
|
440
|
-
|
|
441
|
-
// Verify env vars are captured even when service rejects
|
|
442
|
-
const result = await sniffService(asyncThrowingService);
|
|
443
|
-
expect(result.envVars).toEqual(['AUTH_SECRET', 'FRONTEND_URL']);
|
|
444
|
-
expect(result.error).toBeDefined();
|
|
445
|
-
expect(result.error?.message).toBe('Frontend URL is required');
|
|
446
|
-
|
|
447
|
-
// Also verify via construct
|
|
448
|
-
const fn = f
|
|
449
|
-
.services([asyncThrowingService])
|
|
450
|
-
.handle(async () => ({ success: true }));
|
|
451
|
-
|
|
452
|
-
const envVars = await fn.getEnvironment();
|
|
453
|
-
expect(envVars).toEqual(['AUTH_SECRET', 'FRONTEND_URL']);
|
|
454
|
-
});
|
|
455
|
-
|
|
456
|
-
it('should handle services that create fire-and-forget rejecting promises (BetterAuth scenario)', async () => {
|
|
457
|
-
// This test uses the REAL better-auth library to verify that
|
|
458
|
-
// the sniffer gracefully handles libraries that create internal
|
|
459
|
-
// fire-and-forget promises which reject on invalid config
|
|
460
|
-
const { betterAuth } = await import('better-auth');
|
|
461
|
-
|
|
462
|
-
const betterAuthService = {
|
|
463
|
-
serviceName: 'auth' as const,
|
|
464
|
-
register({ envParser }) {
|
|
465
|
-
const config = envParser
|
|
466
|
-
.create((get) => ({
|
|
467
|
-
secret: get('BETTER_AUTH_SECRET').string(),
|
|
468
|
-
baseURL: get('BETTER_AUTH_URL').string(),
|
|
469
|
-
trustedOrigins: get('BETTER_AUTH_TRUSTED_ORIGINS').string(),
|
|
470
|
-
}))
|
|
471
|
-
.parse();
|
|
472
|
-
|
|
473
|
-
// When sniffer runs, config values are empty strings
|
|
474
|
-
// BetterAuth will create fire-and-forget promises that reject
|
|
475
|
-
// when it tries to validate trustedOrigins with new URL('')
|
|
476
|
-
const auth = betterAuth({
|
|
477
|
-
secret: config.secret,
|
|
478
|
-
baseURL: config.baseURL,
|
|
479
|
-
trustedOrigins: config.trustedOrigins
|
|
480
|
-
? config.trustedOrigins.split(',')
|
|
481
|
-
: [],
|
|
482
|
-
database: {
|
|
483
|
-
// Use memory adapter to avoid DB setup
|
|
484
|
-
type: 'sqlite',
|
|
485
|
-
url: ':memory:',
|
|
486
|
-
},
|
|
487
|
-
});
|
|
488
|
-
|
|
489
|
-
return auth;
|
|
490
|
-
},
|
|
491
|
-
} satisfies Service<'auth', any>;
|
|
492
|
-
|
|
493
|
-
// Verify env vars are captured even though BetterAuth's internal
|
|
494
|
-
// fire-and-forget promise will reject on invalid trustedOrigins
|
|
495
|
-
const result = await sniffService(betterAuthService);
|
|
496
|
-
expect(result.envVars).toEqual([
|
|
497
|
-
'BETTER_AUTH_SECRET',
|
|
498
|
-
'BETTER_AUTH_TRUSTED_ORIGINS',
|
|
499
|
-
'BETTER_AUTH_URL',
|
|
500
|
-
]);
|
|
501
|
-
// Synchronous registration succeeds
|
|
502
|
-
expect(result.error).toBeUndefined();
|
|
503
|
-
// But fire-and-forget rejections are captured from better-auth
|
|
504
|
-
expect(result.unhandledRejections.length).toBeGreaterThan(0);
|
|
505
|
-
// Log the actual errors for debugging visibility
|
|
506
|
-
console.log(
|
|
507
|
-
'Captured better-auth unhandled rejections:',
|
|
508
|
-
result.unhandledRejections.map((e) => e.message),
|
|
509
|
-
);
|
|
510
|
-
|
|
511
|
-
// Most importantly: the process should NOT crash from unhandled rejection
|
|
512
|
-
const fn = f
|
|
513
|
-
.services([betterAuthService])
|
|
514
|
-
.handle(async () => ({ success: true }));
|
|
515
|
-
|
|
516
|
-
const envVars = await fn.getEnvironment();
|
|
517
|
-
expect(envVars).toEqual([
|
|
518
|
-
'BETTER_AUTH_SECRET',
|
|
519
|
-
'BETTER_AUTH_TRUSTED_ORIGINS',
|
|
520
|
-
'BETTER_AUTH_URL',
|
|
521
|
-
]);
|
|
522
|
-
});
|
|
523
|
-
|
|
524
|
-
it('should handle multiple problematic services without crashing', async () => {
|
|
525
|
-
const service1 = {
|
|
526
|
-
serviceName: 'service1' as const,
|
|
527
|
-
register({ envParser }) {
|
|
528
|
-
envParser.create((get) => ({
|
|
529
|
-
var1: get('VAR_1').string(),
|
|
530
|
-
}));
|
|
531
|
-
throw new Error('Service 1 failed');
|
|
532
|
-
},
|
|
533
|
-
} satisfies Service<'service1', any>;
|
|
534
|
-
|
|
535
|
-
const service2 = {
|
|
536
|
-
serviceName: 'service2' as const,
|
|
537
|
-
register({ envParser }) {
|
|
538
|
-
const config = envParser.create((get) => ({
|
|
539
|
-
var2: get('VAR_2').string(),
|
|
540
|
-
}));
|
|
541
|
-
|
|
542
|
-
// Fire-and-forget rejection
|
|
543
|
-
Promise.reject(new Error('Service 2 async error'));
|
|
544
|
-
|
|
545
|
-
return config;
|
|
546
|
-
},
|
|
547
|
-
} satisfies Service<'service2', any>;
|
|
548
|
-
|
|
549
|
-
const service3 = {
|
|
550
|
-
serviceName: 'service3' as const,
|
|
551
|
-
register({ envParser }) {
|
|
552
|
-
return envParser.create((get) => ({
|
|
553
|
-
var3: get('VAR_3').string(),
|
|
554
|
-
}));
|
|
555
|
-
},
|
|
556
|
-
} satisfies Service<'service3', any>;
|
|
557
|
-
|
|
558
|
-
// Verify individual services
|
|
559
|
-
const result1 = await sniffService(service1);
|
|
560
|
-
expect(result1.envVars).toEqual(['VAR_1']);
|
|
561
|
-
expect(result1.error?.message).toBe('Service 1 failed');
|
|
562
|
-
|
|
563
|
-
const result2 = await sniffService(service2);
|
|
564
|
-
expect(result2.envVars).toEqual(['VAR_2']);
|
|
565
|
-
// Fire-and-forget - no error captured
|
|
566
|
-
expect(result2.error).toBeUndefined();
|
|
567
|
-
|
|
568
|
-
const result3 = await sniffService(service3);
|
|
569
|
-
expect(result3.envVars).toEqual(['VAR_3']);
|
|
570
|
-
expect(result3.error).toBeUndefined();
|
|
571
|
-
|
|
572
|
-
// Verify all work together in construct
|
|
573
|
-
const fn = f
|
|
574
|
-
.services([service1, service2, service3])
|
|
575
|
-
.handle(async () => ({ success: true }));
|
|
576
|
-
|
|
577
|
-
const envVars = await fn.getEnvironment();
|
|
578
|
-
expect(envVars).toEqual(['VAR_1', 'VAR_2', 'VAR_3']);
|
|
579
|
-
});
|
|
580
|
-
});
|
|
581
|
-
|
|
582
|
-
describe('markOptional option', () => {
|
|
583
|
-
const dbService = {
|
|
584
|
-
serviceName: 'db' as const,
|
|
585
|
-
register({ envParser }) {
|
|
586
|
-
return envParser
|
|
587
|
-
.create((get) => ({
|
|
588
|
-
url: get('DATABASE_URL').string(),
|
|
589
|
-
pool: get('DB_POOL_SIZE').string().transform(Number).default(10),
|
|
590
|
-
}))
|
|
591
|
-
.parse();
|
|
592
|
-
},
|
|
593
|
-
} satisfies Service<'db', any>;
|
|
594
|
-
|
|
595
|
-
const authService = {
|
|
596
|
-
serviceName: 'auth' as const,
|
|
597
|
-
register({ envParser }) {
|
|
598
|
-
return envParser
|
|
599
|
-
.create((get) => ({
|
|
600
|
-
secret: get('JWT_SECRET').string(),
|
|
601
|
-
ttl: get('JWT_TTL').string().optional(),
|
|
602
|
-
}))
|
|
603
|
-
.parse();
|
|
604
|
-
},
|
|
605
|
-
} satisfies Service<'auth', any>;
|
|
606
|
-
|
|
607
|
-
it('returns plain var names when markOptional is false (default)', async () => {
|
|
608
|
-
const fn = f
|
|
609
|
-
.services([dbService])
|
|
610
|
-
.handle(async () => ({ success: true }));
|
|
611
|
-
|
|
612
|
-
expect(await fn.getEnvironment()).toEqual([
|
|
613
|
-
'DATABASE_URL',
|
|
614
|
-
'DB_POOL_SIZE',
|
|
615
|
-
]);
|
|
616
|
-
expect(await fn.getEnvironment({ markOptional: false })).toEqual([
|
|
617
|
-
'DATABASE_URL',
|
|
618
|
-
'DB_POOL_SIZE',
|
|
619
|
-
]);
|
|
620
|
-
});
|
|
621
|
-
|
|
622
|
-
it('suffixes optional vars with ? when markOptional is true', async () => {
|
|
623
|
-
const fn = f
|
|
624
|
-
.services([dbService])
|
|
625
|
-
.handle(async () => ({ success: true }));
|
|
626
|
-
|
|
627
|
-
expect(await fn.getEnvironment({ markOptional: true })).toEqual([
|
|
628
|
-
'DATABASE_URL',
|
|
629
|
-
'DB_POOL_SIZE?',
|
|
630
|
-
]);
|
|
631
|
-
});
|
|
632
|
-
|
|
633
|
-
it('marks vars with .optional() as optional', async () => {
|
|
634
|
-
const fn = f
|
|
635
|
-
.services([authService])
|
|
636
|
-
.handle(async () => ({ success: true }));
|
|
637
|
-
|
|
638
|
-
expect(await fn.getEnvironment({ markOptional: true })).toEqual([
|
|
639
|
-
'JWT_SECRET',
|
|
640
|
-
'JWT_TTL?',
|
|
641
|
-
]);
|
|
642
|
-
});
|
|
643
|
-
|
|
644
|
-
it('marks optional vars across multiple services', async () => {
|
|
645
|
-
const fn = f
|
|
646
|
-
.services([dbService, authService])
|
|
647
|
-
.handle(async () => ({ success: true }));
|
|
648
|
-
|
|
649
|
-
expect(await fn.getEnvironment({ markOptional: true })).toEqual([
|
|
650
|
-
'DATABASE_URL',
|
|
651
|
-
'DB_POOL_SIZE?',
|
|
652
|
-
'JWT_SECRET',
|
|
653
|
-
'JWT_TTL?',
|
|
654
|
-
]);
|
|
655
|
-
});
|
|
656
|
-
|
|
657
|
-
it('works on Endpoint constructs', async () => {
|
|
658
|
-
const endpoint = e
|
|
659
|
-
.services([dbService])
|
|
660
|
-
.get('/users')
|
|
661
|
-
.handle(async () => []);
|
|
662
|
-
|
|
663
|
-
expect(await endpoint.getEnvironment({ markOptional: true })).toEqual([
|
|
664
|
-
'DATABASE_URL',
|
|
665
|
-
'DB_POOL_SIZE?',
|
|
666
|
-
]);
|
|
667
|
-
});
|
|
668
|
-
|
|
669
|
-
it('works on Cron constructs', async () => {
|
|
670
|
-
const cron = c
|
|
671
|
-
.schedule('rate(1 hour)')
|
|
672
|
-
.services([authService])
|
|
673
|
-
.handle(async () => {});
|
|
674
|
-
|
|
675
|
-
expect(await cron.getEnvironment({ markOptional: true })).toEqual([
|
|
676
|
-
'JWT_SECRET',
|
|
677
|
-
'JWT_TTL?',
|
|
678
|
-
]);
|
|
679
|
-
});
|
|
680
|
-
|
|
681
|
-
it('required-only vars have no ? suffix', async () => {
|
|
682
|
-
const requiredOnly = {
|
|
683
|
-
serviceName: 'required' as const,
|
|
684
|
-
register({ envParser }) {
|
|
685
|
-
return envParser
|
|
686
|
-
.create((get) => ({
|
|
687
|
-
a: get('VAR_A').string(),
|
|
688
|
-
b: get('VAR_B').string(),
|
|
689
|
-
}))
|
|
690
|
-
.parse();
|
|
691
|
-
},
|
|
692
|
-
} satisfies Service<'required', any>;
|
|
693
|
-
|
|
694
|
-
const fn = f
|
|
695
|
-
.services([requiredOnly])
|
|
696
|
-
.handle(async () => ({ success: true }));
|
|
697
|
-
|
|
698
|
-
expect(await fn.getEnvironment({ markOptional: true })).toEqual([
|
|
699
|
-
'VAR_A',
|
|
700
|
-
'VAR_B',
|
|
701
|
-
]);
|
|
702
|
-
});
|
|
703
|
-
});
|
|
704
|
-
});
|