@velajs/cloudflare 1.10.1 → 2.0.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 +6 -0
- package/LICENSE +21 -0
- package/README.md +197 -322
- package/dist/durable-objects.d.ts +28 -0
- package/dist/durable-objects.js +494 -0
- package/dist/durable-objects.js.map +1 -0
- package/dist/index.d.ts +193 -376
- package/dist/index.js +412 -1034
- package/dist/index.js.map +1 -1
- package/dist/nonce-validation-LE0vFk-7.js +445 -0
- package/dist/nonce-validation-LE0vFk-7.js.map +1 -0
- package/dist/nonce.durable-object-Df3_42Sy.d.ts +141 -0
- package/package.json +34 -26
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { Type } from "@velajs/vela";
|
|
2
|
+
import { DurableObject } from "cloudflare:workers";
|
|
3
|
+
//#region src/root-module.d.ts
|
|
4
|
+
/** A static module, or a module graph built from this Worker's native environment. */
|
|
5
|
+
type CloudflareRoot<T extends object> = Type | {
|
|
6
|
+
create(env: T): Type;
|
|
7
|
+
};
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/websocket/do-pitr.d.ts
|
|
10
|
+
/**
|
|
11
|
+
* Durable Object point-in-time recovery (PITR) — thin, testable wrappers over a
|
|
12
|
+
* SQLite-backed DO's native bookmark API. A SQLite Durable Object exposes three
|
|
13
|
+
* storage methods (last-30-days PITR):
|
|
14
|
+
*
|
|
15
|
+
* - `getCurrentBookmark()` — an opaque bookmark for the storage's current state.
|
|
16
|
+
* - `getBookmarkForTime(t)` — the bookmark closest to a wall-clock instant.
|
|
17
|
+
* - `onNextSessionRestoreBookmark(b)` — arm a restore to bookmark `b`; the DO
|
|
18
|
+
* restores to it the next time it starts a session, and the call RETURNS a
|
|
19
|
+
* bookmark for the state JUST BEFORE the restore (the undo handle).
|
|
20
|
+
*
|
|
21
|
+
* These methods are ABSENT on a non-SQLite DO (key-value storage) and in some
|
|
22
|
+
* local-dev runtimes, so this module models storage structurally with all three
|
|
23
|
+
* methods OPTIONAL and degrades to a typed {@link DoPitrUnavailableError} (a
|
|
24
|
+
* `code: 'PITR_UNAVAILABLE'`, HTTP 409 error) rather than an
|
|
25
|
+
* `undefined is not a function` TypeError when a needed method is missing.
|
|
26
|
+
*
|
|
27
|
+
* Neither wrapper aborts the DO — `armDoPitr` only ARMS the restore and returns
|
|
28
|
+
* the undo bookmark; the caller (the WS-DO RPC method) decides whether to
|
|
29
|
+
* `ctx.abort()` to apply it immediately vs. on the next natural restart.
|
|
30
|
+
*
|
|
31
|
+
* This file is `cloudflare:workers`-free and pulls in NOTHING from `@velajs/vela`
|
|
32
|
+
* or `@velajs/studio` — it is the raw capability the studio `TimeTravelPort`
|
|
33
|
+
* wraps. Dependency direction is one-way: studio → cloudflare, never the reverse.
|
|
34
|
+
*/
|
|
35
|
+
/**
|
|
36
|
+
* The subset of `DurableObjectStorage` this module touches, with every method
|
|
37
|
+
* OPTIONAL so it structurally models a non-SQLite DO whose storage has none of
|
|
38
|
+
* them. A real `DurableObjectStorage` (whose methods are required) is assignable
|
|
39
|
+
* to this shape.
|
|
40
|
+
*/
|
|
41
|
+
interface DoPitrStorage {
|
|
42
|
+
getCurrentBookmark?(): Promise<string>;
|
|
43
|
+
getBookmarkForTime?(timestamp: number | Date): Promise<string>;
|
|
44
|
+
onNextSessionRestoreBookmark?(bookmark: string): Promise<string>;
|
|
45
|
+
}
|
|
46
|
+
/** A read of a DO's current bookmark (+ the by-time bookmark when a time is given). */
|
|
47
|
+
interface DoPitrBookmarkRead {
|
|
48
|
+
/** The bookmark for the DO storage's current state. */
|
|
49
|
+
current: string;
|
|
50
|
+
/** The bookmark closest to the requested time (only when `time` was passed). */
|
|
51
|
+
forTime?: string;
|
|
52
|
+
}
|
|
53
|
+
/** Arming input for {@link armDoPitr}: a target (bookmark WINS over time) + restart intent. */
|
|
54
|
+
interface DoPitrArmOptions {
|
|
55
|
+
/** An explicit target bookmark. Takes precedence over `time`. */
|
|
56
|
+
bookmark?: string;
|
|
57
|
+
/** A wall-clock target (epoch ms, ISO string, or Date), resolved to a bookmark. */
|
|
58
|
+
time?: number | string | Date;
|
|
59
|
+
/** Caller intent to restart-now; recorded on the result. `armDoPitr` never aborts. */
|
|
60
|
+
restart?: boolean;
|
|
61
|
+
}
|
|
62
|
+
/** The result of arming a PITR restore (before any restart is applied). */
|
|
63
|
+
interface DoPitrArmResult {
|
|
64
|
+
/** The bookmark the restore is armed to. */
|
|
65
|
+
restoredTo: string;
|
|
66
|
+
/** The bookmark for the pre-restore state — restore to this to undo. */
|
|
67
|
+
undoBookmark: string;
|
|
68
|
+
/** Whether a restart-now was requested (the RPC layer performs the actual abort). */
|
|
69
|
+
restarted: boolean;
|
|
70
|
+
}
|
|
71
|
+
/** The RPC surface a PITR-capable Vela WebSocket DO stub exposes to a Worker. */
|
|
72
|
+
interface VelaDoPitrRpc {
|
|
73
|
+
pitrCurrentBookmark(): Promise<DoPitrBookmarkRead>;
|
|
74
|
+
pitrBookmarkForTime(time: number | string): Promise<DoPitrBookmarkRead>;
|
|
75
|
+
pitrArmRestore(opts: DoPitrArmOptions): Promise<DoPitrArmResult>;
|
|
76
|
+
}
|
|
77
|
+
/** Structural view of a DO id (avoids depending on `@cloudflare/workers-types` downstream). */
|
|
78
|
+
interface DoPitrId {
|
|
79
|
+
toString(): string;
|
|
80
|
+
readonly name?: string | null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Structural view of a DO namespace binding whose stubs speak the PITR RPC. A
|
|
84
|
+
* downstream (the studio `@velajs/studio/cloudflare` port) types the app's
|
|
85
|
+
* namespace binding as this shape to reach the PITR methods without importing
|
|
86
|
+
* `@cloudflare/workers-types`.
|
|
87
|
+
*/
|
|
88
|
+
interface DoPitrNamespace {
|
|
89
|
+
idFromName(name: string): DoPitrId;
|
|
90
|
+
get(id: DoPitrId): VelaDoPitrRpc;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Thrown when a DO's storage lacks the SQLite bookmark API (non-SQLite DO, or a
|
|
94
|
+
* local runtime without PITR). Carries a stable `code` + HTTP 409 `status`, and
|
|
95
|
+
* a recognizable `name`/message so the studio port can map it to
|
|
96
|
+
* `TIMETRAVEL_UNAVAILABLE` even after the error crosses the Worker→DO RPC hop
|
|
97
|
+
* (which preserves `name` + `message`, not arbitrary own-properties).
|
|
98
|
+
*/
|
|
99
|
+
declare class DoPitrUnavailableError extends Error {
|
|
100
|
+
readonly code = "PITR_UNAVAILABLE";
|
|
101
|
+
readonly status = 409;
|
|
102
|
+
constructor(message?: string);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* True when `error` signals DO PITR unavailability. Robust across the Worker→DO
|
|
106
|
+
* RPC hop: checks the `code` own-property (same process) AND the `name` / message
|
|
107
|
+
* sentinel (survive RPC serialization) so a downstream can classify it either way.
|
|
108
|
+
*/
|
|
109
|
+
declare function isDoPitrUnavailable(error: unknown): boolean;
|
|
110
|
+
/**
|
|
111
|
+
* Read a DO's current bookmark, and — when `time` is given — the bookmark closest
|
|
112
|
+
* to that instant. Throws {@link DoPitrUnavailableError} when a needed method is
|
|
113
|
+
* absent, never `undefined is not a function`.
|
|
114
|
+
*/
|
|
115
|
+
declare function readDoPitrBookmark(storage: DoPitrStorage, time?: number | string | Date): Promise<DoPitrBookmarkRead>;
|
|
116
|
+
/**
|
|
117
|
+
* Arm a PITR restore. Resolves the target (an explicit `bookmark` WINS over
|
|
118
|
+
* `time`), arms it via `onNextSessionRestoreBookmark`, and returns the undo
|
|
119
|
+
* bookmark the DO reports for the pre-restore state. Does NOT abort — the caller
|
|
120
|
+
* decides whether to restart now. Throws {@link DoPitrUnavailableError} when the
|
|
121
|
+
* arming API (or the by-time resolver a `time` target needs) is absent.
|
|
122
|
+
*/
|
|
123
|
+
declare function armDoPitr(storage: DoPitrStorage, opts: DoPitrArmOptions): Promise<DoPitrArmResult>;
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/nonce/nonce.durable-object.d.ts
|
|
126
|
+
/**
|
|
127
|
+
* SQLite Durable Object that atomically consumes nonces.
|
|
128
|
+
*
|
|
129
|
+
* Export this class from the Worker entry and register it through a Wrangler
|
|
130
|
+
* `new_sqlite_classes` migration. `INSERT ... ON CONFLICT DO NOTHING RETURNING`
|
|
131
|
+
* is the single-use decision; all SQL runs synchronously before the RPC method
|
|
132
|
+
* yields, and the nonce primary key is the final concurrency boundary.
|
|
133
|
+
*/
|
|
134
|
+
declare class VelaNonceDurableObject extends DurableObject<Record<string, unknown>> {
|
|
135
|
+
private sql?;
|
|
136
|
+
constructor(ctx: DurableObjectState, env: Record<string, unknown>);
|
|
137
|
+
claim(nonce: string, expEpochSeconds: number): Promise<boolean>;
|
|
138
|
+
}
|
|
139
|
+
//#endregion
|
|
140
|
+
export { DoPitrId as a, DoPitrUnavailableError as c, isDoPitrUnavailable as d, readDoPitrBookmark as f, DoPitrBookmarkRead as i, VelaDoPitrRpc as l, DoPitrArmOptions as n, DoPitrNamespace as o, CloudflareRoot as p, DoPitrArmResult as r, DoPitrStorage as s, VelaNonceDurableObject as t, armDoPitr as u };
|
|
141
|
+
//# sourceMappingURL=nonce.durable-object-Df3_42Sy.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velajs/cloudflare",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "Cloudflare Workers integration for Vela framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -14,15 +14,16 @@
|
|
|
14
14
|
"r2",
|
|
15
15
|
"vela"
|
|
16
16
|
],
|
|
17
|
-
"homepage": "https://github.com/velajs/cloudflare#readme",
|
|
17
|
+
"homepage": "https://github.com/velajs/vela/tree/main/cloudflare#readme",
|
|
18
18
|
"bugs": {
|
|
19
|
-
"url": "https://github.com/velajs/
|
|
19
|
+
"url": "https://github.com/velajs/vela/issues"
|
|
20
20
|
},
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"author": "ksh",
|
|
23
23
|
"repository": {
|
|
24
24
|
"type": "git",
|
|
25
|
-
"url": "git+https://github.com/velajs/
|
|
25
|
+
"url": "git+https://github.com/velajs/vela.git",
|
|
26
|
+
"directory": "cloudflare"
|
|
26
27
|
},
|
|
27
28
|
"files": [
|
|
28
29
|
"dist",
|
|
@@ -38,29 +39,35 @@
|
|
|
38
39
|
".": {
|
|
39
40
|
"types": "./dist/index.d.ts",
|
|
40
41
|
"import": "./dist/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./durable-objects": {
|
|
44
|
+
"types": "./dist/durable-objects.d.ts",
|
|
45
|
+
"import": "./dist/durable-objects.js"
|
|
41
46
|
}
|
|
42
47
|
},
|
|
43
48
|
"devDependencies": {
|
|
44
|
-
"@arethetypeswrong/cli": "
|
|
45
|
-
"@changesets/cli": "
|
|
46
|
-
"@cloudflare/
|
|
47
|
-
"@
|
|
48
|
-
"@
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
49
|
+
"@arethetypeswrong/cli": "0.18.5",
|
|
50
|
+
"@changesets/cli": "2.31.0",
|
|
51
|
+
"@cloudflare/vitest-plugin": "1.1.13",
|
|
52
|
+
"@cloudflare/workers-types": "5.20260920.1",
|
|
53
|
+
"@swc/core": "1.15.43",
|
|
54
|
+
"hono": "4.13.8",
|
|
55
|
+
"oxfmt": "0.58.0",
|
|
56
|
+
"oxlint": "1.73.0",
|
|
57
|
+
"publint": "0.3.21",
|
|
58
|
+
"tsdown": "0.23.0",
|
|
59
|
+
"typescript": "7.0.2",
|
|
60
|
+
"unplugin-swc": "1.5.9",
|
|
61
|
+
"vitest": "4.1.10",
|
|
62
|
+
"zod": "^3.25.76",
|
|
63
|
+
"@velajs/feature-flags": "2.0.0",
|
|
64
|
+
"@velajs/vela": "2.0.0"
|
|
58
65
|
},
|
|
59
66
|
"peerDependencies": {
|
|
60
67
|
"@cloudflare/workers-types": ">=4",
|
|
61
|
-
"
|
|
62
|
-
"@velajs/
|
|
63
|
-
"
|
|
68
|
+
"hono": ">=4",
|
|
69
|
+
"@velajs/feature-flags": "^2.0.0",
|
|
70
|
+
"@velajs/vela": "^2.0.0"
|
|
64
71
|
},
|
|
65
72
|
"peerDependenciesMeta": {
|
|
66
73
|
"@velajs/feature-flags": {
|
|
@@ -70,18 +77,19 @@
|
|
|
70
77
|
"engines": {
|
|
71
78
|
"node": ">=24"
|
|
72
79
|
},
|
|
80
|
+
"publishConfig": {
|
|
81
|
+
"access": "public"
|
|
82
|
+
},
|
|
73
83
|
"scripts": {
|
|
74
84
|
"build": "tsdown",
|
|
75
85
|
"test": "vitest run",
|
|
76
|
-
"
|
|
86
|
+
"test:workers": "vitest run --config vitest.config.workers.ts",
|
|
87
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
|
|
77
88
|
"lint": "oxlint .",
|
|
78
89
|
"format": "oxfmt .",
|
|
79
90
|
"format:check": "oxfmt --check .",
|
|
80
91
|
"publint": "publint",
|
|
81
92
|
"attw": "attw --pack . --profile esm-only",
|
|
82
|
-
"
|
|
83
|
-
"version-packages": "changeset version",
|
|
84
|
-
"release": "pnpm build && changeset publish",
|
|
85
|
-
"verify": "pnpm lint && pnpm format:check && pnpm build && pnpm typecheck && pnpm test && pnpm publint && pnpm attw"
|
|
93
|
+
"verify": "pnpm lint && pnpm format:check && pnpm build && pnpm typecheck && pnpm test && pnpm test:workers && pnpm publint && pnpm attw"
|
|
86
94
|
}
|
|
87
95
|
}
|