@rivetkit/cloudflare-workers 2.0.6 → 2.0.7
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/dist/mod.cjs +54 -48
- package/dist/mod.cjs.map +1 -1
- package/dist/mod.d.cts +52 -25
- package/dist/mod.d.ts +52 -25
- package/dist/mod.js +59 -53
- package/dist/mod.js.map +1 -1
- package/package.json +6 -3
- package/src/actor-driver.ts +4 -19
- package/src/actor-handler-do.ts +19 -18
- package/src/manager-driver.ts +40 -18
- package/src/websocket.ts +9 -2
package/src/actor-driver.ts
CHANGED
|
@@ -4,17 +4,14 @@ import type {
|
|
|
4
4
|
RegistryConfig,
|
|
5
5
|
RunConfig,
|
|
6
6
|
} from "rivetkit";
|
|
7
|
-
import {
|
|
8
|
-
createGenericConnDrivers,
|
|
9
|
-
GenericConnGlobalState,
|
|
10
|
-
lookupInRegistry,
|
|
11
|
-
} from "rivetkit";
|
|
7
|
+
import { lookupInRegistry } from "rivetkit";
|
|
12
8
|
import type { Client } from "rivetkit/client";
|
|
13
9
|
import type {
|
|
14
10
|
ActorDriver,
|
|
15
11
|
AnyActorInstance,
|
|
16
12
|
ManagerDriver,
|
|
17
13
|
} from "rivetkit/driver-helpers";
|
|
14
|
+
import { promiseWithResolvers } from "rivetkit/utils";
|
|
18
15
|
import { KEYS } from "./actor-handler-do";
|
|
19
16
|
|
|
20
17
|
interface DurableObjectGlobalState {
|
|
@@ -49,8 +46,8 @@ export interface DriverContext {
|
|
|
49
46
|
// Actor handler to track running instances
|
|
50
47
|
class ActorHandler {
|
|
51
48
|
actor?: AnyActorInstance;
|
|
52
|
-
actorPromise?:
|
|
53
|
-
|
|
49
|
+
actorPromise?: ReturnType<typeof promiseWithResolvers<void>> =
|
|
50
|
+
promiseWithResolvers();
|
|
54
51
|
}
|
|
55
52
|
|
|
56
53
|
export class CloudflareActorsActorDriver implements ActorDriver {
|
|
@@ -114,11 +111,7 @@ export class CloudflareActorsActorDriver implements ActorDriver {
|
|
|
114
111
|
handler.actor = definition.instantiate();
|
|
115
112
|
|
|
116
113
|
// Start actor
|
|
117
|
-
const connDrivers = createGenericConnDrivers(
|
|
118
|
-
handler.genericConnGlobalState,
|
|
119
|
-
);
|
|
120
114
|
await handler.actor.start(
|
|
121
|
-
connDrivers,
|
|
122
115
|
this,
|
|
123
116
|
this.#inlineClient,
|
|
124
117
|
actorId,
|
|
@@ -134,14 +127,6 @@ export class CloudflareActorsActorDriver implements ActorDriver {
|
|
|
134
127
|
return handler.actor;
|
|
135
128
|
}
|
|
136
129
|
|
|
137
|
-
getGenericConnGlobalState(actorId: string): GenericConnGlobalState {
|
|
138
|
-
const handler = this.#actors.get(actorId);
|
|
139
|
-
if (!handler) {
|
|
140
|
-
throw new Error(`Actor ${actorId} not loaded`);
|
|
141
|
-
}
|
|
142
|
-
return handler.genericConnGlobalState;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
130
|
getContext(actorId: string): DriverContext {
|
|
146
131
|
const state = this.#globalState.getDOState(actorId);
|
|
147
132
|
return { state: state.ctx };
|
package/src/actor-handler-do.ts
CHANGED
|
@@ -3,7 +3,12 @@ import type { ExecutionContext } from "hono";
|
|
|
3
3
|
import invariant from "invariant";
|
|
4
4
|
import type { ActorKey, ActorRouter, Registry, RunConfig } from "rivetkit";
|
|
5
5
|
import { createActorRouter, createClientWithDriver } from "rivetkit";
|
|
6
|
-
import {
|
|
6
|
+
import type { ActorDriver } from "rivetkit/driver-helpers";
|
|
7
|
+
import {
|
|
8
|
+
type ManagerDriver,
|
|
9
|
+
serializeEmptyPersistData,
|
|
10
|
+
} from "rivetkit/driver-helpers";
|
|
11
|
+
import { promiseWithResolvers } from "rivetkit/utils";
|
|
7
12
|
import {
|
|
8
13
|
CloudflareDurableObjectGlobalState,
|
|
9
14
|
createCloudflareActorsActorDriverBuilder,
|
|
@@ -38,6 +43,7 @@ export type DurableObjectConstructor = new (
|
|
|
38
43
|
|
|
39
44
|
interface LoadedActor {
|
|
40
45
|
actorRouter: ActorRouter;
|
|
46
|
+
actorDriver: ActorDriver;
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
export function createActorDurableObject(
|
|
@@ -60,7 +66,7 @@ export function createActorDurableObject(
|
|
|
60
66
|
implements ActorHandlerInterface
|
|
61
67
|
{
|
|
62
68
|
#initialized?: InitializedData;
|
|
63
|
-
#initializedPromise?:
|
|
69
|
+
#initializedPromise?: ReturnType<typeof promiseWithResolvers<void>>;
|
|
64
70
|
|
|
65
71
|
#actor?: LoadedActor;
|
|
66
72
|
|
|
@@ -71,7 +77,7 @@ export function createActorDurableObject(
|
|
|
71
77
|
if (this.#initializedPromise) {
|
|
72
78
|
await this.#initializedPromise.promise;
|
|
73
79
|
} else {
|
|
74
|
-
this.#initializedPromise =
|
|
80
|
+
this.#initializedPromise = promiseWithResolvers();
|
|
75
81
|
const res = await this.ctx.storage.get([
|
|
76
82
|
KEYS.NAME,
|
|
77
83
|
KEYS.KEY,
|
|
@@ -118,6 +124,8 @@ export function createActorDurableObject(
|
|
|
118
124
|
runConfig,
|
|
119
125
|
);
|
|
120
126
|
|
|
127
|
+
configureInspectorAccessToken(registry.config, managerDriver);
|
|
128
|
+
|
|
121
129
|
// Create inline client
|
|
122
130
|
const inlineClient = createClientWithDriver(managerDriver);
|
|
123
131
|
|
|
@@ -135,6 +143,7 @@ export function createActorDurableObject(
|
|
|
135
143
|
// Save actor
|
|
136
144
|
this.#actor = {
|
|
137
145
|
actorRouter,
|
|
146
|
+
actorDriver,
|
|
138
147
|
};
|
|
139
148
|
|
|
140
149
|
// Initialize the actor instance with proper metadata
|
|
@@ -174,26 +183,18 @@ export function createActorDurableObject(
|
|
|
174
183
|
}
|
|
175
184
|
|
|
176
185
|
async alarm(): Promise<void> {
|
|
177
|
-
await this.#loadActor();
|
|
186
|
+
const { actorDriver } = await this.#loadActor();
|
|
178
187
|
const actorId = this.ctx.id.toString();
|
|
179
188
|
|
|
180
|
-
// Get the actor driver
|
|
181
|
-
invariant(runConfig.driver, "runConfig.driver");
|
|
182
|
-
const managerDriver = runConfig.driver.manager(
|
|
183
|
-
registry.config,
|
|
184
|
-
runConfig,
|
|
185
|
-
);
|
|
186
|
-
const inlineClient = createClientWithDriver(managerDriver);
|
|
187
|
-
const actorDriver = runConfig.driver.actor(
|
|
188
|
-
registry.config,
|
|
189
|
-
runConfig,
|
|
190
|
-
managerDriver,
|
|
191
|
-
inlineClient,
|
|
192
|
-
);
|
|
193
|
-
|
|
194
189
|
// Load the actor instance and trigger alarm
|
|
195
190
|
const actor = await actorDriver.loadActor(actorId);
|
|
196
191
|
await actor._onAlarm();
|
|
197
192
|
}
|
|
198
193
|
};
|
|
199
194
|
}
|
|
195
|
+
function configureInspectorAccessToken(
|
|
196
|
+
config: any,
|
|
197
|
+
managerDriver: ManagerDriver,
|
|
198
|
+
) {
|
|
199
|
+
throw new Error("Function not implemented.");
|
|
200
|
+
}
|
package/src/manager-driver.ts
CHANGED
|
@@ -6,11 +6,15 @@ import {
|
|
|
6
6
|
type GetForIdInput,
|
|
7
7
|
type GetOrCreateWithKeyInput,
|
|
8
8
|
type GetWithKeyInput,
|
|
9
|
-
HEADER_AUTH_DATA,
|
|
10
|
-
HEADER_CONN_PARAMS,
|
|
11
|
-
HEADER_ENCODING,
|
|
12
9
|
type ManagerDisplayInformation,
|
|
13
10
|
type ManagerDriver,
|
|
11
|
+
WS_PROTOCOL_ACTOR,
|
|
12
|
+
WS_PROTOCOL_CONN_ID,
|
|
13
|
+
WS_PROTOCOL_CONN_PARAMS,
|
|
14
|
+
WS_PROTOCOL_CONN_TOKEN,
|
|
15
|
+
WS_PROTOCOL_ENCODING,
|
|
16
|
+
WS_PROTOCOL_STANDARD,
|
|
17
|
+
WS_PROTOCOL_TARGET,
|
|
14
18
|
} from "rivetkit/driver-helpers";
|
|
15
19
|
import { ActorAlreadyExists, InternalError } from "rivetkit/errors";
|
|
16
20
|
import { getCloudflareAmbientEnv } from "./handler";
|
|
@@ -68,6 +72,8 @@ export class CloudflareActorsManagerDriver implements ManagerDriver {
|
|
|
68
72
|
actorId: string,
|
|
69
73
|
encoding: Encoding,
|
|
70
74
|
params: unknown,
|
|
75
|
+
connId?: string,
|
|
76
|
+
connToken?: string,
|
|
71
77
|
): Promise<UniversalWebSocket> {
|
|
72
78
|
const env = getCloudflareAmbientEnv();
|
|
73
79
|
|
|
@@ -81,19 +87,32 @@ export class CloudflareActorsManagerDriver implements ManagerDriver {
|
|
|
81
87
|
const id = env.ACTOR_DO.idFromString(actorId);
|
|
82
88
|
const stub = env.ACTOR_DO.get(id);
|
|
83
89
|
|
|
90
|
+
const protocols: string[] = [];
|
|
91
|
+
protocols.push(WS_PROTOCOL_STANDARD);
|
|
92
|
+
protocols.push(`${WS_PROTOCOL_TARGET}actor`);
|
|
93
|
+
protocols.push(`${WS_PROTOCOL_ACTOR}${actorId}`);
|
|
94
|
+
protocols.push(`${WS_PROTOCOL_ENCODING}${encoding}`);
|
|
95
|
+
if (params) {
|
|
96
|
+
protocols.push(
|
|
97
|
+
`${WS_PROTOCOL_CONN_PARAMS}${encodeURIComponent(JSON.stringify(params))}`,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
if (connId) {
|
|
101
|
+
protocols.push(`${WS_PROTOCOL_CONN_ID}${connId}`);
|
|
102
|
+
}
|
|
103
|
+
if (connToken) {
|
|
104
|
+
protocols.push(`${WS_PROTOCOL_CONN_TOKEN}${connToken}`);
|
|
105
|
+
}
|
|
106
|
+
|
|
84
107
|
const headers: Record<string, string> = {
|
|
85
108
|
Upgrade: "websocket",
|
|
86
109
|
Connection: "Upgrade",
|
|
87
|
-
|
|
110
|
+
"sec-websocket-protocol": protocols.join(", "),
|
|
88
111
|
};
|
|
89
|
-
if (params) {
|
|
90
|
-
headers[HEADER_CONN_PARAMS] = JSON.stringify(params);
|
|
91
|
-
}
|
|
92
|
-
// HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
|
|
93
|
-
headers["sec-websocket-protocol"] = "rivetkit";
|
|
94
112
|
|
|
95
113
|
// Use the path parameter to determine the URL
|
|
96
|
-
const
|
|
114
|
+
const normalizedPath = path.startsWith("/") ? path : `/${path}`;
|
|
115
|
+
const url = `http://actor${normalizedPath}`;
|
|
97
116
|
|
|
98
117
|
logger().debug({ msg: "rewriting websocket url", from: path, to: url });
|
|
99
118
|
|
|
@@ -104,7 +123,7 @@ export class CloudflareActorsManagerDriver implements ManagerDriver {
|
|
|
104
123
|
|
|
105
124
|
if (!webSocket) {
|
|
106
125
|
throw new InternalError(
|
|
107
|
-
|
|
126
|
+
`missing websocket connection in response from DO\n\nStatus: ${response.status}\nResponse: ${await response.text()}`,
|
|
108
127
|
);
|
|
109
128
|
}
|
|
110
129
|
|
|
@@ -151,7 +170,6 @@ export class CloudflareActorsManagerDriver implements ManagerDriver {
|
|
|
151
170
|
actorId: string,
|
|
152
171
|
encoding: Encoding,
|
|
153
172
|
params: unknown,
|
|
154
|
-
authData: unknown,
|
|
155
173
|
): Promise<Response> {
|
|
156
174
|
logger().debug({
|
|
157
175
|
msg: "forwarding websocket to durable object",
|
|
@@ -187,14 +205,18 @@ export class CloudflareActorsManagerDriver implements ManagerDriver {
|
|
|
187
205
|
}
|
|
188
206
|
}
|
|
189
207
|
|
|
190
|
-
//
|
|
191
|
-
|
|
208
|
+
// Build protocols for WebSocket connection
|
|
209
|
+
const protocols: string[] = [];
|
|
210
|
+
protocols.push(WS_PROTOCOL_STANDARD);
|
|
211
|
+
protocols.push(`${WS_PROTOCOL_TARGET}actor`);
|
|
212
|
+
protocols.push(`${WS_PROTOCOL_ACTOR}${actorId}`);
|
|
213
|
+
protocols.push(`${WS_PROTOCOL_ENCODING}${encoding}`);
|
|
192
214
|
if (params) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
actorRequest.headers.set(HEADER_AUTH_DATA, JSON.stringify(authData));
|
|
215
|
+
protocols.push(
|
|
216
|
+
`${WS_PROTOCOL_CONN_PARAMS}${encodeURIComponent(JSON.stringify(params))}`,
|
|
217
|
+
);
|
|
197
218
|
}
|
|
219
|
+
actorRequest.headers.set("sec-websocket-protocol", protocols.join(", "));
|
|
198
220
|
|
|
199
221
|
const id = c.env.ACTOR_DO.idFromString(actorId);
|
|
200
222
|
const stub = c.env.ACTOR_DO.get(id);
|
package/src/websocket.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import type { UpgradeWebSocket, WSEvents, WSReadyState } from "hono/ws";
|
|
6
6
|
import { defineWebSocketHelper, WSContext } from "hono/ws";
|
|
7
|
+
import { WS_PROTOCOL_STANDARD } from "rivetkit/driver-helpers";
|
|
7
8
|
|
|
8
9
|
// Based on https://github.com/honojs/hono/issues/1153#issuecomment-1767321332
|
|
9
10
|
export const upgradeWebSocket: UpgradeWebSocket<
|
|
@@ -62,8 +63,14 @@ export const upgradeWebSocket: UpgradeWebSocket<
|
|
|
62
63
|
|
|
63
64
|
// Set Sec-WebSocket-Protocol if does not exist
|
|
64
65
|
const protocols = c.req.header("Sec-WebSocket-Protocol");
|
|
65
|
-
if (
|
|
66
|
-
|
|
66
|
+
if (
|
|
67
|
+
typeof protocols === "string" &&
|
|
68
|
+
protocols
|
|
69
|
+
.split(",")
|
|
70
|
+
.map((x) => x.trim())
|
|
71
|
+
.includes(WS_PROTOCOL_STANDARD)
|
|
72
|
+
) {
|
|
73
|
+
headers["Sec-WebSocket-Protocol"] = WS_PROTOCOL_STANDARD;
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
return new Response(null, {
|