@geekmidas/constructs 10.0.0-alpha.40 → 10.0.0-alpha.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Cron-CMEGfRs8.d.cts → Cron-DI3nKoic.d.cts} +3 -2
- package/dist/Cron-DI3nKoic.d.cts.map +1 -0
- package/dist/{Cron-D6X4-xjB.d.mts → Cron-uYAHPnp7.d.mts} +3 -2
- package/dist/Cron-uYAHPnp7.d.mts.map +1 -0
- package/dist/{CronBuilder-DB35T5dL.cjs → CronBuilder-BoHzlWU_.cjs} +8 -3
- package/dist/CronBuilder-BoHzlWU_.cjs.map +1 -0
- package/dist/{CronBuilder-Dv0IlZs0.mjs → CronBuilder-CCgt0wCE.mjs} +9 -4
- package/dist/CronBuilder-CCgt0wCE.mjs.map +1 -0
- package/dist/{CronBuilder-O_gvButp.d.mts → CronBuilder-DaSUm2Na.d.mts} +5 -4
- package/dist/CronBuilder-DaSUm2Na.d.mts.map +1 -0
- package/dist/{CronBuilder-CEK7aOqD.d.cts → CronBuilder-g1lZLWyG.d.cts} +5 -4
- package/dist/CronBuilder-g1lZLWyG.d.cts.map +1 -0
- package/dist/{Endpoint-CQAeh1Rh.mjs → Endpoint-BDgmfml0.mjs} +2 -2
- package/dist/{Endpoint-CQAeh1Rh.mjs.map → Endpoint-BDgmfml0.mjs.map} +1 -1
- package/dist/{Endpoint-Dp5AKIXl.d.cts → Endpoint-BkzU6nn1.d.cts} +5 -4
- package/dist/Endpoint-BkzU6nn1.d.cts.map +1 -0
- package/dist/{Endpoint-DtI7heFm.d.mts → Endpoint-BpboleFh.d.mts} +5 -4
- package/dist/Endpoint-BpboleFh.d.mts.map +1 -0
- package/dist/{Endpoint-D1L9qu5C.cjs → Endpoint-wSCHSnqb.cjs} +2 -2
- package/dist/{Endpoint-D1L9qu5C.cjs.map → Endpoint-wSCHSnqb.cjs.map} +1 -1
- package/dist/{EndpointFactory-FeFRmlDZ.d.cts → EndpointFactory-BZZOleQT.d.cts} +4 -4
- package/dist/{EndpointFactory-CgMDvERK.d.mts.map → EndpointFactory-BZZOleQT.d.cts.map} +1 -1
- package/dist/{EndpointFactory-BBdNeaGJ.mjs → EndpointFactory-C9G2pz86.mjs} +3 -3
- package/dist/{EndpointFactory-BBdNeaGJ.mjs.map → EndpointFactory-C9G2pz86.mjs.map} +1 -1
- package/dist/{EndpointFactory-CgMDvERK.d.mts → EndpointFactory-DnNlYflU.d.mts} +4 -4
- package/dist/{EndpointFactory-FeFRmlDZ.d.cts.map → EndpointFactory-DnNlYflU.d.mts.map} +1 -1
- package/dist/{EndpointFactory-BZOCOaK6.cjs → EndpointFactory-G1g1kiqC.cjs} +3 -3
- package/dist/{EndpointFactory-BZOCOaK6.cjs.map → EndpointFactory-G1g1kiqC.cjs.map} +1 -1
- package/dist/Function-DuqGcbOI.d.mts +76 -0
- package/dist/Function-DuqGcbOI.d.mts.map +1 -0
- package/dist/Function-Pu-1kKZz.d.cts +76 -0
- package/dist/Function-Pu-1kKZz.d.cts.map +1 -0
- package/dist/{HonoEndpointAdaptor-Cq99r9H7.cjs → HonoEndpointAdaptor-CBoSm3TM.cjs} +3 -3
- package/dist/{HonoEndpointAdaptor-Cq99r9H7.cjs.map → HonoEndpointAdaptor-CBoSm3TM.cjs.map} +1 -1
- package/dist/{HonoEndpointAdaptor-Aui-x9Lg.mjs → HonoEndpointAdaptor-DL_fCB9O.mjs} +3 -3
- package/dist/{HonoEndpointAdaptor-Aui-x9Lg.mjs.map → HonoEndpointAdaptor-DL_fCB9O.mjs.map} +1 -1
- package/dist/{Queue-Ckmudcm8.cjs → Queue-D5jcw0mu.cjs} +6 -2
- package/dist/Queue-D5jcw0mu.cjs.map +1 -0
- package/dist/{Queue-YmvN2vEP.d.mts → Queue-DlsHRzUp.d.mts} +22 -10
- package/dist/Queue-DlsHRzUp.d.mts.map +1 -0
- package/dist/{Queue-CpQIGB_2.d.cts → Queue-HPyi0e1i.d.cts} +22 -10
- package/dist/Queue-HPyi0e1i.d.cts.map +1 -0
- package/dist/{Queue-C1uDgjxt.mjs → Queue-hwPN-t31.mjs} +6 -2
- package/dist/Queue-hwPN-t31.mjs.map +1 -0
- package/dist/{QueueBuilder-CJNcv4dy.cjs → QueueBuilder-BFQn3OzZ.cjs} +27 -4
- package/dist/QueueBuilder-BFQn3OzZ.cjs.map +1 -0
- package/dist/{QueueBuilder-XuPKZwKH.mjs → QueueBuilder-DCuYdjMw.mjs} +28 -5
- package/dist/QueueBuilder-DCuYdjMw.mjs.map +1 -0
- package/dist/{QueueBuilder-XEnnOWGe.d.cts → QueueBuilder-OSi6LkV9.d.cts} +24 -11
- package/dist/QueueBuilder-OSi6LkV9.d.cts.map +1 -0
- package/dist/{QueueBuilder-CM0WUxfw.d.mts → QueueBuilder-QHsnVt1P.d.mts} +24 -11
- package/dist/QueueBuilder-QHsnVt1P.d.mts.map +1 -0
- package/dist/{Subscriber-B91YSkZt.d.cts → Subscriber-Bpp02cGr.d.cts} +20 -9
- package/dist/Subscriber-Bpp02cGr.d.cts.map +1 -0
- package/dist/{Subscriber-BjHYe5hK.d.mts → Subscriber-CtN9R48-.d.mts} +20 -9
- package/dist/Subscriber-CtN9R48-.d.mts.map +1 -0
- package/dist/{SubscriberBuilder-Duk028pD.cjs → SubscriberBuilder-C2PwqwIl.cjs} +31 -3
- package/dist/SubscriberBuilder-C2PwqwIl.cjs.map +1 -0
- package/dist/{SubscriberBuilder-BhMphk4z.d.mts → SubscriberBuilder-CuCMFpYW.d.mts} +23 -11
- package/dist/SubscriberBuilder-CuCMFpYW.d.mts.map +1 -0
- package/dist/{SubscriberBuilder-DzQUWE08.mjs → SubscriberBuilder-DMFk_Ap1.mjs} +32 -4
- package/dist/SubscriberBuilder-DMFk_Ap1.mjs.map +1 -0
- package/dist/{SubscriberBuilder-BSpQX1JT.d.cts → SubscriberBuilder-g3fAVWgs.d.cts} +23 -11
- package/dist/SubscriberBuilder-g3fAVWgs.d.cts.map +1 -0
- package/dist/adaptors/aws.cjs +20 -4
- package/dist/adaptors/aws.cjs.map +1 -1
- package/dist/adaptors/aws.d.cts +17 -13
- package/dist/adaptors/aws.d.cts.map +1 -1
- package/dist/adaptors/aws.d.mts +17 -13
- package/dist/adaptors/aws.d.mts.map +1 -1
- package/dist/adaptors/aws.mjs +20 -4
- package/dist/adaptors/aws.mjs.map +1 -1
- package/dist/adaptors/hono.cjs +1 -1
- package/dist/adaptors/hono.d.cts +1 -1
- package/dist/adaptors/hono.d.mts +1 -1
- package/dist/adaptors/hono.mjs +1 -1
- package/dist/adaptors/testing.cjs +170 -13
- package/dist/adaptors/testing.cjs.map +1 -1
- package/dist/adaptors/testing.d.cts +38 -21
- package/dist/adaptors/testing.d.cts.map +1 -1
- package/dist/adaptors/testing.d.mts +38 -21
- package/dist/adaptors/testing.d.mts.map +1 -1
- package/dist/adaptors/testing.mjs +170 -13
- package/dist/adaptors/testing.mjs.map +1 -1
- package/dist/{auth-CMwml9QN.d.mts → auth-3OAmK42n.d.cts} +4 -4
- package/dist/{auth-CMwml9QN.d.mts.map → auth-3OAmK42n.d.cts.map} +1 -1
- package/dist/{auth-rVRDjIw_.d.cts → auth-BWbiewHa.d.mts} +4 -4
- package/dist/{auth-rVRDjIw_.d.cts.map → auth-BWbiewHa.d.mts.map} +1 -1
- package/dist/auth.d.cts +1 -1
- package/dist/auth.d.mts +1 -1
- package/dist/{cache-C9a_hVCc.d.cts → cache-CXh6GIgb.d.mts} +3 -3
- package/dist/{cache-C9a_hVCc.d.cts.map → cache-CXh6GIgb.d.mts.map} +1 -1
- package/dist/{cache-CeTMI8LR.d.mts → cache-DnGDGly3.d.cts} +3 -3
- package/dist/{cache-CeTMI8LR.d.mts.map → cache-DnGDGly3.d.cts.map} +1 -1
- package/dist/cache.d.cts +1 -1
- package/dist/cache.d.mts +1 -1
- package/dist/{construct-interface-_3zgxzXl.d.mts → construct-interface-B1AfqRl4.d.cts} +25 -3
- package/dist/{construct-interface-_3zgxzXl.d.mts.map → construct-interface-B1AfqRl4.d.cts.map} +1 -1
- package/dist/{construct-interface-_xi4BPN8.d.cts → construct-interface-DluK3_da.d.mts} +25 -3
- package/dist/{construct-interface-_xi4BPN8.d.cts.map → construct-interface-DluK3_da.d.mts.map} +1 -1
- package/dist/construct-interface.cjs +26 -0
- 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 +26 -1
- package/dist/construct-interface.mjs.map +1 -1
- package/dist/credential.d.cts +1 -1
- package/dist/credential.d.mts +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 +3 -3
- package/dist/endpoints/index.d.cts +2 -2
- package/dist/endpoints/index.d.mts +2 -2
- package/dist/endpoints/index.mjs +3 -3
- package/dist/{external-api-DS3mujT5.d.mts → external-api-CWY9orcO.d.mts} +2 -2
- package/dist/{external-api-DS3mujT5.d.mts.map → external-api-CWY9orcO.d.mts.map} +1 -1
- package/dist/{external-api-LBfE-q3g.d.cts → external-api-D-5WB-sr.d.cts} +2 -2
- package/dist/{external-api-LBfE-q3g.d.cts.map → external-api-D-5WB-sr.d.cts.map} +1 -1
- package/dist/external-api.d.cts +1 -1
- package/dist/external-api.d.mts +1 -1
- 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 +2 -1
- package/dist/functions/index.d.mts +2 -1
- package/dist/functions/index.mjs +1 -1
- package/dist/{functions-ZH60FE7H.cjs → functions-CbP5ZKma.cjs} +15 -3
- package/dist/functions-CbP5ZKma.cjs.map +1 -0
- package/dist/{functions-DCIfCRR-.mjs → functions-Di6n5ltG.mjs} +16 -4
- package/dist/{functions-DCIfCRR-.mjs.map → functions-Di6n5ltG.mjs.map} +1 -1
- package/dist/{index-B0kxstwf.d.cts → index-BuzRvKOQ.d.cts} +9 -71
- package/dist/index-BuzRvKOQ.d.cts.map +1 -0
- package/dist/{index-CjVEjOw0.d.mts → index-CTkKOer4.d.mts} +9 -71
- package/dist/index-CTkKOer4.d.mts.map +1 -0
- package/dist/{kysely-BJ8IQ_1P.d.mts → kysely-Bqov3fwv.d.mts} +3 -3
- package/dist/{kysely-BJ8IQ_1P.d.mts.map → kysely-Bqov3fwv.d.mts.map} +1 -1
- package/dist/{kysely-DVF8wOT4.d.cts → kysely-DTnkZsub.d.cts} +3 -3
- package/dist/{kysely-DVF8wOT4.d.cts.map → kysely-DTnkZsub.d.cts.map} +1 -1
- 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/queue/index.cjs +2 -2
- package/dist/queue/index.d.cts +2 -2
- package/dist/queue/index.d.mts +2 -2
- package/dist/queue/index.mjs +2 -2
- package/dist/rest-api.cjs +1 -1
- package/dist/rest-api.d.cts +3 -3
- package/dist/rest-api.d.mts +3 -3
- package/dist/rest-api.mjs +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/worker.cjs +26 -10
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +38 -22
- package/dist/worker.d.cts.map +1 -1
- package/dist/worker.d.mts +38 -22
- package/dist/worker.d.mts.map +1 -1
- package/dist/worker.mjs +26 -10
- package/dist/worker.mjs.map +1 -1
- package/package.json +31 -31
- package/dist/Cron-CMEGfRs8.d.cts.map +0 -1
- package/dist/Cron-D6X4-xjB.d.mts.map +0 -1
- package/dist/CronBuilder-CEK7aOqD.d.cts.map +0 -1
- package/dist/CronBuilder-DB35T5dL.cjs.map +0 -1
- package/dist/CronBuilder-Dv0IlZs0.mjs.map +0 -1
- package/dist/CronBuilder-O_gvButp.d.mts.map +0 -1
- package/dist/Endpoint-Dp5AKIXl.d.cts.map +0 -1
- package/dist/Endpoint-DtI7heFm.d.mts.map +0 -1
- package/dist/Queue-C1uDgjxt.mjs.map +0 -1
- package/dist/Queue-Ckmudcm8.cjs.map +0 -1
- package/dist/Queue-CpQIGB_2.d.cts.map +0 -1
- package/dist/Queue-YmvN2vEP.d.mts.map +0 -1
- package/dist/QueueBuilder-CJNcv4dy.cjs.map +0 -1
- package/dist/QueueBuilder-CM0WUxfw.d.mts.map +0 -1
- package/dist/QueueBuilder-XEnnOWGe.d.cts.map +0 -1
- package/dist/QueueBuilder-XuPKZwKH.mjs.map +0 -1
- package/dist/Subscriber-B91YSkZt.d.cts.map +0 -1
- package/dist/Subscriber-BjHYe5hK.d.mts.map +0 -1
- package/dist/SubscriberBuilder-BSpQX1JT.d.cts.map +0 -1
- package/dist/SubscriberBuilder-BhMphk4z.d.mts.map +0 -1
- package/dist/SubscriberBuilder-Duk028pD.cjs.map +0 -1
- package/dist/SubscriberBuilder-DzQUWE08.mjs.map +0 -1
- package/dist/functions-ZH60FE7H.cjs.map +0 -1
- package/dist/index-B0kxstwf.d.cts.map +0 -1
- package/dist/index-CjVEjOw0.d.mts.map +0 -1
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("../rolldown-runtime-y5ARvAq5.cjs");
|
|
3
3
|
const require_auth = require("../auth.cjs");
|
|
4
|
-
const require_functions = require("../functions-
|
|
5
|
-
const require_Endpoint = require("../Endpoint-
|
|
6
|
-
const require_Queue = require("../Queue-
|
|
4
|
+
const require_functions = require("../functions-CbP5ZKma.cjs");
|
|
5
|
+
const require_Endpoint = require("../Endpoint-wSCHSnqb.cjs");
|
|
6
|
+
const require_Queue = require("../Queue-D5jcw0mu.cjs");
|
|
7
7
|
const require_email = require("../email.cjs");
|
|
8
8
|
const require_database_kysely = require("../database/kysely.cjs");
|
|
9
9
|
const require_lazyAccessors = require("../lazyAccessors-hJKGv8Ay.cjs");
|
|
10
10
|
const require_Topic = require("../Topic-CkxOTrMv.cjs");
|
|
11
|
-
const require_HonoEndpointAdaptor = require("../HonoEndpointAdaptor-
|
|
11
|
+
const require_HonoEndpointAdaptor = require("../HonoEndpointAdaptor-CBoSm3TM.cjs");
|
|
12
12
|
const require_processAudits = require("../processAudits-D_2W5x8k.cjs");
|
|
13
13
|
let _geekmidas_manifest = require("@geekmidas/manifest");
|
|
14
14
|
let _geekmidas_errors = require("@geekmidas/errors");
|
|
@@ -345,7 +345,8 @@ var TestFunctionAdaptor = class TestFunctionAdaptor {
|
|
|
345
345
|
/**
|
|
346
346
|
* In-memory test driver for a {@link Queue} worker. Hand it a batch of messages
|
|
347
347
|
* and it registers the queue's services, runs the handler in a request context,
|
|
348
|
-
* and returns the handler result — no SQS/pg-boss required.
|
|
348
|
+
* and returns the handler result — no SQS/pg-boss required. A queue with a
|
|
349
|
+
* database gets `db` registered from it, or the one the request passes.
|
|
349
350
|
*
|
|
350
351
|
* @example
|
|
351
352
|
* const adapter = new TestQueueAdaptor(ordersQueue);
|
|
@@ -364,6 +365,7 @@ var TestQueueAdaptor = class TestQueueAdaptor {
|
|
|
364
365
|
async invoke(request) {
|
|
365
366
|
const logger = this.queue.logger.child({ test: true });
|
|
366
367
|
const services = request.services ?? await this.serviceDiscovery.register(this.queue.services);
|
|
368
|
+
const db = request.db !== void 0 ? request.db : await this.getDatabase();
|
|
367
369
|
const requestId = `test-${Date.now()}`;
|
|
368
370
|
return (0, _geekmidas_services.runWithRequestContext)({
|
|
369
371
|
logger,
|
|
@@ -372,9 +374,15 @@ var TestQueueAdaptor = class TestQueueAdaptor {
|
|
|
372
374
|
}, () => this.queue.handler({
|
|
373
375
|
messages: request.messages,
|
|
374
376
|
services,
|
|
375
|
-
logger
|
|
377
|
+
logger,
|
|
378
|
+
db
|
|
376
379
|
}));
|
|
377
380
|
}
|
|
381
|
+
async getDatabase() {
|
|
382
|
+
const service = this.queue.databaseService;
|
|
383
|
+
if (!service) return void 0;
|
|
384
|
+
return (await this.serviceDiscovery.register([service]))[service.serviceName];
|
|
385
|
+
}
|
|
378
386
|
};
|
|
379
387
|
//#endregion
|
|
380
388
|
//#region src/subscribers/TestSubscriberAdaptor.ts
|
|
@@ -393,6 +401,7 @@ var TestSubscriberAdaptor = class TestSubscriberAdaptor {
|
|
|
393
401
|
let services;
|
|
394
402
|
if (request.services) services = request.services;
|
|
395
403
|
else services = await this.serviceDiscovery.register(this.subscriber.services);
|
|
404
|
+
const db = request.db !== void 0 ? request.db : await this.getDatabase();
|
|
396
405
|
const filteredEvents = this.filterEvents(request.events);
|
|
397
406
|
if (filteredEvents.length === 0) return { batchItemFailures: [] };
|
|
398
407
|
const requestId = `test-${Date.now()}`;
|
|
@@ -404,7 +413,8 @@ var TestSubscriberAdaptor = class TestSubscriberAdaptor {
|
|
|
404
413
|
const result = await this.subscriber.handler({
|
|
405
414
|
events: filteredEvents,
|
|
406
415
|
services,
|
|
407
|
-
logger
|
|
416
|
+
logger,
|
|
417
|
+
db
|
|
408
418
|
});
|
|
409
419
|
let output = result;
|
|
410
420
|
if (this.subscriber.outputSchema && result) {
|
|
@@ -415,6 +425,11 @@ var TestSubscriberAdaptor = class TestSubscriberAdaptor {
|
|
|
415
425
|
return output;
|
|
416
426
|
});
|
|
417
427
|
}
|
|
428
|
+
async getDatabase() {
|
|
429
|
+
const service = this.subscriber.databaseService;
|
|
430
|
+
if (!service) return void 0;
|
|
431
|
+
return (await this.serviceDiscovery.register([service]))[service.serviceName];
|
|
432
|
+
}
|
|
418
433
|
filterEvents(events) {
|
|
419
434
|
if (!this.subscriber.subscribedEvents) return events;
|
|
420
435
|
return events.filter((event) => this.subscriber.subscribedEvents.includes(event.type));
|
|
@@ -518,7 +533,16 @@ function featureTest(options = {}) {
|
|
|
518
533
|
if (isLocal(new URL(request.url))) return;
|
|
519
534
|
print.error();
|
|
520
535
|
} });
|
|
521
|
-
|
|
536
|
+
const restoreStamp = (0, _geekmidas_testkit_context.installContextFetch)();
|
|
537
|
+
const stamped = globalThis.fetch;
|
|
538
|
+
globalThis.fetch = deliveringFetch(stamped, (id) => {
|
|
539
|
+
const state = contexts.get(id);
|
|
540
|
+
return state ? deliver(app, state, id) : Promise.resolve();
|
|
541
|
+
});
|
|
542
|
+
restoreFetch = () => {
|
|
543
|
+
globalThis.fetch = stamped;
|
|
544
|
+
restoreStamp();
|
|
545
|
+
};
|
|
522
546
|
});
|
|
523
547
|
(0, vitest.afterAll)(() => {
|
|
524
548
|
restoreFetch();
|
|
@@ -533,7 +557,9 @@ function featureTest(options = {}) {
|
|
|
533
557
|
surfaces: /* @__PURE__ */ new Map(),
|
|
534
558
|
auth: /* @__PURE__ */ new Map(),
|
|
535
559
|
addresses: /* @__PURE__ */ new Set(),
|
|
536
|
-
published: /* @__PURE__ */ new Map()
|
|
560
|
+
published: /* @__PURE__ */ new Map(),
|
|
561
|
+
pending: [],
|
|
562
|
+
delivering: false
|
|
537
563
|
};
|
|
538
564
|
const readMail = app.readMail;
|
|
539
565
|
if (readMail) state.mailbox = (address) => {
|
|
@@ -573,8 +599,8 @@ function featureTest(options = {}) {
|
|
|
573
599
|
return state.mailbox(address);
|
|
574
600
|
},
|
|
575
601
|
published: (channel) => [...state.published.get(channel.id) ?? []],
|
|
576
|
-
subscriber: (subscriber) => new TestSubscriberAdaptor(subscriber, state.discovery),
|
|
577
|
-
queue: (queue) => new TestQueueAdaptor(queue, state.discovery)
|
|
602
|
+
subscriber: (subscriber) => thenDeliver(new TestSubscriberAdaptor(subscriber, state.discovery), () => deliver(app, state, id)),
|
|
603
|
+
queue: (queue) => thenDeliver(new TestQueueAdaptor(queue, state.discovery), () => deliver(app, state, id))
|
|
578
604
|
});
|
|
579
605
|
} finally {
|
|
580
606
|
restore();
|
|
@@ -610,6 +636,10 @@ async function load(manifest, modules) {
|
|
|
610
636
|
const imported = async ({ file, export: name }) => (modules[file] ?? await import(file))[name];
|
|
611
637
|
const constructs = await Promise.all(Object.values(manifest.constructs).map(({ source }) => imported(source)));
|
|
612
638
|
const endpoints = (await Promise.all(manifest.endpoints.map(({ source }) => imported(source)))).filter((value) => require_Endpoint.Endpoint.isEndpoint(value));
|
|
639
|
+
const subscribers = (await Promise.all((manifest.subscribers ?? []).map(async ({ source }) => ({
|
|
640
|
+
name: source.export,
|
|
641
|
+
subscriber: await imported(source)
|
|
642
|
+
})))).filter((entry) => entry.subscriber?.__IS_SUBSCRIBER__ === true);
|
|
613
643
|
const unique = (values) => [...new Set(values)];
|
|
614
644
|
const databases = unique(constructs.filter((value) => value instanceof require_database_kysely.KyselyDatabase));
|
|
615
645
|
const auths = unique(constructs.filter((value) => value instanceof require_auth.BetterAuth));
|
|
@@ -623,6 +653,7 @@ async function load(manifest, modules) {
|
|
|
623
653
|
auths,
|
|
624
654
|
emails,
|
|
625
655
|
channels,
|
|
656
|
+
subscribers,
|
|
626
657
|
...inbox ? { readMail: (0, _geekmidas_testkit_mailbox.createMailbox)({ inbox }) } : {}
|
|
627
658
|
};
|
|
628
659
|
}
|
|
@@ -634,10 +665,15 @@ async function load(manifest, modules) {
|
|
|
634
665
|
function recorders(channels, state) {
|
|
635
666
|
return channels.map((channel) => {
|
|
636
667
|
const publisher = { async publish(messages) {
|
|
637
|
-
|
|
668
|
+
const sent = messages.map(({ type, payload }) => ({
|
|
638
669
|
type,
|
|
639
670
|
payload
|
|
640
|
-
}))
|
|
671
|
+
}));
|
|
672
|
+
state.published.set(channel.id, [...state.published.get(channel.id) ?? [], ...sent]);
|
|
673
|
+
state.pending.push({
|
|
674
|
+
channel,
|
|
675
|
+
messages: sent
|
|
676
|
+
});
|
|
641
677
|
} };
|
|
642
678
|
return {
|
|
643
679
|
serviceName: channel.service.serviceName,
|
|
@@ -671,6 +707,90 @@ function databasesFor(factories, databases) {
|
|
|
671
707
|
* the one place a test's connection can be handed over. Outside a test it is
|
|
672
708
|
* the database it always was.
|
|
673
709
|
*/
|
|
710
|
+
/** Rounds of delivery before a chain of consumers is called a loop. */
|
|
711
|
+
const MAX_DELIVERY_ROUNDS = 25;
|
|
712
|
+
/**
|
|
713
|
+
* Deliver what this test published, in-process, as the broker would — and
|
|
714
|
+
* keep delivering what the consumers publish in turn, until nothing is left.
|
|
715
|
+
*
|
|
716
|
+
* - A queue's messages go to its one consumer, as a batch.
|
|
717
|
+
* - A topic's events go to every subscriber that named their type, and only
|
|
718
|
+
* those: fan-out, as the filter policy (SNS) or the per-subscriber queue
|
|
719
|
+
* (pg-boss) does it.
|
|
720
|
+
* - Each payload is checked against the consumer's schema first. Turning an
|
|
721
|
+
* SNS envelope or an SQS record into `{ type, payload }` is each adaptor's
|
|
722
|
+
* job and tested there; what is tested here is what the handler is handed.
|
|
723
|
+
* - Consumers run as the server side of this test, so their databases are
|
|
724
|
+
* this test's transactions and their writes roll back with it.
|
|
725
|
+
* - A consumer that throws fails the test. Deployed, the message would be
|
|
726
|
+
* retried; here a retry would only hide the bug.
|
|
727
|
+
*/
|
|
728
|
+
async function deliver(app, state, id) {
|
|
729
|
+
if (state.delivering) return;
|
|
730
|
+
state.delivering = true;
|
|
731
|
+
try {
|
|
732
|
+
for (let round = 0; state.pending.length > 0; round++) {
|
|
733
|
+
if (round === MAX_DELIVERY_ROUNDS) throw new DeliveryDidNotSettle(MAX_DELIVERY_ROUNDS, [...new Set(state.pending.map(({ channel }) => channel.id))]);
|
|
734
|
+
for (const { channel, messages } of state.pending.splice(0)) if (channel instanceof require_Queue.Queue) await toQueue(channel, messages, state, id);
|
|
735
|
+
else await toSubscribers(channel, messages, app, state, id);
|
|
736
|
+
}
|
|
737
|
+
} finally {
|
|
738
|
+
state.delivering = false;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
async function toQueue(queue, messages, state, id) {
|
|
742
|
+
const payloads = [];
|
|
743
|
+
for (const message of messages) payloads.push(await accepted(queue.messageSchema, message, `queue '${queue.name}'`));
|
|
744
|
+
await (0, _geekmidas_testkit_context.runAsServer)(id, () => new TestQueueAdaptor(queue, state.discovery).invoke({ messages: payloads })).catch((error) => {
|
|
745
|
+
throw new DeliveryFailed(`queue '${queue.name}'`, messages, error);
|
|
746
|
+
});
|
|
747
|
+
}
|
|
748
|
+
async function toSubscribers(topic, messages, app, state, id) {
|
|
749
|
+
for (const { name, subscriber } of app.subscribers) {
|
|
750
|
+
if (subscriber.topicName !== topic.name) continue;
|
|
751
|
+
const named = messages.filter(({ type }) => (subscriber.subscribedEvents ?? []).includes(type));
|
|
752
|
+
if (named.length === 0) continue;
|
|
753
|
+
const consumer = `subscriber '${name}'`;
|
|
754
|
+
const events = [];
|
|
755
|
+
for (const message of named) {
|
|
756
|
+
const schema = topic.eventSchemas[message.type];
|
|
757
|
+
events.push({
|
|
758
|
+
type: message.type,
|
|
759
|
+
payload: await accepted(schema, message, consumer)
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
await (0, _geekmidas_testkit_context.runAsServer)(id, () => new TestSubscriberAdaptor(subscriber, state.discovery).invoke({ events })).catch((error) => {
|
|
763
|
+
throw new DeliveryFailed(consumer, named, error);
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
/** The payload, if the consumer's schema takes it — what the handler is handed. */
|
|
768
|
+
async function accepted(schema, message, consumer) {
|
|
769
|
+
const standard = schema?.["~standard"];
|
|
770
|
+
if (!standard) return message.payload;
|
|
771
|
+
const result = await standard.validate(message.payload);
|
|
772
|
+
if (result.issues) throw new MessageRejected(consumer, message, result.issues);
|
|
773
|
+
return result.value;
|
|
774
|
+
}
|
|
775
|
+
/** `fetch`, delivering what the test published once each of its requests answers. */
|
|
776
|
+
function deliveringFetch(inner, settle) {
|
|
777
|
+
return async (input, init) => {
|
|
778
|
+
const context = (0, _geekmidas_testkit_context.currentTestContext)();
|
|
779
|
+
const response = await inner(input, init);
|
|
780
|
+
if (context?.side === "client") await settle(context.id);
|
|
781
|
+
return response;
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
/** An adaptor whose `invoke` delivers what it published before returning. */
|
|
785
|
+
function thenDeliver(adaptor, settle) {
|
|
786
|
+
const invoke = adaptor.invoke.bind(adaptor);
|
|
787
|
+
adaptor.invoke = (async (...args) => {
|
|
788
|
+
const result = await invoke(...args);
|
|
789
|
+
await settle();
|
|
790
|
+
return result;
|
|
791
|
+
});
|
|
792
|
+
return adaptor;
|
|
793
|
+
}
|
|
674
794
|
function bindToTests(database) {
|
|
675
795
|
if (bound.has(database)) return;
|
|
676
796
|
bound.add(database);
|
|
@@ -841,6 +961,43 @@ var UnknownFactory = class extends Error {
|
|
|
841
961
|
this.name = "UnknownFactory";
|
|
842
962
|
}
|
|
843
963
|
};
|
|
964
|
+
/** A published message the consumer's own schema refuses. */
|
|
965
|
+
var MessageRejected = class extends Error {
|
|
966
|
+
consumer;
|
|
967
|
+
published;
|
|
968
|
+
issues;
|
|
969
|
+
constructor(consumer, published, issues) {
|
|
970
|
+
super(`${consumer} refuses '${published.type}': ${issues.map((issue) => issue.message).join("; ")}. What is published must be what the consumer's schema takes — fix the producer, or the schema.`);
|
|
971
|
+
this.consumer = consumer;
|
|
972
|
+
this.published = published;
|
|
973
|
+
this.issues = issues;
|
|
974
|
+
this.name = "MessageRejected";
|
|
975
|
+
}
|
|
976
|
+
};
|
|
977
|
+
/** A consumer that threw while handling what the test published. */
|
|
978
|
+
var DeliveryFailed = class extends Error {
|
|
979
|
+
consumer;
|
|
980
|
+
messages;
|
|
981
|
+
cause;
|
|
982
|
+
constructor(consumer, messages, cause) {
|
|
983
|
+
super(`${consumer} failed handling ${messages.map(({ type }) => `'${type}'`).join(", ")}: ${cause?.message ?? String(cause)}. Deployed, the message would be retried; here the failure is the result.`, { cause });
|
|
984
|
+
this.consumer = consumer;
|
|
985
|
+
this.messages = messages;
|
|
986
|
+
this.cause = cause;
|
|
987
|
+
this.name = "DeliveryFailed";
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
/** Consumers that kept publishing to each other without settling. */
|
|
991
|
+
var DeliveryDidNotSettle = class extends Error {
|
|
992
|
+
rounds;
|
|
993
|
+
channels;
|
|
994
|
+
constructor(rounds, channels) {
|
|
995
|
+
super(`Delivery did not settle after ${rounds} rounds — consumers are still publishing to ${channels.join(", ")}. A consumer that publishes to what triggers it loops forever deployed too.`);
|
|
996
|
+
this.rounds = rounds;
|
|
997
|
+
this.channels = channels;
|
|
998
|
+
this.name = "DeliveryDidNotSettle";
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
844
1001
|
//#endregion
|
|
845
1002
|
exports.NoInbox = NoInbox;
|
|
846
1003
|
exports.NoTestManifest = NoTestManifest;
|