bunderstack 0.17.0-beta.2 → 0.17.0-beta.4
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/CHANGELOG.md +233 -0
- package/README.md +11 -1
- package/dist/access.d.ts +116 -0
- package/dist/access.d.ts.map +1 -0
- package/dist/access.js +325 -0
- package/dist/access.js.map +1 -0
- package/dist/api/builder.d.ts +145 -0
- package/dist/api/builder.d.ts.map +1 -0
- package/dist/api/builder.js +28 -0
- package/dist/api/builder.js.map +1 -0
- package/dist/api/context.d.ts +34 -0
- package/dist/api/context.d.ts.map +1 -0
- package/dist/api/context.js +32 -0
- package/dist/api/context.js.map +1 -0
- package/dist/api/crud-router.d.ts +290 -0
- package/dist/api/crud-router.d.ts.map +1 -0
- package/dist/api/crud-router.js +249 -0
- package/dist/api/crud-router.js.map +1 -0
- package/dist/api/openapi.d.ts +6 -0
- package/dist/api/openapi.d.ts.map +1 -0
- package/dist/api/openapi.js +146 -0
- package/dist/api/openapi.js.map +1 -0
- package/dist/api/realtime-router.d.ts +76 -0
- package/dist/api/realtime-router.d.ts.map +1 -0
- package/dist/api/realtime-router.js +41 -0
- package/dist/api/realtime-router.js.map +1 -0
- package/dist/api/registry.d.ts +30 -0
- package/dist/api/registry.d.ts.map +1 -0
- package/dist/api/registry.js +239 -0
- package/dist/api/registry.js.map +1 -0
- package/dist/api/router.d.ts +9 -0
- package/dist/api/router.d.ts.map +1 -0
- package/dist/api/router.js +19 -0
- package/dist/api/router.js.map +1 -0
- package/dist/api/storage-router.d.ts +279 -0
- package/dist/api/storage-router.d.ts.map +1 -0
- package/dist/api/storage-router.js +155 -0
- package/dist/api/storage-router.js.map +1 -0
- package/dist/api/types.d.ts +55 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +2 -0
- package/dist/api/types.js.map +1 -0
- package/dist/auth.d.ts +31 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +102 -0
- package/dist/auth.js.map +1 -0
- package/dist/blueprint-generator.d.ts +18 -0
- package/dist/blueprint-generator.d.ts.map +1 -0
- package/dist/blueprint-generator.js +125 -0
- package/dist/blueprint-generator.js.map +1 -0
- package/dist/blueprint.d.ts +46 -0
- package/dist/blueprint.d.ts.map +1 -0
- package/dist/blueprint.js +162 -0
- package/dist/blueprint.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +68 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +108 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +90 -0
- package/dist/config.js.map +1 -0
- package/dist/cron.d.ts +4 -0
- package/dist/cron.d.ts.map +1 -0
- package/dist/cron.js +3 -0
- package/dist/cron.js.map +1 -0
- package/dist/crud-operations.d.ts +43 -0
- package/dist/crud-operations.d.ts.map +1 -0
- package/dist/crud-operations.js +238 -0
- package/dist/crud-operations.js.map +1 -0
- package/dist/database/adapter.d.ts +20 -0
- package/dist/database/adapter.d.ts.map +1 -0
- package/dist/database/adapter.js +2 -0
- package/dist/database/adapter.js.map +1 -0
- package/dist/database/bun-sql.d.ts +3 -0
- package/dist/database/bun-sql.d.ts.map +1 -0
- package/dist/database/bun-sql.js +21 -0
- package/dist/database/bun-sql.js.map +1 -0
- package/dist/database/libsql.d.ts +3 -0
- package/dist/database/libsql.d.ts.map +1 -0
- package/dist/database/libsql.js +22 -0
- package/dist/database/libsql.js.map +1 -0
- package/dist/database/pglite.d.ts +3 -0
- package/dist/database/pglite.d.ts.map +1 -0
- package/dist/database/pglite.js +27 -0
- package/dist/database/pglite.js.map +1 -0
- package/dist/database/postgres-js.d.ts +3 -0
- package/dist/database/postgres-js.d.ts.map +1 -0
- package/dist/database/postgres-js.js +21 -0
- package/dist/database/postgres-js.js.map +1 -0
- package/dist/db.d.ts +18 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +26 -0
- package/dist/db.js.map +1 -0
- package/dist/dialect.d.ts +17 -0
- package/dist/dialect.d.ts.map +1 -0
- package/dist/dialect.js +22 -0
- package/dist/dialect.js.map +1 -0
- package/dist/email/smtp.d.ts +14 -0
- package/dist/email/smtp.d.ts.map +1 -0
- package/dist/email/smtp.js +27 -0
- package/dist/email/smtp.js.map +1 -0
- package/dist/email.d.ts +39 -0
- package/dist/email.d.ts.map +1 -0
- package/dist/email.js +97 -0
- package/dist/email.js.map +1 -0
- package/dist/env.d.ts +47 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +99 -0
- package/dist/env.js.map +1 -0
- package/dist/errors.d.ts +125 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +92 -0
- package/dist/errors.js.map +1 -0
- package/dist/handler.d.ts +9 -0
- package/dist/handler.d.ts.map +1 -0
- package/dist/handler.js +22 -0
- package/dist/handler.js.map +1 -0
- package/dist/idempotency.d.ts +17 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +65 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/index.d.ts +134 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +480 -0
- package/dist/index.js.map +1 -0
- package/dist/internal-tables-pg.d.ts +481 -0
- package/dist/internal-tables-pg.d.ts.map +1 -0
- package/{src/internal-tables-pg.ts → dist/internal-tables-pg.js} +10 -34
- package/dist/internal-tables-pg.js.map +1 -0
- package/dist/internal-tables.d.ts +2509 -0
- package/dist/internal-tables.d.ts.map +1 -0
- package/dist/internal-tables.js +108 -0
- package/dist/internal-tables.js.map +1 -0
- package/dist/jobs/cron.d.ts +15 -0
- package/dist/jobs/cron.d.ts.map +1 -0
- package/dist/jobs/cron.js +74 -0
- package/dist/jobs/cron.js.map +1 -0
- package/dist/jobs/define.d.ts +133 -0
- package/dist/jobs/define.d.ts.map +1 -0
- package/dist/jobs/define.js +74 -0
- package/dist/jobs/define.js.map +1 -0
- package/dist/jobs/index.d.ts +11 -0
- package/dist/jobs/index.d.ts.map +1 -0
- package/dist/jobs/index.js +8 -0
- package/dist/jobs/index.js.map +1 -0
- package/dist/jobs/queue.d.ts +6 -0
- package/dist/jobs/queue.d.ts.map +1 -0
- package/dist/jobs/queue.js +55 -0
- package/dist/jobs/queue.js.map +1 -0
- package/dist/jobs/runtime.d.ts +13 -0
- package/dist/jobs/runtime.d.ts.map +1 -0
- package/dist/jobs/runtime.js +46 -0
- package/dist/jobs/runtime.js.map +1 -0
- package/dist/jobs/slots.d.ts +25 -0
- package/dist/jobs/slots.d.ts.map +1 -0
- package/dist/jobs/slots.js +41 -0
- package/dist/jobs/slots.js.map +1 -0
- package/dist/jobs/worker.d.ts +12 -0
- package/dist/jobs/worker.d.ts.map +1 -0
- package/dist/jobs/worker.js +311 -0
- package/dist/jobs/worker.js.map +1 -0
- package/dist/lifecycle.d.ts +10 -0
- package/dist/lifecycle.d.ts.map +1 -0
- package/dist/lifecycle.js +37 -0
- package/dist/lifecycle.js.map +1 -0
- package/dist/list-query.d.ts +62 -0
- package/dist/list-query.d.ts.map +1 -0
- package/dist/list-query.js +194 -0
- package/dist/list-query.js.map +1 -0
- package/dist/manifest.d.ts +59 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +167 -0
- package/dist/manifest.js.map +1 -0
- package/dist/provision-internals.d.ts +24 -0
- package/dist/provision-internals.d.ts.map +1 -0
- package/dist/provision-internals.js +7 -0
- package/dist/provision-internals.js.map +1 -0
- package/dist/provision.d.ts +23 -0
- package/dist/provision.d.ts.map +1 -0
- package/dist/provision.js +96 -0
- package/dist/provision.js.map +1 -0
- package/dist/rate-limit.d.ts +7 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +49 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/realtime/facade.d.ts +18 -0
- package/dist/realtime/facade.d.ts.map +1 -0
- package/dist/realtime/facade.js +36 -0
- package/dist/realtime/facade.js.map +1 -0
- package/dist/realtime/filter.d.ts +13 -0
- package/dist/realtime/filter.d.ts.map +1 -0
- package/dist/realtime/filter.js +48 -0
- package/dist/realtime/filter.js.map +1 -0
- package/dist/realtime/heartbeat.d.ts +14 -0
- package/dist/realtime/heartbeat.d.ts.map +1 -0
- package/dist/realtime/heartbeat.js +64 -0
- package/dist/realtime/heartbeat.js.map +1 -0
- package/dist/realtime/publisher.d.ts +21 -0
- package/dist/realtime/publisher.d.ts.map +1 -0
- package/dist/realtime/publisher.js +17 -0
- package/dist/realtime/publisher.js.map +1 -0
- package/dist/schema-export-pg.d.ts +2 -0
- package/dist/schema-export-pg.d.ts.map +1 -0
- package/dist/schema-export-pg.js +4 -0
- package/dist/schema-export-pg.js.map +1 -0
- package/dist/schema-export.d.ts +2 -0
- package/dist/schema-export.d.ts.map +1 -0
- package/dist/schema-export.js +2 -0
- package/dist/schema-export.js.map +1 -0
- package/dist/scope.d.ts +4 -0
- package/dist/scope.d.ts.map +1 -0
- package/dist/scope.js +13 -0
- package/dist/scope.js.map +1 -0
- package/dist/standard-schema.d.ts +13 -0
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js +34 -0
- package/dist/standard-schema.js.map +1 -0
- package/dist/storage/buckets.d.ts +80 -0
- package/dist/storage/buckets.d.ts.map +1 -0
- package/dist/storage/buckets.js +178 -0
- package/dist/storage/buckets.js.map +1 -0
- package/dist/storage/delete.d.ts +11 -0
- package/dist/storage/delete.d.ts.map +1 -0
- package/dist/storage/delete.js +18 -0
- package/dist/storage/delete.js.map +1 -0
- package/dist/storage/file-meta.d.ts +37 -0
- package/dist/storage/file-meta.d.ts.map +1 -0
- package/dist/storage/file-meta.js +166 -0
- package/dist/storage/file-meta.js.map +1 -0
- package/dist/storage/index.d.ts +28 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +5 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/local.d.ts +15 -0
- package/dist/storage/local.d.ts.map +1 -0
- package/dist/storage/local.js +56 -0
- package/dist/storage/local.js.map +1 -0
- package/dist/storage/operations.d.ts +54 -0
- package/dist/storage/operations.d.ts.map +1 -0
- package/dist/storage/operations.js +250 -0
- package/dist/storage/operations.js.map +1 -0
- package/dist/storage/registry.d.ts +10 -0
- package/dist/storage/registry.d.ts.map +1 -0
- package/dist/storage/registry.js +23 -0
- package/dist/storage/registry.js.map +1 -0
- package/dist/storage/s3.d.ts +28 -0
- package/dist/storage/s3.d.ts.map +1 -0
- package/dist/storage/s3.js +71 -0
- package/dist/storage/s3.js.map +1 -0
- package/dist/storage/sweep.d.ts +9 -0
- package/dist/storage/sweep.d.ts.map +1 -0
- package/dist/storage/sweep.js +17 -0
- package/dist/storage/sweep.js.map +1 -0
- package/dist/storage/thumbnails.d.ts +11 -0
- package/dist/storage/thumbnails.d.ts.map +1 -0
- package/dist/storage/thumbnails.js +60 -0
- package/dist/storage/thumbnails.js.map +1 -0
- package/dist/testing.d.ts +27 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/testing.js +11 -0
- package/dist/testing.js.map +1 -0
- package/dist/typeid-pg.d.ts +19 -0
- package/dist/typeid-pg.d.ts.map +1 -0
- package/{src/typeid-pg.ts → dist/typeid-pg.js} +10 -13
- package/dist/typeid-pg.js.map +1 -0
- package/dist/typeid.d.ts +45 -0
- package/dist/typeid.d.ts.map +1 -0
- package/dist/typeid.js +100 -0
- package/dist/typeid.js.map +1 -0
- package/package.json +77 -28
- package/src/access.ts +0 -532
- package/src/api/builder.ts +0 -52
- package/src/api/context.ts +0 -83
- package/src/api/crud-router.ts +0 -386
- package/src/api/openapi.ts +0 -184
- package/src/api/realtime-router.ts +0 -75
- package/src/api/registry.ts +0 -338
- package/src/api/router.ts +0 -34
- package/src/api/storage-router.ts +0 -224
- package/src/api/types.ts +0 -105
- package/src/auth.ts +0 -117
- package/src/blueprint-generator.ts +0 -203
- package/src/blueprint.ts +0 -264
- package/src/cli.ts +0 -90
- package/src/config.ts +0 -215
- package/src/cron.ts +0 -3
- package/src/crud-operations.ts +0 -478
- package/src/database/adapter.ts +0 -26
- package/src/database/bun-sql.ts +0 -23
- package/src/database/libsql.ts +0 -28
- package/src/database/pglite.ts +0 -33
- package/src/database/postgres-js.ts +0 -33
- package/src/db.ts +0 -61
- package/src/dialect.ts +0 -38
- package/src/email/smtp.ts +0 -45
- package/src/email.ts +0 -154
- package/src/env.ts +0 -180
- package/src/errors.ts +0 -123
- package/src/handler.ts +0 -30
- package/src/idempotency.ts +0 -97
- package/src/index.ts +0 -834
- package/src/internal-tables.ts +0 -149
- package/src/jobs/cron.ts +0 -87
- package/src/jobs/define.ts +0 -283
- package/src/jobs/index.ts +0 -37
- package/src/jobs/queue.ts +0 -67
- package/src/jobs/runtime.ts +0 -58
- package/src/jobs/slots.ts +0 -52
- package/src/jobs/worker.ts +0 -369
- package/src/lifecycle.ts +0 -49
- package/src/list-query.ts +0 -333
- package/src/manifest.ts +0 -297
- package/src/provision-internals.ts +0 -29
- package/src/provision.ts +0 -128
- package/src/rate-limit.ts +0 -71
- package/src/realtime/facade.ts +0 -74
- package/src/realtime/filter.ts +0 -81
- package/src/realtime/heartbeat.ts +0 -80
- package/src/realtime/publisher.ts +0 -46
- package/src/schema-export-pg.ts +0 -7
- package/src/schema-export.ts +0 -5
- package/src/scope.ts +0 -17
- package/src/standard-schema.ts +0 -59
- package/src/storage/buckets.ts +0 -308
- package/src/storage/delete.ts +0 -26
- package/src/storage/file-meta.ts +0 -222
- package/src/storage/index.ts +0 -39
- package/src/storage/local.ts +0 -69
- package/src/storage/operations.ts +0 -398
- package/src/storage/registry.ts +0 -40
- package/src/storage/s3.ts +0 -99
- package/src/storage/sweep.ts +0 -25
- package/src/storage/thumbnails.ts +0 -65
- package/src/testing.ts +0 -31
- package/src/typeid.ts +0 -116
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type ParsedCron } from './cron.js';
|
|
2
|
+
/** Slot granularity. Every slot timestamp satisfies `slot % SLOT_MS === 0`. */
|
|
3
|
+
export declare const SLOT_MS = 60000;
|
|
4
|
+
/** Reserved job-type prefix for cron occurrences. */
|
|
5
|
+
export declare const CRON_PREFIX = "cron:";
|
|
6
|
+
/** How far back either catch-up mode will look. */
|
|
7
|
+
export declare const DEFAULT_CATCH_UP_WINDOW_MS: number;
|
|
8
|
+
export type CatchUp = 'latest' | 'all';
|
|
9
|
+
/** Aligns `ms` down to its containing slot. */
|
|
10
|
+
export declare function floorSlot(ms: number): number;
|
|
11
|
+
/**
|
|
12
|
+
* Slots matching `cron` in the half-open range `(from, to]`, oldest first.
|
|
13
|
+
*
|
|
14
|
+
* `from` is exclusive so a stored watermark is never re-emitted. Both modes are
|
|
15
|
+
* clamped to `catchUpWindowMs` — without it a watermark far in the past would
|
|
16
|
+
* make this iterate unbounded minutes.
|
|
17
|
+
*/
|
|
18
|
+
export declare function slotsDue(args: {
|
|
19
|
+
cron: ParsedCron;
|
|
20
|
+
from: number;
|
|
21
|
+
to: number;
|
|
22
|
+
catchUp?: CatchUp;
|
|
23
|
+
catchUpWindowMs?: number;
|
|
24
|
+
}): number[];
|
|
25
|
+
//# sourceMappingURL=slots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../src/jobs/slots.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAA;AAErD,+EAA+E;AAC/E,eAAO,MAAM,OAAO,QAAS,CAAA;AAE7B,qDAAqD;AACrD,eAAO,MAAM,WAAW,UAAU,CAAA;AAElC,mDAAmD;AACnD,eAAO,MAAM,0BAA0B,QAAe,CAAA;AAEtD,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAA;AAEtC,+CAA+C;AAC/C,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED;;;;;;GAMG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE;IAC7B,IAAI,EAAE,UAAU,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,GAAG,MAAM,EAAE,CAmBX"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// src/jobs/slots.ts — cron slot enumeration. Pure; no db, no clock reads.
|
|
2
|
+
import { cronMatches } from './cron.js';
|
|
3
|
+
/** Slot granularity. Every slot timestamp satisfies `slot % SLOT_MS === 0`. */
|
|
4
|
+
export const SLOT_MS = 60_000;
|
|
5
|
+
/** Reserved job-type prefix for cron occurrences. */
|
|
6
|
+
export const CRON_PREFIX = 'cron:';
|
|
7
|
+
/** How far back either catch-up mode will look. */
|
|
8
|
+
export const DEFAULT_CATCH_UP_WINDOW_MS = 60 * SLOT_MS;
|
|
9
|
+
/** Aligns `ms` down to its containing slot. */
|
|
10
|
+
export function floorSlot(ms) {
|
|
11
|
+
return Math.floor(ms / SLOT_MS) * SLOT_MS;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Slots matching `cron` in the half-open range `(from, to]`, oldest first.
|
|
15
|
+
*
|
|
16
|
+
* `from` is exclusive so a stored watermark is never re-emitted. Both modes are
|
|
17
|
+
* clamped to `catchUpWindowMs` — without it a watermark far in the past would
|
|
18
|
+
* make this iterate unbounded minutes.
|
|
19
|
+
*/
|
|
20
|
+
export function slotsDue(args) {
|
|
21
|
+
const catchUp = args.catchUp ?? 'latest';
|
|
22
|
+
const windowMs = args.catchUpWindowMs ?? DEFAULT_CATCH_UP_WINDOW_MS;
|
|
23
|
+
const to = floorSlot(args.to);
|
|
24
|
+
const from = Math.max(floorSlot(args.from), to - windowMs);
|
|
25
|
+
if (to <= from)
|
|
26
|
+
return [];
|
|
27
|
+
if (catchUp === 'latest') {
|
|
28
|
+
for (let s = to; s > from; s -= SLOT_MS) {
|
|
29
|
+
if (cronMatches(args.cron, s))
|
|
30
|
+
return [s];
|
|
31
|
+
}
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
const slots = [];
|
|
35
|
+
for (let s = from + SLOT_MS; s <= to; s += SLOT_MS) {
|
|
36
|
+
if (cronMatches(args.cron, s))
|
|
37
|
+
slots.push(s);
|
|
38
|
+
}
|
|
39
|
+
return slots;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=slots.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slots.js","sourceRoot":"","sources":["../../src/jobs/slots.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,OAAO,EAAE,WAAW,EAAmB,MAAM,QAAQ,CAAA;AAErD,+EAA+E;AAC/E,MAAM,CAAC,MAAM,OAAO,GAAG,MAAM,CAAA;AAE7B,qDAAqD;AACrD,MAAM,CAAC,MAAM,WAAW,GAAG,OAAO,CAAA;AAElC,mDAAmD;AACnD,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,GAAG,OAAO,CAAA;AAItD,+CAA+C;AAC/C,MAAM,UAAU,SAAS,CAAC,EAAU;IAClC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,OAAO,CAAA;AAC3C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,QAAQ,CAAC,IAMxB;IACC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAA;IACxC,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,IAAI,0BAA0B,CAAA;IACnE,MAAM,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,GAAG,QAAQ,CAAC,CAAA;IAC1D,IAAI,EAAE,IAAI,IAAI;QAAE,OAAO,EAAE,CAAA;IAEzB,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC;YACxC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBAAE,OAAO,CAAC,CAAC,CAAC,CAAA;QAC3C,CAAC;QACD,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,OAAO,EAAE,CAAC;QACnD,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC9C,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AnyDb } from '../dialect.js';
|
|
2
|
+
import type { JobsDefs, JobsRuntimeFacade, TickResult } from './define.js';
|
|
3
|
+
export declare function createJobRunner(deps: {
|
|
4
|
+
db: AnyDb;
|
|
5
|
+
defs: JobsDefs;
|
|
6
|
+
/** Handler ctx WITHOUT `jobs`; the facade is injected via setJobsFacade. */
|
|
7
|
+
ctx: Record<string, unknown>;
|
|
8
|
+
}): {
|
|
9
|
+
tick(now?: number): Promise<TickResult>;
|
|
10
|
+
setJobsFacade(f: JobsRuntimeFacade): void;
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=worker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../src/jobs/worker.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,KAAK,EAEV,QAAQ,EACR,iBAAiB,EACjB,UAAU,EACX,MAAM,UAAU,CAAA;AAgDjB,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,EAAE,EAAE,KAAK,CAAA;IACT,IAAI,EAAE,QAAQ,CAAA;IACd,4EAA4E;IAC5E,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAC7B;eAmSmB,MAAM,GAAgB,OAAO,CAAC,UAAU,CAAC;qBASxC,iBAAiB;EAIrC"}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
// src/jobs/worker.ts — the queue worker. One `tick()` is a full cycle:
|
|
2
|
+
// recover expired leases → reap old succeeded rows → claim and run queue jobs.
|
|
3
|
+
import { and, eq, inArray, is, isNotNull, lt, lte, max, sql } from 'drizzle-orm';
|
|
4
|
+
import { PgDatabase } from 'drizzle-orm/pg-core';
|
|
5
|
+
import { jobsTableFor } from '../internal-tables.js';
|
|
6
|
+
import { validateStandardSchema } from '../standard-schema.js';
|
|
7
|
+
import { parseCron } from './cron.js';
|
|
8
|
+
import { backoffMs, DEFAULT_RETRIES, DEFAULT_TIMEOUT_MS } from './define.js';
|
|
9
|
+
import { enqueueJob } from './queue.js';
|
|
10
|
+
import { CRON_PREFIX, floorSlot, slotsDue, SLOT_MS } from './slots.js';
|
|
11
|
+
const CLAIM_BATCH = 10;
|
|
12
|
+
const SUCCEEDED_RETENTION_MS = 24 * 60 * 60 * 1000;
|
|
13
|
+
const REAP_INTERVAL_MS = 60 * 60_000;
|
|
14
|
+
function toError(err) {
|
|
15
|
+
return err instanceof Error ? err : new Error(String(err));
|
|
16
|
+
}
|
|
17
|
+
function maxAttempts(def) {
|
|
18
|
+
return 1 + (def.retries ?? DEFAULT_RETRIES);
|
|
19
|
+
}
|
|
20
|
+
/** Resolve a stored row type back to its definition. Cron rows carry the
|
|
21
|
+
* reserved prefix; queue rows use the definition key verbatim. */
|
|
22
|
+
function definitionFor(defs, type) {
|
|
23
|
+
if (type.startsWith(CRON_PREFIX)) {
|
|
24
|
+
const def = defs[type.slice(CRON_PREFIX.length)];
|
|
25
|
+
return def?.kind === 'cron' ? def : undefined;
|
|
26
|
+
}
|
|
27
|
+
const def = defs[type];
|
|
28
|
+
return def?.kind === 'job' ? def : undefined;
|
|
29
|
+
}
|
|
30
|
+
/** Terminal queue rows release their dedupe key. */
|
|
31
|
+
function terminalPatch() {
|
|
32
|
+
return { dedupeKey: null };
|
|
33
|
+
}
|
|
34
|
+
export function createJobRunner(deps) {
|
|
35
|
+
const { db, defs } = deps;
|
|
36
|
+
const t = jobsTableFor(db);
|
|
37
|
+
const ctx = { ...deps.ctx };
|
|
38
|
+
let lastReapAt = 0;
|
|
39
|
+
/** Cron rows carry no payload — their handler input is the slot itself. */
|
|
40
|
+
function resolveInput(def, row) {
|
|
41
|
+
if (def.kind === 'cron') {
|
|
42
|
+
return { scheduledFor: new Date(Number(row.runAt)) };
|
|
43
|
+
}
|
|
44
|
+
const raw = JSON.parse(row.payloadJson);
|
|
45
|
+
return def.input
|
|
46
|
+
? validateStandardSchema(def.input, raw, 'job payload')
|
|
47
|
+
: undefined;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The watermark is the newest slot we already stored for this cron. When no
|
|
51
|
+
* rows exist — a newly declared cron, or one whose rows were reaped — anchor
|
|
52
|
+
* one slot before now so the current minute is eligible and nothing older is.
|
|
53
|
+
*/
|
|
54
|
+
async function cronWatermark(type, now) {
|
|
55
|
+
const rows = await db
|
|
56
|
+
.select({ latest: max(t.runAt) })
|
|
57
|
+
.from(t)
|
|
58
|
+
.where(eq(t.type, type));
|
|
59
|
+
const latest = rows[0]?.latest;
|
|
60
|
+
return latest == null ? floorSlot(now) - SLOT_MS : Number(latest);
|
|
61
|
+
}
|
|
62
|
+
/** Enqueue a row per due slot. The unique(type, dedupeKey) constraint makes
|
|
63
|
+
* this safe to run concurrently in any number of processes. */
|
|
64
|
+
async function materializeCronSlots(now) {
|
|
65
|
+
for (const [name, def] of Object.entries(defs)) {
|
|
66
|
+
if (def.kind !== 'cron')
|
|
67
|
+
continue;
|
|
68
|
+
const type = `${CRON_PREFIX}${name}`;
|
|
69
|
+
const from = await cronWatermark(type, now);
|
|
70
|
+
const slots = slotsDue({
|
|
71
|
+
cron: parseCron(def.schedule),
|
|
72
|
+
from,
|
|
73
|
+
to: now,
|
|
74
|
+
catchUp: def.catchUp,
|
|
75
|
+
catchUpWindowMs: def.catchUpWindow,
|
|
76
|
+
});
|
|
77
|
+
for (const slot of slots) {
|
|
78
|
+
await enqueueJob(db, defs, name, null, {
|
|
79
|
+
runAt: slot,
|
|
80
|
+
dedupeKey: String(slot),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function fireOnFailed(def, input, error) {
|
|
86
|
+
if (!def.onFailed)
|
|
87
|
+
return;
|
|
88
|
+
try {
|
|
89
|
+
await def.onFailed(input, error, ctx);
|
|
90
|
+
}
|
|
91
|
+
catch (hookErr) {
|
|
92
|
+
console.error('[bunderstack] onFailed hook threw:', hookErr);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** running rows whose lease expired → pending (or failed when exhausted). */
|
|
96
|
+
async function recoverExpiredLeases(now) {
|
|
97
|
+
const expired = await db
|
|
98
|
+
.select({
|
|
99
|
+
id: t.id,
|
|
100
|
+
type: t.type,
|
|
101
|
+
payloadJson: t.payloadJson,
|
|
102
|
+
attempts: t.attempts,
|
|
103
|
+
lastError: t.lastError,
|
|
104
|
+
runAt: t.runAt,
|
|
105
|
+
})
|
|
106
|
+
.from(t)
|
|
107
|
+
.where(and(eq(t.status, 'running'), isNotNull(t.lockedUntil), lt(t.lockedUntil, now)));
|
|
108
|
+
for (const row of expired) {
|
|
109
|
+
const def = definitionFor(defs, row.type);
|
|
110
|
+
const error = new Error('lease expired (worker crashed or timed out)');
|
|
111
|
+
if (!def) {
|
|
112
|
+
await db
|
|
113
|
+
.update(t)
|
|
114
|
+
.set({
|
|
115
|
+
status: 'failed',
|
|
116
|
+
finishedAt: now,
|
|
117
|
+
lockedUntil: null,
|
|
118
|
+
lastError: `unknown job type "${row.type}"`,
|
|
119
|
+
dedupeKey: null,
|
|
120
|
+
})
|
|
121
|
+
.where(eq(t.id, row.id));
|
|
122
|
+
continue;
|
|
123
|
+
}
|
|
124
|
+
if (Number(row.attempts) >= maxAttempts(def)) {
|
|
125
|
+
await db
|
|
126
|
+
.update(t)
|
|
127
|
+
.set({
|
|
128
|
+
status: 'failed',
|
|
129
|
+
finishedAt: now,
|
|
130
|
+
lockedUntil: null,
|
|
131
|
+
lastError: error.message,
|
|
132
|
+
...terminalPatch(),
|
|
133
|
+
})
|
|
134
|
+
.where(eq(t.id, row.id));
|
|
135
|
+
await fireOnFailed(def, resolveInput(def, row), error);
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
await db
|
|
139
|
+
.update(t)
|
|
140
|
+
.set({
|
|
141
|
+
status: 'pending',
|
|
142
|
+
lockedUntil: null,
|
|
143
|
+
runAt: now + backoffMs(def, Number(row.attempts)),
|
|
144
|
+
lastError: error.message,
|
|
145
|
+
})
|
|
146
|
+
.where(eq(t.id, row.id));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async function reapSucceeded(now) {
|
|
151
|
+
await db
|
|
152
|
+
.delete(t)
|
|
153
|
+
.where(and(eq(t.status, 'succeeded'), lt(t.finishedAt, now - SUCCEEDED_RETENTION_MS)));
|
|
154
|
+
}
|
|
155
|
+
/** Atomically claim up to `limit` runnable jobs of one type. */
|
|
156
|
+
async function claim(type, limit, now, leaseUntil) {
|
|
157
|
+
const pendingIds = db
|
|
158
|
+
.select({ id: t.id })
|
|
159
|
+
.from(t)
|
|
160
|
+
.where(and(eq(t.type, type), eq(t.status, 'pending'), lte(t.runAt, now)))
|
|
161
|
+
.orderBy(t.runAt)
|
|
162
|
+
.limit(limit);
|
|
163
|
+
// PG: lock the selected rows so concurrent replicas skip them. SQLite's
|
|
164
|
+
// single-writer model makes the one-statement UPDATE atomic on its own.
|
|
165
|
+
const sub = is(db, PgDatabase)
|
|
166
|
+
? pendingIds.for('update', { skipLocked: true })
|
|
167
|
+
: pendingIds;
|
|
168
|
+
const rows = await db
|
|
169
|
+
.update(t)
|
|
170
|
+
.set({
|
|
171
|
+
status: 'running',
|
|
172
|
+
lockedUntil: leaseUntil,
|
|
173
|
+
attempts: sql `${t.attempts} + 1`,
|
|
174
|
+
})
|
|
175
|
+
.where(and(inArray(t.id, sub), eq(t.status, 'pending')))
|
|
176
|
+
.returning({
|
|
177
|
+
id: t.id,
|
|
178
|
+
type: t.type,
|
|
179
|
+
payloadJson: t.payloadJson,
|
|
180
|
+
attempts: t.attempts,
|
|
181
|
+
runAt: t.runAt,
|
|
182
|
+
});
|
|
183
|
+
return rows;
|
|
184
|
+
}
|
|
185
|
+
// `now` is the tick's injected clock: retry runAt math uses it so tests can
|
|
186
|
+
// drive backoff deterministically. finishedAt uses the real clock (a handler
|
|
187
|
+
// may run long past the tick's start).
|
|
188
|
+
async function runJob(row, def, now, leaseUntil) {
|
|
189
|
+
let input;
|
|
190
|
+
try {
|
|
191
|
+
input = resolveInput(def, row);
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
// Stored payload no longer parses (schema drift): retrying can't help.
|
|
195
|
+
const e = toError(err);
|
|
196
|
+
const updated = await db
|
|
197
|
+
.update(t)
|
|
198
|
+
.set({
|
|
199
|
+
status: 'failed',
|
|
200
|
+
finishedAt: Date.now(),
|
|
201
|
+
lockedUntil: null,
|
|
202
|
+
lastError: e.message,
|
|
203
|
+
...terminalPatch(),
|
|
204
|
+
})
|
|
205
|
+
.where(and(eq(t.id, row.id), eq(t.lockedUntil, leaseUntil)))
|
|
206
|
+
.returning({ id: t.id });
|
|
207
|
+
if (!updated[0])
|
|
208
|
+
return 'lost';
|
|
209
|
+
await fireOnFailed(def, undefined, e);
|
|
210
|
+
return 'failed';
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
await def.handler(input, ctx);
|
|
214
|
+
const updated = await db
|
|
215
|
+
.update(t)
|
|
216
|
+
.set({
|
|
217
|
+
status: 'succeeded',
|
|
218
|
+
finishedAt: Date.now(),
|
|
219
|
+
lockedUntil: null,
|
|
220
|
+
...terminalPatch(),
|
|
221
|
+
})
|
|
222
|
+
.where(and(eq(t.id, row.id), eq(t.lockedUntil, leaseUntil)))
|
|
223
|
+
.returning({ id: t.id });
|
|
224
|
+
if (!updated[0])
|
|
225
|
+
return 'lost';
|
|
226
|
+
return 'ran';
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
const e = toError(err);
|
|
230
|
+
if (Number(row.attempts) < maxAttempts(def)) {
|
|
231
|
+
const updated = await db
|
|
232
|
+
.update(t)
|
|
233
|
+
.set({
|
|
234
|
+
status: 'pending',
|
|
235
|
+
lockedUntil: null,
|
|
236
|
+
runAt: now + backoffMs(def, Number(row.attempts)),
|
|
237
|
+
lastError: e.message,
|
|
238
|
+
})
|
|
239
|
+
.where(and(eq(t.id, row.id), eq(t.lockedUntil, leaseUntil)))
|
|
240
|
+
.returning({ id: t.id });
|
|
241
|
+
if (!updated[0])
|
|
242
|
+
return 'lost';
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
const updated = await db
|
|
246
|
+
.update(t)
|
|
247
|
+
.set({
|
|
248
|
+
status: 'failed',
|
|
249
|
+
finishedAt: Date.now(),
|
|
250
|
+
lockedUntil: null,
|
|
251
|
+
lastError: e.message,
|
|
252
|
+
...terminalPatch(),
|
|
253
|
+
})
|
|
254
|
+
.where(and(eq(t.id, row.id), eq(t.lockedUntil, leaseUntil)))
|
|
255
|
+
.returning({ id: t.id });
|
|
256
|
+
if (!updated[0])
|
|
257
|
+
return 'lost';
|
|
258
|
+
await fireOnFailed(def, input, e);
|
|
259
|
+
}
|
|
260
|
+
return 'failed';
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
async function runClaimable(now) {
|
|
264
|
+
const work = [];
|
|
265
|
+
let totalClaimed = 0;
|
|
266
|
+
for (const [name, def] of Object.entries(defs)) {
|
|
267
|
+
const type = def.kind === 'cron' ? `${CRON_PREFIX}${name}` : name;
|
|
268
|
+
let limit = CLAIM_BATCH;
|
|
269
|
+
if (def.kind === 'job' && def.concurrency !== undefined) {
|
|
270
|
+
const runningRows = await db
|
|
271
|
+
.select({ id: t.id })
|
|
272
|
+
.from(t)
|
|
273
|
+
.where(and(eq(t.type, type), eq(t.status, 'running')));
|
|
274
|
+
const capacity = def.concurrency - runningRows.length;
|
|
275
|
+
if (capacity <= 0)
|
|
276
|
+
continue;
|
|
277
|
+
limit = Math.min(limit, capacity);
|
|
278
|
+
}
|
|
279
|
+
const leaseUntil = now + (def.timeout ?? DEFAULT_TIMEOUT_MS);
|
|
280
|
+
const claimed = await claim(type, limit, now, leaseUntil);
|
|
281
|
+
totalClaimed += claimed.length;
|
|
282
|
+
for (const row of claimed)
|
|
283
|
+
work.push(runJob(row, def, now, leaseUntil));
|
|
284
|
+
}
|
|
285
|
+
const outcomes = await Promise.all(work);
|
|
286
|
+
let ran = 0;
|
|
287
|
+
let failed = 0;
|
|
288
|
+
for (const outcome of outcomes) {
|
|
289
|
+
if (outcome === 'ran')
|
|
290
|
+
ran++;
|
|
291
|
+
else if (outcome === 'failed')
|
|
292
|
+
failed++;
|
|
293
|
+
}
|
|
294
|
+
return { claimed: totalClaimed, ran, failed };
|
|
295
|
+
}
|
|
296
|
+
return {
|
|
297
|
+
async tick(now = Date.now()) {
|
|
298
|
+
await materializeCronSlots(now);
|
|
299
|
+
await recoverExpiredLeases(now);
|
|
300
|
+
if (now - lastReapAt >= REAP_INTERVAL_MS) {
|
|
301
|
+
lastReapAt = now;
|
|
302
|
+
await reapSucceeded(now);
|
|
303
|
+
}
|
|
304
|
+
return runClaimable(now);
|
|
305
|
+
},
|
|
306
|
+
setJobsFacade(f) {
|
|
307
|
+
ctx.jobs = f;
|
|
308
|
+
},
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
//# sourceMappingURL=worker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../src/jobs/worker.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,+EAA+E;AAC/E,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,aAAa,CAAA;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAA;AAUhD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAClC,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AACzE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AAEnE,MAAM,WAAW,GAAG,EAAE,CAAA;AACtB,MAAM,sBAAsB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAClD,MAAM,gBAAgB,GAAG,EAAE,GAAG,MAAM,CAAA;AAUpC,SAAS,OAAO,CAAC,GAAY;IAC3B,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAA;AAC5D,CAAC;AAED,SAAS,WAAW,CAAC,GAA4B;IAC/C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,eAAe,CAAC,CAAA;AAC7C,CAAC;AAED;mEACmE;AACnE,SAAS,aAAa,CACpB,IAAc,EACd,IAAY;IAEZ,IAAI,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAA;QAChD,OAAO,GAAG,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAA;IAC/C,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAA;IACtB,OAAO,GAAG,EAAE,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAA;AAC9C,CAAC;AAED,oDAAoD;AACpD,SAAS,aAAa;IACpB,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAA;AAC5B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAK/B;IACC,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,IAAI,CAAA;IACzB,MAAM,CAAC,GAAG,YAAY,CAAC,EAAE,CAAC,CAAA;IAC1B,MAAM,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,EAA6B,CAAA;IACtD,IAAI,UAAU,GAAG,CAAC,CAAA;IAElB,2EAA2E;IAC3E,SAAS,YAAY,CAAC,GAA4B,EAAE,GAAW;QAC7D,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxB,OAAO,EAAE,YAAY,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAA;QACtD,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACvC,OAAO,GAAG,CAAC,KAAK;YACd,CAAC,CAAC,sBAAsB,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,EAAE,aAAa,CAAC;YACvD,CAAC,CAAC,SAAS,CAAA;IACf,CAAC;IAED;;;;OAIG;IACH,KAAK,UAAU,aAAa,CAAC,IAAY,EAAE,GAAW;QACpD,MAAM,IAAI,GAAG,MAAM,EAAE;aAClB,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;aAChC,IAAI,CAAC,CAAC,CAAC;aACP,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAA;QAC9B,OAAO,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACnE,CAAC;IAED;oEACgE;IAChE,KAAK,UAAU,oBAAoB,CAAC,GAAW;QAC7C,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM;gBAAE,SAAQ;YACjC,MAAM,IAAI,GAAG,GAAG,WAAW,GAAG,IAAI,EAAE,CAAA;YACpC,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC;gBACrB,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC;gBAC7B,IAAI;gBACJ,EAAE,EAAE,GAAG;gBACP,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,eAAe,EAAE,GAAG,CAAC,aAAa;aACnC,CAAC,CAAA;YACF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE;oBACrC,KAAK,EAAE,IAAI;oBACX,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC;iBACxB,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,UAAU,YAAY,CACzB,GAA4B,EAC5B,KAAc,EACd,KAAY;QAEZ,IAAI,CAAC,GAAG,CAAC,QAAQ;YAAE,OAAM;QACzB,IAAI,CAAC;YACH,MAAO,GAAG,CAAC,QAA0D,CACnE,KAAK,EACL,KAAK,EACL,GAAG,CACJ,CAAA;QACH,CAAC;QAAC,OAAO,OAAO,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,OAAO,CAAC,CAAA;QAC9D,CAAC;IACH,CAAC;IAED,6EAA6E;IAC7E,KAAK,UAAU,oBAAoB,CAAC,GAAW;QAC7C,MAAM,OAAO,GAA8C,MAAM,EAAE;aAChE,MAAM,CAAC;YACN,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,KAAK,EAAE,CAAC,CAAC,KAAK;SACf,CAAC;aACD,IAAI,CAAC,CAAC,CAAC;aACP,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,EACvB,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,EACxB,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CACvB,CACF,CAAA;QACH,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,CAAA;YACzC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAA;YACtE,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,MAAM,EAAE;qBACL,MAAM,CAAC,CAAC,CAAC;qBACT,GAAG,CAAC;oBACH,MAAM,EAAE,QAAQ;oBAChB,UAAU,EAAE,GAAG;oBACf,WAAW,EAAE,IAAI;oBACjB,SAAS,EAAE,qBAAqB,GAAG,CAAC,IAAI,GAAG;oBAC3C,SAAS,EAAE,IAAI;iBAChB,CAAC;qBACD,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC1B,SAAQ;YACV,CAAC;YACD,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC7C,MAAM,EAAE;qBACL,MAAM,CAAC,CAAC,CAAC;qBACT,GAAG,CAAC;oBACH,MAAM,EAAE,QAAQ;oBAChB,UAAU,EAAE,GAAG;oBACf,WAAW,EAAE,IAAI;oBACjB,SAAS,EAAE,KAAK,CAAC,OAAO;oBACxB,GAAG,aAAa,EAAE;iBACnB,CAAC;qBACD,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;gBAC1B,MAAM,YAAY,CAAC,GAAG,EAAE,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,KAAK,CAAC,CAAA;YACxD,CAAC;iBAAM,CAAC;gBACN,MAAM,EAAE;qBACL,MAAM,CAAC,CAAC,CAAC;qBACT,GAAG,CAAC;oBACH,MAAM,EAAE,SAAS;oBACjB,WAAW,EAAE,IAAI;oBACjB,KAAK,EAAE,GAAG,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACjD,SAAS,EAAE,KAAK,CAAC,OAAO;iBACzB,CAAC;qBACD,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;YAC5B,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,UAAU,aAAa,CAAC,GAAW;QACtC,MAAM,EAAE;aACL,MAAM,CAAC,CAAC,CAAC;aACT,KAAK,CACJ,GAAG,CACD,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,EACzB,EAAE,CAAC,CAAC,CAAC,UAAU,EAAE,GAAG,GAAG,sBAAsB,CAAC,CAC/C,CACF,CAAA;IACL,CAAC;IAED,gEAAgE;IAChE,KAAK,UAAU,KAAK,CAClB,IAAY,EACZ,KAAa,EACb,GAAW,EACX,UAAkB;QAElB,MAAM,UAAU,GAAG,EAAE;aAClB,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;aACpB,IAAI,CAAC,CAAC,CAAC;aACP,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;aACxE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;aAChB,KAAK,CAAC,KAAK,CAAC,CAAA;QACf,wEAAwE;QACxE,wEAAwE;QACxE,MAAM,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,UAAU,CAAC;YAC5B,CAAC,CACG,UAGD,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;YACvC,CAAC,CAAC,UAAU,CAAA;QACd,MAAM,IAAI,GAAa,MAAM,EAAE;aAC5B,MAAM,CAAC,CAAC,CAAC;aACT,GAAG,CAAC;YACH,MAAM,EAAE,SAAS;YACjB,WAAW,EAAE,UAAU;YACvB,QAAQ,EAAE,GAAG,CAAA,GAAG,CAAC,CAAC,QAAQ,MAAM;SACjC,CAAC;aACD,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;aACvD,SAAS,CAAC;YACT,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,KAAK,EAAE,CAAC,CAAC,KAAK;SACf,CAAC,CAAA;QACJ,OAAO,IAAI,CAAA;IACb,CAAC;IAED,4EAA4E;IAC5E,6EAA6E;IAC7E,uCAAuC;IACvC,KAAK,UAAU,MAAM,CACnB,GAAW,EACX,GAA4B,EAC5B,GAAW,EACX,UAAkB;QAElB,IAAI,KAAc,CAAA;QAClB,IAAI,CAAC;YACH,KAAK,GAAG,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;QAChC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,uEAAuE;YACvE,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;YACtB,MAAM,OAAO,GAAG,MAAM,EAAE;iBACrB,MAAM,CAAC,CAAC,CAAC;iBACT,GAAG,CAAC;gBACH,MAAM,EAAE,QAAQ;gBAChB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;gBACtB,WAAW,EAAE,IAAI;gBACjB,SAAS,EAAE,CAAC,CAAC,OAAO;gBACpB,GAAG,aAAa,EAAE;aACnB,CAAC;iBACD,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;iBAC3D,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YAC1B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;gBAAE,OAAO,MAAM,CAAA;YAC9B,MAAM,YAAY,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,CAAA;YACrC,OAAO,QAAQ,CAAA;QACjB,CAAC;QACD,IAAI,CAAC;YACH,MAAO,GAAG,CAAC,OAA+C,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YACtE,MAAM,OAAO,GAAG,MAAM,EAAE;iBACrB,MAAM,CAAC,CAAC,CAAC;iBACT,GAAG,CAAC;gBACH,MAAM,EAAE,WAAW;gBACnB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;gBACtB,WAAW,EAAE,IAAI;gBACjB,GAAG,aAAa,EAAE;aACnB,CAAC;iBACD,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;iBAC3D,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;YAC1B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;gBAAE,OAAO,MAAM,CAAA;YAC9B,OAAO,KAAK,CAAA;QACd,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAA;YACtB,IAAI,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC5C,MAAM,OAAO,GAAG,MAAM,EAAE;qBACrB,MAAM,CAAC,CAAC,CAAC;qBACT,GAAG,CAAC;oBACH,MAAM,EAAE,SAAS;oBACjB,WAAW,EAAE,IAAI;oBACjB,KAAK,EAAE,GAAG,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;oBACjD,SAAS,EAAE,CAAC,CAAC,OAAO;iBACrB,CAAC;qBACD,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;qBAC3D,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;gBAC1B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;oBAAE,OAAO,MAAM,CAAA;YAChC,CAAC;iBAAM,CAAC;gBACN,MAAM,OAAO,GAAG,MAAM,EAAE;qBACrB,MAAM,CAAC,CAAC,CAAC;qBACT,GAAG,CAAC;oBACH,MAAM,EAAE,QAAQ;oBAChB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE;oBACtB,WAAW,EAAE,IAAI;oBACjB,SAAS,EAAE,CAAC,CAAC,OAAO;oBACpB,GAAG,aAAa,EAAE;iBACnB,CAAC;qBACD,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;qBAC3D,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;gBAC1B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;oBAAE,OAAO,MAAM,CAAA;gBAC9B,MAAM,YAAY,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;YACnC,CAAC;YACD,OAAO,QAAQ,CAAA;QACjB,CAAC;IACH,CAAC;IAED,KAAK,UAAU,YAAY,CAAC,GAAW;QACrC,MAAM,IAAI,GAAyC,EAAE,CAAA;QACrD,IAAI,YAAY,GAAG,CAAC,CAAA;QACpB,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,WAAW,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;YACjE,IAAI,KAAK,GAAG,WAAW,CAAA;YACvB,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK,IAAI,GAAG,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;gBACxD,MAAM,WAAW,GAAG,MAAM,EAAE;qBACzB,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC;qBACpB,IAAI,CAAC,CAAC,CAAC;qBACP,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC,CAAA;gBACxD,MAAM,QAAQ,GAAG,GAAG,CAAC,WAAW,GAAG,WAAW,CAAC,MAAM,CAAA;gBACrD,IAAI,QAAQ,IAAI,CAAC;oBAAE,SAAQ;gBAC3B,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;YACnC,CAAC;YACD,MAAM,UAAU,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,kBAAkB,CAAC,CAAA;YAC5D,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,UAAU,CAAC,CAAA;YACzD,YAAY,IAAI,OAAO,CAAC,MAAM,CAAA;YAC9B,KAAK,MAAM,GAAG,IAAI,OAAO;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAA;QACzE,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;QACxC,IAAI,GAAG,GAAG,CAAC,CAAA;QACX,IAAI,MAAM,GAAG,CAAC,CAAA;QACd,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,OAAO,KAAK,KAAK;gBAAE,GAAG,EAAE,CAAA;iBACvB,IAAI,OAAO,KAAK,QAAQ;gBAAE,MAAM,EAAE,CAAA;QACzC,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,CAAA;IAC/C,CAAC;IAED,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,MAAc,IAAI,CAAC,GAAG,EAAE;YACjC,MAAM,oBAAoB,CAAC,GAAG,CAAC,CAAA;YAC/B,MAAM,oBAAoB,CAAC,GAAG,CAAC,CAAA;YAC/B,IAAI,GAAG,GAAG,UAAU,IAAI,gBAAgB,EAAE,CAAC;gBACzC,UAAU,GAAG,GAAG,CAAA;gBAChB,MAAM,aAAa,CAAC,GAAG,CAAC,CAAA;YAC1B,CAAC;YACD,OAAO,YAAY,CAAC,GAAG,CAAC,CAAA;QAC1B,CAAC;QACD,aAAa,CAAC,CAAoB;YAChC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAA;QACd,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export type Cleanup = () => void | Promise<void>;
|
|
2
|
+
export type LifecycleStatus = 'ready' | 'closing' | 'closed';
|
|
3
|
+
export declare class Lifecycle {
|
|
4
|
+
#private;
|
|
5
|
+
get signal(): AbortSignal;
|
|
6
|
+
get status(): LifecycleStatus;
|
|
7
|
+
add(cleanup: Cleanup): () => void;
|
|
8
|
+
close(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAChD,MAAM,MAAM,eAAe,GAAG,OAAO,GAAG,SAAS,GAAG,QAAQ,CAAA;AAE5D,qBAAa,SAAS;;IAMpB,IAAI,MAAM,IAAI,WAAW,CAExB;IAED,IAAI,MAAM,IAAI,eAAe,CAE5B;IAED,GAAG,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,IAAI;IAQjC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAuBvB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export class Lifecycle {
|
|
2
|
+
#controller = new AbortController();
|
|
3
|
+
#status = 'ready';
|
|
4
|
+
#cleanups = new Set();
|
|
5
|
+
#closePromise;
|
|
6
|
+
get signal() {
|
|
7
|
+
return this.#controller.signal;
|
|
8
|
+
}
|
|
9
|
+
get status() {
|
|
10
|
+
return this.#status;
|
|
11
|
+
}
|
|
12
|
+
add(cleanup) {
|
|
13
|
+
if (this.#status !== 'ready') {
|
|
14
|
+
throw new Error('[bunderstack] application lifecycle is closed');
|
|
15
|
+
}
|
|
16
|
+
this.#cleanups.add(cleanup);
|
|
17
|
+
return () => this.#cleanups.delete(cleanup);
|
|
18
|
+
}
|
|
19
|
+
close() {
|
|
20
|
+
if (this.#closePromise)
|
|
21
|
+
return this.#closePromise;
|
|
22
|
+
this.#status = 'closing';
|
|
23
|
+
this.#controller.abort();
|
|
24
|
+
this.#closePromise = (async () => {
|
|
25
|
+
const cleanups = [...this.#cleanups].reverse();
|
|
26
|
+
this.#cleanups.clear();
|
|
27
|
+
const results = await Promise.allSettled(cleanups.map(async (cleanup) => cleanup()));
|
|
28
|
+
this.#status = 'closed';
|
|
29
|
+
const errors = results.flatMap((result) => result.status === 'rejected' ? [result.reason] : []);
|
|
30
|
+
if (errors.length > 0) {
|
|
31
|
+
throw new AggregateError(errors, '[bunderstack] lifecycle cleanup failed');
|
|
32
|
+
}
|
|
33
|
+
})();
|
|
34
|
+
return this.#closePromise;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.js","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AAGA,MAAM,OAAO,SAAS;IACpB,WAAW,GAAG,IAAI,eAAe,EAAE,CAAA;IACnC,OAAO,GAAoB,OAAO,CAAA;IAClC,SAAS,GAAG,IAAI,GAAG,EAAW,CAAA;IAC9B,aAAa,CAA2B;IAExC,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAA;IAChC,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,OAAO,CAAA;IACrB,CAAC;IAED,GAAG,CAAC,OAAgB;QAClB,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAA;QAClE,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;QAC3B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC7C,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,aAAa;YAAE,OAAO,IAAI,CAAC,aAAa,CAAA;QACjD,IAAI,CAAC,OAAO,GAAG,SAAS,CAAA;QACxB,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAA;QACxB,IAAI,CAAC,aAAa,GAAG,CAAC,KAAK,IAAI,EAAE;YAC/B,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAA;YAC9C,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAA;YACtB,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACtC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,CAC3C,CAAA;YACD,IAAI,CAAC,OAAO,GAAG,QAAQ,CAAA;YACvB,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,CACxC,MAAM,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CACpD,CAAA;YACD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,cAAc,CACtB,MAAM,EACN,wCAAwC,CACzC,CAAA;YACH,CAAC;QACH,CAAC,CAAC,EAAE,CAAA;QACJ,OAAO,IAAI,CAAC,aAAa,CAAA;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { getTableColumns, type SQL } from 'drizzle-orm';
|
|
2
|
+
import type { ResolvedTableAccess, SortOrder } from './access.js';
|
|
3
|
+
import type { AnyDb } from './dialect.js';
|
|
4
|
+
/** Caps both `?limit=` and the number of values in an `IN` filter. */
|
|
5
|
+
export declare const MAX_LIST_LIMIT = 200;
|
|
6
|
+
/** Default page size when a request omits `limit`. */
|
|
7
|
+
export declare const DEFAULT_LIST_LIMIT = 20;
|
|
8
|
+
/**
|
|
9
|
+
* What a list procedure accepts. Shape and column types are enforced by the
|
|
10
|
+
* generated input schema, so by the time these params arrive they are already
|
|
11
|
+
* validated and coerced — this module only applies policy (defaults, the limit
|
|
12
|
+
* cap, cursor rules).
|
|
13
|
+
*/
|
|
14
|
+
export type ListParamsInput = {
|
|
15
|
+
limit?: number;
|
|
16
|
+
offset?: number;
|
|
17
|
+
cursor?: string;
|
|
18
|
+
sort?: string;
|
|
19
|
+
order?: SortOrder;
|
|
20
|
+
q?: string;
|
|
21
|
+
count?: boolean;
|
|
22
|
+
filters?: Record<string, unknown>;
|
|
23
|
+
};
|
|
24
|
+
export type ParsedListParams = {
|
|
25
|
+
limit: number;
|
|
26
|
+
offset?: number;
|
|
27
|
+
sort: string;
|
|
28
|
+
order: SortOrder;
|
|
29
|
+
q: string;
|
|
30
|
+
cursor?: string;
|
|
31
|
+
count: boolean;
|
|
32
|
+
filters: Record<string, unknown>;
|
|
33
|
+
};
|
|
34
|
+
export type ListResult<T> = {
|
|
35
|
+
items: T[];
|
|
36
|
+
limit: number;
|
|
37
|
+
offset?: number;
|
|
38
|
+
cursor?: string;
|
|
39
|
+
nextCursor?: string;
|
|
40
|
+
hasMore: boolean;
|
|
41
|
+
total?: number;
|
|
42
|
+
q?: string;
|
|
43
|
+
sort: string;
|
|
44
|
+
order: SortOrder;
|
|
45
|
+
};
|
|
46
|
+
type CursorPayload = {
|
|
47
|
+
sort: string;
|
|
48
|
+
order: SortOrder;
|
|
49
|
+
v: string | number | null;
|
|
50
|
+
id: string | number;
|
|
51
|
+
};
|
|
52
|
+
/**
|
|
53
|
+
* Applies list policy to already-validated input: defaults, the limit cap, and
|
|
54
|
+
* the rules a schema cannot express (cursor excludes offset, and a cursor must
|
|
55
|
+
* agree with the sort it was minted for).
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveListParams(input: ListParamsInput, access: ResolvedTableAccess): ParsedListParams;
|
|
58
|
+
export declare function encodeCursor(payload: CursorPayload): string;
|
|
59
|
+
export declare function decodeCursor(cursor: string): CursorPayload;
|
|
60
|
+
export declare function executeList<T extends Record<string, unknown>>(db: AnyDb, table: Parameters<typeof getTableColumns>[0], access: ResolvedTableAccess, params: ParsedListParams, idCol: unknown, scopeWhere?: SQL): Promise<ListResult<T>>;
|
|
61
|
+
export {};
|
|
62
|
+
//# sourceMappingURL=list-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-query.d.ts","sourceRoot":"","sources":["../src/list-query.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,eAAe,EASf,KAAK,GAAG,EACT,MAAM,aAAa,CAAA;AAGpB,OAAO,KAAK,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,WAAW,CAAA;AAItC,sEAAsE;AACtE,eAAO,MAAM,cAAc,MAAM,CAAA;AAEjC,sDAAsD;AACtD,eAAO,MAAM,kBAAkB,KAAK,CAAA;AAEpC;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,SAAS,CAAA;IAChB,CAAC,EAAE,MAAM,CAAA;IACT,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,OAAO,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI;IAC1B,KAAK,EAAE,CAAC,EAAE,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,SAAS,CAAA;IAChB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;IACzB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;CACpB,CAAA;AAkBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,eAAe,EACtB,MAAM,EAAE,mBAAmB,GAC1B,gBAAgB,CA6BlB;AAiED,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,CAE3D;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CAU1D;AAqCD,wBAAsB,WAAW,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjE,EAAE,EAAE,KAAK,EACT,KAAK,EAAE,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,EAC5C,MAAM,EAAE,mBAAmB,EAC3B,MAAM,EAAE,gBAAgB,EACxB,KAAK,EAAE,OAAO,EACd,UAAU,CAAC,EAAE,GAAG,GACf,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CA+ExB"}
|