bunderstack 0.17.0-beta.2 → 0.17.0-beta.3
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 +227 -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 +76 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +81 -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 +477 -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 @@
|
|
|
1
|
+
{"version":3,"file":"internal-tables.d.ts","sourceRoot":"","sources":["../src/internal-tables.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { getTableName, is, isTable } from 'drizzle-orm';
|
|
2
|
+
import { PgDatabase } from 'drizzle-orm/pg-core';
|
|
3
|
+
import { index, integer, primaryKey, sqliteTable, text, uniqueIndex, } from 'drizzle-orm/sqlite-core';
|
|
4
|
+
import { detectDialect } from './dialect.js';
|
|
5
|
+
import { bunderstackFilesPg, bunderstackIdempotencyPg, bunderstackJobsPg, } from './internal-tables-pg.js';
|
|
6
|
+
export const bunderstackFiles = sqliteTable('bunderstack_file_meta', {
|
|
7
|
+
fileId: text('file_id').primaryKey(),
|
|
8
|
+
bucket: text('bucket').notNull(),
|
|
9
|
+
ownerId: text('owner_id'),
|
|
10
|
+
scopeJson: text('scope_json'),
|
|
11
|
+
status: text('status').notNull(),
|
|
12
|
+
filename: text('filename'),
|
|
13
|
+
contentType: text('content_type'),
|
|
14
|
+
size: integer('size'),
|
|
15
|
+
createdAt: integer('created_at').notNull(),
|
|
16
|
+
confirmedAt: integer('confirmed_at'),
|
|
17
|
+
}, (t) => [
|
|
18
|
+
index('bfm_owner').on(t.ownerId),
|
|
19
|
+
index('bfm_scope').on(t.bucket, t.scopeJson),
|
|
20
|
+
index('bfm_sweep').on(t.status, t.createdAt),
|
|
21
|
+
]);
|
|
22
|
+
export const bunderstackIdempotency = sqliteTable('_bunderstack_idempotency', {
|
|
23
|
+
key: text('key').notNull(),
|
|
24
|
+
tableName: text('table_name').notNull(),
|
|
25
|
+
bodyHash: text('body_hash').notNull(),
|
|
26
|
+
status: integer('status').notNull(),
|
|
27
|
+
response: text('response').notNull(),
|
|
28
|
+
expiresAt: integer('expires_at').notNull(),
|
|
29
|
+
}, (t) => [primaryKey({ columns: [t.key, t.tableName] })]);
|
|
30
|
+
export const bunderstackJobs = sqliteTable('_bunderstack_jobs', {
|
|
31
|
+
id: text('id').primaryKey(),
|
|
32
|
+
type: text('type').notNull(),
|
|
33
|
+
payloadJson: text('payload_json').notNull(),
|
|
34
|
+
status: text('status').notNull(), // pending | running | succeeded | failed
|
|
35
|
+
attempts: integer('attempts').notNull().default(0),
|
|
36
|
+
runAt: integer('run_at').notNull(),
|
|
37
|
+
lockedUntil: integer('locked_until'),
|
|
38
|
+
dedupeKey: text('dedupe_key'),
|
|
39
|
+
lastError: text('last_error'),
|
|
40
|
+
createdAt: integer('created_at').notNull(),
|
|
41
|
+
finishedAt: integer('finished_at'),
|
|
42
|
+
}, (t) => [
|
|
43
|
+
index('bjq_claim').on(t.status, t.runAt),
|
|
44
|
+
index('bjq_type_status').on(t.type, t.status),
|
|
45
|
+
// NULL dedupe keys are distinct in both dialects, so keyless jobs never collide.
|
|
46
|
+
uniqueIndex('bjq_dedupe').on(t.type, t.dedupeKey),
|
|
47
|
+
]);
|
|
48
|
+
export const INTERNAL_TABLES = {
|
|
49
|
+
bunderstackFiles,
|
|
50
|
+
bunderstackIdempotency,
|
|
51
|
+
bunderstackJobs,
|
|
52
|
+
};
|
|
53
|
+
export const INTERNAL_TABLE_NAMES = new Set([
|
|
54
|
+
'bunderstack_file_meta',
|
|
55
|
+
'_bunderstack_idempotency',
|
|
56
|
+
'_bunderstack_jobs',
|
|
57
|
+
]);
|
|
58
|
+
export const INTERNAL_TABLES_PG = {
|
|
59
|
+
bunderstackFiles: bunderstackFilesPg,
|
|
60
|
+
bunderstackIdempotency: bunderstackIdempotencyPg,
|
|
61
|
+
bunderstackJobs: bunderstackJobsPg,
|
|
62
|
+
};
|
|
63
|
+
// Both dialect twins count as "ours" for the re-export identity check.
|
|
64
|
+
const INTERNAL_TABLE_CANDIDATES = new Map([
|
|
65
|
+
[getTableName(bunderstackFiles), [bunderstackFiles, bunderstackFilesPg]],
|
|
66
|
+
[
|
|
67
|
+
getTableName(bunderstackIdempotency),
|
|
68
|
+
[bunderstackIdempotency, bunderstackIdempotencyPg],
|
|
69
|
+
],
|
|
70
|
+
[getTableName(bunderstackJobs), [bunderstackJobs, bunderstackJobsPg]],
|
|
71
|
+
]);
|
|
72
|
+
/** Internal file-meta table matching the db's dialect. */
|
|
73
|
+
export function filesTableFor(db) {
|
|
74
|
+
return is(db, PgDatabase) ? bunderstackFilesPg : bunderstackFiles;
|
|
75
|
+
}
|
|
76
|
+
/** Internal idempotency table matching the db's dialect. */
|
|
77
|
+
export function idempotencyTableFor(db) {
|
|
78
|
+
return is(db, PgDatabase) ? bunderstackIdempotencyPg : bunderstackIdempotency;
|
|
79
|
+
}
|
|
80
|
+
/** Internal jobs table matching the db's dialect. */
|
|
81
|
+
export function jobsTableFor(db) {
|
|
82
|
+
return is(db, PgDatabase) ? bunderstackJobsPg : bunderstackJobs;
|
|
83
|
+
}
|
|
84
|
+
export function withInternalTables(schema) {
|
|
85
|
+
const merged = { ...schema };
|
|
86
|
+
for (const value of Object.values(schema)) {
|
|
87
|
+
if (!isTable(value))
|
|
88
|
+
continue;
|
|
89
|
+
const name = getTableName(value);
|
|
90
|
+
if (!INTERNAL_TABLE_NAMES.has(name))
|
|
91
|
+
continue;
|
|
92
|
+
const candidates = INTERNAL_TABLE_CANDIDATES.get(name);
|
|
93
|
+
if (candidates?.includes(value)) {
|
|
94
|
+
// Re-exported from bunderstack/schema(-pg) — already in user schema.
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
throw new Error(`[bunderstack] table name "${name}" is reserved by bunderstack`);
|
|
98
|
+
}
|
|
99
|
+
const internal = detectDialect(schema) === 'pg' ? INTERNAL_TABLES_PG : INTERNAL_TABLES;
|
|
100
|
+
for (const [key, table] of Object.entries(internal)) {
|
|
101
|
+
if (!(key in merged)) {
|
|
102
|
+
;
|
|
103
|
+
merged[key] = table;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return merged;
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=internal-tables.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"internal-tables.js","sourceRoot":"","sources":["../src/internal-tables.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type CronField = {
|
|
2
|
+
any: boolean;
|
|
3
|
+
values: ReadonlySet<number>;
|
|
4
|
+
};
|
|
5
|
+
export type ParsedCron = {
|
|
6
|
+
minute: CronField;
|
|
7
|
+
hour: CronField;
|
|
8
|
+
dayOfMonth: CronField;
|
|
9
|
+
month: CronField;
|
|
10
|
+
dayOfWeek: CronField;
|
|
11
|
+
};
|
|
12
|
+
export declare function parseCron(expr: string): ParsedCron;
|
|
13
|
+
/** Whether the minute containing `epochMs` matches, evaluated in UTC. */
|
|
14
|
+
export declare function cronMatches(cron: ParsedCron, epochMs: number): boolean;
|
|
15
|
+
//# sourceMappingURL=cron.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.d.ts","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,SAAS,GAAG;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;CAAE,CAAA;AAErE,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,SAAS,CAAA;IACjB,IAAI,EAAE,SAAS,CAAA;IACf,UAAU,EAAE,SAAS,CAAA;IACrB,KAAK,EAAE,SAAS,CAAA;IAChB,SAAS,EAAE,SAAS,CAAA;CACrB,CAAA;AAsCD,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAkBlD;AAMD,yEAAyE;AACzE,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAWtE"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// src/jobs/cron.ts — minimal 5-field cron parser, UTC, minute granularity.
|
|
2
|
+
// Supports: * , lists (a,b) , ranges (a-b) , steps (*/n, a-b/n, a/n). No
|
|
3
|
+
// month/day names, no seconds field, no @-shortcuts — YAGNI for v1.
|
|
4
|
+
const PART_RE = /^(\*|\d+(?:-\d+)?)(?:\/(\d+))?$/;
|
|
5
|
+
function parseField(spec, min, max, expr) {
|
|
6
|
+
if (spec === '*')
|
|
7
|
+
return { any: true, values: new Set() };
|
|
8
|
+
const values = new Set();
|
|
9
|
+
for (const part of spec.split(',')) {
|
|
10
|
+
const m = PART_RE.exec(part);
|
|
11
|
+
if (!m)
|
|
12
|
+
throw new Error(`[bunderstack] invalid cron "${expr}": "${part}"`);
|
|
13
|
+
const step = m[2] !== undefined ? Number(m[2]) : 1;
|
|
14
|
+
let lo;
|
|
15
|
+
let hi;
|
|
16
|
+
if (m[1] === '*') {
|
|
17
|
+
lo = min;
|
|
18
|
+
hi = max;
|
|
19
|
+
}
|
|
20
|
+
else if (m[1].includes('-')) {
|
|
21
|
+
const [a, b] = m[1].split('-');
|
|
22
|
+
lo = Number(a);
|
|
23
|
+
hi = Number(b);
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
lo = Number(m[1]);
|
|
27
|
+
// "5/15" means "starting at 5, every 15" per cron convention.
|
|
28
|
+
hi = step > 1 ? max : lo;
|
|
29
|
+
}
|
|
30
|
+
if (step < 1 || lo < min || hi > max || lo > hi) {
|
|
31
|
+
throw new Error(`[bunderstack] invalid cron "${expr}": "${part}"`);
|
|
32
|
+
}
|
|
33
|
+
for (let v = lo; v <= hi; v += step)
|
|
34
|
+
values.add(v);
|
|
35
|
+
}
|
|
36
|
+
return { any: false, values };
|
|
37
|
+
}
|
|
38
|
+
export function parseCron(expr) {
|
|
39
|
+
const parts = expr.trim().split(/\s+/);
|
|
40
|
+
if (parts.length !== 5) {
|
|
41
|
+
throw new Error(`[bunderstack] invalid cron "${expr}": expected 5 fields (minute hour day-of-month month day-of-week)`);
|
|
42
|
+
}
|
|
43
|
+
const dow = parseField(parts[4], 0, 7, expr);
|
|
44
|
+
return {
|
|
45
|
+
minute: parseField(parts[0], 0, 59, expr),
|
|
46
|
+
hour: parseField(parts[1], 0, 23, expr),
|
|
47
|
+
dayOfMonth: parseField(parts[2], 1, 31, expr),
|
|
48
|
+
month: parseField(parts[3], 1, 12, expr),
|
|
49
|
+
// 7 is an alias for Sunday (0).
|
|
50
|
+
dayOfWeek: dow.any
|
|
51
|
+
? dow
|
|
52
|
+
: { any: false, values: new Set([...dow.values].map((v) => v % 7)) },
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function inField(field, value) {
|
|
56
|
+
return field.any || field.values.has(value);
|
|
57
|
+
}
|
|
58
|
+
/** Whether the minute containing `epochMs` matches, evaluated in UTC. */
|
|
59
|
+
export function cronMatches(cron, epochMs) {
|
|
60
|
+
const d = new Date(epochMs);
|
|
61
|
+
if (!inField(cron.minute, d.getUTCMinutes()))
|
|
62
|
+
return false;
|
|
63
|
+
if (!inField(cron.hour, d.getUTCHours()))
|
|
64
|
+
return false;
|
|
65
|
+
if (!inField(cron.month, d.getUTCMonth() + 1))
|
|
66
|
+
return false;
|
|
67
|
+
const domOk = inField(cron.dayOfMonth, d.getUTCDate());
|
|
68
|
+
const dowOk = inField(cron.dayOfWeek, d.getUTCDay());
|
|
69
|
+
// Standard cron rule: when BOTH day fields are restricted, either may match.
|
|
70
|
+
return !cron.dayOfMonth.any && !cron.dayOfWeek.any
|
|
71
|
+
? domOk || dowOk
|
|
72
|
+
: domOk && dowOk;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=cron.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cron.js","sourceRoot":"","sources":["../../src/jobs/cron.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec';
|
|
2
|
+
import type { DbFor } from '../db.js';
|
|
3
|
+
import type { EmailFacade } from '../email.js';
|
|
4
|
+
import type { StorageFacade } from '../index.js';
|
|
5
|
+
import { type CatchUp } from './slots.js';
|
|
6
|
+
export declare const DEFAULT_RETRIES = 3;
|
|
7
|
+
export declare const DEFAULT_TIMEOUT_MS = 60000;
|
|
8
|
+
export type EnqueueOptions = {
|
|
9
|
+
/** Collapse duplicate enqueues while the queue row is non-terminal. */
|
|
10
|
+
dedupeKey?: string;
|
|
11
|
+
/** Milliseconds from now until the job becomes claimable. */
|
|
12
|
+
delay?: number;
|
|
13
|
+
/** Absolute time the job becomes claimable; wins over `delay`. */
|
|
14
|
+
runAt?: Date | number;
|
|
15
|
+
};
|
|
16
|
+
export type TickResult = {
|
|
17
|
+
/** Rows moved from pending to running this tick. */
|
|
18
|
+
claimed: number;
|
|
19
|
+
/** Handlers that completed successfully. */
|
|
20
|
+
ran: number;
|
|
21
|
+
/** Handlers that threw, whether or not they will be retried. */
|
|
22
|
+
failed: number;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* The untyped runtime facade. Job handlers and API context expose this shape;
|
|
26
|
+
* `app.jobs` narrows `enqueue` to the declared job names/payloads.
|
|
27
|
+
*/
|
|
28
|
+
export type JobsRuntimeFacade = {
|
|
29
|
+
enqueue(name: string, input?: unknown, opts?: EnqueueOptions): Promise<{
|
|
30
|
+
id: string;
|
|
31
|
+
}>;
|
|
32
|
+
/** Run one poll cycle deterministically (tests). `now` defaults to Date.now(). */
|
|
33
|
+
tick(now?: number): Promise<TickResult>;
|
|
34
|
+
};
|
|
35
|
+
import type { RealtimeFacade } from '../realtime/facade.js';
|
|
36
|
+
export type JobContext<TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>> = {
|
|
37
|
+
db: DbFor<TSchema>;
|
|
38
|
+
env: TEnvResult;
|
|
39
|
+
email: EmailFacade;
|
|
40
|
+
storage: StorageFacade;
|
|
41
|
+
jobs: JobsRuntimeFacade;
|
|
42
|
+
realtime: RealtimeFacade<TSchema>;
|
|
43
|
+
};
|
|
44
|
+
export type BunderstackJobContext<TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>> = JobContext<TSchema, TEnvResult>;
|
|
45
|
+
export type QueueJobDefinition<TInput, TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>> = {
|
|
46
|
+
kind: 'job';
|
|
47
|
+
/** Standard Schema payload; parsed at enqueue AND before the handler runs. */
|
|
48
|
+
input?: StandardSchemaV1<unknown, TInput>;
|
|
49
|
+
/** Attempts after the first failure. Default 3 (so 4 total attempts). */
|
|
50
|
+
retries?: number;
|
|
51
|
+
/** Delay before retry N (1-based). Default exponential: 1s, 2s, 4s, … */
|
|
52
|
+
backoff?: ((attempt: number) => number) | {
|
|
53
|
+
baseMs?: number;
|
|
54
|
+
factor?: number;
|
|
55
|
+
};
|
|
56
|
+
/** Max simultaneous `running` rows of this type, enforced per worker. */
|
|
57
|
+
concurrency?: number;
|
|
58
|
+
/** Lease duration in ms; an expired lease sends the job back to pending. */
|
|
59
|
+
timeout?: number;
|
|
60
|
+
handler: (input: TInput, ctx: JobContext<TSchema, TEnvResult>) => Promise<void> | void;
|
|
61
|
+
/** Fires once, after the final attempt fails. Errors here are logged, never retried. */
|
|
62
|
+
onFailed?: (input: TInput, error: Error, ctx: JobContext<TSchema, TEnvResult>) => Promise<void> | void;
|
|
63
|
+
};
|
|
64
|
+
export type CronInvocation = {
|
|
65
|
+
scheduledFor: Date;
|
|
66
|
+
};
|
|
67
|
+
export type CronDefinition<TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>, TSchedule extends string = string> = {
|
|
68
|
+
kind: 'cron';
|
|
69
|
+
schedule: TSchedule;
|
|
70
|
+
/** Attempts after the first failure. Default 3 (so 4 total attempts). */
|
|
71
|
+
retries?: number;
|
|
72
|
+
/** Delay before retry N (1-based). Default exponential: 1s, 2s, 4s, … */
|
|
73
|
+
backoff?: ((attempt: number) => number) | {
|
|
74
|
+
baseMs?: number;
|
|
75
|
+
factor?: number;
|
|
76
|
+
};
|
|
77
|
+
/** Lease duration in ms; an expired lease sends the slot back to pending. */
|
|
78
|
+
timeout?: number;
|
|
79
|
+
/** How missed slots are handled on wake. Default 'latest'. */
|
|
80
|
+
catchUp?: CatchUp;
|
|
81
|
+
/** How far back catch-up looks, in ms. Default 1 hour. */
|
|
82
|
+
catchUpWindow?: number;
|
|
83
|
+
handler: (invocation: CronInvocation, ctx: JobContext<TSchema, TEnvResult>) => Promise<void> | void;
|
|
84
|
+
/** Fires once, after the final attempt fails. Errors here are logged, never retried. */
|
|
85
|
+
onFailed?: (invocation: CronInvocation, error: Error, ctx: JobContext<TSchema, TEnvResult>) => Promise<void> | void;
|
|
86
|
+
};
|
|
87
|
+
export type BackgroundDefinition = QueueJobDefinition<any, any, any> | CronDefinition<any, any>;
|
|
88
|
+
export type BackgroundDefs = Record<string, BackgroundDefinition>;
|
|
89
|
+
/** @deprecated Use QueueJobDefinition. */
|
|
90
|
+
export type JobDefinition<TInput, TSchema extends Record<string, unknown> = Record<string, unknown>, TEnvResult = Record<string, unknown>> = QueueJobDefinition<TInput, TSchema, TEnvResult>;
|
|
91
|
+
export type AnyJobDefinition = QueueJobDefinition<any, any, any>;
|
|
92
|
+
export type AnyBackgroundDefinition = QueueJobDefinition<any, any, any> | CronDefinition<any, any, any>;
|
|
93
|
+
export type JobsDefs = BackgroundDefs;
|
|
94
|
+
export type QueueJobKeys<TDefs extends BackgroundDefs> = {
|
|
95
|
+
[K in keyof TDefs & string]: TDefs[K] extends QueueJobDefinition<any, any, any> ? K : never;
|
|
96
|
+
}[keyof TDefs & string];
|
|
97
|
+
/** Throws when a definition is unusable. Safe to call more than once. */
|
|
98
|
+
export declare function validateBackgroundDefs(defs: BackgroundDefs): void;
|
|
99
|
+
/** @deprecated Use validateBackgroundDefs. */
|
|
100
|
+
export declare const validateJobsDefs: typeof validateBackgroundDefs;
|
|
101
|
+
/**
|
|
102
|
+
* Delay in ms before retry `attempt` (1-based = the attempt that just failed).
|
|
103
|
+
* Jittered by ±20% so a shared outage does not retry every job in lockstep.
|
|
104
|
+
* A caller-supplied backoff function is returned verbatim — the caller owns it.
|
|
105
|
+
*/
|
|
106
|
+
export declare function backoffMs(def: AnyBackgroundDefinition, attempt: number): number;
|
|
107
|
+
/**
|
|
108
|
+
* Build the `j` instance bunderstack hands to the config's `jobs` builder
|
|
109
|
+
* callback (and exports for multi-file job setups).
|
|
110
|
+
*/
|
|
111
|
+
export declare function createJobsBuilder<TSchema extends Record<string, unknown>, TEnvResult = Record<string, unknown>>(): {
|
|
112
|
+
/** Identity with inference: pins TInput from the schema output. */
|
|
113
|
+
job<TInput = undefined>(def: Omit<QueueJobDefinition<TInput, TSchema, TEnvResult>, "kind">): QueueJobDefinition<TInput, TSchema, TEnvResult>;
|
|
114
|
+
cron<const TSchedule extends string>(def: Omit<CronDefinition<TSchema, TEnvResult, TSchedule>, "kind">): CronDefinition<TSchema, TEnvResult, TSchedule>;
|
|
115
|
+
/** Identity with validation: returns the defs map, typed. */
|
|
116
|
+
define<TDefs extends BackgroundDefs>(defs: TDefs): TDefs;
|
|
117
|
+
};
|
|
118
|
+
/** Type of the `j` instance — for builder callbacks declared in separate files. */
|
|
119
|
+
export type BunderstackJobsBuilder<TSchema extends Record<string, unknown>, TEnvResult = Record<string, unknown>> = ReturnType<typeof createJobsBuilder<TSchema, TEnvResult>>;
|
|
120
|
+
type JobInputOf<TDef> = TDef extends QueueJobDefinition<infer TInput, any, any> ? TInput : undefined;
|
|
121
|
+
/**
|
|
122
|
+
* `app.jobs`: `enqueue` narrowed to declared names + payloads. `Omit`s the
|
|
123
|
+
* runtime facade's loose `enqueue` first — intersecting two same-named
|
|
124
|
+
* methods instead would make TS treat them as overloaded, so the loose
|
|
125
|
+
* `(name: string, ...)` signature would still accept any name.
|
|
126
|
+
*/
|
|
127
|
+
export type JobsFacade<TDefs extends JobsDefs> = Omit<JobsRuntimeFacade, 'enqueue'> & {
|
|
128
|
+
enqueue<K extends QueueJobKeys<TDefs>>(name: K, ...rest: JobInputOf<TDefs[K]> extends undefined ? [input?: undefined, opts?: EnqueueOptions] : [input: JobInputOf<TDefs[K]>, opts?: EnqueueOptions]): Promise<{
|
|
129
|
+
id: string;
|
|
130
|
+
}>;
|
|
131
|
+
};
|
|
132
|
+
export {};
|
|
133
|
+
//# sourceMappingURL=define.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.d.ts","sourceRoot":"","sources":["../../src/jobs/define.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { parseCron } from './cron.js';
|
|
2
|
+
import { CRON_PREFIX } from './slots.js';
|
|
3
|
+
export const DEFAULT_RETRIES = 3;
|
|
4
|
+
export const DEFAULT_TIMEOUT_MS = 60_000;
|
|
5
|
+
/** Throws when a definition is unusable. Safe to call more than once. */
|
|
6
|
+
export function validateBackgroundDefs(defs) {
|
|
7
|
+
for (const [name, def] of Object.entries(defs)) {
|
|
8
|
+
if (typeof def.handler !== 'function') {
|
|
9
|
+
throw new Error(`[bunderstack] background task "${name}" has no handler`);
|
|
10
|
+
}
|
|
11
|
+
if (def.kind === 'job' && name.startsWith(CRON_PREFIX)) {
|
|
12
|
+
throw new Error(`[bunderstack] job "${name}": the "${CRON_PREFIX}" prefix is reserved for cron tasks`);
|
|
13
|
+
}
|
|
14
|
+
if (def.retries !== undefined &&
|
|
15
|
+
(def.retries < 0 || !Number.isInteger(def.retries))) {
|
|
16
|
+
throw new Error(`[bunderstack] background task "${name}": retries must be a non-negative integer`);
|
|
17
|
+
}
|
|
18
|
+
if (def.timeout !== undefined && def.timeout <= 0) {
|
|
19
|
+
throw new Error(`[bunderstack] background task "${name}": timeout must be positive`);
|
|
20
|
+
}
|
|
21
|
+
if (def.kind === 'cron') {
|
|
22
|
+
parseCron(def.schedule);
|
|
23
|
+
if (def.concurrency !== undefined) {
|
|
24
|
+
throw new Error(`[bunderstack] cron "${name}": concurrency is not supported for cron tasks — slots are already unique`);
|
|
25
|
+
}
|
|
26
|
+
if (def.catchUpWindow !== undefined && def.catchUpWindow <= 0) {
|
|
27
|
+
throw new Error(`[bunderstack] cron "${name}": catchUpWindow must be positive`);
|
|
28
|
+
}
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (def.concurrency !== undefined &&
|
|
32
|
+
(def.concurrency < 1 || !Number.isInteger(def.concurrency))) {
|
|
33
|
+
throw new Error(`[bunderstack] job "${name}": concurrency must be a positive integer`);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** @deprecated Use validateBackgroundDefs. */
|
|
38
|
+
export const validateJobsDefs = validateBackgroundDefs;
|
|
39
|
+
/**
|
|
40
|
+
* Delay in ms before retry `attempt` (1-based = the attempt that just failed).
|
|
41
|
+
* Jittered by ±20% so a shared outage does not retry every job in lockstep.
|
|
42
|
+
* A caller-supplied backoff function is returned verbatim — the caller owns it.
|
|
43
|
+
*/
|
|
44
|
+
export function backoffMs(def, attempt) {
|
|
45
|
+
const b = def.backoff;
|
|
46
|
+
if (typeof b === 'function')
|
|
47
|
+
return b(attempt);
|
|
48
|
+
const baseMs = b?.baseMs ?? 1000;
|
|
49
|
+
const factor = b?.factor ?? 2;
|
|
50
|
+
const flat = baseMs * factor ** (attempt - 1);
|
|
51
|
+
return Math.round(flat * (0.8 + Math.random() * 0.4));
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Build the `j` instance bunderstack hands to the config's `jobs` builder
|
|
55
|
+
* callback (and exports for multi-file job setups).
|
|
56
|
+
*/
|
|
57
|
+
export function createJobsBuilder() {
|
|
58
|
+
return {
|
|
59
|
+
/** Identity with inference: pins TInput from the schema output. */
|
|
60
|
+
job(def) {
|
|
61
|
+
return { kind: 'job', ...def };
|
|
62
|
+
},
|
|
63
|
+
cron(def) {
|
|
64
|
+
parseCron(def.schedule);
|
|
65
|
+
return { kind: 'cron', ...def };
|
|
66
|
+
},
|
|
67
|
+
/** Identity with validation: returns the defs map, typed. */
|
|
68
|
+
define(defs) {
|
|
69
|
+
validateBackgroundDefs(defs);
|
|
70
|
+
return defs;
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=define.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"define.js","sourceRoot":"","sources":["../../src/jobs/define.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { createJobsBuilder, validateBackgroundDefs, validateJobsDefs, DEFAULT_RETRIES, DEFAULT_TIMEOUT_MS, } from './define.js';
|
|
2
|
+
export type { AnyJobDefinition, BackgroundDefinition, BackgroundDefs, BunderstackJobContext, BunderstackJobsBuilder, EnqueueOptions, JobContext, JobDefinition, QueueJobDefinition, CronDefinition, CronInvocation, QueueJobKeys, JobsDefs, JobsFacade, JobsRuntimeFacade, } from './define.js';
|
|
3
|
+
export { enqueueJob } from './queue.js';
|
|
4
|
+
export { createJobRunner } from './worker.js';
|
|
5
|
+
export { startJobWorker } from './runtime.js';
|
|
6
|
+
export type { StartWorkerOptions, RunWorkerOptions, WorkerHandle, } from './runtime.js';
|
|
7
|
+
export { parseCron, cronMatches } from './cron.js';
|
|
8
|
+
export { slotsDue, floorSlot, CRON_PREFIX, SLOT_MS } from './slots.js';
|
|
9
|
+
export type { CatchUp } from './slots.js';
|
|
10
|
+
export type { TickResult } from './define.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,MAAM,UAAU,CAAA;AACjB,YAAY,EACV,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,qBAAqB,EACrB,sBAAsB,EACtB,cAAc,EACd,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,iBAAiB,GAClB,MAAM,UAAU,CAAA;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,YAAY,EACV,kBAAkB,EAClB,gBAAgB,EAChB,YAAY,GACb,MAAM,WAAW,CAAA;AAClB,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACnE,YAAY,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA;AACtC,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// src/jobs/index.ts — module surface consumed by createBunderstack.
|
|
2
|
+
export { createJobsBuilder, validateBackgroundDefs, validateJobsDefs, DEFAULT_RETRIES, DEFAULT_TIMEOUT_MS, } from './define.js';
|
|
3
|
+
export { enqueueJob } from './queue.js';
|
|
4
|
+
export { createJobRunner } from './worker.js';
|
|
5
|
+
export { startJobWorker } from './runtime.js';
|
|
6
|
+
export { parseCron, cronMatches } from './cron.js';
|
|
7
|
+
export { slotsDue, floorSlot, CRON_PREFIX, SLOT_MS } from './slots.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/jobs/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EACf,kBAAkB,GACnB,MAAM,UAAU,CAAA;AAkBjB,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA;AACpC,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAM1C,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAC/C,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { AnyDb } from '../dialect.js';
|
|
2
|
+
import type { EnqueueOptions, JobsDefs } from './define.js';
|
|
3
|
+
export declare function enqueueJob(db: AnyDb, defs: JobsDefs, name: string, input: unknown, opts?: EnqueueOptions): Promise<{
|
|
4
|
+
id: string;
|
|
5
|
+
}>;
|
|
6
|
+
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/jobs/queue.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAOxD,wBAAsB,UAAU,CAC9B,EAAE,EAAE,KAAK,EACT,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,OAAO,EACd,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAiDzB"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// src/jobs/queue.ts — durable enqueue with constraint-backed dedupe.
|
|
2
|
+
import { and, eq } from 'drizzle-orm';
|
|
3
|
+
import { jobsTableFor } from '../internal-tables.js';
|
|
4
|
+
import { validateStandardSchema } from '../standard-schema.js';
|
|
5
|
+
import { generate } from '../typeid.js';
|
|
6
|
+
import { CRON_PREFIX } from './slots.js';
|
|
7
|
+
export async function enqueueJob(db, defs, name, input, opts = {}) {
|
|
8
|
+
const def = defs[name];
|
|
9
|
+
if (!def) {
|
|
10
|
+
throw new Error(`[bunderstack] unknown background task "${name}"`);
|
|
11
|
+
}
|
|
12
|
+
const isCron = def.kind === 'cron';
|
|
13
|
+
const type = isCron ? `${CRON_PREFIX}${name}` : name;
|
|
14
|
+
// Cron slots carry no payload; queue jobs validate theirs at the call site.
|
|
15
|
+
const parsed = isCron
|
|
16
|
+
? null
|
|
17
|
+
: def.input
|
|
18
|
+
? validateStandardSchema(def.input, input, `job "${name}" input`)
|
|
19
|
+
: null;
|
|
20
|
+
const t = jobsTableFor(db);
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
const runAt = opts.runAt !== undefined
|
|
23
|
+
? new Date(opts.runAt).getTime()
|
|
24
|
+
: now + (opts.delay ?? 0);
|
|
25
|
+
// Two rounds cover the race where the deduping row reaches a terminal state
|
|
26
|
+
// (clearing its key) between our failed insert and our read.
|
|
27
|
+
for (let round = 0; round < 2; round++) {
|
|
28
|
+
const id = generate('job');
|
|
29
|
+
const insertedRows = await db
|
|
30
|
+
.insert(t)
|
|
31
|
+
.values({
|
|
32
|
+
id,
|
|
33
|
+
type,
|
|
34
|
+
payloadJson: JSON.stringify(parsed),
|
|
35
|
+
status: 'pending',
|
|
36
|
+
attempts: 0,
|
|
37
|
+
runAt,
|
|
38
|
+
dedupeKey: opts.dedupeKey ?? null,
|
|
39
|
+
createdAt: now,
|
|
40
|
+
})
|
|
41
|
+
.onConflictDoNothing({ target: [t.type, t.dedupeKey] })
|
|
42
|
+
.returning({ id: t.id });
|
|
43
|
+
if (insertedRows[0])
|
|
44
|
+
return { id: String(insertedRows[0].id) };
|
|
45
|
+
const existing = await db
|
|
46
|
+
.select({ id: t.id })
|
|
47
|
+
.from(t)
|
|
48
|
+
.where(and(eq(t.type, type), eq(t.dedupeKey, opts.dedupeKey ?? '')))
|
|
49
|
+
.limit(1);
|
|
50
|
+
if (existing[0])
|
|
51
|
+
return { id: String(existing[0].id) };
|
|
52
|
+
}
|
|
53
|
+
throw new Error(`[bunderstack] enqueue of "${name}" lost a dedupe race twice — please retry`);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/jobs/queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type WorkerHandle = {
|
|
2
|
+
readonly closed: Promise<void>;
|
|
3
|
+
close(): Promise<void>;
|
|
4
|
+
};
|
|
5
|
+
export type StartWorkerOptions = {
|
|
6
|
+
signal?: AbortSignal;
|
|
7
|
+
pollIntervalMs?: number;
|
|
8
|
+
tick: (now: number) => Promise<void>;
|
|
9
|
+
onError?: (error: Error) => void;
|
|
10
|
+
};
|
|
11
|
+
export type RunWorkerOptions = StartWorkerOptions;
|
|
12
|
+
export declare function startJobWorker(options: StartWorkerOptions): WorkerHandle;
|
|
13
|
+
//# sourceMappingURL=runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/jobs/runtime.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;IAC9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG,kBAAkB,CAAA;AAmBjD,wBAAgB,cAAc,CAAC,OAAO,EAAE,kBAAkB,GAAG,YAAY,CA0BxE"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
function toError(error) {
|
|
2
|
+
return error instanceof Error ? error : new Error(String(error));
|
|
3
|
+
}
|
|
4
|
+
function wait(ms, signal) {
|
|
5
|
+
return new Promise((resolve) => {
|
|
6
|
+
if (signal.aborted)
|
|
7
|
+
return resolve();
|
|
8
|
+
const timer = setTimeout(done, ms);
|
|
9
|
+
function done() {
|
|
10
|
+
clearTimeout(timer);
|
|
11
|
+
signal.removeEventListener('abort', done);
|
|
12
|
+
resolve();
|
|
13
|
+
}
|
|
14
|
+
signal.addEventListener('abort', done, { once: true });
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
export function startJobWorker(options) {
|
|
18
|
+
const controller = new AbortController();
|
|
19
|
+
const pollIntervalMs = options.pollIntervalMs ?? 1_000;
|
|
20
|
+
const abort = () => controller.abort();
|
|
21
|
+
options.signal?.addEventListener('abort', abort, { once: true });
|
|
22
|
+
if (options.signal?.aborted)
|
|
23
|
+
abort();
|
|
24
|
+
const closed = (async () => {
|
|
25
|
+
try {
|
|
26
|
+
while (!controller.signal.aborted) {
|
|
27
|
+
try {
|
|
28
|
+
await options.tick(Date.now());
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
options.onError?.(toError(error));
|
|
32
|
+
}
|
|
33
|
+
await wait(pollIntervalMs, controller.signal);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
finally {
|
|
37
|
+
options.signal?.removeEventListener('abort', abort);
|
|
38
|
+
}
|
|
39
|
+
})();
|
|
40
|
+
const close = () => {
|
|
41
|
+
controller.abort();
|
|
42
|
+
return closed;
|
|
43
|
+
};
|
|
44
|
+
return { closed, close };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=runtime.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/jobs/runtime.ts"],"names":[],"mappings":"AAcA,SAAS,OAAO,CAAC,KAAc;IAC7B,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;AAClE,CAAC;AAED,SAAS,IAAI,CAAC,EAAU,EAAE,MAAmB;IAC3C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,IAAI,MAAM,CAAC,OAAO;YAAE,OAAO,OAAO,EAAE,CAAA;QACpC,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAClC,SAAS,IAAI;YACX,YAAY,CAAC,KAAK,CAAC,CAAA;YACnB,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;YACzC,OAAO,EAAE,CAAA;QACX,CAAC;QACD,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAA2B;IACxD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAA;IACxC,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,KAAK,CAAA;IACtD,MAAM,KAAK,GAAG,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAA;IACtC,OAAO,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;IAChE,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO;QAAE,KAAK,EAAE,CAAA;IAEpC,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE;QACzB,IAAI,CAAC;YACH,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;gBAClC,IAAI,CAAC;oBACH,MAAM,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAA;gBAChC,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,OAAO,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;gBACnC,CAAC;gBACD,MAAM,IAAI,CAAC,cAAc,EAAE,UAAU,CAAC,MAAM,CAAC,CAAA;YAC/C,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;QACrD,CAAC;IACH,CAAC,CAAC,EAAE,CAAA;IACJ,MAAM,KAAK,GAAG,GAAG,EAAE;QACjB,UAAU,CAAC,KAAK,EAAE,CAAA;QAClB,OAAO,MAAM,CAAA;IACf,CAAC,CAAA;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAA;AAC1B,CAAC"}
|