@zintrust/queue-cloudflare 2.4.1

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.
Files changed (36) hide show
  1. package/README.md +158 -0
  2. package/dist/CloudflareJobStore.d.ts +50 -0
  3. package/dist/CloudflareJobStore.js +435 -0
  4. package/dist/CloudflareQueueConsumer.d.ts +39 -0
  5. package/dist/CloudflareQueueConsumer.js +184 -0
  6. package/dist/CloudflareQueueCoordinator.d.ts +21 -0
  7. package/dist/CloudflareQueueCoordinator.js +57 -0
  8. package/dist/CloudflareQueueMigrator.d.ts +14 -0
  9. package/dist/CloudflareQueueMigrator.js +22 -0
  10. package/dist/CloudflareQueueScheduler.d.ts +43 -0
  11. package/dist/CloudflareQueueScheduler.js +99 -0
  12. package/dist/cli/MigrateCloudflareQueueCommand.d.ts +10 -0
  13. package/dist/cli/MigrateCloudflareQueueCommand.js +51 -0
  14. package/dist/cli-register.d.ts +9 -0
  15. package/dist/cli-register.js +21 -0
  16. package/dist/index.d.ts +50 -0
  17. package/dist/index.js +499 -0
  18. package/dist/migrationSql.d.ts +2 -0
  19. package/dist/migrationSql.js +104 -0
  20. package/dist/migrations/20260608000001_create_cloudflare_queue_jobs_table.d.ts +6 -0
  21. package/dist/migrations/20260608000001_create_cloudflare_queue_jobs_table.js +37 -0
  22. package/dist/migrations/20260608000002_create_cloudflare_queue_job_events_table.d.ts +6 -0
  23. package/dist/migrations/20260608000002_create_cloudflare_queue_job_events_table.js +21 -0
  24. package/dist/migrations/20260608000003_create_cloudflare_queue_job_logs_table.d.ts +6 -0
  25. package/dist/migrations/20260608000003_create_cloudflare_queue_job_logs_table.js +22 -0
  26. package/dist/migrations/20260608000004_create_cloudflare_queue_repeatables_table.d.ts +6 -0
  27. package/dist/migrations/20260608000004_create_cloudflare_queue_repeatables_table.js +28 -0
  28. package/dist/migrations/20260608000005_create_cloudflare_queue_flow_dependencies_table.d.ts +6 -0
  29. package/dist/migrations/20260608000005_create_cloudflare_queue_flow_dependencies_table.js +22 -0
  30. package/dist/migrations/index.d.ts +2 -0
  31. package/dist/migrations/index.js +12 -0
  32. package/dist/register.d.ts +5 -0
  33. package/dist/register.js +20 -0
  34. package/dist/types.d.ts +240 -0
  35. package/dist/types.js +1 -0
  36. package/package.json +52 -0
@@ -0,0 +1,22 @@
1
+ import { MigrationSchema } from '@zintrust/core/database';
2
+ export const migration = {
3
+ async up(db) {
4
+ const schema = MigrationSchema.create(db);
5
+ await schema.create('cf_queue_job_logs', (table) => {
6
+ table.string('id').primary();
7
+ table.string('job_id');
8
+ table.string('queue_name');
9
+ table.string('level');
10
+ table.text('message');
11
+ table.text('data').nullable();
12
+ table.timestamp('created_at');
13
+ table.index(['job_id', 'queue_name']);
14
+ table.index(['queue_name', 'level', 'created_at']);
15
+ table.index('created_at');
16
+ });
17
+ },
18
+ async down(db) {
19
+ const schema = MigrationSchema.create(db);
20
+ await schema.dropIfExists('cf_queue_job_logs');
21
+ },
22
+ };
@@ -0,0 +1,6 @@
1
+ import { type IDatabase } from '@zintrust/core/database';
2
+ export interface Migration {
3
+ up(db: IDatabase): Promise<void>;
4
+ down(db: IDatabase): Promise<void>;
5
+ }
6
+ export declare const migration: Migration;
@@ -0,0 +1,28 @@
1
+ import { MigrationSchema } from '@zintrust/core/database';
2
+ export const migration = {
3
+ async up(db) {
4
+ const schema = MigrationSchema.create(db);
5
+ await schema.create('cf_queue_repeatables', (table) => {
6
+ table.string('id').primary();
7
+ table.string('queue_name');
8
+ table.string('name');
9
+ table.text('payload');
10
+ table.string('cron').nullable();
11
+ table.integer('every_ms').nullable();
12
+ table.timestamp('start_at').nullable();
13
+ table.timestamp('end_at').nullable();
14
+ table.integer('limit_count').nullable();
15
+ table.integer('run_count').default(0);
16
+ table.timestamp('next_run_at');
17
+ table.boolean('active').default(true);
18
+ table.timestamp('created_at');
19
+ table.timestamp('updated_at');
20
+ table.index(['active', 'next_run_at']);
21
+ table.index(['queue_name', 'active']);
22
+ });
23
+ },
24
+ async down(db) {
25
+ const schema = MigrationSchema.create(db);
26
+ await schema.dropIfExists('cf_queue_repeatables');
27
+ },
28
+ };
@@ -0,0 +1,6 @@
1
+ import { type IDatabase } from '@zintrust/core/database';
2
+ export interface Migration {
3
+ up(db: IDatabase): Promise<void>;
4
+ down(db: IDatabase): Promise<void>;
5
+ }
6
+ export declare const migration: Migration;
@@ -0,0 +1,22 @@
1
+ import { MigrationSchema } from '@zintrust/core/database';
2
+ export const migration = {
3
+ async up(db) {
4
+ const schema = MigrationSchema.create(db);
5
+ await schema.create('cf_queue_flow_dependencies', (table) => {
6
+ table.string('id').primary();
7
+ table.string('queue_name');
8
+ table.string('parent_job_id');
9
+ table.string('child_job_id');
10
+ table.string('state');
11
+ table.timestamp('created_at');
12
+ table.timestamp('updated_at');
13
+ table.index(['queue_name', 'parent_job_id']);
14
+ table.index(['queue_name', 'child_job_id']);
15
+ table.index(['queue_name', 'state']);
16
+ });
17
+ },
18
+ async down(db) {
19
+ const schema = MigrationSchema.create(db);
20
+ await schema.dropIfExists('cf_queue_flow_dependencies');
21
+ },
22
+ };
@@ -0,0 +1,2 @@
1
+ export type { Migration } from './20260608000001_create_cloudflare_queue_jobs_table';
2
+ export declare const migrations: import("./20260608000001_create_cloudflare_queue_jobs_table").Migration[];
@@ -0,0 +1,12 @@
1
+ import { migration as createJobs } from './20260608000001_create_cloudflare_queue_jobs_table.js';
2
+ import { migration as createEvents } from './20260608000002_create_cloudflare_queue_job_events_table.js';
3
+ import { migration as createLogs } from './20260608000003_create_cloudflare_queue_job_logs_table.js';
4
+ import { migration as createRepeatables } from './20260608000004_create_cloudflare_queue_repeatables_table.js';
5
+ import { migration as createFlowDependencies } from './20260608000005_create_cloudflare_queue_flow_dependencies_table.js';
6
+ export const migrations = [
7
+ createJobs,
8
+ createEvents,
9
+ createLogs,
10
+ createRepeatables,
11
+ createFlowDependencies,
12
+ ];
@@ -0,0 +1,5 @@
1
+ type QueueApi = {
2
+ register?: (name: string, driver: unknown) => void;
3
+ };
4
+ export declare function registerCloudflareQueueDriver(queue: QueueApi): Promise<void>;
5
+ export {};
@@ -0,0 +1,20 @@
1
+ export async function registerCloudflareQueueDriver(queue) {
2
+ const { CloudflareQueues } = (await import('./index.js'));
3
+ if (typeof queue.register !== 'function')
4
+ return;
5
+ const driver = CloudflareQueues.create();
6
+ queue.register('cloudflare', driver);
7
+ queue.register('cloudflare-queues', driver);
8
+ }
9
+ const importCore = async () => {
10
+ try {
11
+ return await import('@zintrust/core');
12
+ }
13
+ catch {
14
+ return {};
15
+ }
16
+ };
17
+ const core = (await importCore());
18
+ if (typeof core.Queue?.register === 'function') {
19
+ await registerCloudflareQueueDriver(core.Queue);
20
+ }
@@ -0,0 +1,240 @@
1
+ export type CloudflareQueueContentType = 'json' | 'text' | 'bytes' | 'v8';
2
+ export type CloudflareQueueState = 'waiting' | 'queued' | 'delayed' | 'prioritized' | 'active' | 'completed' | 'failed' | 'retrying' | 'stalled' | 'waiting_children' | 'canceled' | 'dead_lettered';
3
+ export type CloudflareQueueBackoff = {
4
+ type: 'fixed' | 'exponential';
5
+ delay: number;
6
+ };
7
+ export type CloudflareQueueRetention = boolean | number | {
8
+ age?: number;
9
+ count?: number;
10
+ };
11
+ export type CloudflareRepeatOptions = {
12
+ every?: number;
13
+ cron?: string;
14
+ limit?: number;
15
+ startDate?: Date;
16
+ endDate?: Date;
17
+ };
18
+ export type CloudflareJobOptions = {
19
+ jobId?: string;
20
+ attempts?: number;
21
+ delay?: number;
22
+ priority?: number;
23
+ lifo?: boolean;
24
+ backoff?: CloudflareQueueBackoff;
25
+ removeOnComplete?: CloudflareQueueRetention;
26
+ removeOnFail?: CloudflareQueueRetention;
27
+ deduplication?: {
28
+ id: string;
29
+ ttl?: number;
30
+ collisionBehavior?: 'suppress' | 'enqueue';
31
+ };
32
+ uniqueId?: string;
33
+ repeat?: CloudflareRepeatOptions;
34
+ };
35
+ export type CloudflareQueueEnvelope = {
36
+ protocol: 'zintrust.cf.queue.v1';
37
+ jobId: string;
38
+ queueName: string;
39
+ name: string;
40
+ attempt: number;
41
+ availableAt: string;
42
+ traceId?: string;
43
+ };
44
+ export type QueueMessage<T = unknown> = {
45
+ id: string;
46
+ payload: T;
47
+ attempts: number;
48
+ };
49
+ export type CloudflareQueueSendOptions = {
50
+ contentType?: CloudflareQueueContentType;
51
+ delaySeconds?: number;
52
+ };
53
+ export type CloudflareQueueBatchMessage = {
54
+ body: unknown;
55
+ options?: CloudflareQueueSendOptions;
56
+ };
57
+ export type CloudflareQueueBinding = {
58
+ send: (body: unknown, options?: CloudflareQueueSendOptions) => Promise<void>;
59
+ sendBatch?: (messages: CloudflareQueueBatchMessage[]) => Promise<void>;
60
+ };
61
+ export type D1PreparedStatementLike = {
62
+ bind: (...values: unknown[]) => D1PreparedStatementLike;
63
+ all: <T = Record<string, unknown>>() => Promise<{
64
+ results?: T[];
65
+ }>;
66
+ first: <T = Record<string, unknown>>() => Promise<T | null>;
67
+ run: () => Promise<unknown>;
68
+ };
69
+ export type D1DatabaseLike = {
70
+ prepare: (query: string) => D1PreparedStatementLike;
71
+ batch?: (statements: D1PreparedStatementLike[]) => Promise<unknown[]>;
72
+ exec?: (query: string) => Promise<unknown>;
73
+ };
74
+ export type ZinTrustDatabaseLike = {
75
+ query: (sql: string, parameters?: unknown[]) => Promise<unknown[]>;
76
+ queryOne: (sql: string, parameters?: unknown[]) => Promise<unknown>;
77
+ execute: (sql: string, parameters?: unknown[]) => Promise<unknown>;
78
+ };
79
+ export type CloudflareQueueStateConfig = {
80
+ d1?: D1DatabaseLike;
81
+ db?: ZinTrustDatabaseLike;
82
+ d1BindingName?: string;
83
+ kv?: CloudflareQueueKvBinding;
84
+ kvBindingName?: string;
85
+ coordinator?: CloudflareQueueCoordinatorBinding;
86
+ coordinatorBindingName?: string;
87
+ workerId?: string;
88
+ heartbeatTtlMs?: number;
89
+ rateLimit?: {
90
+ max: number;
91
+ durationMs: number;
92
+ key?: string;
93
+ };
94
+ };
95
+ export type CloudflareQueueKvBinding = {
96
+ get: (key: string) => Promise<string | null>;
97
+ put: (key: string, value: string, options?: {
98
+ expirationTtl?: number;
99
+ }) => Promise<void>;
100
+ delete: (key: string) => Promise<void>;
101
+ };
102
+ export type CloudflareQueueCoordinatorBinding = {
103
+ getByName?: (name: string) => CloudflareQueueCoordinatorStub;
104
+ idFromName?: (name: string) => unknown;
105
+ get?: (id: unknown) => CloudflareQueueCoordinatorStub;
106
+ };
107
+ export type CloudflareQueueCoordinatorStub = {
108
+ acquireLease?: (input: LeaseInput) => Promise<LeaseResult>;
109
+ heartbeat?: (input: LeaseInput) => Promise<LeaseResult>;
110
+ releaseLease?: (input: LeaseInput) => Promise<void>;
111
+ pause?: () => Promise<void>;
112
+ resume?: () => Promise<void>;
113
+ isPaused?: () => Promise<boolean>;
114
+ rateLimit?: (input: RateLimitInput) => Promise<RateLimitResult>;
115
+ };
116
+ export type LeaseInput = {
117
+ queueName: string;
118
+ jobId: string;
119
+ workerId: string;
120
+ ttlMs: number;
121
+ };
122
+ export type LeaseResult = {
123
+ acquired: boolean;
124
+ expiresAt?: number;
125
+ owner?: string;
126
+ };
127
+ export type RateLimitInput = {
128
+ key: string;
129
+ max: number;
130
+ durationMs: number;
131
+ };
132
+ export type RateLimitResult = {
133
+ allowed: boolean;
134
+ remaining: number;
135
+ resetAt: number;
136
+ };
137
+ export type CloudflareQueueConfig = {
138
+ driver: 'cloudflare' | 'cloudflare-queues';
139
+ bindingName?: string;
140
+ bindings?: Record<string, CloudflareQueueBinding | undefined>;
141
+ accountId?: string;
142
+ queueId?: string;
143
+ apiToken?: string;
144
+ apiBaseUrl?: string;
145
+ contentType?: CloudflareQueueContentType;
146
+ delaySeconds?: number;
147
+ batchSize?: number;
148
+ visibilityTimeoutMs?: number;
149
+ state?: CloudflareQueueStateConfig;
150
+ };
151
+ export type CloudflareQueueJobRow = {
152
+ id: string;
153
+ queue_name: string;
154
+ name: string;
155
+ payload: string;
156
+ opts: string | null;
157
+ state: CloudflareQueueState;
158
+ priority: number;
159
+ attempts: number;
160
+ max_attempts: number;
161
+ progress: string | null;
162
+ result: string | null;
163
+ error: string | null;
164
+ dedupe_key: string | null;
165
+ idempotency_key: string | null;
166
+ available_at: string;
167
+ started_at: string | null;
168
+ completed_at: string | null;
169
+ failed_at: string | null;
170
+ stalled_at: string | null;
171
+ created_at: string;
172
+ updated_at: string;
173
+ };
174
+ export type CloudflareQueueJob<T = unknown> = {
175
+ id: string;
176
+ queueName: string;
177
+ name: string;
178
+ data: T;
179
+ state: CloudflareQueueState;
180
+ attemptsMade: number;
181
+ maxAttempts: number;
182
+ priority: number;
183
+ progress: unknown;
184
+ result: unknown;
185
+ error: unknown;
186
+ opts: CloudflareJobOptions;
187
+ availableAt: string;
188
+ createdAt: string;
189
+ updatedAt: string;
190
+ updateProgress(progress: unknown): Promise<void>;
191
+ log(message: string, data?: unknown): Promise<void>;
192
+ remove(): Promise<void>;
193
+ retry(): Promise<void>;
194
+ };
195
+ export type CloudflareQueueProcessorContext<T = unknown> = {
196
+ job: CloudflareQueueJob<T>;
197
+ attempt: number;
198
+ updateProgress(progress: unknown): Promise<void>;
199
+ log(message: string, data?: unknown): Promise<void>;
200
+ heartbeat(): Promise<void>;
201
+ };
202
+ export type CloudflareQueueProcessor<T = unknown, TResult = unknown> = (data: T, context: CloudflareQueueProcessorContext<T>) => Promise<TResult> | TResult;
203
+ export type CloudflareRepeatableRow = {
204
+ id: string;
205
+ queue_name: string;
206
+ name: string;
207
+ payload: string;
208
+ cron: string | null;
209
+ every_ms: number | null;
210
+ start_at: string | null;
211
+ end_at: string | null;
212
+ limit_count: number | null;
213
+ run_count: number;
214
+ next_run_at: string;
215
+ active: number;
216
+ created_at: string;
217
+ updated_at: string;
218
+ };
219
+ export type CloudflareFlowInput<TParent = unknown, TChild = unknown> = {
220
+ queueName: string;
221
+ parent: {
222
+ name: string;
223
+ data: TParent;
224
+ options?: CloudflareJobOptions;
225
+ };
226
+ children: Array<{
227
+ name: string;
228
+ data: TChild;
229
+ options?: CloudflareJobOptions;
230
+ }>;
231
+ };
232
+ export type CloudflareFlowResult<TParent = unknown, TChild = unknown> = {
233
+ parent: CloudflareQueueJob<TParent>;
234
+ children: Array<CloudflareQueueJob<TChild>>;
235
+ };
236
+ export type CloudflareQueueMetrics = {
237
+ queueName: string;
238
+ counts: Record<string, number>;
239
+ total: number;
240
+ };
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@zintrust/queue-cloudflare",
3
+ "version": "2.4.1",
4
+ "description": "Cloudflare Queues driver for ZinTrust.",
5
+ "private": false,
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "exports": {
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "./register": {
19
+ "types": "./dist/register.d.ts",
20
+ "default": "./dist/register.js"
21
+ },
22
+ "./cli-register": {
23
+ "types": "./dist/cli-register.d.ts",
24
+ "default": "./dist/cli-register.js"
25
+ },
26
+ "./migrations": {
27
+ "types": "./dist/migrations/index.d.ts",
28
+ "default": "./dist/migrations/index.js"
29
+ }
30
+ },
31
+ "engines": {
32
+ "node": ">=20.0.0"
33
+ },
34
+ "peerDependencies": {
35
+ "@zintrust/core": "*"
36
+ },
37
+ "publishConfig": {
38
+ "access": "public"
39
+ },
40
+ "keywords": [
41
+ "zintrust",
42
+ "queue",
43
+ "cloudflare",
44
+ "cloudflare-queues",
45
+ "workers",
46
+ "adapter"
47
+ ],
48
+ "scripts": {
49
+ "build": "tsc -p tsconfig.json && tsc -p tsconfig.migrations.json && node ../../scripts/fix-dist-esm-imports.mjs dist",
50
+ "prepublishOnly": "npm run build"
51
+ }
52
+ }