rivetkit 2.0.2 → 2.0.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/dist/schemas/actor-persist/v1.ts +228 -0
- package/dist/schemas/client-protocol/v1.ts +429 -0
- package/dist/schemas/file-system-driver/v1.ts +102 -0
- package/dist/tsup/actor/errors.cjs +69 -0
- package/dist/tsup/actor/errors.cjs.map +1 -0
- package/dist/tsup/actor/errors.d.cts +143 -0
- package/dist/tsup/actor/errors.d.ts +143 -0
- package/dist/tsup/actor/errors.js +69 -0
- package/dist/tsup/actor/errors.js.map +1 -0
- package/dist/tsup/chunk-2CRLFV6Z.cjs +202 -0
- package/dist/tsup/chunk-2CRLFV6Z.cjs.map +1 -0
- package/dist/tsup/chunk-3H7O2A7I.js +525 -0
- package/dist/tsup/chunk-3H7O2A7I.js.map +1 -0
- package/dist/tsup/chunk-42I3OZ3Q.js +15 -0
- package/dist/tsup/chunk-42I3OZ3Q.js.map +1 -0
- package/dist/tsup/chunk-4NSUQZ2H.js +1790 -0
- package/dist/tsup/chunk-4NSUQZ2H.js.map +1 -0
- package/dist/tsup/chunk-6PDXBYI5.js +132 -0
- package/dist/tsup/chunk-6PDXBYI5.js.map +1 -0
- package/dist/tsup/chunk-6WKQDDUD.cjs +1790 -0
- package/dist/tsup/chunk-6WKQDDUD.cjs.map +1 -0
- package/dist/tsup/chunk-CTBOSFUH.cjs +116 -0
- package/dist/tsup/chunk-CTBOSFUH.cjs.map +1 -0
- package/dist/tsup/chunk-EGVZZFE2.js +2857 -0
- package/dist/tsup/chunk-EGVZZFE2.js.map +1 -0
- package/dist/tsup/chunk-FCCPJNMA.cjs +132 -0
- package/dist/tsup/chunk-FCCPJNMA.cjs.map +1 -0
- package/dist/tsup/chunk-FLMTTN27.js +244 -0
- package/dist/tsup/chunk-FLMTTN27.js.map +1 -0
- package/dist/tsup/chunk-GIR3AFFI.cjs +315 -0
- package/dist/tsup/chunk-GIR3AFFI.cjs.map +1 -0
- package/dist/tsup/chunk-INGJP237.js +315 -0
- package/dist/tsup/chunk-INGJP237.js.map +1 -0
- package/dist/tsup/chunk-KJCJLKRM.js +116 -0
- package/dist/tsup/chunk-KJCJLKRM.js.map +1 -0
- package/dist/tsup/chunk-KUPQZYUQ.cjs +15 -0
- package/dist/tsup/chunk-KUPQZYUQ.cjs.map +1 -0
- package/dist/tsup/chunk-O2MBYIXO.cjs +2857 -0
- package/dist/tsup/chunk-O2MBYIXO.cjs.map +1 -0
- package/dist/tsup/chunk-OGAPU3UG.cjs +525 -0
- package/dist/tsup/chunk-OGAPU3UG.cjs.map +1 -0
- package/dist/tsup/chunk-OV6AYD4S.js +4406 -0
- package/dist/tsup/chunk-OV6AYD4S.js.map +1 -0
- package/dist/tsup/chunk-PO4VLDWA.js +47 -0
- package/dist/tsup/chunk-PO4VLDWA.js.map +1 -0
- package/dist/tsup/chunk-R2OPSKIV.cjs +244 -0
- package/dist/tsup/chunk-R2OPSKIV.cjs.map +1 -0
- package/dist/tsup/chunk-TZJKSBUQ.cjs +47 -0
- package/dist/tsup/chunk-TZJKSBUQ.cjs.map +1 -0
- package/dist/tsup/chunk-UBUC5C3G.cjs +189 -0
- package/dist/tsup/chunk-UBUC5C3G.cjs.map +1 -0
- package/dist/tsup/chunk-UIM22YJL.cjs +4406 -0
- package/dist/tsup/chunk-UIM22YJL.cjs.map +1 -0
- package/dist/tsup/chunk-URVFQMYI.cjs +230 -0
- package/dist/tsup/chunk-URVFQMYI.cjs.map +1 -0
- package/dist/tsup/chunk-UVUPOS46.js +230 -0
- package/dist/tsup/chunk-UVUPOS46.js.map +1 -0
- package/dist/tsup/chunk-VRRHBNJC.js +189 -0
- package/dist/tsup/chunk-VRRHBNJC.js.map +1 -0
- package/dist/tsup/chunk-XFSS33EQ.js +202 -0
- package/dist/tsup/chunk-XFSS33EQ.js.map +1 -0
- package/dist/tsup/client/mod.cjs +32 -0
- package/dist/tsup/client/mod.cjs.map +1 -0
- package/dist/tsup/client/mod.d.cts +26 -0
- package/dist/tsup/client/mod.d.ts +26 -0
- package/dist/tsup/client/mod.js +32 -0
- package/dist/tsup/client/mod.js.map +1 -0
- package/dist/tsup/common/log.cjs +13 -0
- package/dist/tsup/common/log.cjs.map +1 -0
- package/dist/tsup/common/log.d.cts +20 -0
- package/dist/tsup/common/log.d.ts +20 -0
- package/dist/tsup/common/log.js +13 -0
- package/dist/tsup/common/log.js.map +1 -0
- package/dist/tsup/common/websocket.cjs +10 -0
- package/dist/tsup/common/websocket.cjs.map +1 -0
- package/dist/tsup/common/websocket.d.cts +3 -0
- package/dist/tsup/common/websocket.d.ts +3 -0
- package/dist/tsup/common/websocket.js +10 -0
- package/dist/tsup/common/websocket.js.map +1 -0
- package/dist/tsup/common-CpqORuCq.d.cts +218 -0
- package/dist/tsup/common-CpqORuCq.d.ts +218 -0
- package/dist/tsup/connection-BR_Ve4ku.d.cts +2117 -0
- package/dist/tsup/connection-BwUMoe6n.d.ts +2117 -0
- package/dist/tsup/driver-helpers/mod.cjs +33 -0
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
- package/dist/tsup/driver-helpers/mod.d.cts +18 -0
- package/dist/tsup/driver-helpers/mod.d.ts +18 -0
- package/dist/tsup/driver-helpers/mod.js +33 -0
- package/dist/tsup/driver-helpers/mod.js.map +1 -0
- package/dist/tsup/driver-test-suite/mod.cjs +4619 -0
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
- package/dist/tsup/driver-test-suite/mod.d.cts +57 -0
- package/dist/tsup/driver-test-suite/mod.d.ts +57 -0
- package/dist/tsup/driver-test-suite/mod.js +4619 -0
- package/dist/tsup/driver-test-suite/mod.js.map +1 -0
- package/dist/tsup/inspector/mod.cjs +53 -0
- package/dist/tsup/inspector/mod.cjs.map +1 -0
- package/dist/tsup/inspector/mod.d.cts +408 -0
- package/dist/tsup/inspector/mod.d.ts +408 -0
- package/dist/tsup/inspector/mod.js +53 -0
- package/dist/tsup/inspector/mod.js.map +1 -0
- package/dist/tsup/mod.cjs +73 -0
- package/dist/tsup/mod.cjs.map +1 -0
- package/dist/tsup/mod.d.cts +100 -0
- package/dist/tsup/mod.d.ts +100 -0
- package/dist/tsup/mod.js +73 -0
- package/dist/tsup/mod.js.map +1 -0
- package/dist/tsup/router-endpoints-AYkXG8Tl.d.cts +66 -0
- package/dist/tsup/router-endpoints-DAbqVFx2.d.ts +66 -0
- package/dist/tsup/test/mod.cjs +21 -0
- package/dist/tsup/test/mod.cjs.map +1 -0
- package/dist/tsup/test/mod.d.cts +27 -0
- package/dist/tsup/test/mod.d.ts +27 -0
- package/dist/tsup/test/mod.js +21 -0
- package/dist/tsup/test/mod.js.map +1 -0
- package/dist/tsup/utils-CT0cv4jd.d.cts +17 -0
- package/dist/tsup/utils-CT0cv4jd.d.ts +17 -0
- package/dist/tsup/utils.cjs +26 -0
- package/dist/tsup/utils.cjs.map +1 -0
- package/dist/tsup/utils.d.cts +36 -0
- package/dist/tsup/utils.d.ts +36 -0
- package/dist/tsup/utils.js +26 -0
- package/dist/tsup/utils.js.map +1 -0
- package/package.json +208 -5
- package/src/actor/action.ts +182 -0
- package/src/actor/config.ts +765 -0
- package/src/actor/connection.ts +260 -0
- package/src/actor/context.ts +171 -0
- package/src/actor/database.ts +23 -0
- package/src/actor/definition.ts +86 -0
- package/src/actor/driver.ts +84 -0
- package/src/actor/errors.ts +360 -0
- package/src/actor/generic-conn-driver.ts +234 -0
- package/src/actor/instance.ts +1800 -0
- package/src/actor/log.ts +15 -0
- package/src/actor/mod.ts +113 -0
- package/src/actor/persisted.ts +42 -0
- package/src/actor/protocol/old.ts +281 -0
- package/src/actor/protocol/serde.ts +131 -0
- package/src/actor/router-endpoints.ts +685 -0
- package/src/actor/router.ts +263 -0
- package/src/actor/schedule.ts +17 -0
- package/src/actor/unstable-react.ts +110 -0
- package/src/actor/utils.ts +98 -0
- package/src/client/actor-common.ts +30 -0
- package/src/client/actor-conn.ts +804 -0
- package/src/client/actor-handle.ts +208 -0
- package/src/client/client.ts +623 -0
- package/src/client/errors.ts +41 -0
- package/src/client/http-client-driver.ts +326 -0
- package/src/client/log.ts +7 -0
- package/src/client/mod.ts +56 -0
- package/src/client/raw-utils.ts +92 -0
- package/src/client/test.ts +44 -0
- package/src/client/utils.ts +150 -0
- package/src/common/eventsource-interface.ts +47 -0
- package/src/common/eventsource.ts +80 -0
- package/src/common/fake-event-source.ts +266 -0
- package/src/common/inline-websocket-adapter2.ts +445 -0
- package/src/common/log-levels.ts +27 -0
- package/src/common/log.ts +139 -0
- package/src/common/logfmt.ts +228 -0
- package/src/common/network.ts +2 -0
- package/src/common/router.ts +87 -0
- package/src/common/utils.ts +322 -0
- package/src/common/versioned-data.ts +95 -0
- package/src/common/websocket-interface.ts +49 -0
- package/src/common/websocket.ts +43 -0
- package/src/driver-helpers/mod.ts +22 -0
- package/src/driver-helpers/utils.ts +17 -0
- package/src/driver-test-suite/log.ts +7 -0
- package/src/driver-test-suite/mod.ts +213 -0
- package/src/driver-test-suite/test-inline-client-driver.ts +402 -0
- package/src/driver-test-suite/tests/action-features.ts +136 -0
- package/src/driver-test-suite/tests/actor-auth.ts +591 -0
- package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
- package/src/driver-test-suite/tests/actor-conn.ts +349 -0
- package/src/driver-test-suite/tests/actor-driver.ts +25 -0
- package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
- package/src/driver-test-suite/tests/actor-handle.ts +259 -0
- package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
- package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
- package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
- package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
- package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
- package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
- package/src/driver-test-suite/tests/actor-state.ts +54 -0
- package/src/driver-test-suite/tests/actor-vars.ts +93 -0
- package/src/driver-test-suite/tests/manager-driver.ts +365 -0
- package/src/driver-test-suite/tests/raw-http-direct-registry.ts +226 -0
- package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
- package/src/driver-test-suite/tests/raw-http.ts +347 -0
- package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +392 -0
- package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
- package/src/driver-test-suite/tests/request-access.ts +244 -0
- package/src/driver-test-suite/utils.ts +68 -0
- package/src/drivers/default.ts +31 -0
- package/src/drivers/engine/actor-driver.ts +360 -0
- package/src/drivers/engine/api-endpoints.ts +128 -0
- package/src/drivers/engine/api-utils.ts +70 -0
- package/src/drivers/engine/config.ts +39 -0
- package/src/drivers/engine/keys.test.ts +266 -0
- package/src/drivers/engine/keys.ts +89 -0
- package/src/drivers/engine/kv.ts +3 -0
- package/src/drivers/engine/log.ts +7 -0
- package/src/drivers/engine/manager-driver.ts +391 -0
- package/src/drivers/engine/mod.ts +36 -0
- package/src/drivers/engine/ws-proxy.ts +170 -0
- package/src/drivers/file-system/actor.ts +91 -0
- package/src/drivers/file-system/global-state.ts +673 -0
- package/src/drivers/file-system/log.ts +7 -0
- package/src/drivers/file-system/manager.ts +306 -0
- package/src/drivers/file-system/mod.ts +48 -0
- package/src/drivers/file-system/utils.ts +109 -0
- package/src/globals.d.ts +6 -0
- package/src/inline-client-driver/log.ts +7 -0
- package/src/inline-client-driver/mod.ts +385 -0
- package/src/inspector/actor.ts +298 -0
- package/src/inspector/config.ts +83 -0
- package/src/inspector/log.ts +5 -0
- package/src/inspector/manager.ts +86 -0
- package/src/inspector/mod.ts +2 -0
- package/src/inspector/protocol/actor.ts +10 -0
- package/src/inspector/protocol/common.ts +196 -0
- package/src/inspector/protocol/manager.ts +10 -0
- package/src/inspector/protocol/mod.ts +2 -0
- package/src/inspector/utils.ts +76 -0
- package/src/manager/auth.ts +121 -0
- package/src/manager/driver.ts +80 -0
- package/src/manager/hono-websocket-adapter.ts +333 -0
- package/src/manager/log.ts +7 -0
- package/src/manager/mod.ts +2 -0
- package/src/manager/protocol/mod.ts +24 -0
- package/src/manager/protocol/query.ts +89 -0
- package/src/manager/router.ts +1792 -0
- package/src/mod.ts +20 -0
- package/src/registry/config.ts +32 -0
- package/src/registry/log.ts +7 -0
- package/src/registry/mod.ts +124 -0
- package/src/registry/run-config.ts +54 -0
- package/src/registry/serve.ts +53 -0
- package/src/schemas/actor-persist/mod.ts +1 -0
- package/src/schemas/actor-persist/versioned.ts +25 -0
- package/src/schemas/client-protocol/mod.ts +1 -0
- package/src/schemas/client-protocol/versioned.ts +63 -0
- package/src/schemas/file-system-driver/mod.ts +1 -0
- package/src/schemas/file-system-driver/versioned.ts +28 -0
- package/src/serde.ts +84 -0
- package/src/test/config.ts +16 -0
- package/src/test/log.ts +7 -0
- package/src/test/mod.ts +153 -0
- package/src/utils.ts +172 -0
- package/README.md +0 -13
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import type { DriverTestConfig } from "../mod";
|
|
3
|
+
import { setupDriverTest } from "../utils";
|
|
4
|
+
|
|
5
|
+
export function runRequestAccessTests(driverTestConfig: DriverTestConfig) {
|
|
6
|
+
describe("Request Access in Lifecycle Hooks", () => {
|
|
7
|
+
test("should have access to request object in onBeforeConnect and createConnState", async (c) => {
|
|
8
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
9
|
+
|
|
10
|
+
// Create actor with request tracking enabled
|
|
11
|
+
const handle = client.requestAccessActor.getOrCreate(["test-request"], {
|
|
12
|
+
params: { trackRequest: true },
|
|
13
|
+
});
|
|
14
|
+
const connection = handle.connect();
|
|
15
|
+
|
|
16
|
+
// Get request info that was captured in onBeforeConnect
|
|
17
|
+
const requestInfo = await connection.getRequestInfo();
|
|
18
|
+
|
|
19
|
+
// Verify request was accessible in HTTP mode, but not in inline mode
|
|
20
|
+
if (driverTestConfig.clientType === "http") {
|
|
21
|
+
// Check onBeforeConnect
|
|
22
|
+
expect(requestInfo.onBeforeConnect.hasRequest).toBe(true);
|
|
23
|
+
expect(requestInfo.onBeforeConnect.requestUrl).toBeDefined();
|
|
24
|
+
expect(requestInfo.onBeforeConnect.requestMethod).toBeDefined();
|
|
25
|
+
expect(requestInfo.onBeforeConnect.requestHeaders).toBeDefined();
|
|
26
|
+
|
|
27
|
+
// Check createConnState
|
|
28
|
+
expect(requestInfo.createConnState.hasRequest).toBe(true);
|
|
29
|
+
expect(requestInfo.createConnState.requestUrl).toBeDefined();
|
|
30
|
+
expect(requestInfo.createConnState.requestMethod).toBeDefined();
|
|
31
|
+
expect(requestInfo.createConnState.requestHeaders).toBeDefined();
|
|
32
|
+
} else {
|
|
33
|
+
// Inline client may or may not have request object depending on the driver
|
|
34
|
+
//
|
|
35
|
+
// e.g.
|
|
36
|
+
// - File system does not have a request for inline requests
|
|
37
|
+
// - Rivet Engine proxies the request so it has access to the request object
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Clean up
|
|
41
|
+
await connection.dispose();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
test("should not have request when trackRequest is false", async (c) => {
|
|
45
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
46
|
+
|
|
47
|
+
// Create actor without request tracking
|
|
48
|
+
const handle = client.requestAccessActor.getOrCreate(
|
|
49
|
+
["test-no-request"],
|
|
50
|
+
{
|
|
51
|
+
params: { trackRequest: false },
|
|
52
|
+
},
|
|
53
|
+
);
|
|
54
|
+
const connection = handle.connect();
|
|
55
|
+
|
|
56
|
+
// Get request info
|
|
57
|
+
const requestInfo = await connection.getRequestInfo();
|
|
58
|
+
|
|
59
|
+
// Verify request was not tracked
|
|
60
|
+
expect(requestInfo.onBeforeConnect.hasRequest).toBe(false);
|
|
61
|
+
expect(requestInfo.onBeforeConnect.requestUrl).toBeNull();
|
|
62
|
+
expect(requestInfo.onBeforeConnect.requestMethod).toBeNull();
|
|
63
|
+
expect(
|
|
64
|
+
Object.keys(requestInfo.onBeforeConnect.requestHeaders),
|
|
65
|
+
).toHaveLength(0);
|
|
66
|
+
|
|
67
|
+
expect(requestInfo.createConnState.hasRequest).toBe(false);
|
|
68
|
+
expect(requestInfo.createConnState.requestUrl).toBeNull();
|
|
69
|
+
expect(requestInfo.createConnState.requestMethod).toBeNull();
|
|
70
|
+
expect(
|
|
71
|
+
Object.keys(requestInfo.createConnState.requestHeaders),
|
|
72
|
+
).toHaveLength(0);
|
|
73
|
+
|
|
74
|
+
// Clean up
|
|
75
|
+
await connection.dispose();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
test("should capture request headers and method", async (c) => {
|
|
79
|
+
const { client } = await setupDriverTest(c, driverTestConfig);
|
|
80
|
+
|
|
81
|
+
// Create actor and connect with request tracking
|
|
82
|
+
const handle = client.requestAccessActor.getOrCreate(["test-headers"], {
|
|
83
|
+
params: { trackRequest: true },
|
|
84
|
+
});
|
|
85
|
+
const connection = handle.connect();
|
|
86
|
+
|
|
87
|
+
// Get request info
|
|
88
|
+
const requestInfo = await connection.getRequestInfo();
|
|
89
|
+
|
|
90
|
+
if (driverTestConfig.clientType === "http") {
|
|
91
|
+
// Verify request details were captured in both hooks
|
|
92
|
+
expect(requestInfo.onBeforeConnect.hasRequest).toBe(true);
|
|
93
|
+
expect(requestInfo.onBeforeConnect.requestMethod).toBeTruthy();
|
|
94
|
+
expect(requestInfo.onBeforeConnect.requestUrl).toBeTruthy();
|
|
95
|
+
expect(requestInfo.onBeforeConnect.requestHeaders).toBeTruthy();
|
|
96
|
+
expect(typeof requestInfo.onBeforeConnect.requestHeaders).toBe(
|
|
97
|
+
"object",
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
expect(requestInfo.createConnState.hasRequest).toBe(true);
|
|
101
|
+
expect(requestInfo.createConnState.requestMethod).toBeTruthy();
|
|
102
|
+
expect(requestInfo.createConnState.requestUrl).toBeTruthy();
|
|
103
|
+
expect(requestInfo.createConnState.requestHeaders).toBeTruthy();
|
|
104
|
+
expect(typeof requestInfo.createConnState.requestHeaders).toBe(
|
|
105
|
+
"object",
|
|
106
|
+
);
|
|
107
|
+
} else {
|
|
108
|
+
// Inline client may or may not have request object depending on the driver
|
|
109
|
+
//
|
|
110
|
+
// See "should have access to request object in onBeforeConnect and createConnState"
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Clean up
|
|
114
|
+
await connection.dispose();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
test("should have access to request object in onAuth", async (c) => {
|
|
118
|
+
const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
|
|
119
|
+
|
|
120
|
+
// Only test in HTTP mode as onAuth only runs for public endpoints
|
|
121
|
+
if (driverTestConfig.clientType === "http") {
|
|
122
|
+
// For now, skip this test as onAuth might not be properly invoked in test environment
|
|
123
|
+
// The onAuth hook is designed for public endpoints and might require special setup
|
|
124
|
+
console.log("Skipping onAuth test - requires public endpoint setup");
|
|
125
|
+
|
|
126
|
+
// TODO: Implement proper public endpoint test for onAuth
|
|
127
|
+
// This would require setting up the actor with public access and making
|
|
128
|
+
// requests from outside the internal client
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
test("should have access to request object in onFetch", async (c) => {
|
|
133
|
+
const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
|
|
134
|
+
|
|
135
|
+
// Create actor
|
|
136
|
+
const handle = client.requestAccessActor.getOrCreate(["test-fetch"]);
|
|
137
|
+
|
|
138
|
+
// Make a raw HTTP request to the actor
|
|
139
|
+
await handle.resolve(); // Ensure actor is created
|
|
140
|
+
|
|
141
|
+
const actorQuery = {
|
|
142
|
+
getOrCreateForKey: {
|
|
143
|
+
name: "requestAccessActor",
|
|
144
|
+
key: ["test-fetch"],
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const url = `${endpoint}/registry/actors/raw/http/test-path`;
|
|
149
|
+
const response = await fetch(url, {
|
|
150
|
+
method: "POST",
|
|
151
|
+
headers: {
|
|
152
|
+
"Content-Type": "application/json",
|
|
153
|
+
"X-Test-Header": "test-value",
|
|
154
|
+
"X-RivetKit-Query": JSON.stringify(actorQuery),
|
|
155
|
+
},
|
|
156
|
+
body: JSON.stringify({ test: "data" }),
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (!response.ok) {
|
|
160
|
+
const errorText = await response.text();
|
|
161
|
+
console.error(
|
|
162
|
+
`HTTP request failed: ${response.status} ${response.statusText}`,
|
|
163
|
+
errorText,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
expect(response.ok).toBe(true);
|
|
168
|
+
const data = await response.json();
|
|
169
|
+
|
|
170
|
+
// Verify request info from onFetch
|
|
171
|
+
expect((data as any).hasRequest).toBe(true);
|
|
172
|
+
expect((data as any).requestUrl).toContain("/test-path");
|
|
173
|
+
expect((data as any).requestMethod).toBe("POST");
|
|
174
|
+
expect((data as any).requestHeaders).toBeDefined();
|
|
175
|
+
expect((data as any).requestHeaders["content-type"]).toBe(
|
|
176
|
+
"application/json",
|
|
177
|
+
);
|
|
178
|
+
expect((data as any).requestHeaders["x-test-header"]).toBe("test-value");
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("should have access to request object in onWebSocket", async (c) => {
|
|
182
|
+
const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
|
|
183
|
+
|
|
184
|
+
// Only test in environments that support WebSocket
|
|
185
|
+
if (typeof WebSocket !== "undefined") {
|
|
186
|
+
// Create actor
|
|
187
|
+
const handle = client.requestAccessActor.getOrCreate([
|
|
188
|
+
"test-websocket",
|
|
189
|
+
]);
|
|
190
|
+
await handle.resolve(); // Ensure actor is created
|
|
191
|
+
|
|
192
|
+
const actorQuery = {
|
|
193
|
+
getOrCreateForKey: {
|
|
194
|
+
name: "requestAccessActor",
|
|
195
|
+
key: ["test-websocket"],
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// Encode query as WebSocket subprotocol
|
|
200
|
+
const queryProtocol = `query.${encodeURIComponent(JSON.stringify(actorQuery))}`;
|
|
201
|
+
|
|
202
|
+
// Create raw WebSocket connection
|
|
203
|
+
const wsUrl = endpoint
|
|
204
|
+
.replace("http://", "ws://")
|
|
205
|
+
.replace("https://", "wss://");
|
|
206
|
+
const ws = new WebSocket(
|
|
207
|
+
`${wsUrl}/registry/actors/raw/websocket/test-path`,
|
|
208
|
+
[
|
|
209
|
+
queryProtocol,
|
|
210
|
+
"rivetkit", // Required protocol
|
|
211
|
+
],
|
|
212
|
+
);
|
|
213
|
+
|
|
214
|
+
// Wait for connection and first message
|
|
215
|
+
await new Promise<void>((resolve, reject) => {
|
|
216
|
+
ws.onopen = () => {
|
|
217
|
+
// Connection established
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
ws.onmessage = (event) => {
|
|
221
|
+
try {
|
|
222
|
+
const data = JSON.parse(event.data);
|
|
223
|
+
|
|
224
|
+
// Verify request info from onWebSocket
|
|
225
|
+
expect(data.hasRequest).toBe(true);
|
|
226
|
+
expect(data.requestUrl).toContain("/test-path");
|
|
227
|
+
expect(data.requestMethod).toBe("GET");
|
|
228
|
+
expect(data.requestHeaders).toBeDefined();
|
|
229
|
+
|
|
230
|
+
ws.close();
|
|
231
|
+
resolve();
|
|
232
|
+
} catch (error) {
|
|
233
|
+
reject(error);
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
ws.onerror = (error) => {
|
|
238
|
+
reject(error);
|
|
239
|
+
};
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
2
|
+
import { type TestContext, vi } from "vitest";
|
|
3
|
+
import { assertUnreachable } from "@/actor/utils";
|
|
4
|
+
import { createClientWithDriver } from "@/client/client";
|
|
5
|
+
import { type Client, createClient } from "@/client/mod";
|
|
6
|
+
import type { registry } from "../../fixtures/driver-test-suite/registry";
|
|
7
|
+
import type { DriverTestConfig } from "./mod";
|
|
8
|
+
import { createTestInlineClientDriver } from "./test-inline-client-driver";
|
|
9
|
+
|
|
10
|
+
export const FAKE_TIME = new Date("2024-01-01T00:00:00.000Z");
|
|
11
|
+
|
|
12
|
+
// Must use `TestContext` since global hooks do not work when running concurrently
|
|
13
|
+
export async function setupDriverTest(
|
|
14
|
+
c: TestContext,
|
|
15
|
+
driverTestConfig: DriverTestConfig,
|
|
16
|
+
): Promise<{
|
|
17
|
+
client: Client<typeof registry>;
|
|
18
|
+
endpoint: string;
|
|
19
|
+
}> {
|
|
20
|
+
if (!driverTestConfig.useRealTimers) {
|
|
21
|
+
vi.useFakeTimers();
|
|
22
|
+
vi.setSystemTime(FAKE_TIME);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Build drivers
|
|
26
|
+
const projectPath = resolve(__dirname, "../../fixtures/driver-test-suite");
|
|
27
|
+
const { endpoint, cleanup } = await driverTestConfig.start(projectPath);
|
|
28
|
+
c.onTestFinished(cleanup);
|
|
29
|
+
|
|
30
|
+
let client: Client<typeof registry>;
|
|
31
|
+
if (driverTestConfig.clientType === "http") {
|
|
32
|
+
// Create client
|
|
33
|
+
client = createClient<typeof registry>(endpoint, {
|
|
34
|
+
transport: driverTestConfig.transport,
|
|
35
|
+
});
|
|
36
|
+
} else if (driverTestConfig.clientType === "inline") {
|
|
37
|
+
// Use inline client from driver
|
|
38
|
+
const clientDriver = createTestInlineClientDriver(
|
|
39
|
+
endpoint,
|
|
40
|
+
driverTestConfig.transport ?? "websocket",
|
|
41
|
+
);
|
|
42
|
+
client = createClientWithDriver(clientDriver);
|
|
43
|
+
} else {
|
|
44
|
+
assertUnreachable(driverTestConfig.clientType);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Cleanup client
|
|
48
|
+
if (!driverTestConfig.HACK_skipCleanupNet) {
|
|
49
|
+
c.onTestFinished(async () => await client.dispose());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return {
|
|
53
|
+
client,
|
|
54
|
+
endpoint,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function waitFor(
|
|
59
|
+
driverTestConfig: DriverTestConfig,
|
|
60
|
+
ms: number,
|
|
61
|
+
): Promise<void> {
|
|
62
|
+
if (driverTestConfig.useRealTimers) {
|
|
63
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
64
|
+
} else {
|
|
65
|
+
vi.advanceTimersByTime(ms);
|
|
66
|
+
return Promise.resolve();
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { UserError } from "@/actor/errors";
|
|
2
|
+
import { logger } from "@/actor/log";
|
|
3
|
+
import { createEngineDriver } from "@/drivers/engine/mod";
|
|
4
|
+
import { createFileSystemOrMemoryDriver } from "@/drivers/file-system/mod";
|
|
5
|
+
import type { DriverConfig, RunConfig } from "@/registry/run-config";
|
|
6
|
+
import { getEnvUniversal } from "@/utils";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Chooses the appropriate driver based on the run configuration.
|
|
10
|
+
*/
|
|
11
|
+
export function chooseDefaultDriver(runConfig: RunConfig): DriverConfig {
|
|
12
|
+
const engineEndpoint = runConfig.engine || getEnvUniversal("RIVET_ENGINE");
|
|
13
|
+
|
|
14
|
+
if (engineEndpoint && runConfig.driver) {
|
|
15
|
+
throw new UserError(
|
|
16
|
+
"Cannot specify both 'engine' and 'driver' in configuration",
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (runConfig.driver) {
|
|
21
|
+
return runConfig.driver;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (engineEndpoint) {
|
|
25
|
+
logger().debug("using rivet engine driver", { endpoint: engineEndpoint });
|
|
26
|
+
return createEngineDriver({ endpoint: engineEndpoint });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
logger().debug("using default file system driver");
|
|
30
|
+
return createFileSystemOrMemoryDriver(true);
|
|
31
|
+
}
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ActorConfig as RunnerActorConfig,
|
|
3
|
+
RunnerConfig,
|
|
4
|
+
} from "@rivetkit/engine-runner";
|
|
5
|
+
import { Runner } from "@rivetkit/engine-runner";
|
|
6
|
+
import * as cbor from "cbor-x";
|
|
7
|
+
import { WSContext } from "hono/ws";
|
|
8
|
+
import invariant from "invariant";
|
|
9
|
+
import { EncodingSchema } from "@/actor/protocol/serde";
|
|
10
|
+
import type { Client } from "@/client/client";
|
|
11
|
+
import {
|
|
12
|
+
type ActorDriver,
|
|
13
|
+
type AnyActorInstance,
|
|
14
|
+
HEADER_AUTH_DATA,
|
|
15
|
+
HEADER_CONN_PARAMS,
|
|
16
|
+
HEADER_ENCODING,
|
|
17
|
+
type ManagerDriver,
|
|
18
|
+
serializeEmptyPersistData,
|
|
19
|
+
} from "@/driver-helpers/mod";
|
|
20
|
+
import type {
|
|
21
|
+
ActorRouter,
|
|
22
|
+
RegistryConfig,
|
|
23
|
+
RunConfig,
|
|
24
|
+
UniversalWebSocket,
|
|
25
|
+
UpgradeWebSocketArgs,
|
|
26
|
+
} from "@/mod";
|
|
27
|
+
import {
|
|
28
|
+
createActorRouter,
|
|
29
|
+
createGenericConnDrivers,
|
|
30
|
+
GenericConnGlobalState,
|
|
31
|
+
handleRawWebSocketHandler,
|
|
32
|
+
handleWebSocketConnect,
|
|
33
|
+
lookupInRegistry,
|
|
34
|
+
PATH_CONNECT_WEBSOCKET,
|
|
35
|
+
PATH_RAW_WEBSOCKET_PREFIX,
|
|
36
|
+
} from "@/mod";
|
|
37
|
+
import type { Config } from "./config";
|
|
38
|
+
import { deserializeActorKey } from "./keys";
|
|
39
|
+
import { KEYS } from "./kv";
|
|
40
|
+
import { logger } from "./log";
|
|
41
|
+
|
|
42
|
+
interface ActorHandler {
|
|
43
|
+
actor?: AnyActorInstance;
|
|
44
|
+
actorStartPromise?: PromiseWithResolvers<void>;
|
|
45
|
+
genericConnGlobalState: GenericConnGlobalState;
|
|
46
|
+
persistedData?: Uint8Array;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type DriverContext = {};
|
|
50
|
+
|
|
51
|
+
export class EngineActorDriver implements ActorDriver {
|
|
52
|
+
#registryConfig: RegistryConfig;
|
|
53
|
+
#runConfig: RunConfig;
|
|
54
|
+
#managerDriver: ManagerDriver;
|
|
55
|
+
#inlineClient: Client<any>;
|
|
56
|
+
#config: Config;
|
|
57
|
+
#runner: Runner;
|
|
58
|
+
#actors: Map<string, ActorHandler> = new Map();
|
|
59
|
+
#actorRouter: ActorRouter;
|
|
60
|
+
#version: number = 1; // Version for the runner protocol
|
|
61
|
+
|
|
62
|
+
constructor(
|
|
63
|
+
registryConfig: RegistryConfig,
|
|
64
|
+
runConfig: RunConfig,
|
|
65
|
+
managerDriver: ManagerDriver,
|
|
66
|
+
inlineClient: Client<any>,
|
|
67
|
+
config: Config,
|
|
68
|
+
) {
|
|
69
|
+
this.#registryConfig = registryConfig;
|
|
70
|
+
this.#runConfig = runConfig;
|
|
71
|
+
this.#managerDriver = managerDriver;
|
|
72
|
+
this.#inlineClient = inlineClient;
|
|
73
|
+
this.#config = config;
|
|
74
|
+
this.#actorRouter = createActorRouter(runConfig, this);
|
|
75
|
+
|
|
76
|
+
// Create runner configuration
|
|
77
|
+
let hasDisconnected = false;
|
|
78
|
+
const runnerConfig: RunnerConfig = {
|
|
79
|
+
version: this.#version,
|
|
80
|
+
endpoint: config.endpoint,
|
|
81
|
+
pegboardEndpoint: config.pegboardEndpoint,
|
|
82
|
+
namespace: config.namespace,
|
|
83
|
+
totalSlots: config.totalSlots,
|
|
84
|
+
runnerName: config.runnerName,
|
|
85
|
+
runnerKey: config.runnerKey,
|
|
86
|
+
metadata: {
|
|
87
|
+
inspectorToken: this.#runConfig.inspector.token(),
|
|
88
|
+
},
|
|
89
|
+
prepopulateActorNames: Object.fromEntries(
|
|
90
|
+
Object.keys(this.#registryConfig.use).map((name) => [
|
|
91
|
+
name,
|
|
92
|
+
{ metadata: {} },
|
|
93
|
+
]),
|
|
94
|
+
),
|
|
95
|
+
onConnected: () => {
|
|
96
|
+
if (hasDisconnected) {
|
|
97
|
+
logger().info("runner reconnected", {
|
|
98
|
+
namespace: this.#config.namespace,
|
|
99
|
+
runnerName: this.#config.runnerName,
|
|
100
|
+
});
|
|
101
|
+
} else {
|
|
102
|
+
logger().debug("runner connected", {
|
|
103
|
+
namespace: this.#config.namespace,
|
|
104
|
+
runnerName: this.#config.runnerName,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
onDisconnected: () => {
|
|
109
|
+
logger().warn("runner disconnected", {
|
|
110
|
+
namespace: this.#config.namespace,
|
|
111
|
+
runnerName: this.#config.runnerName,
|
|
112
|
+
});
|
|
113
|
+
hasDisconnected = true;
|
|
114
|
+
},
|
|
115
|
+
fetch: this.#runnerFetch.bind(this),
|
|
116
|
+
websocket: this.#runnerWebSocket.bind(this),
|
|
117
|
+
onActorStart: this.#runnerOnActorStart.bind(this),
|
|
118
|
+
onActorStop: this.#runnerOnActorStop.bind(this),
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Create and start runner
|
|
122
|
+
this.#runner = new Runner(runnerConfig);
|
|
123
|
+
this.#runner.start();
|
|
124
|
+
logger().debug("engine runner started", {
|
|
125
|
+
endpoint: config.endpoint,
|
|
126
|
+
namespace: config.namespace,
|
|
127
|
+
runnerName: config.runnerName,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async #loadActorHandler(actorId: string): Promise<ActorHandler> {
|
|
132
|
+
// Check if actor is already loaded
|
|
133
|
+
const handler = this.#actors.get(actorId);
|
|
134
|
+
if (!handler) throw new Error(`Actor handler does not exist ${actorId}`);
|
|
135
|
+
if (handler.actorStartPromise) await handler.actorStartPromise.promise;
|
|
136
|
+
if (!handler.actor) throw new Error("Actor should be loaded");
|
|
137
|
+
return handler;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async loadActor(actorId: string): Promise<AnyActorInstance> {
|
|
141
|
+
const handler = await this.#loadActorHandler(actorId);
|
|
142
|
+
if (!handler.actor) throw new Error(`Actor ${actorId} failed to load`);
|
|
143
|
+
return handler.actor;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
getGenericConnGlobalState(actorId: string): GenericConnGlobalState {
|
|
147
|
+
const handler = this.#actors.get(actorId);
|
|
148
|
+
if (!handler) {
|
|
149
|
+
throw new Error(`Actor ${actorId} not loaded`);
|
|
150
|
+
}
|
|
151
|
+
return handler.genericConnGlobalState;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
getContext(actorId: string): DriverContext {
|
|
155
|
+
return {};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async readPersistedData(actorId: string): Promise<Uint8Array | undefined> {
|
|
159
|
+
const handler = this.#actors.get(actorId);
|
|
160
|
+
if (!handler) throw new Error(`Actor ${actorId} not loaded`);
|
|
161
|
+
if (handler.persistedData) return handler.persistedData;
|
|
162
|
+
|
|
163
|
+
const [value] = await this.#runner.kvGet(actorId, [KEYS.PERSIST_DATA]);
|
|
164
|
+
|
|
165
|
+
if (value !== null) {
|
|
166
|
+
handler.persistedData = value;
|
|
167
|
+
return value;
|
|
168
|
+
} else {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
async writePersistedData(actorId: string, data: Uint8Array): Promise<void> {
|
|
174
|
+
const handler = this.#actors.get(actorId);
|
|
175
|
+
if (!handler) throw new Error(`Actor ${actorId} not loaded`);
|
|
176
|
+
|
|
177
|
+
handler.persistedData = data;
|
|
178
|
+
|
|
179
|
+
await this.#runner.kvPut(actorId, [[KEYS.PERSIST_DATA, data]]);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
async setAlarm(actor: AnyActorInstance, timestamp: number): Promise<void> {
|
|
183
|
+
// TODO: Set timeout
|
|
184
|
+
// TODO: Use alarm on sleep
|
|
185
|
+
// TODO: Send alarm to runner
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async getDatabase(_actorId: string): Promise<unknown | undefined> {
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Runner lifecycle callbacks
|
|
193
|
+
async #runnerOnActorStart(
|
|
194
|
+
actorId: string,
|
|
195
|
+
generation: number,
|
|
196
|
+
config: RunnerActorConfig,
|
|
197
|
+
): Promise<void> {
|
|
198
|
+
logger().debug("runner actor starting", {
|
|
199
|
+
actorId,
|
|
200
|
+
name: config.name,
|
|
201
|
+
key: config.key,
|
|
202
|
+
generation,
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Deserialize input
|
|
206
|
+
let input: any;
|
|
207
|
+
if (config.input) {
|
|
208
|
+
input = cbor.decode(config.input);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Get or create handler
|
|
212
|
+
let handler = this.#actors.get(actorId);
|
|
213
|
+
if (!handler) {
|
|
214
|
+
handler = {
|
|
215
|
+
genericConnGlobalState: new GenericConnGlobalState(),
|
|
216
|
+
actorStartPromise: Promise.withResolvers(),
|
|
217
|
+
persistedData: serializeEmptyPersistData(input),
|
|
218
|
+
};
|
|
219
|
+
this.#actors.set(actorId, handler);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const name = config.name as string;
|
|
223
|
+
invariant(config.key, "actor should have a key");
|
|
224
|
+
const key = deserializeActorKey(config.key);
|
|
225
|
+
|
|
226
|
+
// Create actor instance
|
|
227
|
+
const definition = lookupInRegistry(
|
|
228
|
+
this.#registryConfig,
|
|
229
|
+
config.name as string, // TODO: Remove cast
|
|
230
|
+
);
|
|
231
|
+
handler.actor = definition.instantiate();
|
|
232
|
+
|
|
233
|
+
// Start actor
|
|
234
|
+
const connDrivers = createGenericConnDrivers(
|
|
235
|
+
handler.genericConnGlobalState,
|
|
236
|
+
);
|
|
237
|
+
await handler.actor.start(
|
|
238
|
+
connDrivers,
|
|
239
|
+
this,
|
|
240
|
+
this.#inlineClient,
|
|
241
|
+
actorId,
|
|
242
|
+
name,
|
|
243
|
+
key,
|
|
244
|
+
"unknown", // TODO: Add regions
|
|
245
|
+
);
|
|
246
|
+
|
|
247
|
+
// Resolve promise if waiting
|
|
248
|
+
handler.actorStartPromise?.resolve();
|
|
249
|
+
handler.actorStartPromise = undefined;
|
|
250
|
+
|
|
251
|
+
logger().debug("runner actor started", { actorId, name, key });
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async #runnerOnActorStop(actorId: string, generation: number): Promise<void> {
|
|
255
|
+
logger().debug("runner actor stopping", { actorId, generation });
|
|
256
|
+
|
|
257
|
+
const handler = this.#actors.get(actorId);
|
|
258
|
+
if (handler?.actor) {
|
|
259
|
+
await handler.actor._stop();
|
|
260
|
+
this.#actors.delete(actorId);
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
logger().debug("runner actor stopped", { actorId });
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async #runnerFetch(actorId: string, request: Request): Promise<Response> {
|
|
267
|
+
logger().debug("runner fetch", {
|
|
268
|
+
actorId,
|
|
269
|
+
url: request.url,
|
|
270
|
+
method: request.method,
|
|
271
|
+
});
|
|
272
|
+
return await this.#actorRouter.fetch(request, { actorId });
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async #runnerWebSocket(
|
|
276
|
+
actorId: string,
|
|
277
|
+
websocketRaw: any,
|
|
278
|
+
request: Request,
|
|
279
|
+
): Promise<void> {
|
|
280
|
+
const websocket = websocketRaw as UniversalWebSocket;
|
|
281
|
+
|
|
282
|
+
logger().debug("runner websocket", { actorId, url: request.url });
|
|
283
|
+
|
|
284
|
+
const url = new URL(request.url);
|
|
285
|
+
|
|
286
|
+
// Parse headers
|
|
287
|
+
const encodingRaw = request.headers.get(HEADER_ENCODING);
|
|
288
|
+
const connParamsRaw = request.headers.get(HEADER_CONN_PARAMS);
|
|
289
|
+
const authDataRaw = request.headers.get(HEADER_AUTH_DATA);
|
|
290
|
+
|
|
291
|
+
const encoding = EncodingSchema.parse(encodingRaw);
|
|
292
|
+
const connParams = connParamsRaw ? JSON.parse(connParamsRaw) : undefined;
|
|
293
|
+
const authData = authDataRaw ? JSON.parse(authDataRaw) : undefined;
|
|
294
|
+
|
|
295
|
+
// Fetch WS handler
|
|
296
|
+
//
|
|
297
|
+
// We store the promise since we need to add WebSocket event listeners immediately that will wait for the promise to resolve
|
|
298
|
+
let wsHandlerPromise: Promise<UpgradeWebSocketArgs>;
|
|
299
|
+
if (url.pathname === PATH_CONNECT_WEBSOCKET) {
|
|
300
|
+
wsHandlerPromise = handleWebSocketConnect(
|
|
301
|
+
request,
|
|
302
|
+
this.#runConfig,
|
|
303
|
+
this,
|
|
304
|
+
actorId,
|
|
305
|
+
encoding,
|
|
306
|
+
connParams,
|
|
307
|
+
authData,
|
|
308
|
+
);
|
|
309
|
+
} else if (url.pathname.startsWith(PATH_RAW_WEBSOCKET_PREFIX)) {
|
|
310
|
+
wsHandlerPromise = handleRawWebSocketHandler(
|
|
311
|
+
request,
|
|
312
|
+
url.pathname + url.search,
|
|
313
|
+
this,
|
|
314
|
+
actorId,
|
|
315
|
+
authData,
|
|
316
|
+
);
|
|
317
|
+
} else {
|
|
318
|
+
throw new Error(`Unreachable path: ${url.pathname}`);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// TODO: Add close
|
|
322
|
+
|
|
323
|
+
// Connect the Hono WS hook to the adapter
|
|
324
|
+
const wsContext = new WSContext(websocket);
|
|
325
|
+
|
|
326
|
+
wsHandlerPromise.catch((err) => {
|
|
327
|
+
logger().error("building websocket handlers errored", { err });
|
|
328
|
+
wsContext.close(1011, `${err}`);
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
if (websocket.readyState === 1) {
|
|
332
|
+
wsHandlerPromise.then((x) => x.onOpen?.(new Event("open"), wsContext));
|
|
333
|
+
} else {
|
|
334
|
+
websocket.addEventListener("open", (event) => {
|
|
335
|
+
wsHandlerPromise.then((x) => x.onOpen?.(event, wsContext));
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
websocket.addEventListener("message", (event) => {
|
|
340
|
+
wsHandlerPromise.then((x) => x.onMessage?.(event, wsContext));
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
websocket.addEventListener("close", (event) => {
|
|
344
|
+
wsHandlerPromise.then((x) => x.onClose?.(event, wsContext));
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
websocket.addEventListener("error", (event) => {
|
|
348
|
+
wsHandlerPromise.then((x) => x.onError?.(event, wsContext));
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async sleep(actorId: string) {
|
|
353
|
+
this.#runner.sleepActor(actorId);
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
async shutdown(immediate: boolean): Promise<void> {
|
|
357
|
+
logger().info("stopping engine actor driver");
|
|
358
|
+
await this.#runner.shutdown(immediate);
|
|
359
|
+
}
|
|
360
|
+
}
|