@velajs/cloudflare 1.28.0 → 1.30.0
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 +113 -0
- package/README.md +190 -69
- package/dist/_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js +9 -0
- package/dist/_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js +6 -0
- package/dist/_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateParam.js +8 -0
- package/dist/cloudflare-application.js +309 -0
- package/dist/cloudflare-application.js.map +1 -0
- package/dist/cloudflare-factory.js +109 -0
- package/dist/cloudflare-factory.js.map +1 -0
- package/dist/decorators/queue-consumer.js +39 -0
- package/dist/decorators/queue-consumer.js.map +1 -0
- package/dist/durable-objects.d.ts +11 -11
- package/dist/durable-objects.js +2 -512
- package/dist/environment.js +19 -0
- package/dist/environment.js.map +1 -0
- package/dist/index.d.ts +146 -111
- package/dist/index.js +21 -1130
- package/dist/nonce/durable-object-nonce.store.js +33 -0
- package/dist/nonce/durable-object-nonce.store.js.map +1 -0
- package/dist/nonce/nonce-validation.js +18 -0
- package/dist/nonce/nonce-validation.js.map +1 -0
- package/dist/nonce/nonce.durable-object.js +54 -0
- package/dist/nonce/nonce.durable-object.js.map +1 -0
- package/dist/{nonce.durable-object-DffHMRnU.d.ts → nonce.durable-object-Ci9AGssY.d.ts} +9 -7
- package/dist/queue/cloudflare-queues.js +215 -0
- package/dist/queue/cloudflare-queues.js.map +1 -0
- package/dist/queues.d.ts +48 -0
- package/dist/queues.js +2 -0
- package/dist/rate-limit/cloudflare-rate-limit.store.js +40 -0
- package/dist/rate-limit/cloudflare-rate-limit.store.js.map +1 -0
- package/dist/schedule-diagnostics.js +51 -0
- package/dist/schedule-diagnostics.js.map +1 -0
- package/dist/scheduled-event.js +68 -0
- package/dist/scheduled-event.js.map +1 -0
- package/dist/services/flagship-flag.driver.js +52 -0
- package/dist/services/flagship-flag.driver.js.map +1 -0
- package/dist/services/kv-cache.store.js +82 -0
- package/dist/services/kv-cache.store.js.map +1 -0
- package/dist/services/kv-flag.driver.js +62 -0
- package/dist/services/kv-flag.driver.js.map +1 -0
- package/dist/storage/r2-storage.driver.js +67 -0
- package/dist/storage/r2-storage.driver.js.map +1 -0
- package/dist/storage/storage-key-claim.js +74 -0
- package/dist/storage/storage-key-claim.js.map +1 -0
- package/dist/storage/storage-manager.service.js +38 -0
- package/dist/storage/storage-manager.service.js.map +1 -0
- package/dist/storage/storage.controller.js +64 -0
- package/dist/storage/storage.controller.js.map +1 -0
- package/dist/storage/storage.module.js +25 -0
- package/dist/storage/storage.module.js.map +1 -0
- package/dist/storage/storage.service.js +64 -0
- package/dist/storage/storage.service.js.map +1 -0
- package/dist/storage/storage.tokens.js +7 -0
- package/dist/storage/storage.tokens.js.map +1 -0
- package/dist/vela-env-DFvyoNT3.d.ts +9 -0
- package/dist/websocket/broadcast.js +32 -0
- package/dist/websocket/broadcast.js.map +1 -0
- package/dist/websocket/cf-room-registry.js +137 -0
- package/dist/websocket/cf-room-registry.js.map +1 -0
- package/dist/websocket/cf-ws-client.js +94 -0
- package/dist/websocket/cf-ws-client.js.map +1 -0
- package/dist/websocket/cloudflare-websocket.module.js +25 -0
- package/dist/websocket/cloudflare-websocket.module.js.map +1 -0
- package/dist/websocket/do-bootstrap.js +56 -0
- package/dist/websocket/do-bootstrap.js.map +1 -0
- package/dist/websocket/do-live.js +184 -0
- package/dist/websocket/do-live.js.map +1 -0
- package/dist/websocket/do-pitr.js +81 -0
- package/dist/websocket/do-pitr.js.map +1 -0
- package/dist/websocket/do-state.js +7 -0
- package/dist/websocket/do-state.js.map +1 -0
- package/dist/websocket/do-websocket-host.js +169 -0
- package/dist/websocket/do-websocket-host.js.map +1 -0
- package/dist/websocket/room-id.js +27 -0
- package/dist/websocket/room-id.js.map +1 -0
- package/dist/websocket/websocket-routing.js +133 -0
- package/dist/websocket/websocket-routing.js.map +1 -0
- package/dist/websocket/websocket.durable-object.js +138 -0
- package/dist/websocket/websocket.durable-object.js.map +1 -0
- package/dist/websocket/ws-attachment.js +79 -0
- package/dist/websocket/ws-attachment.js.map +1 -0
- package/dist/websocket/ws-server-holder.js +38 -0
- package/dist/websocket/ws-server-holder.js.map +1 -0
- package/package.json +14 -11
- package/dist/durable-objects.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/nonce-validation-CeVihShV.js +0 -517
- package/dist/nonce-validation-CeVihShV.js.map +0 -1
- package/dist/queue.d.ts +0 -32
- package/dist/queue.js +0 -78
- package/dist/queue.js.map +0 -1
package/dist/queue.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { observeMessage, parseQueueJob } from "@velajs/vela/queue";
|
|
2
|
-
//#region src/queue/cloudflare-queue.ts
|
|
3
|
-
function nativeBatch(payload) {
|
|
4
|
-
if (typeof payload !== "object" || payload === null || !("queue" in payload) || typeof payload.queue !== "string" || !("messages" in payload) || !Array.isArray(payload.messages)) throw new TypeError("Invalid native queue batch.");
|
|
5
|
-
const messages = [];
|
|
6
|
-
for (const message of payload.messages) {
|
|
7
|
-
if (typeof message !== "object" || message === null || !("body" in message) || !("ack" in message) || typeof message.ack !== "function" || !("retry" in message) || typeof message.retry !== "function" || !("id" in message) || typeof message.id !== "string" || !("timestamp" in message) || !(message.timestamp instanceof Date) || !("attempts" in message) || typeof message.attempts !== "number") throw new TypeError("Invalid native queue message.");
|
|
8
|
-
messages.push(message);
|
|
9
|
-
}
|
|
10
|
-
return {
|
|
11
|
-
queue: payload.queue,
|
|
12
|
-
messages
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
/** Native sends are awaited. No buffering, implicit retry, or deferred error handling. */
|
|
16
|
-
function cloudflareQueueDriver(bindings, options = {}) {
|
|
17
|
-
const queues = new Map(Object.entries(bindings));
|
|
18
|
-
const consumers = new Map(Object.entries(options.consumers ?? {}));
|
|
19
|
-
for (const [physical, logical] of consumers) if (!physical.trim() || !logical.trim()) throw new TypeError("Queue mapping names must not be empty.");
|
|
20
|
-
const producerBindings = Object.entries(options.producerBindings ?? {});
|
|
21
|
-
for (const [logical, binding] of producerBindings) if (!queues.has(logical) || !binding.trim()) throw new TypeError("Invalid queue producer binding declaration.");
|
|
22
|
-
return {
|
|
23
|
-
kind: "cloudflare",
|
|
24
|
-
entrypoints: [...[...consumers].map(([queueName, queue]) => ({
|
|
25
|
-
kind: "cf:queue:module",
|
|
26
|
-
queue,
|
|
27
|
-
meta: {
|
|
28
|
-
queueName,
|
|
29
|
-
logicalQueue: queue
|
|
30
|
-
}
|
|
31
|
-
})), ...producerBindings.map(([queue, binding]) => ({
|
|
32
|
-
kind: "cf:queue:producer",
|
|
33
|
-
queue,
|
|
34
|
-
meta: {
|
|
35
|
-
logicalQueue: queue,
|
|
36
|
-
binding
|
|
37
|
-
}
|
|
38
|
-
}))],
|
|
39
|
-
async consume(payload, dispatch) {
|
|
40
|
-
const batch = nativeBatch(payload);
|
|
41
|
-
const queue = consumers.get(batch.queue);
|
|
42
|
-
if (!queue) throw new Error(`No consumer mapping for queue '${batch.queue}'.`);
|
|
43
|
-
await consumeQueueBatch(batch, (job) => dispatch(job), { queue });
|
|
44
|
-
},
|
|
45
|
-
async enqueue(job, options) {
|
|
46
|
-
const queue = queues.get(job.queue);
|
|
47
|
-
if (!queue) throw new Error(`No Cloudflare producer binding for queue '${job.queue}'.`);
|
|
48
|
-
const delayMs = options?.delayMs;
|
|
49
|
-
if (delayMs !== void 0 && (!Number.isFinite(delayMs) || delayMs < 0 || delayMs > 864e5)) throw new RangeError("Queue delayMs must be between 0 and 86400000.");
|
|
50
|
-
await queue.send(parseQueueJob(job), delayMs === void 0 ? void 0 : { delaySeconds: Math.ceil(delayMs / 1e3) });
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Bridge native messages to portable dispatch. Attempts come from the host.
|
|
56
|
-
* Process every message; ack successful/unsettled deliveries, then rethrow any
|
|
57
|
-
* failures so the host retries the unsettled remainder. Explicit settlement wins.
|
|
58
|
-
* The callback must await all work that should determine delivery success.
|
|
59
|
-
*/
|
|
60
|
-
async function consumeQueueBatch(batch, dispatch, options = {}) {
|
|
61
|
-
const errors = [];
|
|
62
|
-
const queue = options.queue ?? batch.queue;
|
|
63
|
-
for (const message of batch.messages) try {
|
|
64
|
-
const job = parseQueueJob(message.body, message.attempts);
|
|
65
|
-
if (job.queue !== queue) throw new Error(`Queue envelope '${job.queue}' does not match '${queue}'.`);
|
|
66
|
-
const observed = observeMessage(message);
|
|
67
|
-
if ((await dispatch(job, observed.message))?.handled === 0) throw new Error(`Queue job '${job.name}' has no handler.`);
|
|
68
|
-
if (observed.disposition().outcome === "unsettled") observed.message.ack();
|
|
69
|
-
} catch (error) {
|
|
70
|
-
errors.push(error);
|
|
71
|
-
}
|
|
72
|
-
if (errors.length === 1) throw errors[0];
|
|
73
|
-
if (errors.length > 1) throw new AggregateError(errors, "Queue batch deliveries failed.");
|
|
74
|
-
}
|
|
75
|
-
//#endregion
|
|
76
|
-
export { cloudflareQueueDriver, consumeQueueBatch };
|
|
77
|
-
|
|
78
|
-
//# sourceMappingURL=queue.js.map
|
package/dist/queue.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"queue.js","names":[],"sources":["../src/queue/cloudflare-queue.ts"],"sourcesContent":["import { observeMessage, parseQueueJob } from '@velajs/vela/queue';\nimport type {\n QueueDispatchResult,\n QueueDriver,\n QueueJob,\n QueueMessageLike,\n} from '@velajs/vela/queue';\n\n/** Logical queue names mapped to native producer bindings from this application's environment. */\nexport interface CloudflareQueueProducer {\n // Both older void-returning bindings and current metric-returning bindings work.\n send(message: QueueJob, options?: QueueSendOptions): Promise<unknown>;\n}\nexport type CloudflareQueueBindings = Readonly<Record<string, CloudflareQueueProducer>>;\n\nexport interface CloudflareQueueDriverOptions {\n /** Physical delivery queue name -> logical QueueModule name. */\n consumers?: Readonly<Record<string, string>>;\n /** Logical queue -> Wrangler producer binding name, for deployment inspection. */\n producerBindings?: Readonly<Record<string, string>>;\n}\n\nfunction nativeBatch(payload: unknown): {\n queue: string;\n messages: QueueMessageLike[];\n} {\n if (\n typeof payload !== 'object' ||\n payload === null ||\n !('queue' in payload) ||\n typeof payload.queue !== 'string' ||\n !('messages' in payload) ||\n !Array.isArray(payload.messages)\n )\n throw new TypeError('Invalid native queue batch.');\n const messages: QueueMessageLike[] = [];\n for (const message of payload.messages as unknown[]) {\n if (\n typeof message !== 'object' ||\n message === null ||\n !('body' in message) ||\n !('ack' in message) ||\n typeof message.ack !== 'function' ||\n !('retry' in message) ||\n typeof message.retry !== 'function' ||\n !('id' in message) ||\n typeof message.id !== 'string' ||\n !('timestamp' in message) ||\n !(message.timestamp instanceof Date) ||\n !('attempts' in message) ||\n typeof message.attempts !== 'number'\n )\n throw new TypeError('Invalid native queue message.');\n messages.push(message as QueueMessageLike);\n }\n return { queue: payload.queue, messages };\n}\n\n/** Native sends are awaited. No buffering, implicit retry, or deferred error handling. */\nexport function cloudflareQueueDriver(\n bindings: CloudflareQueueBindings,\n options: CloudflareQueueDriverOptions = {},\n): QueueDriver {\n const queues = new Map(Object.entries(bindings));\n const consumers = new Map(Object.entries(options.consumers ?? {}));\n for (const [physical, logical] of consumers) {\n if (!physical.trim() || !logical.trim())\n throw new TypeError('Queue mapping names must not be empty.');\n }\n const producerBindings = Object.entries(options.producerBindings ?? {});\n for (const [logical, binding] of producerBindings) {\n if (!queues.has(logical) || !binding.trim())\n throw new TypeError('Invalid queue producer binding declaration.');\n }\n return {\n kind: 'cloudflare',\n entrypoints: [\n ...[...consumers].map(([queueName, queue]) => ({\n kind: 'cf:queue:module',\n queue,\n meta: { queueName, logicalQueue: queue },\n })),\n ...producerBindings.map(([queue, binding]) => ({\n kind: 'cf:queue:producer',\n queue,\n meta: { logicalQueue: queue, binding },\n })),\n ],\n async consume(payload, dispatch) {\n const batch = nativeBatch(payload);\n const queue = consumers.get(batch.queue);\n if (!queue) throw new Error(`No consumer mapping for queue '${batch.queue}'.`);\n await consumeQueueBatch(batch, (job) => dispatch(job), { queue });\n },\n async enqueue(job, options) {\n const queue = queues.get(job.queue);\n if (!queue) throw new Error(`No Cloudflare producer binding for queue '${job.queue}'.`);\n const delayMs = options?.delayMs;\n if (\n delayMs !== undefined &&\n (!Number.isFinite(delayMs) || delayMs < 0 || delayMs > 86_400_000)\n ) {\n throw new RangeError('Queue delayMs must be between 0 and 86400000.');\n }\n await queue.send(\n parseQueueJob(job),\n delayMs === undefined ? undefined : { delaySeconds: Math.ceil(delayMs / 1000) },\n );\n },\n };\n}\n\nexport interface ConsumeQueueBatchOptions {\n /** Logical queue name. Defaults to the native batch queue name. */\n queue?: string;\n}\n\n/**\n * Bridge native messages to portable dispatch. Attempts come from the host.\n * Process every message; ack successful/unsettled deliveries, then rethrow any\n * failures so the host retries the unsettled remainder. Explicit settlement wins.\n * The callback must await all work that should determine delivery success.\n */\nexport async function consumeQueueBatch(\n batch: { readonly queue: string; readonly messages: readonly QueueMessageLike[] },\n dispatch: (job: QueueJob, message: QueueMessageLike) => Promise<QueueDispatchResult | void>,\n options: ConsumeQueueBatchOptions = {},\n): Promise<void> {\n const errors: unknown[] = [];\n const queue = options.queue ?? batch.queue;\n for (const message of batch.messages) {\n try {\n const job = parseQueueJob(message.body, message.attempts);\n if (job.queue !== queue)\n throw new Error(`Queue envelope '${job.queue}' does not match '${queue}'.`);\n const observed = observeMessage(message);\n const result = await dispatch(job, observed.message);\n if (result?.handled === 0) throw new Error(`Queue job '${job.name}' has no handler.`);\n if (observed.disposition().outcome === 'unsettled') observed.message.ack();\n } catch (error) {\n errors.push(error);\n }\n }\n if (errors.length === 1) throw errors[0];\n if (errors.length > 1) throw new AggregateError(errors, 'Queue batch deliveries failed.');\n}\n"],"mappings":"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"}
|