@geekmidas/constructs 10.0.0-alpha.37 → 10.0.0-alpha.39
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 +156 -155
- package/dist/{Construct-Detz65RA.mjs → Construct-BO1X-kt9.mjs} +3 -6
- package/dist/Construct-BO1X-kt9.mjs.map +1 -0
- package/dist/Construct-BQALFCh2.d.cts +230 -0
- package/dist/Construct-BQALFCh2.d.cts.map +1 -0
- package/dist/{Construct-yG9Sw-5p.cjs → Construct-DmvXceVY.cjs} +3 -6
- package/dist/Construct-DmvXceVY.cjs.map +1 -0
- package/dist/Construct-QXnl3VqT.d.mts +230 -0
- package/dist/Construct-QXnl3VqT.d.mts.map +1 -0
- package/dist/{Cron-CA2oa2nC.d.cts → Cron-CMEGfRs8.d.cts} +7 -5
- package/dist/Cron-CMEGfRs8.d.cts.map +1 -0
- package/dist/{Cron-B_iuyNxr.d.mts → Cron-D6X4-xjB.d.mts} +7 -5
- package/dist/Cron-D6X4-xjB.d.mts.map +1 -0
- package/dist/{CronBuilder-B_KqaodP.d.cts → CronBuilder-CEK7aOqD.d.cts} +21 -16
- package/dist/CronBuilder-CEK7aOqD.d.cts.map +1 -0
- package/dist/{CronBuilder-BbnT7tqo.cjs → CronBuilder-DB35T5dL.cjs} +13 -11
- package/dist/CronBuilder-DB35T5dL.cjs.map +1 -0
- package/dist/{CronBuilder-BRkzUOAs.mjs → CronBuilder-Dv0IlZs0.mjs} +14 -12
- package/dist/CronBuilder-Dv0IlZs0.mjs.map +1 -0
- package/dist/{CronBuilder-BIKCLWu7.d.mts → CronBuilder-O_gvButp.d.mts} +21 -16
- package/dist/CronBuilder-O_gvButp.d.mts.map +1 -0
- package/dist/{Endpoint-DO332Dnm.mjs → Endpoint-CQAeh1Rh.mjs} +5 -5
- package/dist/Endpoint-CQAeh1Rh.mjs.map +1 -0
- package/dist/{Endpoint-QKuFg5gs.cjs → Endpoint-D1L9qu5C.cjs} +5 -5
- package/dist/Endpoint-D1L9qu5C.cjs.map +1 -0
- package/dist/{Endpoint-1-XYQSx0.d.cts → Endpoint-Dp5AKIXl.d.cts} +10 -13
- package/dist/Endpoint-Dp5AKIXl.d.cts.map +1 -0
- package/dist/{Endpoint-GFIxYb9L.d.mts → Endpoint-DtI7heFm.d.mts} +10 -13
- package/dist/Endpoint-DtI7heFm.d.mts.map +1 -0
- package/dist/{EndpointFactory-B9HAjDAP.mjs → EndpointFactory-BBdNeaGJ.mjs} +23 -52
- package/dist/EndpointFactory-BBdNeaGJ.mjs.map +1 -0
- package/dist/{EndpointFactory-BmO0WnXE.cjs → EndpointFactory-BZOCOaK6.cjs} +22 -51
- package/dist/EndpointFactory-BZOCOaK6.cjs.map +1 -0
- package/dist/{EndpointFactory-BCZdh_u3.d.mts → EndpointFactory-CgMDvERK.d.mts} +58 -48
- package/dist/EndpointFactory-CgMDvERK.d.mts.map +1 -0
- package/dist/{EndpointFactory-BnK_YkW1.d.cts → EndpointFactory-FeFRmlDZ.d.cts} +58 -48
- package/dist/EndpointFactory-FeFRmlDZ.d.cts.map +1 -0
- package/dist/{HonoEndpointAdaptor-CiqAZ5Mt.mjs → HonoEndpointAdaptor-Aui-x9Lg.mjs} +4 -3
- package/dist/HonoEndpointAdaptor-Aui-x9Lg.mjs.map +1 -0
- package/dist/{HonoEndpointAdaptor-DoEQdC3r.cjs → HonoEndpointAdaptor-Cq99r9H7.cjs} +5 -4
- package/dist/HonoEndpointAdaptor-Cq99r9H7.cjs.map +1 -0
- package/dist/{Queue-DpKTLl6E.mjs → Queue-C1uDgjxt.mjs} +29 -48
- package/dist/Queue-C1uDgjxt.mjs.map +1 -0
- package/dist/{Queue-B7yRXQmL.cjs → Queue-Ckmudcm8.cjs} +29 -48
- package/dist/Queue-Ckmudcm8.cjs.map +1 -0
- package/dist/{Queue-Bhzi2WQC.d.cts → Queue-CpQIGB_2.d.cts} +22 -33
- package/dist/Queue-CpQIGB_2.d.cts.map +1 -0
- package/dist/{Queue-BoUA-e83.d.mts → Queue-YmvN2vEP.d.mts} +21 -32
- package/dist/Queue-YmvN2vEP.d.mts.map +1 -0
- package/dist/QueueBuilder-CJNcv4dy.cjs +112 -0
- package/dist/QueueBuilder-CJNcv4dy.cjs.map +1 -0
- package/dist/QueueBuilder-CM0WUxfw.d.mts +62 -0
- package/dist/QueueBuilder-CM0WUxfw.d.mts.map +1 -0
- package/dist/QueueBuilder-XEnnOWGe.d.cts +62 -0
- package/dist/QueueBuilder-XEnnOWGe.d.cts.map +1 -0
- package/dist/QueueBuilder-XuPKZwKH.mjs +95 -0
- package/dist/QueueBuilder-XuPKZwKH.mjs.map +1 -0
- package/dist/{Subscriber-DQCaiOXF.d.cts → Subscriber-B91YSkZt.d.cts} +12 -13
- package/dist/Subscriber-B91YSkZt.d.cts.map +1 -0
- package/dist/{Subscriber-CIO3pwji.d.mts → Subscriber-BjHYe5hK.d.mts} +11 -12
- package/dist/Subscriber-BjHYe5hK.d.mts.map +1 -0
- package/dist/{SubscriberBuilder-CjDGSTZc.d.cts → SubscriberBuilder-BSpQX1JT.d.cts} +19 -23
- package/dist/SubscriberBuilder-BSpQX1JT.d.cts.map +1 -0
- package/dist/{SubscriberBuilder-C2FRfd26.d.mts → SubscriberBuilder-BhMphk4z.d.mts} +18 -22
- package/dist/SubscriberBuilder-BhMphk4z.d.mts.map +1 -0
- package/dist/{SubscriberBuilder-C2bCOuPT.cjs → SubscriberBuilder-Duk028pD.cjs} +11 -19
- package/dist/SubscriberBuilder-Duk028pD.cjs.map +1 -0
- package/dist/{SubscriberBuilder-B4YRTBng.mjs → SubscriberBuilder-DzQUWE08.mjs} +11 -19
- package/dist/SubscriberBuilder-DzQUWE08.mjs.map +1 -0
- package/dist/{Topic-D5rlM9wS.cjs → Topic-BBVXC3H4.cjs} +46 -51
- package/dist/Topic-BBVXC3H4.cjs.map +1 -0
- package/dist/Topic-DOw051ch.mjs +98 -0
- package/dist/Topic-DOw051ch.mjs.map +1 -0
- package/dist/adaptors/aws.cjs +5 -5
- package/dist/adaptors/aws.cjs.map +1 -1
- package/dist/adaptors/aws.d.cts +26 -26
- package/dist/adaptors/aws.d.cts.map +1 -1
- package/dist/adaptors/aws.d.mts +25 -25
- package/dist/adaptors/aws.d.mts.map +1 -1
- package/dist/adaptors/aws.mjs +5 -5
- package/dist/adaptors/aws.mjs.map +1 -1
- package/dist/adaptors/hono.cjs +1 -1
- package/dist/adaptors/hono.d.cts +4 -5
- package/dist/adaptors/hono.d.cts.map +1 -1
- package/dist/adaptors/hono.d.mts +4 -5
- package/dist/adaptors/hono.d.mts.map +1 -1
- package/dist/adaptors/hono.mjs +1 -1
- package/dist/adaptors/testing.cjs +59 -23
- package/dist/adaptors/testing.cjs.map +1 -1
- package/dist/adaptors/testing.d.cts +40 -28
- package/dist/adaptors/testing.d.cts.map +1 -1
- package/dist/adaptors/testing.d.mts +40 -28
- package/dist/adaptors/testing.d.mts.map +1 -1
- package/dist/adaptors/testing.mjs +59 -23
- package/dist/adaptors/testing.mjs.map +1 -1
- package/dist/{auth-c6nWnvD8.d.cts → auth-CMwml9QN.d.mts} +4 -4
- package/dist/{auth-c6nWnvD8.d.cts.map → auth-CMwml9QN.d.mts.map} +1 -1
- package/dist/{auth-pS_U1H_X.d.mts → auth-rVRDjIw_.d.cts} +4 -4
- package/dist/{auth-pS_U1H_X.d.mts.map → auth-rVRDjIw_.d.cts.map} +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.mts +1 -1
- package/dist/{cache-B2s0b-ss.d.mts → cache-C9a_hVCc.d.cts} +3 -3
- package/dist/{cache-B2s0b-ss.d.mts.map → cache-C9a_hVCc.d.cts.map} +1 -1
- package/dist/{cache-CYe2Kzjc.d.cts → cache-CeTMI8LR.d.mts} +3 -3
- package/dist/{cache-CYe2Kzjc.d.cts.map → cache-CeTMI8LR.d.mts.map} +1 -1
- package/dist/cache.d.cts +1 -1
- package/dist/cache.d.mts +1 -1
- package/dist/{construct-interface-D2gesxos.d.mts → construct-interface-_3zgxzXl.d.mts} +11 -20
- package/dist/{construct-interface-D2gesxos.d.mts.map → construct-interface-_3zgxzXl.d.mts.map} +1 -1
- package/dist/{construct-interface-DPusCUSQ.d.cts → construct-interface-_xi4BPN8.d.cts} +11 -20
- package/dist/{construct-interface-DPusCUSQ.d.cts.map → construct-interface-_xi4BPN8.d.cts.map} +1 -1
- package/dist/construct-interface.cjs +4 -33
- package/dist/construct-interface.cjs.map +1 -1
- package/dist/construct-interface.d.cts +2 -2
- package/dist/construct-interface.d.mts +2 -2
- package/dist/construct-interface.mjs +5 -32
- package/dist/construct-interface.mjs.map +1 -1
- package/dist/credential.cjs +22 -9
- package/dist/credential.cjs.map +1 -1
- package/dist/credential.d.cts +12 -2
- package/dist/credential.d.cts.map +1 -1
- package/dist/credential.d.mts +12 -2
- package/dist/credential.d.mts.map +1 -1
- package/dist/credential.mjs +22 -10
- package/dist/credential.mjs.map +1 -1
- package/dist/crons/index.cjs +1 -1
- package/dist/crons/index.d.cts +2 -2
- package/dist/crons/index.d.mts +2 -2
- package/dist/crons/index.mjs +1 -1
- package/dist/database/kysely.d.cts +1 -1
- package/dist/database/kysely.d.mts +1 -1
- package/dist/email.d.cts +1 -1
- package/dist/email.d.mts +1 -1
- package/dist/endpoints/index.cjs +5 -4
- package/dist/endpoints/index.d.cts +4 -13
- package/dist/endpoints/index.d.cts.map +1 -1
- package/dist/endpoints/index.d.mts +4 -13
- package/dist/endpoints/index.d.mts.map +1 -1
- package/dist/endpoints/index.mjs +4 -3
- package/dist/external-api-DS3mujT5.d.mts +86 -0
- package/dist/external-api-DS3mujT5.d.mts.map +1 -0
- package/dist/external-api-LBfE-q3g.d.cts +86 -0
- package/dist/external-api-LBfE-q3g.d.cts.map +1 -0
- package/dist/external-api.cjs +124 -0
- package/dist/external-api.cjs.map +1 -0
- package/dist/external-api.d.cts +2 -0
- package/dist/external-api.d.mts +2 -0
- package/dist/external-api.mjs +121 -0
- package/dist/external-api.mjs.map +1 -0
- package/dist/file-server.d.cts +1 -1
- package/dist/file-server.d.mts +1 -1
- package/dist/functions/index.cjs +1 -1
- package/dist/functions/index.d.cts +1 -1
- package/dist/functions/index.d.mts +1 -1
- package/dist/functions/index.mjs +1 -1
- package/dist/{functions-DlFm8HmH.mjs → functions-DCIfCRR-.mjs} +94 -23
- package/dist/functions-DCIfCRR-.mjs.map +1 -0
- package/dist/{functions-DKN6aQWJ.cjs → functions-ZH60FE7H.cjs} +99 -19
- package/dist/functions-ZH60FE7H.cjs.map +1 -0
- package/dist/{index-BI23K3wy.d.cts → index-B0kxstwf.d.cts} +36 -24
- package/dist/index-B0kxstwf.d.cts.map +1 -0
- package/dist/{index-yb3fXNyH.d.mts → index-CjVEjOw0.d.mts} +36 -24
- package/dist/index-CjVEjOw0.d.mts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{kysely-CEVXacPN.d.cts → kysely-BJ8IQ_1P.d.mts} +4 -4
- package/dist/{kysely-CEVXacPN.d.cts.map → kysely-BJ8IQ_1P.d.mts.map} +1 -1
- package/dist/{kysely-mcTdPNhl.d.mts → kysely-DVF8wOT4.d.cts} +4 -4
- package/dist/{kysely-mcTdPNhl.d.mts.map → kysely-DVF8wOT4.d.cts.map} +1 -1
- package/dist/{lazyAccessors-BHtcqgz2.mjs → lazyAccessors-CFanua0O.mjs} +2 -39
- package/dist/lazyAccessors-CFanua0O.mjs.map +1 -0
- package/dist/{lazyAccessors-Dx9NLwJZ.cjs → lazyAccessors-hJKGv8Ay.cjs} +1 -50
- package/dist/lazyAccessors-hJKGv8Ay.cjs.map +1 -0
- package/dist/mobile-app.d.cts +1 -1
- package/dist/mobile-app.d.mts +1 -1
- package/dist/object-storage.d.cts +1 -1
- package/dist/object-storage.d.mts +1 -1
- package/dist/processAudits-BpRlPQMW.mjs.map +1 -1
- package/dist/processAudits-D_2W5x8k.cjs.map +1 -1
- package/dist/queue/index.cjs +4 -78
- package/dist/queue/index.d.cts +3 -53
- package/dist/queue/index.d.mts +3 -53
- package/dist/queue/index.mjs +3 -77
- package/dist/rest-api.cjs +2 -4
- package/dist/rest-api.cjs.map +1 -1
- package/dist/rest-api.d.cts +4 -5
- package/dist/rest-api.d.cts.map +1 -1
- package/dist/rest-api.d.mts +4 -5
- package/dist/rest-api.d.mts.map +1 -1
- package/dist/rest-api.mjs +2 -4
- package/dist/rest-api.mjs.map +1 -1
- package/dist/site.d.cts +1 -1
- package/dist/site.d.mts +1 -1
- package/dist/subscribers/index.cjs +1 -1
- package/dist/subscribers/index.d.cts +2 -2
- package/dist/subscribers/index.d.mts +2 -2
- package/dist/subscribers/index.mjs +1 -1
- package/dist/topic/index.cjs +1 -36
- package/dist/topic/index.d.cts +2 -3
- package/dist/topic/index.d.mts +2 -3
- package/dist/topic/index.mjs +2 -35
- package/dist/worker.cjs +26 -17
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +37 -29
- package/dist/worker.d.cts.map +1 -1
- package/dist/worker.d.mts +37 -29
- package/dist/worker.d.mts.map +1 -1
- package/dist/worker.mjs +26 -17
- package/dist/worker.mjs.map +1 -1
- package/package.json +41 -31
- package/dist/Construct-DTqYvkPG.d.cts +0 -115
- package/dist/Construct-DTqYvkPG.d.cts.map +0 -1
- package/dist/Construct-Detz65RA.mjs.map +0 -1
- package/dist/Construct-pVadmURD.d.mts +0 -115
- package/dist/Construct-pVadmURD.d.mts.map +0 -1
- package/dist/Construct-yG9Sw-5p.cjs.map +0 -1
- package/dist/Cron-B_iuyNxr.d.mts.map +0 -1
- package/dist/Cron-CA2oa2nC.d.cts.map +0 -1
- package/dist/CronBuilder-BIKCLWu7.d.mts.map +0 -1
- package/dist/CronBuilder-BRkzUOAs.mjs.map +0 -1
- package/dist/CronBuilder-B_KqaodP.d.cts.map +0 -1
- package/dist/CronBuilder-BbnT7tqo.cjs.map +0 -1
- package/dist/Endpoint-1-XYQSx0.d.cts.map +0 -1
- package/dist/Endpoint-DO332Dnm.mjs.map +0 -1
- package/dist/Endpoint-GFIxYb9L.d.mts.map +0 -1
- package/dist/Endpoint-QKuFg5gs.cjs.map +0 -1
- package/dist/EndpointFactory-B9HAjDAP.mjs.map +0 -1
- package/dist/EndpointFactory-BCZdh_u3.d.mts.map +0 -1
- package/dist/EndpointFactory-BmO0WnXE.cjs.map +0 -1
- package/dist/EndpointFactory-BnK_YkW1.d.cts.map +0 -1
- package/dist/HonoEndpointAdaptor-CiqAZ5Mt.mjs.map +0 -1
- package/dist/HonoEndpointAdaptor-DoEQdC3r.cjs.map +0 -1
- package/dist/Queue-B7yRXQmL.cjs.map +0 -1
- package/dist/Queue-Bhzi2WQC.d.cts.map +0 -1
- package/dist/Queue-BoUA-e83.d.mts.map +0 -1
- package/dist/Queue-DpKTLl6E.mjs.map +0 -1
- package/dist/Subscriber-CIO3pwji.d.mts.map +0 -1
- package/dist/Subscriber-DQCaiOXF.d.cts.map +0 -1
- package/dist/SubscriberBuilder-B4YRTBng.mjs.map +0 -1
- package/dist/SubscriberBuilder-C2FRfd26.d.mts.map +0 -1
- package/dist/SubscriberBuilder-C2bCOuPT.cjs.map +0 -1
- package/dist/SubscriberBuilder-CjDGSTZc.d.cts.map +0 -1
- package/dist/Topic-Ct3Le8Wt.mjs +0 -103
- package/dist/Topic-Ct3Le8Wt.mjs.map +0 -1
- package/dist/Topic-D5rlM9wS.cjs.map +0 -1
- package/dist/Topic-D6blllEn.d.cts +0 -89
- package/dist/Topic-D6blllEn.d.cts.map +0 -1
- package/dist/Topic-DVvheJ_-.d.mts +0 -89
- package/dist/Topic-DVvheJ_-.d.mts.map +0 -1
- package/dist/functions-DKN6aQWJ.cjs.map +0 -1
- package/dist/functions-DlFm8HmH.mjs.map +0 -1
- package/dist/index-BI23K3wy.d.cts.map +0 -1
- package/dist/index-fnpjXiA-.d.mts +0 -26
- package/dist/index-fnpjXiA-.d.mts.map +0 -1
- package/dist/index-tE_119SX.d.cts +0 -26
- package/dist/index-tE_119SX.d.cts.map +0 -1
- package/dist/index-yb3fXNyH.d.mts.map +0 -1
- package/dist/lazyAccessors-BHtcqgz2.mjs.map +0 -1
- package/dist/lazyAccessors-Dx9NLwJZ.cjs.map +0 -1
- package/dist/queue/index.cjs.map +0 -1
- package/dist/queue/index.d.cts.map +0 -1
- package/dist/queue/index.d.mts.map +0 -1
- package/dist/queue/index.mjs.map +0 -1
- package/dist/topic/index.cjs.map +0 -1
- package/dist/topic/index.mjs.map +0 -1
package/dist/crons/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as ScheduleExpression, n as CronExpression, r as RateExpression, t as Cron } from "../Cron-
|
|
2
|
-
import { t as CronBuilder } from "../CronBuilder-
|
|
1
|
+
import { i as ScheduleExpression, n as CronExpression, r as RateExpression, t as Cron } from "../Cron-CMEGfRs8.cjs";
|
|
2
|
+
import { t as CronBuilder } from "../CronBuilder-CEK7aOqD.cjs";
|
|
3
3
|
//#region src/crons/schedule.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* A schedule a cron runner can take, as standard five-field cron.
|
package/dist/crons/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as ScheduleExpression, n as CronExpression, r as RateExpression, t as Cron } from "../Cron-
|
|
2
|
-
import { t as CronBuilder } from "../CronBuilder-
|
|
1
|
+
import { i as ScheduleExpression, n as CronExpression, r as RateExpression, t as Cron } from "../Cron-D6X4-xjB.mjs";
|
|
2
|
+
import { t as CronBuilder } from "../CronBuilder-O_gvButp.mjs";
|
|
3
3
|
//#region src/crons/schedule.d.ts
|
|
4
4
|
/**
|
|
5
5
|
* A schedule a cron runner can take, as standard five-field cron.
|
package/dist/crons/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as KyselyDatabaseOptions, r as ReadOnlyDatabase, t as KyselyDatabase } from "../kysely-
|
|
1
|
+
import { n as KyselyDatabaseOptions, r as ReadOnlyDatabase, t as KyselyDatabase } from "../kysely-DVF8wOT4.cjs";
|
|
2
2
|
export { KyselyDatabase, KyselyDatabaseOptions, ReadOnlyDatabase };
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as KyselyDatabaseOptions, r as ReadOnlyDatabase, t as KyselyDatabase } from "../kysely-
|
|
1
|
+
import { n as KyselyDatabaseOptions, r as ReadOnlyDatabase, t as KyselyDatabase } from "../kysely-BJ8IQ_1P.mjs";
|
|
2
2
|
export { KyselyDatabase, KyselyDatabaseOptions, ReadOnlyDatabase };
|
package/dist/email.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as Construct } from "./construct-interface-
|
|
1
|
+
import { n as Construct } from "./construct-interface-_xi4BPN8.cjs";
|
|
2
2
|
import { Service } from "@geekmidas/services";
|
|
3
3
|
import { ConstructName, Declaration } from "@geekmidas/manifest";
|
|
4
4
|
import { EmailClient, TemplateRecord } from "@geekmidas/emailkit";
|
package/dist/email.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as Construct } from "./construct-interface-
|
|
1
|
+
import { n as Construct } from "./construct-interface-_3zgxzXl.mjs";
|
|
2
2
|
import { ConstructName, Declaration } from "@geekmidas/manifest";
|
|
3
3
|
import { EmailClient, TemplateRecord } from "@geekmidas/emailkit";
|
|
4
4
|
import { Service } from "@geekmidas/services";
|
package/dist/endpoints/index.cjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
-
const require_EndpointFactory = require("../EndpointFactory-
|
|
3
|
-
const
|
|
2
|
+
const require_EndpointFactory = require("../EndpointFactory-BZOCOaK6.cjs");
|
|
3
|
+
const require_functions = require("../functions-ZH60FE7H.cjs");
|
|
4
|
+
const require_Endpoint = require("../Endpoint-D1L9qu5C.cjs");
|
|
4
5
|
const require_surfaceEnv = require("../surfaceEnv-CNimK76p.cjs");
|
|
5
|
-
const require_lazyAccessors = require("../lazyAccessors-
|
|
6
|
+
const require_lazyAccessors = require("../lazyAccessors-hJKGv8Ay.cjs");
|
|
6
7
|
exports.BUILT_IN_SECURITY_SCHEMES = require_EndpointFactory.BUILT_IN_SECURITY_SCHEMES;
|
|
7
8
|
exports.Endpoint = require_Endpoint.Endpoint;
|
|
8
9
|
exports.EndpointBuilder = require_EndpointFactory.EndpointBuilder;
|
|
@@ -21,4 +22,4 @@ exports.defaultEnvParser = require_surfaceEnv.defaultEnvParser;
|
|
|
21
22
|
exports.envParserFor = require_surfaceEnv.envParserFor;
|
|
22
23
|
exports.getSecurityScheme = require_EndpointFactory.getSecurityScheme;
|
|
23
24
|
exports.isBuiltInSecurityScheme = require_EndpointFactory.isBuiltInSecurityScheme;
|
|
24
|
-
exports.publishConstructEvents =
|
|
25
|
+
exports.publishConstructEvents = require_functions.publishConstructEvents;
|
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { n as EndpointBuilder, t as EndpointFactory } from "../EndpointFactory-BnK_YkW1.cjs";
|
|
1
|
+
import { s as publishConstructEvents } from "../Construct-BQALFCh2.cjs";
|
|
2
|
+
import { A as getSecurityScheme, C as Authorizer, D as OAuthFlows, E as OAuthFlow, O as SecurityScheme, S as MappedAudit, T as BuiltInSecuritySchemeId, _ as RlsBypass, a as EndpointContext, b as RlsContextExtractor, c as EndpointSchemas, d as ResponseBuilder, g as RLS_BYPASS, h as SessionAuth, i as Endpoint, j as isBuiltInSecurityScheme, k as createAuthorizer, l as EndpointSurface, m as NoAuthenticator, n as ConvertRouteParams, o as EndpointHandler, r as CookieFn, s as EndpointOutput, u as HeaderFn, v as RlsConfig, w as BUILT_IN_SECURITY_SCHEMES, x as ActorExtractor, y as RlsContext } from "../Endpoint-Dp5AKIXl.cjs";
|
|
3
|
+
import { n as EndpointBuilder, t as EndpointFactory } from "../EndpointFactory-FeFRmlDZ.cjs";
|
|
5
4
|
import { EnvironmentParser } from "@geekmidas/envkit";
|
|
6
|
-
import { EventPublisher, MappedEvent } from "@geekmidas/events";
|
|
7
|
-
import { Logger } from "@geekmidas/logger";
|
|
8
|
-
import { InferStandardSchema } from "@geekmidas/schema";
|
|
9
|
-
import { Service, ServiceDiscovery } from "@geekmidas/services";
|
|
10
|
-
import { AuditStorage } from "@geekmidas/audit";
|
|
11
5
|
import { Context } from "hono";
|
|
12
|
-
//#region src/publisher.d.ts
|
|
13
|
-
export declare function publishConstructEvents<T extends EventPublisher<any> | undefined, OutSchema extends StandardSchemaV1 | undefined = undefined, TServiceName extends string = string, TServices extends Service[] = [], TAuditStorageServiceName extends string = string, TAuditStorage extends AuditStorage | undefined = undefined>(construct: Construct<Logger, TServiceName, T, OutSchema, TServices, TAuditStorageServiceName, TAuditStorage>, response: InferStandardSchema<OutSchema>, serviceDiscovery: ServiceDiscovery<any>, logger?: Logger): Promise<void>;
|
|
14
|
-
//#endregion
|
|
15
6
|
//#region src/endpoints/lazyAccessors.d.ts
|
|
16
7
|
/**
|
|
17
8
|
* Create a lazy header accessor for Hono.
|
|
@@ -56,5 +47,5 @@ export declare function defaultEnvParser(): EnvironmentParser<{}>;
|
|
|
56
47
|
/** The parser for an endpoint, from its surface or the default. */
|
|
57
48
|
export declare function envParserFor(surface: EndpointSurface | undefined): EnvironmentParser<{}>;
|
|
58
49
|
//#endregion
|
|
59
|
-
export { type ActorExtractor, type Authorizer, BUILT_IN_SECURITY_SCHEMES, type BuiltInSecuritySchemeId, type ConvertRouteParams, Endpoint, EndpointBuilder, type EndpointContext, EndpointFactory, type EndpointHandler, type EndpointOutput, type EndpointSchemas, type MappedAudit, NoAuthenticator, type OAuthFlow, type OAuthFlows, RLS_BYPASS, ResponseBuilder, type RlsBypass, type RlsConfig, type RlsContext, type RlsContextExtractor, type SecurityScheme, type SessionAuth, createAuthorizer, getSecurityScheme, isBuiltInSecurityScheme };
|
|
50
|
+
export { type ActorExtractor, type Authorizer, BUILT_IN_SECURITY_SCHEMES, type BuiltInSecuritySchemeId, type ConvertRouteParams, Endpoint, EndpointBuilder, type EndpointContext, EndpointFactory, type EndpointHandler, type EndpointOutput, type EndpointSchemas, type MappedAudit, NoAuthenticator, type OAuthFlow, type OAuthFlows, RLS_BYPASS, ResponseBuilder, type RlsBypass, type RlsConfig, type RlsContext, type RlsContextExtractor, type SecurityScheme, type SessionAuth, createAuthorizer, getSecurityScheme, isBuiltInSecurityScheme, publishConstructEvents };
|
|
60
51
|
//# sourceMappingURL=index.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../../src/endpoints/lazyAccessors.ts","../../src/endpoints/surfaceEnv.ts"],"mappings":";;;;;;;;;;;wBAgBgB,kBAAkB,GAAG,UAAU;;;;;;wBAqB/B,kBAAkB,GAAG,UAAU;;;;;wBAgC/B,wBACf,SAAS,wDACP;;;;;wBAoCa,wBACf,+BACA,mCACE;;;;wBAmHa,qBAAqB;;;;wBAUrB,qBAAqB;;;;;;;;;;wBC1MrB,oBAAoB;;wBASpB,aACf,SAAS,8BACP"}
|
|
@@ -1,17 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { n as EndpointBuilder, t as EndpointFactory } from "../EndpointFactory-BCZdh_u3.mjs";
|
|
1
|
+
import { s as publishConstructEvents } from "../Construct-QXnl3VqT.mjs";
|
|
2
|
+
import { A as getSecurityScheme, C as Authorizer, D as OAuthFlows, E as OAuthFlow, O as SecurityScheme, S as MappedAudit, T as BuiltInSecuritySchemeId, _ as RlsBypass, a as EndpointContext, b as RlsContextExtractor, c as EndpointSchemas, d as ResponseBuilder, g as RLS_BYPASS, h as SessionAuth, i as Endpoint, j as isBuiltInSecurityScheme, k as createAuthorizer, l as EndpointSurface, m as NoAuthenticator, n as ConvertRouteParams, o as EndpointHandler, r as CookieFn, s as EndpointOutput, u as HeaderFn, v as RlsConfig, w as BUILT_IN_SECURITY_SCHEMES, x as ActorExtractor, y as RlsContext } from "../Endpoint-DtI7heFm.mjs";
|
|
3
|
+
import { n as EndpointBuilder, t as EndpointFactory } from "../EndpointFactory-CgMDvERK.mjs";
|
|
5
4
|
import { EnvironmentParser } from "@geekmidas/envkit";
|
|
6
|
-
import { EventPublisher, MappedEvent } from "@geekmidas/events";
|
|
7
|
-
import { Service, ServiceDiscovery } from "@geekmidas/services";
|
|
8
5
|
import { Context } from "hono";
|
|
9
|
-
import { AuditStorage } from "@geekmidas/audit";
|
|
10
|
-
import { Logger } from "@geekmidas/logger";
|
|
11
|
-
import { InferStandardSchema } from "@geekmidas/schema";
|
|
12
|
-
//#region src/publisher.d.ts
|
|
13
|
-
export declare function publishConstructEvents<T extends EventPublisher<any> | undefined, OutSchema extends StandardSchemaV1 | undefined = undefined, TServiceName extends string = string, TServices extends Service[] = [], TAuditStorageServiceName extends string = string, TAuditStorage extends AuditStorage | undefined = undefined>(construct: Construct<Logger, TServiceName, T, OutSchema, TServices, TAuditStorageServiceName, TAuditStorage>, response: InferStandardSchema<OutSchema>, serviceDiscovery: ServiceDiscovery<any>, logger?: Logger): Promise<void>;
|
|
14
|
-
//#endregion
|
|
15
6
|
//#region src/endpoints/lazyAccessors.d.ts
|
|
16
7
|
/**
|
|
17
8
|
* Create a lazy header accessor for Hono.
|
|
@@ -56,5 +47,5 @@ export declare function defaultEnvParser(): EnvironmentParser<{}>;
|
|
|
56
47
|
/** The parser for an endpoint, from its surface or the default. */
|
|
57
48
|
export declare function envParserFor(surface: EndpointSurface | undefined): EnvironmentParser<{}>;
|
|
58
49
|
//#endregion
|
|
59
|
-
export { type ActorExtractor, type Authorizer, BUILT_IN_SECURITY_SCHEMES, type BuiltInSecuritySchemeId, type ConvertRouteParams, Endpoint, EndpointBuilder, type EndpointContext, EndpointFactory, type EndpointHandler, type EndpointOutput, type EndpointSchemas, type MappedAudit, NoAuthenticator, type OAuthFlow, type OAuthFlows, RLS_BYPASS, ResponseBuilder, type RlsBypass, type RlsConfig, type RlsContext, type RlsContextExtractor, type SecurityScheme, type SessionAuth, createAuthorizer, getSecurityScheme, isBuiltInSecurityScheme };
|
|
50
|
+
export { type ActorExtractor, type Authorizer, BUILT_IN_SECURITY_SCHEMES, type BuiltInSecuritySchemeId, type ConvertRouteParams, Endpoint, EndpointBuilder, type EndpointContext, EndpointFactory, type EndpointHandler, type EndpointOutput, type EndpointSchemas, type MappedAudit, NoAuthenticator, type OAuthFlow, type OAuthFlows, RLS_BYPASS, ResponseBuilder, type RlsBypass, type RlsConfig, type RlsContext, type RlsContextExtractor, type SecurityScheme, type SessionAuth, createAuthorizer, getSecurityScheme, isBuiltInSecurityScheme, publishConstructEvents };
|
|
60
51
|
//# sourceMappingURL=index.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/endpoints/lazyAccessors.ts","../../src/endpoints/surfaceEnv.ts"],"mappings":";;;;;;;;;;;wBAgBgB,kBAAkB,GAAG,UAAU;;;;;;wBAqB/B,kBAAkB,GAAG,UAAU;;;;;wBAgC/B,wBACf,SAAS,wDACP;;;;;wBAoCa,wBACf,+BACA,mCACE;;;;wBAmHa,qBAAqB;;;;wBAUrB,qBAAqB;;;;;;;;;;wBC1MrB,oBAAoB;;wBASpB,aACf,SAAS,8BACP"}
|
package/dist/endpoints/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { a as createAuthorizer, i as BUILT_IN_SECURITY_SCHEMES, n as EndpointBuilder, o as getSecurityScheme, r as RLS_BYPASS, s as isBuiltInSecurityScheme, t as EndpointFactory } from "../EndpointFactory-
|
|
2
|
-
import {
|
|
1
|
+
import { a as createAuthorizer, i as BUILT_IN_SECURITY_SCHEMES, n as EndpointBuilder, o as getSecurityScheme, r as RLS_BYPASS, s as isBuiltInSecurityScheme, t as EndpointFactory } from "../EndpointFactory-BBdNeaGJ.mjs";
|
|
2
|
+
import { i as publishConstructEvents } from "../functions-DCIfCRR-.mjs";
|
|
3
|
+
import { n as ResponseBuilder, r as NoAuthenticator, t as Endpoint } from "../Endpoint-CQAeh1Rh.mjs";
|
|
3
4
|
import { n as envParserFor, t as defaultEnvParser } from "../surfaceEnv-wMT5QzgZ.mjs";
|
|
4
|
-
import { a as createHonoHeaders, i as createHonoCookies,
|
|
5
|
+
import { a as createHonoHeaders, i as createHonoCookies, n as createApiGatewayHeaders, o as createNoopCookies, s as createNoopHeaders, t as createApiGatewayCookies } from "../lazyAccessors-CFanua0O.mjs";
|
|
5
6
|
export { BUILT_IN_SECURITY_SCHEMES, Endpoint, EndpointBuilder, EndpointFactory, NoAuthenticator, RLS_BYPASS, ResponseBuilder, createApiGatewayCookies, createApiGatewayHeaders, createAuthorizer, createHonoCookies, createHonoHeaders, createNoopCookies, createNoopHeaders, defaultEnvParser, envParserFor, getSecurityScheme, isBuiltInSecurityScheme, publishConstructEvents };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { t as StandardSchemaV1 } from "./index-CeEtxDmK.mjs";
|
|
2
|
+
import { r as Consumable } from "./construct-interface-_3zgxzXl.mjs";
|
|
3
|
+
import { ConstructName, Declaration } from "@geekmidas/manifest";
|
|
4
|
+
import { Service } from "@geekmidas/services";
|
|
5
|
+
//#region src/external-api.d.ts
|
|
6
|
+
/** What a credentials schema yields. */
|
|
7
|
+
type Value<TSchema extends StandardSchemaV1> = StandardSchemaV1.InferOutput<TSchema>;
|
|
8
|
+
interface ExternalApiOptions<TSchema extends StandardSchemaV1, TClient> {
|
|
9
|
+
/**
|
|
10
|
+
* Where it answers deployed: one URL for every stage, or one per stage
|
|
11
|
+
* name, with `default` for any stage not listed.
|
|
12
|
+
*/
|
|
13
|
+
url: string | Readonly<Record<string, string>>;
|
|
14
|
+
/** What the stage's `<ID>_CREDENTIALS` must look like. */
|
|
15
|
+
credentials: TSchema;
|
|
16
|
+
/** What a handler is handed, built from where it answers and the credentials. */
|
|
17
|
+
client: (connection: {
|
|
18
|
+
url: string;
|
|
19
|
+
credentials: Value<TSchema>;
|
|
20
|
+
}) => TClient | Promise<TClient>;
|
|
21
|
+
}
|
|
22
|
+
declare class ExternalApi<TName extends string = string, TSchema extends StandardSchemaV1 = StandardSchemaV1, TClient = unknown> implements Consumable<TName, TClient> {
|
|
23
|
+
private readonly options;
|
|
24
|
+
readonly id: TName;
|
|
25
|
+
readonly service: Service<Uncapitalize<TName>, TClient>;
|
|
26
|
+
/** Read by both `declare()` and `connect()`, so the two cannot drift. */
|
|
27
|
+
private readonly keys;
|
|
28
|
+
/** The promise, so concurrent registrations share one client. */
|
|
29
|
+
private connected?;
|
|
30
|
+
constructor(id: ConstructName<TName>, options: ExternalApiOptions<TSchema, TClient>);
|
|
31
|
+
declare(): Declaration[];
|
|
32
|
+
private connect;
|
|
33
|
+
}
|
|
34
|
+
/** Anything that answers a request — a Hono app, or a bare `{ fetch }`. */
|
|
35
|
+
interface FetchHandler {
|
|
36
|
+
fetch(request: Request): Response | Promise<Response>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Marks a fake. A registered symbol, so a fake built by a second copy of this
|
|
40
|
+
* package — a linked workspace, two versions in a lockfile — is still one.
|
|
41
|
+
*/
|
|
42
|
+
declare const FAKE: unique symbol;
|
|
43
|
+
/** What an external API's credentials look like going in, for a fake to supply. */
|
|
44
|
+
type CredentialsOf<TApi> = TApi extends ExternalApi<string, infer TSchema, unknown> ? StandardSchemaV1.InferInput<TSchema> : unknown;
|
|
45
|
+
/**
|
|
46
|
+
* An external API's stand-in, as `test/fakes/<id>.ts` default-exports it.
|
|
47
|
+
*
|
|
48
|
+
* `credentials` are what the fake accepts, and what a local or test stage is
|
|
49
|
+
* handed as `<ID>_CREDENTIALS` in place of the stage's own.
|
|
50
|
+
*/
|
|
51
|
+
type Fake = {
|
|
52
|
+
readonly [FAKE]: true;
|
|
53
|
+
readonly credentials: unknown;
|
|
54
|
+
} & ({
|
|
55
|
+
readonly kind: 'app';
|
|
56
|
+
/** Served by gkm: in-process in a test, on its own port in `gkm dev`. */
|
|
57
|
+
readonly handler: FetchHandler;
|
|
58
|
+
} | {
|
|
59
|
+
readonly kind: 'image';
|
|
60
|
+
/** The provider's own local server, run as a container. */
|
|
61
|
+
readonly image: string;
|
|
62
|
+
/** The port it listens on inside the container. */
|
|
63
|
+
readonly port: number;
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Build the fake `test/fakes/<id>.ts` default-exports.
|
|
67
|
+
*
|
|
68
|
+
* Pass the API's type to have the credentials checked against its schema —
|
|
69
|
+
* `fake.app<typeof polar>(…)`.
|
|
70
|
+
*/
|
|
71
|
+
declare const fake: {
|
|
72
|
+
/** A working implementation of the API, kept beside the tests that use it. */
|
|
73
|
+
app<TApi = unknown>(handler: FetchHandler, options: {
|
|
74
|
+
credentials: CredentialsOf<TApi>;
|
|
75
|
+
}): Fake;
|
|
76
|
+
/** A local server the provider publishes — `stripe/stripe-mock`. */
|
|
77
|
+
image<TApi = unknown>(image: string, options: {
|
|
78
|
+
port: number;
|
|
79
|
+
credentials: CredentialsOf<TApi>;
|
|
80
|
+
}): Fake;
|
|
81
|
+
};
|
|
82
|
+
/** Whether a value is a fake — what gkm asks of a `test/fakes` default export. */
|
|
83
|
+
declare function isFake(value: unknown): value is Fake;
|
|
84
|
+
//#endregion
|
|
85
|
+
export { fake as a, FetchHandler as i, ExternalApiOptions as n, isFake as o, Fake as r, ExternalApi as t };
|
|
86
|
+
//# sourceMappingURL=external-api-DS3mujT5.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-api-DS3mujT5.d.mts","names":[],"sources":["../src/external-api.ts"],"mappings":";;;;;;KAmDK,MAAM,gBAAgB,oBAC1B,iBAAiB,YAAY;UAEb,mBAAmB,gBAAgB,kBAAkB;;;;;EAKrE,cAAc,SAAS;;EAEvB,aAAa;;EAEb,SAAS;IACR;IACA,aAAa,MAAM;QACd,UAAU,QAAQ;;cAGZ,YACZ,+BACA,gBAAgB,mBAAmB,kBACnC,8BACY,WAAW,OAAO;mBAeZ;WAXT,IAAI;WACJ,SAAS,QAAQ,aAAa,QAAQ;;mBAG9B;;UAGT;EAER,YACC,IAAI,cAAc,QACD,SAAS,mBAAmB,SAAS;EAoBvD,WAAW;UAWG;;;UAgBE;EAChB,MAAM,SAAS,UAAU,WAAW,QAAQ;;;;;;cAOvC;;KAGD,cAAc,QAClB,aAAa,0BAA0B,oBACpC,iBAAiB,WAAW;;;;;;;KASpB;YACD;WACD;;WAGE;;WAEA,SAAS;;WAGT;;WAEA;;WAEA;;;;;;;;cAUC;;EAEZ,IAAI,gBAAc,SACR,cAAY;IACV,aAAa,cAAc;MACpC;;EAUH,MAAM,gBAAc,eACN;IACF;IAAc,aAAa,cAAc;MAClD;;;iBAYY,OAAO,iBAAiB,SAAS"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { t as StandardSchemaV1 } from "./index-CeEtxDmK.cjs";
|
|
2
|
+
import { r as Consumable } from "./construct-interface-_xi4BPN8.cjs";
|
|
3
|
+
import { Service } from "@geekmidas/services";
|
|
4
|
+
import { ConstructName, Declaration } from "@geekmidas/manifest";
|
|
5
|
+
//#region src/external-api.d.ts
|
|
6
|
+
/** What a credentials schema yields. */
|
|
7
|
+
type Value<TSchema extends StandardSchemaV1> = StandardSchemaV1.InferOutput<TSchema>;
|
|
8
|
+
interface ExternalApiOptions<TSchema extends StandardSchemaV1, TClient> {
|
|
9
|
+
/**
|
|
10
|
+
* Where it answers deployed: one URL for every stage, or one per stage
|
|
11
|
+
* name, with `default` for any stage not listed.
|
|
12
|
+
*/
|
|
13
|
+
url: string | Readonly<Record<string, string>>;
|
|
14
|
+
/** What the stage's `<ID>_CREDENTIALS` must look like. */
|
|
15
|
+
credentials: TSchema;
|
|
16
|
+
/** What a handler is handed, built from where it answers and the credentials. */
|
|
17
|
+
client: (connection: {
|
|
18
|
+
url: string;
|
|
19
|
+
credentials: Value<TSchema>;
|
|
20
|
+
}) => TClient | Promise<TClient>;
|
|
21
|
+
}
|
|
22
|
+
declare class ExternalApi<TName extends string = string, TSchema extends StandardSchemaV1 = StandardSchemaV1, TClient = unknown> implements Consumable<TName, TClient> {
|
|
23
|
+
private readonly options;
|
|
24
|
+
readonly id: TName;
|
|
25
|
+
readonly service: Service<Uncapitalize<TName>, TClient>;
|
|
26
|
+
/** Read by both `declare()` and `connect()`, so the two cannot drift. */
|
|
27
|
+
private readonly keys;
|
|
28
|
+
/** The promise, so concurrent registrations share one client. */
|
|
29
|
+
private connected?;
|
|
30
|
+
constructor(id: ConstructName<TName>, options: ExternalApiOptions<TSchema, TClient>);
|
|
31
|
+
declare(): Declaration[];
|
|
32
|
+
private connect;
|
|
33
|
+
}
|
|
34
|
+
/** Anything that answers a request — a Hono app, or a bare `{ fetch }`. */
|
|
35
|
+
interface FetchHandler {
|
|
36
|
+
fetch(request: Request): Response | Promise<Response>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Marks a fake. A registered symbol, so a fake built by a second copy of this
|
|
40
|
+
* package — a linked workspace, two versions in a lockfile — is still one.
|
|
41
|
+
*/
|
|
42
|
+
declare const FAKE: unique symbol;
|
|
43
|
+
/** What an external API's credentials look like going in, for a fake to supply. */
|
|
44
|
+
type CredentialsOf<TApi> = TApi extends ExternalApi<string, infer TSchema, unknown> ? StandardSchemaV1.InferInput<TSchema> : unknown;
|
|
45
|
+
/**
|
|
46
|
+
* An external API's stand-in, as `test/fakes/<id>.ts` default-exports it.
|
|
47
|
+
*
|
|
48
|
+
* `credentials` are what the fake accepts, and what a local or test stage is
|
|
49
|
+
* handed as `<ID>_CREDENTIALS` in place of the stage's own.
|
|
50
|
+
*/
|
|
51
|
+
type Fake = {
|
|
52
|
+
readonly [FAKE]: true;
|
|
53
|
+
readonly credentials: unknown;
|
|
54
|
+
} & ({
|
|
55
|
+
readonly kind: 'app';
|
|
56
|
+
/** Served by gkm: in-process in a test, on its own port in `gkm dev`. */
|
|
57
|
+
readonly handler: FetchHandler;
|
|
58
|
+
} | {
|
|
59
|
+
readonly kind: 'image';
|
|
60
|
+
/** The provider's own local server, run as a container. */
|
|
61
|
+
readonly image: string;
|
|
62
|
+
/** The port it listens on inside the container. */
|
|
63
|
+
readonly port: number;
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Build the fake `test/fakes/<id>.ts` default-exports.
|
|
67
|
+
*
|
|
68
|
+
* Pass the API's type to have the credentials checked against its schema —
|
|
69
|
+
* `fake.app<typeof polar>(…)`.
|
|
70
|
+
*/
|
|
71
|
+
declare const fake: {
|
|
72
|
+
/** A working implementation of the API, kept beside the tests that use it. */
|
|
73
|
+
app<TApi = unknown>(handler: FetchHandler, options: {
|
|
74
|
+
credentials: CredentialsOf<TApi>;
|
|
75
|
+
}): Fake;
|
|
76
|
+
/** A local server the provider publishes — `stripe/stripe-mock`. */
|
|
77
|
+
image<TApi = unknown>(image: string, options: {
|
|
78
|
+
port: number;
|
|
79
|
+
credentials: CredentialsOf<TApi>;
|
|
80
|
+
}): Fake;
|
|
81
|
+
};
|
|
82
|
+
/** Whether a value is a fake — what gkm asks of a `test/fakes` default export. */
|
|
83
|
+
declare function isFake(value: unknown): value is Fake;
|
|
84
|
+
//#endregion
|
|
85
|
+
export { fake as a, FetchHandler as i, ExternalApiOptions as n, isFake as o, Fake as r, ExternalApi as t };
|
|
86
|
+
//# sourceMappingURL=external-api-LBfE-q3g.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-api-LBfE-q3g.d.cts","names":[],"sources":["../src/external-api.ts"],"mappings":";;;;;;KAmDK,MAAM,gBAAgB,oBAC1B,iBAAiB,YAAY;UAEb,mBAAmB,gBAAgB,kBAAkB;;;;;EAKrE,cAAc,SAAS;;EAEvB,aAAa;;EAEb,SAAS;IACR;IACA,aAAa,MAAM;QACd,UAAU,QAAQ;;cAGZ,YACZ,+BACA,gBAAgB,mBAAmB,kBACnC,8BACY,WAAW,OAAO;mBAeZ;WAXT,IAAI;WACJ,SAAS,QAAQ,aAAa,QAAQ;;mBAG9B;;UAGT;EAER,YACC,IAAI,cAAc,QACD,SAAS,mBAAmB,SAAS;EAoBvD,WAAW;UAWG;;;UAgBE;EAChB,MAAM,SAAS,UAAU,WAAW,QAAQ;;;;;;cAOvC;;KAGD,cAAc,QAClB,aAAa,0BAA0B,oBACpC,iBAAiB,WAAW;;;;;;;KASpB;YACD;WACD;;WAGE;;WAEA,SAAS;;WAGT;;WAEA;;WAEA;;;;;;;;cAUC;;EAEZ,IAAI,gBAAc,SACR,cAAY;IACV,aAAa,cAAc;MACpC;;EAUH,MAAM,gBAAc,eACN;IACF;IAAc,aAAa,cAAc;MAClD;;;iBAYY,OAAO,iBAAiB,SAAS"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_credential = require("./credential.cjs");
|
|
3
|
+
let _geekmidas_manifest = require("@geekmidas/manifest");
|
|
4
|
+
//#region src/external-api.ts
|
|
5
|
+
/**
|
|
6
|
+
* `ExternalApi` — an HTTP API somebody else runs.
|
|
7
|
+
*
|
|
8
|
+
* Polar, Stripe, a payment gateway: nothing to provision, but an address that
|
|
9
|
+
* changes by stage and credentials the provider issued for each one. Without a
|
|
10
|
+
* construct every integration writes that switching by hand — an optional
|
|
11
|
+
* `POLAR_URL`, a fake started somewhere, a client built in a service — and the
|
|
12
|
+
* target cannot see any of it.
|
|
13
|
+
*
|
|
14
|
+
* ```ts
|
|
15
|
+
* // constructs/polar.ts
|
|
16
|
+
* export const polar = new ExternalApi('Polar', {
|
|
17
|
+
* url: 'https://www.polaraccesslink.com',
|
|
18
|
+
* credentials: z.object({ clientId: z.string(), clientSecret: z.string() }),
|
|
19
|
+
* client: ({ url, credentials }) => new PolarClient(url, credentials),
|
|
20
|
+
* });
|
|
21
|
+
*
|
|
22
|
+
* // test/fakes/polar.ts
|
|
23
|
+
* export default fake.app(new Hono().post('/v3/oauth2/token', …), {
|
|
24
|
+
* credentials: { clientId: 'fake', clientSecret: 'fake' },
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* // in a handler — the real API deployed, the fake locally and in tests
|
|
28
|
+
* .dependsOn([polar])
|
|
29
|
+
* .handle(({ services }) => services.polar.exchangeCode(code))
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* Deployed, the URL is `url` — one for every stage, or one per stage name with
|
|
33
|
+
* a `default` — and the credentials are the stage's `<ID>_CREDENTIALS`, one
|
|
34
|
+
* JSON value read the way a `Credential`'s is. Locally and in tests both come
|
|
35
|
+
* from the fake.
|
|
36
|
+
*
|
|
37
|
+
* **The construct never names its fake.** It is found by convention, at
|
|
38
|
+
* `test/fakes/<id>.ts`, and read only by gkm and the generated test harness —
|
|
39
|
+
* so a fake, and the recorded responses it answers from, cannot end up in a
|
|
40
|
+
* deployed bundle however the bundler follows imports.
|
|
41
|
+
*/
|
|
42
|
+
var ExternalApi = class {
|
|
43
|
+
options;
|
|
44
|
+
id;
|
|
45
|
+
service;
|
|
46
|
+
/** Read by both `declare()` and `connect()`, so the two cannot drift. */
|
|
47
|
+
keys;
|
|
48
|
+
/** The promise, so concurrent registrations share one client. */
|
|
49
|
+
connected;
|
|
50
|
+
constructor(id, options) {
|
|
51
|
+
this.options = options;
|
|
52
|
+
const canonical = (0, _geekmidas_manifest.canonicalId)(id);
|
|
53
|
+
this.id = canonical;
|
|
54
|
+
this.keys = {
|
|
55
|
+
url: (0, _geekmidas_manifest.provideKey)(canonical, "url"),
|
|
56
|
+
credentials: (0, _geekmidas_manifest.provideKey)(canonical, "credentials")
|
|
57
|
+
};
|
|
58
|
+
this.service = {
|
|
59
|
+
serviceName: (0, _geekmidas_manifest.serviceKey)(canonical),
|
|
60
|
+
register: (registerOptions) => {
|
|
61
|
+
this.connected ??= this.connect(registerOptions);
|
|
62
|
+
return this.connected;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
declare() {
|
|
67
|
+
return [{
|
|
68
|
+
kind: "external-api",
|
|
69
|
+
id: this.id,
|
|
70
|
+
url: this.options.url,
|
|
71
|
+
provides: [this.keys.url, this.keys.credentials]
|
|
72
|
+
}];
|
|
73
|
+
}
|
|
74
|
+
async connect(options) {
|
|
75
|
+
const { url } = options.envParser.create((get) => ({ url: get(this.keys.url).string() })).parse();
|
|
76
|
+
const credentials = await require_credential.readCredentials(this.id, this.keys.credentials, this.options.credentials, options.envParser);
|
|
77
|
+
return this.options.client({
|
|
78
|
+
url,
|
|
79
|
+
credentials
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Marks a fake. A registered symbol, so a fake built by a second copy of this
|
|
85
|
+
* package — a linked workspace, two versions in a lockfile — is still one.
|
|
86
|
+
*/
|
|
87
|
+
const FAKE = Symbol.for("@geekmidas/constructs/fake");
|
|
88
|
+
/**
|
|
89
|
+
* Build the fake `test/fakes/<id>.ts` default-exports.
|
|
90
|
+
*
|
|
91
|
+
* Pass the API's type to have the credentials checked against its schema —
|
|
92
|
+
* `fake.app<typeof polar>(…)`.
|
|
93
|
+
*/
|
|
94
|
+
const fake = {
|
|
95
|
+
/** A working implementation of the API, kept beside the tests that use it. */
|
|
96
|
+
app(handler, options) {
|
|
97
|
+
return {
|
|
98
|
+
[FAKE]: true,
|
|
99
|
+
kind: "app",
|
|
100
|
+
handler,
|
|
101
|
+
credentials: options.credentials
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
/** A local server the provider publishes — `stripe/stripe-mock`. */
|
|
105
|
+
image(image, options) {
|
|
106
|
+
return {
|
|
107
|
+
[FAKE]: true,
|
|
108
|
+
kind: "image",
|
|
109
|
+
image,
|
|
110
|
+
port: options.port,
|
|
111
|
+
credentials: options.credentials
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
/** Whether a value is a fake — what gkm asks of a `test/fakes` default export. */
|
|
116
|
+
function isFake(value) {
|
|
117
|
+
return typeof value === "object" && value !== null && value[FAKE] === true;
|
|
118
|
+
}
|
|
119
|
+
//#endregion
|
|
120
|
+
exports.ExternalApi = ExternalApi;
|
|
121
|
+
exports.fake = fake;
|
|
122
|
+
exports.isFake = isFake;
|
|
123
|
+
|
|
124
|
+
//# sourceMappingURL=external-api.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-api.cjs","names":["canonicalId","provideKey","serviceKey","readCredentials"],"sources":["../src/external-api.ts"],"sourcesContent":["/**\n * `ExternalApi` — an HTTP API somebody else runs.\n *\n * Polar, Stripe, a payment gateway: nothing to provision, but an address that\n * changes by stage and credentials the provider issued for each one. Without a\n * construct every integration writes that switching by hand — an optional\n * `POLAR_URL`, a fake started somewhere, a client built in a service — and the\n * target cannot see any of it.\n *\n * ```ts\n * // constructs/polar.ts\n * export const polar = new ExternalApi('Polar', {\n * url: 'https://www.polaraccesslink.com',\n * credentials: z.object({ clientId: z.string(), clientSecret: z.string() }),\n * client: ({ url, credentials }) => new PolarClient(url, credentials),\n * });\n *\n * // test/fakes/polar.ts\n * export default fake.app(new Hono().post('/v3/oauth2/token', …), {\n * credentials: { clientId: 'fake', clientSecret: 'fake' },\n * });\n *\n * // in a handler — the real API deployed, the fake locally and in tests\n * .dependsOn([polar])\n * .handle(({ services }) => services.polar.exchangeCode(code))\n * ```\n *\n * Deployed, the URL is `url` — one for every stage, or one per stage name with\n * a `default` — and the credentials are the stage's `<ID>_CREDENTIALS`, one\n * JSON value read the way a `Credential`'s is. Locally and in tests both come\n * from the fake.\n *\n * **The construct never names its fake.** It is found by convention, at\n * `test/fakes/<id>.ts`, and read only by gkm and the generated test harness —\n * so a fake, and the recorded responses it answers from, cannot end up in a\n * deployed bundle however the bundler follows imports.\n */\n\nimport {\n\ttype ConstructName,\n\tcanonicalId,\n\ttype Declaration,\n\tprovideKey,\n\tserviceKey,\n} from '@geekmidas/manifest';\nimport type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { Consumable } from './construct-interface';\nimport { readCredentials } from './credential';\n\n/** What a credentials schema yields. */\ntype Value<TSchema extends StandardSchemaV1> =\n\tStandardSchemaV1.InferOutput<TSchema>;\n\nexport interface ExternalApiOptions<TSchema extends StandardSchemaV1, TClient> {\n\t/**\n\t * Where it answers deployed: one URL for every stage, or one per stage\n\t * name, with `default` for any stage not listed.\n\t */\n\turl: string | Readonly<Record<string, string>>;\n\t/** What the stage's `<ID>_CREDENTIALS` must look like. */\n\tcredentials: TSchema;\n\t/** What a handler is handed, built from where it answers and the credentials. */\n\tclient: (connection: {\n\t\turl: string;\n\t\tcredentials: Value<TSchema>;\n\t}) => TClient | Promise<TClient>;\n}\n\nexport class ExternalApi<\n\tTName extends string = string,\n\tTSchema extends StandardSchemaV1 = StandardSchemaV1,\n\tTClient = unknown,\n> implements Consumable<TName, TClient>\n{\n\t// `Consumable` for the reason `Credential` gives: a client generic in\n\t// `TClient` cannot satisfy `Construct`'s conditional service type.\n\treadonly id: TName;\n\treadonly service: Service<Uncapitalize<TName>, TClient>;\n\n\t/** Read by both `declare()` and `connect()`, so the two cannot drift. */\n\tprivate readonly keys: { url: string; credentials: string };\n\n\t/** The promise, so concurrent registrations share one client. */\n\tprivate connected?: Promise<TClient>;\n\n\tconstructor(\n\t\tid: ConstructName<TName>,\n\t\tprivate readonly options: ExternalApiOptions<TSchema, TClient>,\n\t) {\n\t\tconst canonical = canonicalId(id as string);\n\n\t\tthis.id = canonical as TName;\n\t\tthis.keys = {\n\t\t\turl: provideKey(canonical, 'url'),\n\t\t\tcredentials: provideKey(canonical, 'credentials'),\n\t\t};\n\n\t\t// A field, not a getter: consumers cache services by object identity.\n\t\tthis.service = {\n\t\t\tserviceName: serviceKey(canonical) as Uncapitalize<TName>,\n\t\t\tregister: (registerOptions) => {\n\t\t\t\tthis.connected ??= this.connect(registerOptions);\n\t\t\t\treturn this.connected;\n\t\t\t},\n\t\t};\n\t}\n\n\tdeclare(): Declaration[] {\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: 'external-api',\n\t\t\t\tid: this.id,\n\t\t\t\turl: this.options.url,\n\t\t\t\tprovides: [this.keys.url, this.keys.credentials],\n\t\t\t},\n\t\t];\n\t}\n\n\tprivate async connect(options: ServiceRegisterOptions): Promise<TClient> {\n\t\tconst { url } = options.envParser\n\t\t\t.create((get) => ({ url: get(this.keys.url).string() }))\n\t\t\t.parse();\n\t\tconst credentials = await readCredentials(\n\t\t\tthis.id,\n\t\t\tthis.keys.credentials,\n\t\t\tthis.options.credentials,\n\t\t\toptions.envParser,\n\t\t);\n\n\t\treturn this.options.client({ url, credentials });\n\t}\n}\n\n/** Anything that answers a request — a Hono app, or a bare `{ fetch }`. */\nexport interface FetchHandler {\n\tfetch(request: Request): Response | Promise<Response>;\n}\n\n/**\n * Marks a fake. A registered symbol, so a fake built by a second copy of this\n * package — a linked workspace, two versions in a lockfile — is still one.\n */\nconst FAKE = Symbol.for('@geekmidas/constructs/fake');\n\n/** What an external API's credentials look like going in, for a fake to supply. */\ntype CredentialsOf<TApi> =\n\tTApi extends ExternalApi<string, infer TSchema, unknown>\n\t\t? StandardSchemaV1.InferInput<TSchema>\n\t\t: unknown;\n\n/**\n * An external API's stand-in, as `test/fakes/<id>.ts` default-exports it.\n *\n * `credentials` are what the fake accepts, and what a local or test stage is\n * handed as `<ID>_CREDENTIALS` in place of the stage's own.\n */\nexport type Fake = {\n\treadonly [FAKE]: true;\n\treadonly credentials: unknown;\n} & (\n\t| {\n\t\t\treadonly kind: 'app';\n\t\t\t/** Served by gkm: in-process in a test, on its own port in `gkm dev`. */\n\t\t\treadonly handler: FetchHandler;\n\t }\n\t| {\n\t\t\treadonly kind: 'image';\n\t\t\t/** The provider's own local server, run as a container. */\n\t\t\treadonly image: string;\n\t\t\t/** The port it listens on inside the container. */\n\t\t\treadonly port: number;\n\t }\n);\n\n/**\n * Build the fake `test/fakes/<id>.ts` default-exports.\n *\n * Pass the API's type to have the credentials checked against its schema —\n * `fake.app<typeof polar>(…)`.\n */\nexport const fake = {\n\t/** A working implementation of the API, kept beside the tests that use it. */\n\tapp<TApi = unknown>(\n\t\thandler: FetchHandler,\n\t\toptions: { credentials: CredentialsOf<TApi> },\n\t): Fake {\n\t\treturn {\n\t\t\t[FAKE]: true,\n\t\t\tkind: 'app',\n\t\t\thandler,\n\t\t\tcredentials: options.credentials,\n\t\t};\n\t},\n\n\t/** A local server the provider publishes — `stripe/stripe-mock`. */\n\timage<TApi = unknown>(\n\t\timage: string,\n\t\toptions: { port: number; credentials: CredentialsOf<TApi> },\n\t): Fake {\n\t\treturn {\n\t\t\t[FAKE]: true,\n\t\t\tkind: 'image',\n\t\t\timage,\n\t\t\tport: options.port,\n\t\t\tcredentials: options.credentials,\n\t\t};\n\t},\n};\n\n/** Whether a value is a fake — what gkm asks of a `test/fakes` default export. */\nexport function isFake(value: unknown): value is Fake {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t(value as { [FAKE]?: unknown })[FAKE] === true\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,IAAa,cAAb,MAKA;CAcmB;CAXlB;CACA;;CAGA;;CAGA;CAEA,YACC,IACA,SACC;EADgB,KAAA,UAAA;EAEjB,MAAM,aAAA,GAAYA,oBAAAA,YAAAA,CAAY,EAAY;EAE1C,KAAK,KAAK;EACV,KAAK,OAAO;GACX,MAAA,GAAKC,oBAAAA,WAAAA,CAAW,WAAW,KAAK;GAChC,cAAA,GAAaA,oBAAAA,WAAAA,CAAW,WAAW,aAAa;EACjD;EAGA,KAAK,UAAU;GACd,cAAA,GAAaC,oBAAAA,WAAAA,CAAW,SAAS;GACjC,WAAW,oBAAoB;IAC9B,KAAK,cAAc,KAAK,QAAQ,eAAe;IAC/C,OAAO,KAAK;GACb;EACD;CACD;CAEA,UAAyB;EACxB,OAAO,CACN;GACC,MAAM;GACN,IAAI,KAAK;GACT,KAAK,KAAK,QAAQ;GAClB,UAAU,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,WAAW;EAChD,CACD;CACD;CAEA,MAAc,QAAQ,SAAmD;EACxE,MAAM,EAAE,QAAQ,QAAQ,UACtB,QAAQ,SAAS,EAAE,KAAK,IAAI,KAAK,KAAK,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACvD,MAAM;EACR,MAAM,cAAc,MAAMC,mBAAAA,gBACzB,KAAK,IACL,KAAK,KAAK,aACV,KAAK,QAAQ,aACb,QAAQ,SACT;EAEA,OAAO,KAAK,QAAQ,OAAO;GAAE;GAAK;EAAY,CAAC;CAChD;AACD;;;;;AAWA,MAAM,OAAO,OAAO,IAAI,4BAA4B;;;;;;;AAsCpD,MAAa,OAAO;;CAEnB,IACC,SACA,SACO;EACP,OAAO;IACL,OAAO;GACR,MAAM;GACN;GACA,aAAa,QAAQ;EACtB;CACD;;CAGA,MACC,OACA,SACO;EACP,OAAO;IACL,OAAO;GACR,MAAM;GACN;GACA,MAAM,QAAQ;GACd,aAAa,QAAQ;EACtB;CACD;AACD;;AAGA,SAAgB,OAAO,OAA+B;CACrD,OACC,OAAO,UAAU,YACjB,UAAU,QACT,MAA+B,UAAU;AAE5C"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { readCredentials } from "./credential.mjs";
|
|
2
|
+
import { canonicalId, provideKey, serviceKey } from "@geekmidas/manifest";
|
|
3
|
+
//#region src/external-api.ts
|
|
4
|
+
/**
|
|
5
|
+
* `ExternalApi` — an HTTP API somebody else runs.
|
|
6
|
+
*
|
|
7
|
+
* Polar, Stripe, a payment gateway: nothing to provision, but an address that
|
|
8
|
+
* changes by stage and credentials the provider issued for each one. Without a
|
|
9
|
+
* construct every integration writes that switching by hand — an optional
|
|
10
|
+
* `POLAR_URL`, a fake started somewhere, a client built in a service — and the
|
|
11
|
+
* target cannot see any of it.
|
|
12
|
+
*
|
|
13
|
+
* ```ts
|
|
14
|
+
* // constructs/polar.ts
|
|
15
|
+
* export const polar = new ExternalApi('Polar', {
|
|
16
|
+
* url: 'https://www.polaraccesslink.com',
|
|
17
|
+
* credentials: z.object({ clientId: z.string(), clientSecret: z.string() }),
|
|
18
|
+
* client: ({ url, credentials }) => new PolarClient(url, credentials),
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // test/fakes/polar.ts
|
|
22
|
+
* export default fake.app(new Hono().post('/v3/oauth2/token', …), {
|
|
23
|
+
* credentials: { clientId: 'fake', clientSecret: 'fake' },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // in a handler — the real API deployed, the fake locally and in tests
|
|
27
|
+
* .dependsOn([polar])
|
|
28
|
+
* .handle(({ services }) => services.polar.exchangeCode(code))
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Deployed, the URL is `url` — one for every stage, or one per stage name with
|
|
32
|
+
* a `default` — and the credentials are the stage's `<ID>_CREDENTIALS`, one
|
|
33
|
+
* JSON value read the way a `Credential`'s is. Locally and in tests both come
|
|
34
|
+
* from the fake.
|
|
35
|
+
*
|
|
36
|
+
* **The construct never names its fake.** It is found by convention, at
|
|
37
|
+
* `test/fakes/<id>.ts`, and read only by gkm and the generated test harness —
|
|
38
|
+
* so a fake, and the recorded responses it answers from, cannot end up in a
|
|
39
|
+
* deployed bundle however the bundler follows imports.
|
|
40
|
+
*/
|
|
41
|
+
var ExternalApi = class {
|
|
42
|
+
options;
|
|
43
|
+
id;
|
|
44
|
+
service;
|
|
45
|
+
/** Read by both `declare()` and `connect()`, so the two cannot drift. */
|
|
46
|
+
keys;
|
|
47
|
+
/** The promise, so concurrent registrations share one client. */
|
|
48
|
+
connected;
|
|
49
|
+
constructor(id, options) {
|
|
50
|
+
this.options = options;
|
|
51
|
+
const canonical = canonicalId(id);
|
|
52
|
+
this.id = canonical;
|
|
53
|
+
this.keys = {
|
|
54
|
+
url: provideKey(canonical, "url"),
|
|
55
|
+
credentials: provideKey(canonical, "credentials")
|
|
56
|
+
};
|
|
57
|
+
this.service = {
|
|
58
|
+
serviceName: serviceKey(canonical),
|
|
59
|
+
register: (registerOptions) => {
|
|
60
|
+
this.connected ??= this.connect(registerOptions);
|
|
61
|
+
return this.connected;
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
declare() {
|
|
66
|
+
return [{
|
|
67
|
+
kind: "external-api",
|
|
68
|
+
id: this.id,
|
|
69
|
+
url: this.options.url,
|
|
70
|
+
provides: [this.keys.url, this.keys.credentials]
|
|
71
|
+
}];
|
|
72
|
+
}
|
|
73
|
+
async connect(options) {
|
|
74
|
+
const { url } = options.envParser.create((get) => ({ url: get(this.keys.url).string() })).parse();
|
|
75
|
+
const credentials = await readCredentials(this.id, this.keys.credentials, this.options.credentials, options.envParser);
|
|
76
|
+
return this.options.client({
|
|
77
|
+
url,
|
|
78
|
+
credentials
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Marks a fake. A registered symbol, so a fake built by a second copy of this
|
|
84
|
+
* package — a linked workspace, two versions in a lockfile — is still one.
|
|
85
|
+
*/
|
|
86
|
+
const FAKE = Symbol.for("@geekmidas/constructs/fake");
|
|
87
|
+
/**
|
|
88
|
+
* Build the fake `test/fakes/<id>.ts` default-exports.
|
|
89
|
+
*
|
|
90
|
+
* Pass the API's type to have the credentials checked against its schema —
|
|
91
|
+
* `fake.app<typeof polar>(…)`.
|
|
92
|
+
*/
|
|
93
|
+
const fake = {
|
|
94
|
+
/** A working implementation of the API, kept beside the tests that use it. */
|
|
95
|
+
app(handler, options) {
|
|
96
|
+
return {
|
|
97
|
+
[FAKE]: true,
|
|
98
|
+
kind: "app",
|
|
99
|
+
handler,
|
|
100
|
+
credentials: options.credentials
|
|
101
|
+
};
|
|
102
|
+
},
|
|
103
|
+
/** A local server the provider publishes — `stripe/stripe-mock`. */
|
|
104
|
+
image(image, options) {
|
|
105
|
+
return {
|
|
106
|
+
[FAKE]: true,
|
|
107
|
+
kind: "image",
|
|
108
|
+
image,
|
|
109
|
+
port: options.port,
|
|
110
|
+
credentials: options.credentials
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
/** Whether a value is a fake — what gkm asks of a `test/fakes` default export. */
|
|
115
|
+
function isFake(value) {
|
|
116
|
+
return typeof value === "object" && value !== null && value[FAKE] === true;
|
|
117
|
+
}
|
|
118
|
+
//#endregion
|
|
119
|
+
export { ExternalApi, fake, isFake };
|
|
120
|
+
|
|
121
|
+
//# sourceMappingURL=external-api.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"external-api.mjs","names":[],"sources":["../src/external-api.ts"],"sourcesContent":["/**\n * `ExternalApi` — an HTTP API somebody else runs.\n *\n * Polar, Stripe, a payment gateway: nothing to provision, but an address that\n * changes by stage and credentials the provider issued for each one. Without a\n * construct every integration writes that switching by hand — an optional\n * `POLAR_URL`, a fake started somewhere, a client built in a service — and the\n * target cannot see any of it.\n *\n * ```ts\n * // constructs/polar.ts\n * export const polar = new ExternalApi('Polar', {\n * url: 'https://www.polaraccesslink.com',\n * credentials: z.object({ clientId: z.string(), clientSecret: z.string() }),\n * client: ({ url, credentials }) => new PolarClient(url, credentials),\n * });\n *\n * // test/fakes/polar.ts\n * export default fake.app(new Hono().post('/v3/oauth2/token', …), {\n * credentials: { clientId: 'fake', clientSecret: 'fake' },\n * });\n *\n * // in a handler — the real API deployed, the fake locally and in tests\n * .dependsOn([polar])\n * .handle(({ services }) => services.polar.exchangeCode(code))\n * ```\n *\n * Deployed, the URL is `url` — one for every stage, or one per stage name with\n * a `default` — and the credentials are the stage's `<ID>_CREDENTIALS`, one\n * JSON value read the way a `Credential`'s is. Locally and in tests both come\n * from the fake.\n *\n * **The construct never names its fake.** It is found by convention, at\n * `test/fakes/<id>.ts`, and read only by gkm and the generated test harness —\n * so a fake, and the recorded responses it answers from, cannot end up in a\n * deployed bundle however the bundler follows imports.\n */\n\nimport {\n\ttype ConstructName,\n\tcanonicalId,\n\ttype Declaration,\n\tprovideKey,\n\tserviceKey,\n} from '@geekmidas/manifest';\nimport type { Service, ServiceRegisterOptions } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { Consumable } from './construct-interface';\nimport { readCredentials } from './credential';\n\n/** What a credentials schema yields. */\ntype Value<TSchema extends StandardSchemaV1> =\n\tStandardSchemaV1.InferOutput<TSchema>;\n\nexport interface ExternalApiOptions<TSchema extends StandardSchemaV1, TClient> {\n\t/**\n\t * Where it answers deployed: one URL for every stage, or one per stage\n\t * name, with `default` for any stage not listed.\n\t */\n\turl: string | Readonly<Record<string, string>>;\n\t/** What the stage's `<ID>_CREDENTIALS` must look like. */\n\tcredentials: TSchema;\n\t/** What a handler is handed, built from where it answers and the credentials. */\n\tclient: (connection: {\n\t\turl: string;\n\t\tcredentials: Value<TSchema>;\n\t}) => TClient | Promise<TClient>;\n}\n\nexport class ExternalApi<\n\tTName extends string = string,\n\tTSchema extends StandardSchemaV1 = StandardSchemaV1,\n\tTClient = unknown,\n> implements Consumable<TName, TClient>\n{\n\t// `Consumable` for the reason `Credential` gives: a client generic in\n\t// `TClient` cannot satisfy `Construct`'s conditional service type.\n\treadonly id: TName;\n\treadonly service: Service<Uncapitalize<TName>, TClient>;\n\n\t/** Read by both `declare()` and `connect()`, so the two cannot drift. */\n\tprivate readonly keys: { url: string; credentials: string };\n\n\t/** The promise, so concurrent registrations share one client. */\n\tprivate connected?: Promise<TClient>;\n\n\tconstructor(\n\t\tid: ConstructName<TName>,\n\t\tprivate readonly options: ExternalApiOptions<TSchema, TClient>,\n\t) {\n\t\tconst canonical = canonicalId(id as string);\n\n\t\tthis.id = canonical as TName;\n\t\tthis.keys = {\n\t\t\turl: provideKey(canonical, 'url'),\n\t\t\tcredentials: provideKey(canonical, 'credentials'),\n\t\t};\n\n\t\t// A field, not a getter: consumers cache services by object identity.\n\t\tthis.service = {\n\t\t\tserviceName: serviceKey(canonical) as Uncapitalize<TName>,\n\t\t\tregister: (registerOptions) => {\n\t\t\t\tthis.connected ??= this.connect(registerOptions);\n\t\t\t\treturn this.connected;\n\t\t\t},\n\t\t};\n\t}\n\n\tdeclare(): Declaration[] {\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: 'external-api',\n\t\t\t\tid: this.id,\n\t\t\t\turl: this.options.url,\n\t\t\t\tprovides: [this.keys.url, this.keys.credentials],\n\t\t\t},\n\t\t];\n\t}\n\n\tprivate async connect(options: ServiceRegisterOptions): Promise<TClient> {\n\t\tconst { url } = options.envParser\n\t\t\t.create((get) => ({ url: get(this.keys.url).string() }))\n\t\t\t.parse();\n\t\tconst credentials = await readCredentials(\n\t\t\tthis.id,\n\t\t\tthis.keys.credentials,\n\t\t\tthis.options.credentials,\n\t\t\toptions.envParser,\n\t\t);\n\n\t\treturn this.options.client({ url, credentials });\n\t}\n}\n\n/** Anything that answers a request — a Hono app, or a bare `{ fetch }`. */\nexport interface FetchHandler {\n\tfetch(request: Request): Response | Promise<Response>;\n}\n\n/**\n * Marks a fake. A registered symbol, so a fake built by a second copy of this\n * package — a linked workspace, two versions in a lockfile — is still one.\n */\nconst FAKE = Symbol.for('@geekmidas/constructs/fake');\n\n/** What an external API's credentials look like going in, for a fake to supply. */\ntype CredentialsOf<TApi> =\n\tTApi extends ExternalApi<string, infer TSchema, unknown>\n\t\t? StandardSchemaV1.InferInput<TSchema>\n\t\t: unknown;\n\n/**\n * An external API's stand-in, as `test/fakes/<id>.ts` default-exports it.\n *\n * `credentials` are what the fake accepts, and what a local or test stage is\n * handed as `<ID>_CREDENTIALS` in place of the stage's own.\n */\nexport type Fake = {\n\treadonly [FAKE]: true;\n\treadonly credentials: unknown;\n} & (\n\t| {\n\t\t\treadonly kind: 'app';\n\t\t\t/** Served by gkm: in-process in a test, on its own port in `gkm dev`. */\n\t\t\treadonly handler: FetchHandler;\n\t }\n\t| {\n\t\t\treadonly kind: 'image';\n\t\t\t/** The provider's own local server, run as a container. */\n\t\t\treadonly image: string;\n\t\t\t/** The port it listens on inside the container. */\n\t\t\treadonly port: number;\n\t }\n);\n\n/**\n * Build the fake `test/fakes/<id>.ts` default-exports.\n *\n * Pass the API's type to have the credentials checked against its schema —\n * `fake.app<typeof polar>(…)`.\n */\nexport const fake = {\n\t/** A working implementation of the API, kept beside the tests that use it. */\n\tapp<TApi = unknown>(\n\t\thandler: FetchHandler,\n\t\toptions: { credentials: CredentialsOf<TApi> },\n\t): Fake {\n\t\treturn {\n\t\t\t[FAKE]: true,\n\t\t\tkind: 'app',\n\t\t\thandler,\n\t\t\tcredentials: options.credentials,\n\t\t};\n\t},\n\n\t/** A local server the provider publishes — `stripe/stripe-mock`. */\n\timage<TApi = unknown>(\n\t\timage: string,\n\t\toptions: { port: number; credentials: CredentialsOf<TApi> },\n\t): Fake {\n\t\treturn {\n\t\t\t[FAKE]: true,\n\t\t\tkind: 'image',\n\t\t\timage,\n\t\t\tport: options.port,\n\t\t\tcredentials: options.credentials,\n\t\t};\n\t},\n};\n\n/** Whether a value is a fake — what gkm asks of a `test/fakes` default export. */\nexport function isFake(value: unknown): value is Fake {\n\treturn (\n\t\ttypeof value === 'object' &&\n\t\tvalue !== null &&\n\t\t(value as { [FAKE]?: unknown })[FAKE] === true\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqEA,IAAa,cAAb,MAKA;CAcmB;CAXlB;CACA;;CAGA;;CAGA;CAEA,YACC,IACA,SACC;EADgB,KAAA,UAAA;EAEjB,MAAM,YAAY,YAAY,EAAY;EAE1C,KAAK,KAAK;EACV,KAAK,OAAO;GACX,KAAK,WAAW,WAAW,KAAK;GAChC,aAAa,WAAW,WAAW,aAAa;EACjD;EAGA,KAAK,UAAU;GACd,aAAa,WAAW,SAAS;GACjC,WAAW,oBAAoB;IAC9B,KAAK,cAAc,KAAK,QAAQ,eAAe;IAC/C,OAAO,KAAK;GACb;EACD;CACD;CAEA,UAAyB;EACxB,OAAO,CACN;GACC,MAAM;GACN,IAAI,KAAK;GACT,KAAK,KAAK,QAAQ;GAClB,UAAU,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,WAAW;EAChD,CACD;CACD;CAEA,MAAc,QAAQ,SAAmD;EACxE,MAAM,EAAE,QAAQ,QAAQ,UACtB,QAAQ,SAAS,EAAE,KAAK,IAAI,KAAK,KAAK,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CACvD,MAAM;EACR,MAAM,cAAc,MAAM,gBACzB,KAAK,IACL,KAAK,KAAK,aACV,KAAK,QAAQ,aACb,QAAQ,SACT;EAEA,OAAO,KAAK,QAAQ,OAAO;GAAE;GAAK;EAAY,CAAC;CAChD;AACD;;;;;AAWA,MAAM,OAAO,OAAO,IAAI,4BAA4B;;;;;;;AAsCpD,MAAa,OAAO;;CAEnB,IACC,SACA,SACO;EACP,OAAO;IACL,OAAO;GACR,MAAM;GACN;GACA,aAAa,QAAQ;EACtB;CACD;;CAGA,MACC,OACA,SACO;EACP,OAAO;IACL,OAAO;GACR,MAAM;GACN;GACA,MAAM,QAAQ;GACd,aAAa,QAAQ;EACtB;CACD;AACD;;AAGA,SAAgB,OAAO,OAA+B;CACrD,OACC,OAAO,UAAU,YACjB,UAAU,QACT,MAA+B,UAAU;AAE5C"}
|