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.
Files changed (253) hide show
  1. package/dist/schemas/actor-persist/v1.ts +228 -0
  2. package/dist/schemas/client-protocol/v1.ts +429 -0
  3. package/dist/schemas/file-system-driver/v1.ts +102 -0
  4. package/dist/tsup/actor/errors.cjs +69 -0
  5. package/dist/tsup/actor/errors.cjs.map +1 -0
  6. package/dist/tsup/actor/errors.d.cts +143 -0
  7. package/dist/tsup/actor/errors.d.ts +143 -0
  8. package/dist/tsup/actor/errors.js +69 -0
  9. package/dist/tsup/actor/errors.js.map +1 -0
  10. package/dist/tsup/chunk-2CRLFV6Z.cjs +202 -0
  11. package/dist/tsup/chunk-2CRLFV6Z.cjs.map +1 -0
  12. package/dist/tsup/chunk-3H7O2A7I.js +525 -0
  13. package/dist/tsup/chunk-3H7O2A7I.js.map +1 -0
  14. package/dist/tsup/chunk-42I3OZ3Q.js +15 -0
  15. package/dist/tsup/chunk-42I3OZ3Q.js.map +1 -0
  16. package/dist/tsup/chunk-4NSUQZ2H.js +1790 -0
  17. package/dist/tsup/chunk-4NSUQZ2H.js.map +1 -0
  18. package/dist/tsup/chunk-6PDXBYI5.js +132 -0
  19. package/dist/tsup/chunk-6PDXBYI5.js.map +1 -0
  20. package/dist/tsup/chunk-6WKQDDUD.cjs +1790 -0
  21. package/dist/tsup/chunk-6WKQDDUD.cjs.map +1 -0
  22. package/dist/tsup/chunk-CTBOSFUH.cjs +116 -0
  23. package/dist/tsup/chunk-CTBOSFUH.cjs.map +1 -0
  24. package/dist/tsup/chunk-EGVZZFE2.js +2857 -0
  25. package/dist/tsup/chunk-EGVZZFE2.js.map +1 -0
  26. package/dist/tsup/chunk-FCCPJNMA.cjs +132 -0
  27. package/dist/tsup/chunk-FCCPJNMA.cjs.map +1 -0
  28. package/dist/tsup/chunk-FLMTTN27.js +244 -0
  29. package/dist/tsup/chunk-FLMTTN27.js.map +1 -0
  30. package/dist/tsup/chunk-GIR3AFFI.cjs +315 -0
  31. package/dist/tsup/chunk-GIR3AFFI.cjs.map +1 -0
  32. package/dist/tsup/chunk-INGJP237.js +315 -0
  33. package/dist/tsup/chunk-INGJP237.js.map +1 -0
  34. package/dist/tsup/chunk-KJCJLKRM.js +116 -0
  35. package/dist/tsup/chunk-KJCJLKRM.js.map +1 -0
  36. package/dist/tsup/chunk-KUPQZYUQ.cjs +15 -0
  37. package/dist/tsup/chunk-KUPQZYUQ.cjs.map +1 -0
  38. package/dist/tsup/chunk-O2MBYIXO.cjs +2857 -0
  39. package/dist/tsup/chunk-O2MBYIXO.cjs.map +1 -0
  40. package/dist/tsup/chunk-OGAPU3UG.cjs +525 -0
  41. package/dist/tsup/chunk-OGAPU3UG.cjs.map +1 -0
  42. package/dist/tsup/chunk-OV6AYD4S.js +4406 -0
  43. package/dist/tsup/chunk-OV6AYD4S.js.map +1 -0
  44. package/dist/tsup/chunk-PO4VLDWA.js +47 -0
  45. package/dist/tsup/chunk-PO4VLDWA.js.map +1 -0
  46. package/dist/tsup/chunk-R2OPSKIV.cjs +244 -0
  47. package/dist/tsup/chunk-R2OPSKIV.cjs.map +1 -0
  48. package/dist/tsup/chunk-TZJKSBUQ.cjs +47 -0
  49. package/dist/tsup/chunk-TZJKSBUQ.cjs.map +1 -0
  50. package/dist/tsup/chunk-UBUC5C3G.cjs +189 -0
  51. package/dist/tsup/chunk-UBUC5C3G.cjs.map +1 -0
  52. package/dist/tsup/chunk-UIM22YJL.cjs +4406 -0
  53. package/dist/tsup/chunk-UIM22YJL.cjs.map +1 -0
  54. package/dist/tsup/chunk-URVFQMYI.cjs +230 -0
  55. package/dist/tsup/chunk-URVFQMYI.cjs.map +1 -0
  56. package/dist/tsup/chunk-UVUPOS46.js +230 -0
  57. package/dist/tsup/chunk-UVUPOS46.js.map +1 -0
  58. package/dist/tsup/chunk-VRRHBNJC.js +189 -0
  59. package/dist/tsup/chunk-VRRHBNJC.js.map +1 -0
  60. package/dist/tsup/chunk-XFSS33EQ.js +202 -0
  61. package/dist/tsup/chunk-XFSS33EQ.js.map +1 -0
  62. package/dist/tsup/client/mod.cjs +32 -0
  63. package/dist/tsup/client/mod.cjs.map +1 -0
  64. package/dist/tsup/client/mod.d.cts +26 -0
  65. package/dist/tsup/client/mod.d.ts +26 -0
  66. package/dist/tsup/client/mod.js +32 -0
  67. package/dist/tsup/client/mod.js.map +1 -0
  68. package/dist/tsup/common/log.cjs +13 -0
  69. package/dist/tsup/common/log.cjs.map +1 -0
  70. package/dist/tsup/common/log.d.cts +20 -0
  71. package/dist/tsup/common/log.d.ts +20 -0
  72. package/dist/tsup/common/log.js +13 -0
  73. package/dist/tsup/common/log.js.map +1 -0
  74. package/dist/tsup/common/websocket.cjs +10 -0
  75. package/dist/tsup/common/websocket.cjs.map +1 -0
  76. package/dist/tsup/common/websocket.d.cts +3 -0
  77. package/dist/tsup/common/websocket.d.ts +3 -0
  78. package/dist/tsup/common/websocket.js +10 -0
  79. package/dist/tsup/common/websocket.js.map +1 -0
  80. package/dist/tsup/common-CpqORuCq.d.cts +218 -0
  81. package/dist/tsup/common-CpqORuCq.d.ts +218 -0
  82. package/dist/tsup/connection-BR_Ve4ku.d.cts +2117 -0
  83. package/dist/tsup/connection-BwUMoe6n.d.ts +2117 -0
  84. package/dist/tsup/driver-helpers/mod.cjs +33 -0
  85. package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
  86. package/dist/tsup/driver-helpers/mod.d.cts +18 -0
  87. package/dist/tsup/driver-helpers/mod.d.ts +18 -0
  88. package/dist/tsup/driver-helpers/mod.js +33 -0
  89. package/dist/tsup/driver-helpers/mod.js.map +1 -0
  90. package/dist/tsup/driver-test-suite/mod.cjs +4619 -0
  91. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
  92. package/dist/tsup/driver-test-suite/mod.d.cts +57 -0
  93. package/dist/tsup/driver-test-suite/mod.d.ts +57 -0
  94. package/dist/tsup/driver-test-suite/mod.js +4619 -0
  95. package/dist/tsup/driver-test-suite/mod.js.map +1 -0
  96. package/dist/tsup/inspector/mod.cjs +53 -0
  97. package/dist/tsup/inspector/mod.cjs.map +1 -0
  98. package/dist/tsup/inspector/mod.d.cts +408 -0
  99. package/dist/tsup/inspector/mod.d.ts +408 -0
  100. package/dist/tsup/inspector/mod.js +53 -0
  101. package/dist/tsup/inspector/mod.js.map +1 -0
  102. package/dist/tsup/mod.cjs +73 -0
  103. package/dist/tsup/mod.cjs.map +1 -0
  104. package/dist/tsup/mod.d.cts +100 -0
  105. package/dist/tsup/mod.d.ts +100 -0
  106. package/dist/tsup/mod.js +73 -0
  107. package/dist/tsup/mod.js.map +1 -0
  108. package/dist/tsup/router-endpoints-AYkXG8Tl.d.cts +66 -0
  109. package/dist/tsup/router-endpoints-DAbqVFx2.d.ts +66 -0
  110. package/dist/tsup/test/mod.cjs +21 -0
  111. package/dist/tsup/test/mod.cjs.map +1 -0
  112. package/dist/tsup/test/mod.d.cts +27 -0
  113. package/dist/tsup/test/mod.d.ts +27 -0
  114. package/dist/tsup/test/mod.js +21 -0
  115. package/dist/tsup/test/mod.js.map +1 -0
  116. package/dist/tsup/utils-CT0cv4jd.d.cts +17 -0
  117. package/dist/tsup/utils-CT0cv4jd.d.ts +17 -0
  118. package/dist/tsup/utils.cjs +26 -0
  119. package/dist/tsup/utils.cjs.map +1 -0
  120. package/dist/tsup/utils.d.cts +36 -0
  121. package/dist/tsup/utils.d.ts +36 -0
  122. package/dist/tsup/utils.js +26 -0
  123. package/dist/tsup/utils.js.map +1 -0
  124. package/package.json +208 -5
  125. package/src/actor/action.ts +182 -0
  126. package/src/actor/config.ts +765 -0
  127. package/src/actor/connection.ts +260 -0
  128. package/src/actor/context.ts +171 -0
  129. package/src/actor/database.ts +23 -0
  130. package/src/actor/definition.ts +86 -0
  131. package/src/actor/driver.ts +84 -0
  132. package/src/actor/errors.ts +360 -0
  133. package/src/actor/generic-conn-driver.ts +234 -0
  134. package/src/actor/instance.ts +1800 -0
  135. package/src/actor/log.ts +15 -0
  136. package/src/actor/mod.ts +113 -0
  137. package/src/actor/persisted.ts +42 -0
  138. package/src/actor/protocol/old.ts +281 -0
  139. package/src/actor/protocol/serde.ts +131 -0
  140. package/src/actor/router-endpoints.ts +685 -0
  141. package/src/actor/router.ts +263 -0
  142. package/src/actor/schedule.ts +17 -0
  143. package/src/actor/unstable-react.ts +110 -0
  144. package/src/actor/utils.ts +98 -0
  145. package/src/client/actor-common.ts +30 -0
  146. package/src/client/actor-conn.ts +804 -0
  147. package/src/client/actor-handle.ts +208 -0
  148. package/src/client/client.ts +623 -0
  149. package/src/client/errors.ts +41 -0
  150. package/src/client/http-client-driver.ts +326 -0
  151. package/src/client/log.ts +7 -0
  152. package/src/client/mod.ts +56 -0
  153. package/src/client/raw-utils.ts +92 -0
  154. package/src/client/test.ts +44 -0
  155. package/src/client/utils.ts +150 -0
  156. package/src/common/eventsource-interface.ts +47 -0
  157. package/src/common/eventsource.ts +80 -0
  158. package/src/common/fake-event-source.ts +266 -0
  159. package/src/common/inline-websocket-adapter2.ts +445 -0
  160. package/src/common/log-levels.ts +27 -0
  161. package/src/common/log.ts +139 -0
  162. package/src/common/logfmt.ts +228 -0
  163. package/src/common/network.ts +2 -0
  164. package/src/common/router.ts +87 -0
  165. package/src/common/utils.ts +322 -0
  166. package/src/common/versioned-data.ts +95 -0
  167. package/src/common/websocket-interface.ts +49 -0
  168. package/src/common/websocket.ts +43 -0
  169. package/src/driver-helpers/mod.ts +22 -0
  170. package/src/driver-helpers/utils.ts +17 -0
  171. package/src/driver-test-suite/log.ts +7 -0
  172. package/src/driver-test-suite/mod.ts +213 -0
  173. package/src/driver-test-suite/test-inline-client-driver.ts +402 -0
  174. package/src/driver-test-suite/tests/action-features.ts +136 -0
  175. package/src/driver-test-suite/tests/actor-auth.ts +591 -0
  176. package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
  177. package/src/driver-test-suite/tests/actor-conn.ts +349 -0
  178. package/src/driver-test-suite/tests/actor-driver.ts +25 -0
  179. package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
  180. package/src/driver-test-suite/tests/actor-handle.ts +259 -0
  181. package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
  182. package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
  183. package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
  184. package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
  185. package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
  186. package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
  187. package/src/driver-test-suite/tests/actor-state.ts +54 -0
  188. package/src/driver-test-suite/tests/actor-vars.ts +93 -0
  189. package/src/driver-test-suite/tests/manager-driver.ts +365 -0
  190. package/src/driver-test-suite/tests/raw-http-direct-registry.ts +226 -0
  191. package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
  192. package/src/driver-test-suite/tests/raw-http.ts +347 -0
  193. package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +392 -0
  194. package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
  195. package/src/driver-test-suite/tests/request-access.ts +244 -0
  196. package/src/driver-test-suite/utils.ts +68 -0
  197. package/src/drivers/default.ts +31 -0
  198. package/src/drivers/engine/actor-driver.ts +360 -0
  199. package/src/drivers/engine/api-endpoints.ts +128 -0
  200. package/src/drivers/engine/api-utils.ts +70 -0
  201. package/src/drivers/engine/config.ts +39 -0
  202. package/src/drivers/engine/keys.test.ts +266 -0
  203. package/src/drivers/engine/keys.ts +89 -0
  204. package/src/drivers/engine/kv.ts +3 -0
  205. package/src/drivers/engine/log.ts +7 -0
  206. package/src/drivers/engine/manager-driver.ts +391 -0
  207. package/src/drivers/engine/mod.ts +36 -0
  208. package/src/drivers/engine/ws-proxy.ts +170 -0
  209. package/src/drivers/file-system/actor.ts +91 -0
  210. package/src/drivers/file-system/global-state.ts +673 -0
  211. package/src/drivers/file-system/log.ts +7 -0
  212. package/src/drivers/file-system/manager.ts +306 -0
  213. package/src/drivers/file-system/mod.ts +48 -0
  214. package/src/drivers/file-system/utils.ts +109 -0
  215. package/src/globals.d.ts +6 -0
  216. package/src/inline-client-driver/log.ts +7 -0
  217. package/src/inline-client-driver/mod.ts +385 -0
  218. package/src/inspector/actor.ts +298 -0
  219. package/src/inspector/config.ts +83 -0
  220. package/src/inspector/log.ts +5 -0
  221. package/src/inspector/manager.ts +86 -0
  222. package/src/inspector/mod.ts +2 -0
  223. package/src/inspector/protocol/actor.ts +10 -0
  224. package/src/inspector/protocol/common.ts +196 -0
  225. package/src/inspector/protocol/manager.ts +10 -0
  226. package/src/inspector/protocol/mod.ts +2 -0
  227. package/src/inspector/utils.ts +76 -0
  228. package/src/manager/auth.ts +121 -0
  229. package/src/manager/driver.ts +80 -0
  230. package/src/manager/hono-websocket-adapter.ts +333 -0
  231. package/src/manager/log.ts +7 -0
  232. package/src/manager/mod.ts +2 -0
  233. package/src/manager/protocol/mod.ts +24 -0
  234. package/src/manager/protocol/query.ts +89 -0
  235. package/src/manager/router.ts +1792 -0
  236. package/src/mod.ts +20 -0
  237. package/src/registry/config.ts +32 -0
  238. package/src/registry/log.ts +7 -0
  239. package/src/registry/mod.ts +124 -0
  240. package/src/registry/run-config.ts +54 -0
  241. package/src/registry/serve.ts +53 -0
  242. package/src/schemas/actor-persist/mod.ts +1 -0
  243. package/src/schemas/actor-persist/versioned.ts +25 -0
  244. package/src/schemas/client-protocol/mod.ts +1 -0
  245. package/src/schemas/client-protocol/versioned.ts +63 -0
  246. package/src/schemas/file-system-driver/mod.ts +1 -0
  247. package/src/schemas/file-system-driver/versioned.ts +28 -0
  248. package/src/serde.ts +84 -0
  249. package/src/test/config.ts +16 -0
  250. package/src/test/log.ts +7 -0
  251. package/src/test/mod.ts +153 -0
  252. package/src/utils.ts +172 -0
  253. package/README.md +0 -13
@@ -0,0 +1,4619 @@
1
+ import {
2
+ getPort
3
+ } from "../chunk-6PDXBYI5.js";
4
+ import {
5
+ actor,
6
+ createInlineClientDriver,
7
+ createManagerRouter
8
+ } from "../chunk-OV6AYD4S.js";
9
+ import {
10
+ createActorInspectorClient,
11
+ createManagerInspectorClient
12
+ } from "../chunk-42I3OZ3Q.js";
13
+ import {
14
+ createClient
15
+ } from "../chunk-UVUPOS46.js";
16
+ import {
17
+ ActorError,
18
+ createClientWithDriver
19
+ } from "../chunk-EGVZZFE2.js";
20
+ import "../chunk-FLMTTN27.js";
21
+ import {
22
+ importWebSocket
23
+ } from "../chunk-PO4VLDWA.js";
24
+ import {
25
+ RunConfigSchema
26
+ } from "../chunk-KJCJLKRM.js";
27
+ import "../chunk-VRRHBNJC.js";
28
+ import {
29
+ HEADER_ACTOR_QUERY,
30
+ HEADER_CONN_PARAMS,
31
+ HEADER_ENCODING,
32
+ assertUnreachable
33
+ } from "../chunk-4NSUQZ2H.js";
34
+ import {
35
+ getLogger
36
+ } from "../chunk-XFSS33EQ.js";
37
+ import "../chunk-3H7O2A7I.js";
38
+ import {
39
+ INTERNAL_ERROR_CODE,
40
+ INTERNAL_ERROR_DESCRIPTION
41
+ } from "../chunk-INGJP237.js";
42
+
43
+ // src/driver-test-suite/mod.ts
44
+ import { serve as honoServe } from "@hono/node-server";
45
+ import { createNodeWebSocket } from "@hono/node-ws";
46
+ import { bundleRequire } from "bundle-require";
47
+ import invariant from "invariant";
48
+ import { describe as describe23 } from "vitest";
49
+
50
+ // src/driver-test-suite/tests/action-features.ts
51
+ import { describe, expect, test } from "vitest";
52
+
53
+ // src/driver-test-suite/utils.ts
54
+ import { resolve } from "path";
55
+ import { vi } from "vitest";
56
+
57
+ // src/driver-test-suite/test-inline-client-driver.ts
58
+ import * as cbor from "cbor-x";
59
+
60
+ // src/driver-test-suite/log.ts
61
+ var LOGGER_NAME = "test-suite";
62
+ function logger() {
63
+ return getLogger(LOGGER_NAME);
64
+ }
65
+
66
+ // src/driver-test-suite/test-inline-client-driver.ts
67
+ function createTestInlineClientDriver(endpoint, transport) {
68
+ return {
69
+ action: async (_c, actorQuery, encoding, params, name, args) => {
70
+ return makeInlineRequest(
71
+ endpoint,
72
+ encoding,
73
+ transport,
74
+ "action",
75
+ [void 0, actorQuery, encoding, params, name, args]
76
+ );
77
+ },
78
+ resolveActorId: async (_c, actorQuery, encodingKind, params) => {
79
+ return makeInlineRequest(
80
+ endpoint,
81
+ encodingKind,
82
+ transport,
83
+ "resolveActorId",
84
+ [void 0, actorQuery, encodingKind, params]
85
+ );
86
+ },
87
+ connectWebSocket: async (_c, actorQuery, encodingKind, params) => {
88
+ const WebSocket2 = await importWebSocket();
89
+ logger().debug("creating websocket connection via test inline driver", {
90
+ actorQuery,
91
+ encodingKind
92
+ });
93
+ const wsUrl = new URL(
94
+ `${endpoint}/registry/.test/inline-driver/connect-websocket`
95
+ );
96
+ wsUrl.searchParams.set("actorQuery", JSON.stringify(actorQuery));
97
+ if (params !== void 0)
98
+ wsUrl.searchParams.set("params", JSON.stringify(params));
99
+ wsUrl.searchParams.set("encodingKind", encodingKind);
100
+ const wsProtocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
101
+ const finalWsUrl = `${wsProtocol}//${wsUrl.host}${wsUrl.pathname}${wsUrl.search}`;
102
+ logger().debug("connecting to websocket", { url: finalWsUrl });
103
+ const ws = new WebSocket2(finalWsUrl, [
104
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
105
+ "rivetkit"
106
+ ]);
107
+ return ws;
108
+ },
109
+ connectSse: async (_c, actorQuery, encodingKind, params) => {
110
+ logger().debug("creating sse connection via test inline driver", {
111
+ actorQuery,
112
+ encodingKind,
113
+ params
114
+ });
115
+ const EventSourceImport = await import("eventsource");
116
+ const EventSourceConstructor = EventSourceImport.default || EventSourceImport;
117
+ const actorQueryParam = encodeURIComponent(JSON.stringify(actorQuery));
118
+ const encodingParam = encodeURIComponent(encodingKind);
119
+ const paramsParam = params ? encodeURIComponent(JSON.stringify(params)) : null;
120
+ const sseUrl = new URL(
121
+ `${endpoint}/registry/.test/inline-driver/connect-sse`
122
+ );
123
+ sseUrl.searchParams.set("actorQueryRaw", actorQueryParam);
124
+ sseUrl.searchParams.set("encodingKind", encodingParam);
125
+ if (paramsParam) {
126
+ sseUrl.searchParams.set("params", paramsParam);
127
+ }
128
+ logger().debug("connecting to sse", { url: sseUrl.toString() });
129
+ const eventSource = new EventSourceConstructor(sseUrl.toString());
130
+ await new Promise((resolve2, reject) => {
131
+ eventSource.onopen = () => {
132
+ logger().debug("sse connection established");
133
+ resolve2();
134
+ };
135
+ eventSource.onerror = (event) => {
136
+ logger().error("sse connection failed", { event });
137
+ reject(new Error("Failed to establish SSE connection"));
138
+ };
139
+ setTimeout(() => {
140
+ if (eventSource.readyState !== EventSourceConstructor.OPEN) {
141
+ reject(new Error("SSE connection timed out"));
142
+ }
143
+ }, 1e4);
144
+ });
145
+ return eventSource;
146
+ },
147
+ sendHttpMessage: async (_c, actorId, encoding, connectionId, connectionToken, message) => {
148
+ var _a;
149
+ logger().debug("sending http message via test inline driver", {
150
+ actorId,
151
+ encoding,
152
+ connectionId,
153
+ transport
154
+ });
155
+ const result = await fetch(
156
+ `${endpoint}/registry/.test/inline-driver/call`,
157
+ {
158
+ method: "POST",
159
+ headers: {
160
+ "Content-Type": "application/json"
161
+ },
162
+ body: JSON.stringify({
163
+ encoding,
164
+ transport,
165
+ method: "sendHttpMessage",
166
+ args: [
167
+ void 0,
168
+ actorId,
169
+ encoding,
170
+ connectionId,
171
+ connectionToken,
172
+ message
173
+ ]
174
+ })
175
+ }
176
+ );
177
+ if (!result.ok) {
178
+ throw new Error(`Failed to send HTTP message: ${result.statusText}`);
179
+ }
180
+ await ((_a = result.body) == null ? void 0 : _a.cancel());
181
+ },
182
+ rawHttpRequest: async (_c, actorQuery, encoding, params, path, init) => {
183
+ var _a;
184
+ const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
185
+ logger().debug("sending raw http request via test inline driver", {
186
+ actorQuery,
187
+ encoding,
188
+ path: normalizedPath
189
+ });
190
+ const url = `${endpoint}/registry/.test/inline-driver/raw-http/${normalizedPath}`;
191
+ logger().debug("rewriting http url", {
192
+ from: path,
193
+ to: url
194
+ });
195
+ const headers = new Headers(init.headers);
196
+ headers.set(HEADER_ACTOR_QUERY, JSON.stringify(actorQuery));
197
+ headers.set(HEADER_ENCODING, encoding);
198
+ if (params !== void 0) {
199
+ headers.set(HEADER_CONN_PARAMS, JSON.stringify(params));
200
+ }
201
+ const response = await fetch(url, {
202
+ ...init,
203
+ headers
204
+ });
205
+ if (!response.ok && ((_a = response.headers.get("content-type")) == null ? void 0 : _a.includes("application/json"))) {
206
+ try {
207
+ const clonedResponse = response.clone();
208
+ const errorData = await clonedResponse.json();
209
+ if (errorData.error) {
210
+ if (typeof errorData.error === "object") {
211
+ throw new ActorError(
212
+ errorData.error.code,
213
+ errorData.error.message,
214
+ errorData.error.metadata
215
+ );
216
+ }
217
+ }
218
+ } catch (e) {
219
+ if (!(e instanceof ActorError)) {
220
+ return response;
221
+ }
222
+ throw e;
223
+ }
224
+ }
225
+ return response;
226
+ },
227
+ rawWebSocket: async (_c, actorQuery, encoding, params, path, protocols) => {
228
+ logger().debug("test inline driver rawWebSocket called");
229
+ const WebSocket2 = await importWebSocket();
230
+ const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
231
+ logger().debug(
232
+ "creating raw websocket connection via test inline driver",
233
+ {
234
+ actorQuery,
235
+ encoding,
236
+ path: normalizedPath,
237
+ protocols
238
+ }
239
+ );
240
+ const wsUrl = new URL(
241
+ `${endpoint}/registry/.test/inline-driver/raw-websocket`
242
+ );
243
+ wsUrl.searchParams.set("actorQuery", JSON.stringify(actorQuery));
244
+ if (params !== void 0)
245
+ wsUrl.searchParams.set("params", JSON.stringify(params));
246
+ wsUrl.searchParams.set("encodingKind", encoding);
247
+ wsUrl.searchParams.set("path", normalizedPath);
248
+ if (protocols !== void 0)
249
+ wsUrl.searchParams.set("protocols", JSON.stringify(protocols));
250
+ const wsProtocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
251
+ const finalWsUrl = `${wsProtocol}//${wsUrl.host}${wsUrl.pathname}${wsUrl.search}`;
252
+ logger().debug("connecting to raw websocket", { url: finalWsUrl });
253
+ logger().debug("rewriting websocket url", {
254
+ from: path,
255
+ to: finalWsUrl
256
+ });
257
+ const ws = new WebSocket2(finalWsUrl, [
258
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
259
+ "rivetkit"
260
+ ]);
261
+ logger().debug("test inline driver created websocket", {
262
+ readyState: ws.readyState,
263
+ url: ws.url
264
+ });
265
+ return ws;
266
+ }
267
+ };
268
+ }
269
+ async function makeInlineRequest(endpoint, encoding, transport, method, args) {
270
+ logger().debug("sending inline request", {
271
+ encoding,
272
+ transport,
273
+ method,
274
+ args
275
+ });
276
+ const response = await fetch(
277
+ `${endpoint}/registry/.test/inline-driver/call`,
278
+ {
279
+ method: "POST",
280
+ headers: {
281
+ "Content-Type": "application/json"
282
+ },
283
+ body: cbor.encode({
284
+ encoding,
285
+ transport,
286
+ method,
287
+ args
288
+ })
289
+ }
290
+ );
291
+ if (!response.ok) {
292
+ throw new Error(`Failed to call inline ${method}: ${response.statusText}`);
293
+ }
294
+ const buffer = await response.arrayBuffer();
295
+ const callResponse = cbor.decode(
296
+ new Uint8Array(buffer)
297
+ );
298
+ if ("ok" in callResponse) {
299
+ return callResponse.ok;
300
+ } else if ("err" in callResponse) {
301
+ throw new ActorError(
302
+ callResponse.err.code,
303
+ callResponse.err.message,
304
+ callResponse.err.metadata
305
+ );
306
+ } else {
307
+ assertUnreachable(callResponse);
308
+ }
309
+ }
310
+
311
+ // src/driver-test-suite/utils.ts
312
+ var FAKE_TIME = /* @__PURE__ */ new Date("2024-01-01T00:00:00.000Z");
313
+ async function setupDriverTest(c, driverTestConfig) {
314
+ if (!driverTestConfig.useRealTimers) {
315
+ vi.useFakeTimers();
316
+ vi.setSystemTime(FAKE_TIME);
317
+ }
318
+ const projectPath = resolve(__dirname, "../../fixtures/driver-test-suite");
319
+ const { endpoint, cleanup } = await driverTestConfig.start(projectPath);
320
+ c.onTestFinished(cleanup);
321
+ let client;
322
+ if (driverTestConfig.clientType === "http") {
323
+ client = createClient(endpoint, {
324
+ transport: driverTestConfig.transport
325
+ });
326
+ } else if (driverTestConfig.clientType === "inline") {
327
+ const clientDriver = createTestInlineClientDriver(
328
+ endpoint,
329
+ driverTestConfig.transport ?? "websocket"
330
+ );
331
+ client = createClientWithDriver(clientDriver);
332
+ } else {
333
+ assertUnreachable(driverTestConfig.clientType);
334
+ }
335
+ if (!driverTestConfig.HACK_skipCleanupNet) {
336
+ c.onTestFinished(async () => await client.dispose());
337
+ }
338
+ return {
339
+ client,
340
+ endpoint
341
+ };
342
+ }
343
+ async function waitFor(driverTestConfig, ms) {
344
+ if (driverTestConfig.useRealTimers) {
345
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
346
+ } else {
347
+ vi.advanceTimersByTime(ms);
348
+ return Promise.resolve();
349
+ }
350
+ }
351
+
352
+ // src/driver-test-suite/tests/action-features.ts
353
+ function runActionFeaturesTests(driverTestConfig) {
354
+ describe("Action Features", () => {
355
+ describe("Action Timeouts", () => {
356
+ const usesFakeTimers = !driverTestConfig.useRealTimers;
357
+ test("should timeout actions that exceed the configured timeout", async (c) => {
358
+ const { client } = await setupDriverTest(c, driverTestConfig);
359
+ const quickResult = await client.shortTimeoutActor.getOrCreate().quickAction();
360
+ expect(quickResult).toBe("quick response");
361
+ await expect(
362
+ client.shortTimeoutActor.getOrCreate().slowAction()
363
+ ).rejects.toThrow("Action timed out");
364
+ });
365
+ test("should respect the default timeout", async (c) => {
366
+ const { client } = await setupDriverTest(c, driverTestConfig);
367
+ const result = await client.defaultTimeoutActor.getOrCreate().normalAction();
368
+ expect(result).toBe("normal response");
369
+ });
370
+ test("non-promise action results should not be affected by timeout", async (c) => {
371
+ const { client } = await setupDriverTest(c, driverTestConfig);
372
+ const result = await client.syncTimeoutActor.getOrCreate().syncAction();
373
+ expect(result).toBe("sync response");
374
+ });
375
+ test("should allow configuring different timeouts for different actors", async (c) => {
376
+ const { client } = await setupDriverTest(c, driverTestConfig);
377
+ await expect(
378
+ client.shortTimeoutActor.getOrCreate().slowAction()
379
+ ).rejects.toThrow("Action timed out");
380
+ const result = await client.longTimeoutActor.getOrCreate().delayedAction();
381
+ expect(result).toBe("delayed response");
382
+ });
383
+ });
384
+ describe("Action Sync & Async", () => {
385
+ test("should support synchronous actions", async (c) => {
386
+ const { client } = await setupDriverTest(c, driverTestConfig);
387
+ const instance = client.syncActionActor.getOrCreate();
388
+ let result = await instance.increment(5);
389
+ expect(result).toBe(5);
390
+ result = await instance.increment(3);
391
+ expect(result).toBe(8);
392
+ const info = await instance.getInfo();
393
+ expect(info.currentValue).toBe(8);
394
+ expect(typeof info.timestamp).toBe("number");
395
+ await instance.reset();
396
+ result = await instance.increment(0);
397
+ expect(result).toBe(0);
398
+ });
399
+ test("should support asynchronous actions", async (c) => {
400
+ const { client } = await setupDriverTest(c, driverTestConfig);
401
+ const instance = client.asyncActionActor.getOrCreate();
402
+ const result = await instance.delayedIncrement(5);
403
+ expect(result).toBe(5);
404
+ const data = await instance.fetchData("test-123");
405
+ expect(data.id).toBe("test-123");
406
+ expect(typeof data.timestamp).toBe("number");
407
+ const success = await instance.asyncWithError(false);
408
+ expect(success).toBe("Success");
409
+ try {
410
+ await instance.asyncWithError(true);
411
+ expect.fail("did not error");
412
+ } catch (error) {
413
+ expect(error.message).toBe("Intentional error");
414
+ }
415
+ });
416
+ test("should handle promises returned from actions correctly", async (c) => {
417
+ const { client } = await setupDriverTest(c, driverTestConfig);
418
+ const instance = client.promiseActor.getOrCreate();
419
+ const resolvedValue = await instance.resolvedPromise();
420
+ expect(resolvedValue).toBe("resolved value");
421
+ const delayedValue = await instance.delayedPromise();
422
+ expect(delayedValue).toBe("delayed value");
423
+ await expect(instance.rejectedPromise()).rejects.toThrow(
424
+ "promised rejection"
425
+ );
426
+ const results = await instance.getResults();
427
+ expect(results).toContain("delayed");
428
+ });
429
+ });
430
+ });
431
+ }
432
+
433
+ // src/driver-test-suite/tests/actor-auth.ts
434
+ import { describe as describe2, expect as expect2, test as test2 } from "vitest";
435
+ function runActorAuthTests(driverTestConfig) {
436
+ describe2("Actor Authentication Tests", () => {
437
+ describe2("Basic Authentication", () => {
438
+ test2("should allow access with valid auth", async (c) => {
439
+ const { client } = await setupDriverTest(c, driverTestConfig);
440
+ const instance = client.authActor.getOrCreate(void 0, {
441
+ params: { apiKey: "valid-api-key" }
442
+ });
443
+ const authData = await instance.getUserAuth();
444
+ if (driverTestConfig.clientType === "inline") {
445
+ expect2(authData).toBeUndefined();
446
+ } else {
447
+ expect2(authData).toEqual({
448
+ userId: "user123",
449
+ token: "valid-api-key"
450
+ });
451
+ }
452
+ const requests = await instance.getRequests();
453
+ expect2(requests).toBe(1);
454
+ });
455
+ test2("should deny access with invalid auth", async (c) => {
456
+ const { client } = await setupDriverTest(c, driverTestConfig);
457
+ const instance = client.authActor.getOrCreate();
458
+ if (driverTestConfig.clientType === "inline") {
459
+ const requests = await instance.getRequests();
460
+ expect2(typeof requests).toBe("number");
461
+ } else {
462
+ try {
463
+ await instance.getRequests();
464
+ expect2.fail("Expected authentication error");
465
+ } catch (error) {
466
+ expect2(error.code).toBe("missing_auth");
467
+ }
468
+ }
469
+ });
470
+ test2("should expose auth data on connection", async (c) => {
471
+ const { client } = await setupDriverTest(c, driverTestConfig);
472
+ const instance = client.authActor.getOrCreate(void 0, {
473
+ params: { apiKey: "valid-api-key" }
474
+ });
475
+ const authData = await instance.getUserAuth();
476
+ if (driverTestConfig.clientType === "inline") {
477
+ expect2(authData).toBeUndefined();
478
+ } else {
479
+ expect2(authData).toBeDefined();
480
+ expect2(authData.userId).toBe("user123");
481
+ expect2(authData.token).toBe("valid-api-key");
482
+ }
483
+ });
484
+ });
485
+ describe2("Intent-Based Authentication", () => {
486
+ test2("should allow get operations for any role", async (c) => {
487
+ const { client } = await setupDriverTest(c, driverTestConfig);
488
+ const createdInstance = await client.intentAuthActor.create(["foo"], {
489
+ params: { role: "admin" }
490
+ });
491
+ const actorId = await createdInstance.resolve();
492
+ if (driverTestConfig.clientType === "inline") {
493
+ const instance = client.intentAuthActor.getForId(actorId);
494
+ const value = await instance.getValue();
495
+ expect2(value).toBe(0);
496
+ } else {
497
+ const instance = client.intentAuthActor.getForId(actorId, {
498
+ params: { role: "user" }
499
+ // Actions require user or admin role
500
+ });
501
+ const value = await instance.getValue();
502
+ expect2(value).toBe(0);
503
+ }
504
+ });
505
+ test2("should require admin role for create operations", async (c) => {
506
+ const { client } = await setupDriverTest(c, driverTestConfig);
507
+ if (driverTestConfig.clientType === "inline") {
508
+ const instance = client.intentAuthActor.getOrCreate(void 0, {
509
+ params: { role: "user" }
510
+ });
511
+ const value = await instance.getValue();
512
+ expect2(value).toBe(0);
513
+ } else {
514
+ try {
515
+ const instance = client.intentAuthActor.getOrCreate(void 0, {
516
+ params: { role: "user" }
517
+ });
518
+ await instance.getValue();
519
+ expect2.fail("Expected permission error for create operation");
520
+ } catch (error) {
521
+ expect2(error.code).toBe("insufficient_permissions");
522
+ expect2(error.message).toContain(
523
+ "Admin role required"
524
+ );
525
+ }
526
+ }
527
+ });
528
+ test2("should allow actions for user and admin roles", async (c) => {
529
+ const { client } = await setupDriverTest(c, driverTestConfig);
530
+ const createdInstance = await client.intentAuthActor.create(["foo"], {
531
+ params: { role: "admin" }
532
+ });
533
+ const actorId = await createdInstance.resolve();
534
+ const instance = client.intentAuthActor.getForId(actorId, {
535
+ params: { role: "guest" }
536
+ });
537
+ if (driverTestConfig.clientType === "inline") {
538
+ const result = await instance.setValue(42);
539
+ expect2(result).toBe(42);
540
+ } else {
541
+ try {
542
+ await instance.setValue(42);
543
+ expect2.fail("Expected permission error for action");
544
+ } catch (error) {
545
+ expect2(error.code).toBe("insufficient_permissions");
546
+ expect2(error.message).toContain(
547
+ "User or admin role required"
548
+ );
549
+ }
550
+ }
551
+ });
552
+ });
553
+ describe2("Public Access", () => {
554
+ test2("should allow access with empty onAuth", async (c) => {
555
+ const { client } = await setupDriverTest(c, driverTestConfig);
556
+ const instance = client.publicActor.getOrCreate();
557
+ const visitors = await instance.visit();
558
+ expect2(visitors).toBe(1);
559
+ const visitors2 = await instance.visit();
560
+ expect2(visitors2).toBe(2);
561
+ });
562
+ test2("should deny access without onAuth defined", async (c) => {
563
+ const { client } = await setupDriverTest(c, driverTestConfig);
564
+ const instance = client.noAuthActor.getOrCreate();
565
+ if (driverTestConfig.clientType === "inline") {
566
+ const value = await instance.getValue();
567
+ expect2(value).toBe(42);
568
+ } else {
569
+ try {
570
+ await instance.getValue();
571
+ expect2.fail(
572
+ "Expected access to be denied for actor without onAuth"
573
+ );
574
+ } catch (error) {
575
+ expect2(error.code).toBe("forbidden");
576
+ }
577
+ }
578
+ });
579
+ });
580
+ describe2("Async Authentication", () => {
581
+ test2("should handle promise-based auth", async (c) => {
582
+ const { client } = await setupDriverTest(c, driverTestConfig);
583
+ const instance = client.asyncAuthActor.getOrCreate(void 0, {
584
+ params: { token: "valid" }
585
+ });
586
+ const result = await instance.increment();
587
+ expect2(result).toBe(1);
588
+ const authData = await instance.getAuthData();
589
+ if (driverTestConfig.clientType === "inline") {
590
+ expect2(authData).toBeUndefined();
591
+ } else {
592
+ expect2(authData).toBeDefined();
593
+ expect2(authData.userId).toBe("user-valid");
594
+ expect2(authData.validated).toBe(true);
595
+ }
596
+ });
597
+ test2("should handle async auth failures", async (c) => {
598
+ const { client } = await setupDriverTest(c, driverTestConfig);
599
+ const instance = client.asyncAuthActor.getOrCreate();
600
+ if (driverTestConfig.clientType === "inline") {
601
+ const result = await instance.increment();
602
+ expect2(result).toBe(1);
603
+ } else {
604
+ try {
605
+ await instance.increment();
606
+ expect2.fail("Expected async auth failure");
607
+ } catch (error) {
608
+ expect2(error.code).toBe("missing_token");
609
+ }
610
+ }
611
+ });
612
+ });
613
+ describe2("Authentication Across Transports", () => {
614
+ if (driverTestConfig.transport === "websocket") {
615
+ test2("should authenticate WebSocket connections", async (c) => {
616
+ const { client } = await setupDriverTest(c, driverTestConfig);
617
+ const instance = client.authActor.getOrCreate(void 0, {
618
+ params: { apiKey: "valid-api-key" }
619
+ });
620
+ const authData = await instance.getUserAuth();
621
+ expect2(authData).toBeDefined();
622
+ expect2(authData.userId).toBe("user123");
623
+ });
624
+ }
625
+ test2("should authenticate HTTP actions", async (c) => {
626
+ const { client } = await setupDriverTest(c, driverTestConfig);
627
+ const instance = client.authActor.getOrCreate(void 0, {
628
+ params: { apiKey: "valid-api-key" }
629
+ });
630
+ const requests = await instance.getRequests();
631
+ expect2(typeof requests).toBe("number");
632
+ });
633
+ });
634
+ describe2("Error Handling", () => {
635
+ test2("should handle auth errors gracefully", async (c) => {
636
+ const { client } = await setupDriverTest(c, driverTestConfig);
637
+ const instance = client.authActor.getOrCreate();
638
+ if (driverTestConfig.clientType === "inline") {
639
+ const requests = await instance.getRequests();
640
+ expect2(typeof requests).toBe("number");
641
+ } else {
642
+ try {
643
+ await instance.getRequests();
644
+ expect2.fail("Expected authentication error");
645
+ } catch (error) {
646
+ const actorError = error;
647
+ expect2(actorError.code).toBeDefined();
648
+ expect2(actorError.message).toBeDefined();
649
+ }
650
+ }
651
+ });
652
+ test2("should preserve error details for debugging", async (c) => {
653
+ const { client } = await setupDriverTest(c, driverTestConfig);
654
+ const instance = client.asyncAuthActor.getOrCreate();
655
+ if (driverTestConfig.clientType === "inline") {
656
+ const result = await instance.increment();
657
+ expect2(result).toBe(1);
658
+ } else {
659
+ try {
660
+ await instance.increment();
661
+ expect2.fail("Expected token error");
662
+ } catch (error) {
663
+ const actorError = error;
664
+ expect2(actorError.code).toBe("missing_token");
665
+ expect2(actorError.message).toBe("Token required");
666
+ }
667
+ }
668
+ });
669
+ });
670
+ describe2("Raw HTTP Authentication", () => {
671
+ test2("should allow raw HTTP access with valid auth", async (c) => {
672
+ const { client } = await setupDriverTest(c, driverTestConfig);
673
+ const instance = client.rawHttpAuthActor.getOrCreate(void 0, {
674
+ params: { apiKey: "valid-api-key" }
675
+ });
676
+ const response = await instance.fetch("api/auth-info");
677
+ expect2(response.ok).toBe(true);
678
+ const data = await response.json();
679
+ expect2(data.message).toBe("Authenticated request");
680
+ expect2(data.requestCount).toBe(1);
681
+ const count = await instance.getRequestCount();
682
+ expect2(count).toBe(1);
683
+ });
684
+ test2("should deny raw HTTP access without auth", async (c) => {
685
+ const { client } = await setupDriverTest(c, driverTestConfig);
686
+ const instance = client.rawHttpAuthActor.getOrCreate();
687
+ const response = await instance.fetch("api/protected");
688
+ if (driverTestConfig.clientType === "inline") {
689
+ expect2(response.ok).toBe(true);
690
+ expect2(response.status).toBe(200);
691
+ } else {
692
+ expect2(response.ok).toBe(false);
693
+ expect2(response.status).toBe(400);
694
+ }
695
+ try {
696
+ const errorData = await response.json();
697
+ expect2(errorData.c || errorData.code).toBe("missing_auth");
698
+ } catch {
699
+ }
700
+ });
701
+ test2("should deny raw HTTP for actors without onAuth", async (c) => {
702
+ const { client } = await setupDriverTest(c, driverTestConfig);
703
+ const instance = client.rawHttpNoAuthActor.getOrCreate();
704
+ const response = await instance.fetch("api/test");
705
+ if (driverTestConfig.clientType === "inline") {
706
+ expect2(response.ok).toBe(true);
707
+ expect2(response.status).toBe(200);
708
+ } else {
709
+ expect2(response.ok).toBe(false);
710
+ expect2(response.status).toBe(403);
711
+ }
712
+ try {
713
+ const errorData = await response.json();
714
+ expect2(errorData.c || errorData.code).toBe("forbidden");
715
+ } catch {
716
+ }
717
+ });
718
+ test2("should allow public raw HTTP access", async (c) => {
719
+ const { client } = await setupDriverTest(c, driverTestConfig);
720
+ const instance = client.rawHttpPublicActor.getOrCreate();
721
+ const response = await instance.fetch("api/visit");
722
+ expect2(response.ok).toBe(true);
723
+ const data = await response.json();
724
+ expect2(data.message).toBe("Welcome visitor!");
725
+ expect2(data.count).toBe(1);
726
+ const response2 = await instance.fetch("api/visit");
727
+ const data2 = await response2.json();
728
+ expect2(data2.count).toBe(2);
729
+ });
730
+ test2("should handle custom auth in onFetch", async (c) => {
731
+ const { client } = await setupDriverTest(c, driverTestConfig);
732
+ const instance = client.rawHttpCustomAuthActor.getOrCreate();
733
+ const response1 = await instance.fetch("api/data");
734
+ expect2(response1.ok).toBe(false);
735
+ expect2(response1.status).toBe(401);
736
+ const error1 = await response1.json();
737
+ expect2(error1.error).toBe("Unauthorized");
738
+ const response2 = await instance.fetch("api/data", {
739
+ headers: {
740
+ Authorization: "Bearer wrong-token"
741
+ }
742
+ });
743
+ expect2(response2.ok).toBe(false);
744
+ expect2(response2.status).toBe(403);
745
+ const response3 = await instance.fetch("api/data", {
746
+ headers: {
747
+ Authorization: "Bearer custom-token"
748
+ }
749
+ });
750
+ expect2(response3.ok).toBe(true);
751
+ const data = await response3.json();
752
+ expect2(data.message).toBe("Authorized!");
753
+ expect2(data.authorized).toBe(1);
754
+ const stats = await instance.getStats();
755
+ expect2(stats.authorized).toBe(1);
756
+ expect2(stats.unauthorized).toBe(2);
757
+ });
758
+ });
759
+ describe2("Raw WebSocket Authentication", () => {
760
+ test2("should allow raw WebSocket access with valid auth", async (c) => {
761
+ const { client } = await setupDriverTest(c, driverTestConfig);
762
+ const instance = client.rawWebSocketAuthActor.getOrCreate(void 0, {
763
+ params: { apiKey: "valid-api-key" }
764
+ });
765
+ const ws = await instance.websocket();
766
+ const welcomePromise = new Promise((resolve2, reject) => {
767
+ ws.addEventListener("message", (event) => {
768
+ const data = JSON.parse(event.data);
769
+ if (data.type === "welcome") {
770
+ resolve2(data);
771
+ }
772
+ });
773
+ ws.addEventListener("close", () => reject("closed"));
774
+ });
775
+ const welcomeData = await welcomePromise;
776
+ expect2(welcomeData.message).toBe("Authenticated WebSocket connection");
777
+ expect2(welcomeData.connectionCount).toBe(1);
778
+ ws.close();
779
+ });
780
+ test2("should deny raw WebSocket access without auth", async (c) => {
781
+ const { client } = await setupDriverTest(c, driverTestConfig);
782
+ const instance = client.rawWebSocketAuthActor.getOrCreate();
783
+ try {
784
+ await instance.websocket();
785
+ expect2.fail("Expected authentication error");
786
+ } catch (error) {
787
+ expect2(error).toBeDefined();
788
+ }
789
+ });
790
+ test2("should deny raw WebSocket for actors without onAuth", async (c) => {
791
+ const { client } = await setupDriverTest(c, driverTestConfig);
792
+ const instance = client.rawWebSocketNoAuthActor.getOrCreate();
793
+ try {
794
+ await instance.websocket();
795
+ expect2.fail("Expected forbidden error");
796
+ } catch (error) {
797
+ expect2(error).toBeDefined();
798
+ }
799
+ });
800
+ test2("should allow public raw WebSocket access", async (c) => {
801
+ const { client } = await setupDriverTest(c, driverTestConfig);
802
+ const instance = client.rawWebSocketPublicActor.getOrCreate();
803
+ const ws = await instance.websocket();
804
+ const welcomePromise = new Promise((resolve2, reject) => {
805
+ ws.addEventListener("message", (event) => {
806
+ const data = JSON.parse(event.data);
807
+ if (data.type === "welcome") {
808
+ resolve2(data);
809
+ }
810
+ });
811
+ ws.addEventListener("close", reject);
812
+ });
813
+ const welcomeData = await welcomePromise;
814
+ expect2(welcomeData.message).toBe("Public WebSocket connection");
815
+ expect2(welcomeData.visitorNumber).toBe(1);
816
+ ws.close();
817
+ });
818
+ test2("should handle custom auth in onWebSocket", async (c) => {
819
+ const { client } = await setupDriverTest(c, driverTestConfig);
820
+ const instance = client.rawWebSocketCustomAuthActor.getOrCreate();
821
+ try {
822
+ const ws1 = await instance.websocket();
823
+ const errorPromise = new Promise((resolve2, reject) => {
824
+ ws1.addEventListener("message", (event) => {
825
+ const data = JSON.parse(event.data);
826
+ if (data.type === "error") {
827
+ resolve2(data);
828
+ }
829
+ });
830
+ ws1.addEventListener("close", reject);
831
+ });
832
+ const errorData = await errorPromise;
833
+ expect2(errorData.type).toBe("error");
834
+ expect2(errorData.message).toBe("Unauthorized");
835
+ } catch (error) {
836
+ expect2(error).toBeDefined();
837
+ }
838
+ const ws2 = await instance.websocket("?token=custom-ws-token");
839
+ const authPromise = new Promise((resolve2, reject) => {
840
+ ws2.addEventListener("message", (event) => {
841
+ const data = JSON.parse(event.data);
842
+ if (data.type === "authorized") {
843
+ resolve2(data);
844
+ }
845
+ });
846
+ ws2.addEventListener("close", reject);
847
+ });
848
+ const authData = await authPromise;
849
+ expect2(authData.message).toBe("Welcome authenticated user!");
850
+ ws2.close();
851
+ const stats = await instance.getStats();
852
+ expect2(stats.authorized).toBeGreaterThanOrEqual(1);
853
+ expect2(stats.unauthorized).toBeGreaterThanOrEqual(1);
854
+ });
855
+ });
856
+ });
857
+ }
858
+
859
+ // src/driver-test-suite/tests/actor-conn.ts
860
+ import { describe as describe3, expect as expect3, test as test3 } from "vitest";
861
+ function runActorConnTests(driverTestConfig) {
862
+ describe3("Actor Connection Tests", () => {
863
+ describe3("Connection Methods", () => {
864
+ test3("should connect using .get().connect()", async (c) => {
865
+ const { client } = await setupDriverTest(c, driverTestConfig);
866
+ await client.counter.create(["test-get"]);
867
+ const handle = client.counter.get(["test-get"]);
868
+ const connection = handle.connect();
869
+ const count = await connection.increment(5);
870
+ expect3(count).toBe(5);
871
+ await connection.dispose();
872
+ });
873
+ test3("should connect using .getForId().connect()", async (c) => {
874
+ const { client } = await setupDriverTest(c, driverTestConfig);
875
+ const handle = client.counter.getOrCreate(["test-get-for-id"]);
876
+ await handle.increment(3);
877
+ const actorId = await handle.resolve();
878
+ const idHandle = client.counter.getForId(actorId);
879
+ const connection = idHandle.connect();
880
+ const count = await connection.getCount();
881
+ expect3(count).toBe(3);
882
+ await connection.dispose();
883
+ });
884
+ test3("should connect using .getOrCreate().connect()", async (c) => {
885
+ const { client } = await setupDriverTest(c, driverTestConfig);
886
+ const handle = client.counter.getOrCreate(["test-get-or-create"]);
887
+ const connection = handle.connect();
888
+ const count = await connection.increment(7);
889
+ expect3(count).toBe(7);
890
+ await connection.dispose();
891
+ });
892
+ test3("should connect using (await create()).connect()", async (c) => {
893
+ const { client } = await setupDriverTest(c, driverTestConfig);
894
+ const handle = await client.counter.create(["test-create"]);
895
+ const connection = handle.connect();
896
+ const count = await connection.increment(9);
897
+ expect3(count).toBe(9);
898
+ await connection.dispose();
899
+ });
900
+ });
901
+ describe3("Event Communication", () => {
902
+ test3("should mix RPC calls and WebSocket events", async (c) => {
903
+ const { client } = await setupDriverTest(c, driverTestConfig);
904
+ const handle = client.counter.getOrCreate(["test-mixed-rpc-ws"]);
905
+ const connection = handle.connect();
906
+ const receivedEvents = [];
907
+ const receivedEventsPromise = new Promise((resolve2) => {
908
+ connection.on("newCount", (count) => {
909
+ receivedEvents.push(count);
910
+ if (receivedEvents.includes(1) && receivedEvents.includes(6) && receivedEvents.includes(9))
911
+ resolve2(void 0);
912
+ });
913
+ });
914
+ await connection.increment(1);
915
+ await handle.increment(5);
916
+ await handle.increment(3);
917
+ await receivedEventsPromise;
918
+ await connection.dispose();
919
+ });
920
+ test3("should receive events via broadcast", async (c) => {
921
+ const { client } = await setupDriverTest(c, driverTestConfig);
922
+ const handle = client.counter.getOrCreate(["test-broadcast"]);
923
+ const connection = handle.connect();
924
+ const receivedEvents = [];
925
+ connection.on("newCount", (count) => {
926
+ receivedEvents.push(count);
927
+ });
928
+ await connection.increment(5);
929
+ await connection.increment(3);
930
+ expect3(receivedEvents).toContain(5);
931
+ expect3(receivedEvents).toContain(8);
932
+ await connection.dispose();
933
+ });
934
+ test3("should handle one-time events with once()", async (c) => {
935
+ const { client } = await setupDriverTest(c, driverTestConfig);
936
+ const handle = client.counter.getOrCreate(["test-once"]);
937
+ const connection = handle.connect();
938
+ const receivedEvents = [];
939
+ connection.once("newCount", (count) => {
940
+ receivedEvents.push(count);
941
+ });
942
+ await connection.increment(5);
943
+ await connection.increment(3);
944
+ expect3(receivedEvents).toEqual([5]);
945
+ expect3(receivedEvents).not.toContain(8);
946
+ await connection.dispose();
947
+ });
948
+ test3("should unsubscribe from events", async (c) => {
949
+ const { client } = await setupDriverTest(c, driverTestConfig);
950
+ const handle = client.counter.getOrCreate(["test-unsubscribe"]);
951
+ const connection = handle.connect();
952
+ const receivedEvents = [];
953
+ const unsubscribe = connection.on("newCount", (count) => {
954
+ receivedEvents.push(count);
955
+ });
956
+ await connection.increment(5);
957
+ unsubscribe();
958
+ await connection.increment(3);
959
+ expect3(receivedEvents).toEqual([5]);
960
+ expect3(receivedEvents).not.toContain(8);
961
+ await connection.dispose();
962
+ });
963
+ });
964
+ describe3("Connection Parameters", () => {
965
+ test3("should pass connection parameters", async (c) => {
966
+ const { client } = await setupDriverTest(c, driverTestConfig);
967
+ const handle1 = client.counterWithParams.getOrCreate(["test-params"], {
968
+ params: { name: "user1" }
969
+ });
970
+ const handle2 = client.counterWithParams.getOrCreate(["test-params"], {
971
+ params: { name: "user2" }
972
+ });
973
+ const conn1 = handle1.connect();
974
+ const conn2 = handle2.connect();
975
+ await conn1.getInitializers();
976
+ await conn2.getInitializers();
977
+ const initializers = await conn1.getInitializers();
978
+ expect3(initializers).toContain("user1");
979
+ expect3(initializers).toContain("user2");
980
+ await conn1.dispose();
981
+ await conn2.dispose();
982
+ });
983
+ });
984
+ describe3("Lifecycle Hooks", () => {
985
+ test3("should trigger lifecycle hooks", async (c) => {
986
+ const { client } = await setupDriverTest(c, driverTestConfig);
987
+ const connHandle = client.counterWithLifecycle.getOrCreate(
988
+ ["test-lifecycle"],
989
+ {
990
+ params: { trackLifecycle: true }
991
+ }
992
+ );
993
+ const connection = connHandle.connect();
994
+ const events = await connection.getEvents();
995
+ expect3(events).toEqual(["onStart", "onBeforeConnect", "onConnect"]);
996
+ await connection.dispose();
997
+ const handle = client.counterWithLifecycle.getOrCreate([
998
+ "test-lifecycle"
999
+ ]);
1000
+ const finalEvents = await handle.getEvents();
1001
+ expect3(finalEvents).toBeOneOf([
1002
+ // Still active
1003
+ ["onStart", "onBeforeConnect", "onConnect", "onDisconnect"],
1004
+ // Went to sleep and woke back up
1005
+ [
1006
+ "onStart",
1007
+ "onBeforeConnect",
1008
+ "onConnect",
1009
+ "onDisconnect",
1010
+ "onStart"
1011
+ ]
1012
+ ]);
1013
+ });
1014
+ });
1015
+ describe3("Connection Liveness", () => {
1016
+ test3.skip("should return correct liveness status for connections", async (c) => {
1017
+ const { client } = await setupDriverTest(c, driverTestConfig);
1018
+ const handle = client.connLivenessActor.getOrCreate([
1019
+ "test-liveness-status"
1020
+ ]);
1021
+ const connA = handle.connect();
1022
+ const connB = handle.connect();
1023
+ const connAId = await connA.getConnectionId();
1024
+ const connBId = await connB.getConnectionId();
1025
+ await connA.increment(5);
1026
+ await connB.increment(5);
1027
+ const counter = await handle.getCounter();
1028
+ expect3(counter).toBe(10);
1029
+ const connectionsStatusBeforeKill = await handle.getWsConnectionsLiveness();
1030
+ expect3(connectionsStatusBeforeKill).toHaveLength(2);
1031
+ expect3(connectionsStatusBeforeKill).toContainEqual(
1032
+ expect3.objectContaining({
1033
+ id: connAId,
1034
+ status: "connected",
1035
+ lastSeen: FAKE_TIME.getTime()
1036
+ })
1037
+ );
1038
+ expect3(connectionsStatusBeforeKill).toContainEqual(
1039
+ expect3.objectContaining({
1040
+ id: connBId,
1041
+ status: "connected",
1042
+ lastSeen: FAKE_TIME.getTime()
1043
+ })
1044
+ );
1045
+ await handle.kill(connAId);
1046
+ const connectionsStatusAfterKill = await handle.getWsConnectionsLiveness();
1047
+ expect3(connectionsStatusAfterKill).toEqual(
1048
+ expect3.arrayContaining([
1049
+ expect3.objectContaining({
1050
+ id: connAId,
1051
+ status: "reconnecting",
1052
+ lastSeen: FAKE_TIME.getTime()
1053
+ }),
1054
+ expect3.objectContaining({
1055
+ id: connBId,
1056
+ status: "connected",
1057
+ lastSeen: FAKE_TIME.getTime()
1058
+ })
1059
+ ])
1060
+ );
1061
+ await waitFor(driverTestConfig, 5e3);
1062
+ const connectionsStatusAfterCleanup = await handle.getWsConnectionsLiveness();
1063
+ expect3(connectionsStatusAfterCleanup).not.toContainEqual(
1064
+ expect3.objectContaining({
1065
+ id: connAId
1066
+ })
1067
+ );
1068
+ expect3(connectionsStatusAfterCleanup).toContainEqual(
1069
+ expect3.objectContaining({
1070
+ id: connBId
1071
+ })
1072
+ );
1073
+ });
1074
+ });
1075
+ });
1076
+ }
1077
+
1078
+ // src/driver-test-suite/tests/actor-conn-state.ts
1079
+ import { describe as describe4, expect as expect4, test as test4, vi as vi2 } from "vitest";
1080
+ function runActorConnStateTests(driverTestConfig) {
1081
+ describe4("Actor Connection State Tests", () => {
1082
+ describe4("Connection State Initialization", () => {
1083
+ test4("should retrieve connection state", async (c) => {
1084
+ const { client } = await setupDriverTest(c, driverTestConfig);
1085
+ const connection = client.connStateActor.getOrCreate().connect();
1086
+ const connState = await connection.getConnectionState();
1087
+ expect4(connState.id).toBeDefined();
1088
+ expect4(connState.username).toBeDefined();
1089
+ expect4(connState.role).toBeDefined();
1090
+ expect4(connState.counter).toBeDefined();
1091
+ expect4(connState.createdAt).toBeDefined();
1092
+ await connection.dispose();
1093
+ });
1094
+ test4("should initialize connection state with custom parameters", async (c) => {
1095
+ const { client } = await setupDriverTest(c, driverTestConfig);
1096
+ const connection = client.connStateActor.getOrCreate([], {
1097
+ params: {
1098
+ username: "testuser",
1099
+ role: "admin"
1100
+ }
1101
+ }).connect();
1102
+ const connState = await connection.getConnectionState();
1103
+ expect4(connState.username).toBe("testuser");
1104
+ expect4(connState.role).toBe("admin");
1105
+ await connection.dispose();
1106
+ });
1107
+ });
1108
+ describe4("Connection State Management", () => {
1109
+ test4("should maintain unique state for each connection", async (c) => {
1110
+ const { client } = await setupDriverTest(c, driverTestConfig);
1111
+ const conn1 = client.connStateActor.getOrCreate([], {
1112
+ params: { username: "user1" }
1113
+ }).connect();
1114
+ const conn2 = client.connStateActor.getOrCreate([], {
1115
+ params: { username: "user2" }
1116
+ }).connect();
1117
+ await conn1.incrementConnCounter(5);
1118
+ await conn2.incrementConnCounter(10);
1119
+ const state1 = await conn1.getConnectionState();
1120
+ const state2 = await conn2.getConnectionState();
1121
+ expect4(state1.counter).toBe(5);
1122
+ expect4(state2.counter).toBe(10);
1123
+ expect4(state1.username).toBe("user1");
1124
+ expect4(state2.username).toBe("user2");
1125
+ await conn1.dispose();
1126
+ await conn2.dispose();
1127
+ });
1128
+ test4("should track connections in shared state", async (c) => {
1129
+ const { client } = await setupDriverTest(c, driverTestConfig);
1130
+ const handle = client.connStateActor.getOrCreate();
1131
+ const conn1 = handle.connect();
1132
+ const conn2 = handle.connect();
1133
+ await conn1.getConnectionState();
1134
+ await conn2.getConnectionState();
1135
+ const state1 = await conn1.getConnectionState();
1136
+ const connectionIds = await conn1.getConnectionIds();
1137
+ expect4(connectionIds.length).toBeGreaterThanOrEqual(2);
1138
+ expect4(connectionIds).toContain(state1.id);
1139
+ await conn1.dispose();
1140
+ await conn2.dispose();
1141
+ });
1142
+ test4("should identify different connections in the same actor", async (c) => {
1143
+ const { client } = await setupDriverTest(c, driverTestConfig);
1144
+ const handle = client.connStateActor.getOrCreate();
1145
+ const conn1 = handle.connect();
1146
+ const conn2 = handle.connect();
1147
+ await conn1.getConnectionState();
1148
+ await conn2.getConnectionState();
1149
+ const allStates = await conn1.getAllConnectionStates();
1150
+ expect4(allStates.length).toBeGreaterThanOrEqual(2);
1151
+ const ids = allStates.map((state) => state.id);
1152
+ const uniqueIds = [...new Set(ids)];
1153
+ expect4(uniqueIds.length).toBe(ids.length);
1154
+ await conn1.dispose();
1155
+ await conn2.dispose();
1156
+ });
1157
+ });
1158
+ describe4("Connection Lifecycle", () => {
1159
+ test4("should track connection and disconnection events", async (c) => {
1160
+ const { client } = await setupDriverTest(c, driverTestConfig);
1161
+ const handle = client.connStateActor.getOrCreate();
1162
+ const conn = handle.connect();
1163
+ const connState = await conn.getConnectionState();
1164
+ const connectionIds = await conn.getConnectionIds();
1165
+ expect4(connectionIds).toContain(connState.id);
1166
+ const initialDisconnections = await conn.getDisconnectionCount();
1167
+ await conn.dispose();
1168
+ const newConn = handle.connect();
1169
+ await vi2.waitFor(async () => {
1170
+ const newDisconnections = await newConn.getDisconnectionCount();
1171
+ expect4(newDisconnections).toBeGreaterThan(initialDisconnections);
1172
+ });
1173
+ await newConn.dispose();
1174
+ });
1175
+ test4("should update connection state", async (c) => {
1176
+ const { client } = await setupDriverTest(c, driverTestConfig);
1177
+ const conn = client.connStateActor.getOrCreate().connect();
1178
+ const initialState = await conn.getConnectionState();
1179
+ expect4(initialState.username).toBe("anonymous");
1180
+ const updatedState = await conn.updateConnection({
1181
+ username: "newname",
1182
+ role: "moderator"
1183
+ });
1184
+ expect4(updatedState.username).toBe("newname");
1185
+ expect4(updatedState.role).toBe("moderator");
1186
+ const latestState = await conn.getConnectionState();
1187
+ expect4(latestState.username).toBe("newname");
1188
+ expect4(latestState.role).toBe("moderator");
1189
+ await conn.dispose();
1190
+ });
1191
+ });
1192
+ describe4("Connection Communication", () => {
1193
+ test4("should send messages to specific connections", async (c) => {
1194
+ const { client } = await setupDriverTest(c, driverTestConfig);
1195
+ const handle = client.connStateActor.getOrCreate();
1196
+ const conn1 = handle.connect();
1197
+ const conn2 = handle.connect();
1198
+ const state1 = await conn1.getConnectionState();
1199
+ const state2 = await conn2.getConnectionState();
1200
+ const receivedMessages = [];
1201
+ conn2.on("directMessage", (data) => {
1202
+ receivedMessages.push(data);
1203
+ });
1204
+ const success = await conn1.sendToConnection(
1205
+ state2.id,
1206
+ "Hello from conn1"
1207
+ );
1208
+ expect4(success).toBe(true);
1209
+ expect4(receivedMessages.length).toBe(1);
1210
+ expect4(receivedMessages[0].from).toBe(state1.id);
1211
+ expect4(receivedMessages[0].message).toBe("Hello from conn1");
1212
+ await conn1.dispose();
1213
+ await conn2.dispose();
1214
+ });
1215
+ });
1216
+ });
1217
+ }
1218
+
1219
+ // src/driver-test-suite/tests/actor-driver.ts
1220
+ import { describe as describe8 } from "vitest";
1221
+
1222
+ // src/driver-test-suite/tests/actor-schedule.ts
1223
+ import { describe as describe5, expect as expect5, test as test5 } from "vitest";
1224
+ function runActorScheduleTests(driverTestConfig) {
1225
+ var _a;
1226
+ describe5.skipIf((_a = driverTestConfig.skip) == null ? void 0 : _a.schedule)(
1227
+ "Actor Schedule Tests",
1228
+ () => {
1229
+ describe5("Scheduled Alarms", () => {
1230
+ test5("executes c.schedule.at() with specific timestamp", async (c) => {
1231
+ const { client } = await setupDriverTest(c, driverTestConfig);
1232
+ const scheduled = client.scheduled.getOrCreate();
1233
+ const timestamp = Date.now() + 100;
1234
+ await scheduled.scheduleTaskAt(timestamp);
1235
+ await waitFor(driverTestConfig, 200);
1236
+ const lastRun = await scheduled.getLastRun();
1237
+ const scheduledCount = await scheduled.getScheduledCount();
1238
+ expect5(lastRun).toBeGreaterThan(0);
1239
+ expect5(scheduledCount).toBe(1);
1240
+ });
1241
+ test5("executes c.schedule.after() with delay", async (c) => {
1242
+ const { client } = await setupDriverTest(c, driverTestConfig);
1243
+ const scheduled = client.scheduled.getOrCreate();
1244
+ await scheduled.scheduleTaskAfter(100);
1245
+ await waitFor(driverTestConfig, 200);
1246
+ const lastRun = await scheduled.getLastRun();
1247
+ const scheduledCount = await scheduled.getScheduledCount();
1248
+ expect5(lastRun).toBeGreaterThan(0);
1249
+ expect5(scheduledCount).toBe(1);
1250
+ });
1251
+ test5("scheduled tasks persist across actor restarts", async (c) => {
1252
+ const { client } = await setupDriverTest(c, driverTestConfig);
1253
+ const scheduled = client.scheduled.getOrCreate();
1254
+ await scheduled.scheduleTaskAfter(200);
1255
+ await waitFor(driverTestConfig, 100);
1256
+ const newInstance = client.scheduled.getOrCreate();
1257
+ const initialCount = await newInstance.getScheduledCount();
1258
+ expect5(initialCount).toBe(0);
1259
+ await waitFor(driverTestConfig, 200);
1260
+ const scheduledCount = await newInstance.getScheduledCount();
1261
+ expect5(scheduledCount).toBe(1);
1262
+ });
1263
+ test5("multiple scheduled tasks execute in order", async (c) => {
1264
+ const { client } = await setupDriverTest(c, driverTestConfig);
1265
+ const scheduled = client.scheduled.getOrCreate();
1266
+ await scheduled.clearHistory();
1267
+ await scheduled.scheduleTaskAfterWithId("first", 100);
1268
+ await scheduled.scheduleTaskAfterWithId("second", 300);
1269
+ await scheduled.scheduleTaskAfterWithId("third", 500);
1270
+ await waitFor(driverTestConfig, 200);
1271
+ const history1 = await scheduled.getTaskHistory();
1272
+ expect5(history1).toEqual(["first"]);
1273
+ await waitFor(driverTestConfig, 200);
1274
+ const history2 = await scheduled.getTaskHistory();
1275
+ expect5(history2).toEqual(["first", "second"]);
1276
+ await waitFor(driverTestConfig, 200);
1277
+ const history3 = await scheduled.getTaskHistory();
1278
+ expect5(history3).toEqual(["first", "second", "third"]);
1279
+ });
1280
+ });
1281
+ }
1282
+ );
1283
+ }
1284
+
1285
+ // src/driver-test-suite/tests/actor-sleep.ts
1286
+ import { describe as describe6, expect as expect6, test as test6 } from "vitest";
1287
+
1288
+ // fixtures/driver-test-suite/sleep.ts
1289
+ var SLEEP_TIMEOUT = 500;
1290
+ var sleep = actor({
1291
+ onAuth: () => {
1292
+ },
1293
+ state: { startCount: 0, sleepCount: 0 },
1294
+ onStart: (c) => {
1295
+ c.state.startCount += 1;
1296
+ },
1297
+ onStop: (c) => {
1298
+ c.state.sleepCount += 1;
1299
+ },
1300
+ actions: {
1301
+ triggerSleep: (c) => {
1302
+ c.sleep();
1303
+ },
1304
+ getCounts: (c) => {
1305
+ return { startCount: c.state.startCount, sleepCount: c.state.sleepCount };
1306
+ },
1307
+ setAlarm: async (c, duration) => {
1308
+ await c.schedule.after(duration, "onAlarm");
1309
+ },
1310
+ onAlarm: (c) => {
1311
+ c.log.info("alarm called");
1312
+ }
1313
+ },
1314
+ options: {
1315
+ sleepTimeout: SLEEP_TIMEOUT
1316
+ }
1317
+ });
1318
+ var sleepWithLongRpc = actor({
1319
+ onAuth: () => {
1320
+ },
1321
+ state: { startCount: 0, sleepCount: 0 },
1322
+ createVars: () => ({}),
1323
+ onStart: (c) => {
1324
+ c.state.startCount += 1;
1325
+ },
1326
+ onStop: (c) => {
1327
+ c.state.sleepCount += 1;
1328
+ },
1329
+ actions: {
1330
+ getCounts: (c) => {
1331
+ return { startCount: c.state.startCount, sleepCount: c.state.sleepCount };
1332
+ },
1333
+ longRunningRpc: async (c) => {
1334
+ c.log.info("starting long running rpc");
1335
+ c.vars.longRunningResolve = Promise.withResolvers();
1336
+ c.broadcast("waiting");
1337
+ await c.vars.longRunningResolve.promise;
1338
+ c.log.info("finished long running rpc");
1339
+ },
1340
+ finishLongRunningRpc: (c) => {
1341
+ var _a;
1342
+ return (_a = c.vars.longRunningResolve) == null ? void 0 : _a.resolve();
1343
+ }
1344
+ },
1345
+ options: {
1346
+ sleepTimeout: SLEEP_TIMEOUT
1347
+ }
1348
+ });
1349
+ var sleepWithRawHttp = actor({
1350
+ onAuth: () => {
1351
+ },
1352
+ state: { startCount: 0, sleepCount: 0, requestCount: 0 },
1353
+ onStart: (c) => {
1354
+ c.state.startCount += 1;
1355
+ },
1356
+ onStop: (c) => {
1357
+ c.state.sleepCount += 1;
1358
+ },
1359
+ onFetch: async (c, request) => {
1360
+ c.state.requestCount += 1;
1361
+ const url = new URL(request.url);
1362
+ if (url.pathname === "/long-request") {
1363
+ const duration = parseInt(url.searchParams.get("duration") || "1000");
1364
+ c.log.info("starting long fetch request", { duration });
1365
+ await new Promise((resolve2) => setTimeout(resolve2, duration));
1366
+ c.log.info("finished long fetch request");
1367
+ return new Response(JSON.stringify({ completed: true }), {
1368
+ headers: { "Content-Type": "application/json" }
1369
+ });
1370
+ }
1371
+ return new Response("Not Found", { status: 404 });
1372
+ },
1373
+ actions: {
1374
+ getCounts: (c) => {
1375
+ return {
1376
+ startCount: c.state.startCount,
1377
+ sleepCount: c.state.sleepCount,
1378
+ requestCount: c.state.requestCount
1379
+ };
1380
+ }
1381
+ },
1382
+ options: {
1383
+ sleepTimeout: SLEEP_TIMEOUT
1384
+ }
1385
+ });
1386
+ var sleepWithRawWebSocket = actor({
1387
+ onAuth: () => {
1388
+ },
1389
+ state: { startCount: 0, sleepCount: 0, connectionCount: 0 },
1390
+ onStart: (c) => {
1391
+ c.state.startCount += 1;
1392
+ },
1393
+ onStop: (c) => {
1394
+ c.state.sleepCount += 1;
1395
+ },
1396
+ onWebSocket: (c, websocket, opts) => {
1397
+ c.state.connectionCount += 1;
1398
+ c.log.info("websocket connected", {
1399
+ connectionCount: c.state.connectionCount
1400
+ });
1401
+ websocket.send(
1402
+ JSON.stringify({
1403
+ type: "connected",
1404
+ connectionCount: c.state.connectionCount
1405
+ })
1406
+ );
1407
+ websocket.addEventListener("message", (event) => {
1408
+ const data = event.data;
1409
+ if (typeof data === "string") {
1410
+ try {
1411
+ const parsed = JSON.parse(data);
1412
+ if (parsed.type === "getCounts") {
1413
+ websocket.send(
1414
+ JSON.stringify({
1415
+ type: "counts",
1416
+ startCount: c.state.startCount,
1417
+ sleepCount: c.state.sleepCount,
1418
+ connectionCount: c.state.connectionCount
1419
+ })
1420
+ );
1421
+ } else if (parsed.type === "keepAlive") {
1422
+ websocket.send(JSON.stringify({ type: "ack" }));
1423
+ }
1424
+ } catch {
1425
+ websocket.send(data);
1426
+ }
1427
+ }
1428
+ });
1429
+ websocket.addEventListener("close", () => {
1430
+ c.state.connectionCount -= 1;
1431
+ c.log.info("websocket disconnected", {
1432
+ connectionCount: c.state.connectionCount
1433
+ });
1434
+ });
1435
+ },
1436
+ actions: {
1437
+ getCounts: (c) => {
1438
+ return {
1439
+ startCount: c.state.startCount,
1440
+ sleepCount: c.state.sleepCount,
1441
+ connectionCount: c.state.connectionCount
1442
+ };
1443
+ }
1444
+ },
1445
+ options: {
1446
+ sleepTimeout: SLEEP_TIMEOUT
1447
+ }
1448
+ });
1449
+ var sleepWithNoSleepOption = actor({
1450
+ onAuth: () => {
1451
+ },
1452
+ state: { startCount: 0, sleepCount: 0 },
1453
+ onStart: (c) => {
1454
+ c.state.startCount += 1;
1455
+ },
1456
+ onStop: (c) => {
1457
+ c.state.sleepCount += 1;
1458
+ },
1459
+ actions: {
1460
+ getCounts: (c) => {
1461
+ return { startCount: c.state.startCount, sleepCount: c.state.sleepCount };
1462
+ }
1463
+ },
1464
+ options: {
1465
+ sleepTimeout: SLEEP_TIMEOUT,
1466
+ noSleep: true
1467
+ }
1468
+ });
1469
+
1470
+ // src/driver-test-suite/tests/actor-sleep.ts
1471
+ function runActorSleepTests(driverTestConfig) {
1472
+ var _a;
1473
+ describe6.skipIf((_a = driverTestConfig.skip) == null ? void 0 : _a.sleep)("Actor Sleep Tests", () => {
1474
+ test6("actor sleep persists state", async (c) => {
1475
+ const { client } = await setupDriverTest(c, driverTestConfig);
1476
+ const sleepActor = client.sleep.getOrCreate();
1477
+ {
1478
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1479
+ expect6(sleepCount).toBe(0);
1480
+ expect6(startCount).toBe(1);
1481
+ }
1482
+ await sleepActor.triggerSleep();
1483
+ await waitFor(driverTestConfig, 100);
1484
+ {
1485
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1486
+ expect6(sleepCount).toBe(1);
1487
+ expect6(startCount).toBe(2);
1488
+ }
1489
+ });
1490
+ test6("actor sleep persists state with connect", async (c) => {
1491
+ const { client } = await setupDriverTest(c, driverTestConfig);
1492
+ const sleepActor = client.sleep.getOrCreate().connect();
1493
+ {
1494
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1495
+ expect6(sleepCount).toBe(0);
1496
+ expect6(startCount).toBe(1);
1497
+ }
1498
+ await sleepActor.triggerSleep();
1499
+ await sleepActor.dispose();
1500
+ await waitFor(driverTestConfig, 100);
1501
+ const sleepActor2 = client.sleep.getOrCreate();
1502
+ {
1503
+ const { startCount, sleepCount } = await sleepActor2.getCounts();
1504
+ expect6(sleepCount).toBe(1);
1505
+ expect6(startCount).toBe(2);
1506
+ }
1507
+ });
1508
+ test6("actor automatically sleeps after timeout", async (c) => {
1509
+ const { client } = await setupDriverTest(c, driverTestConfig);
1510
+ const sleepActor = client.sleep.getOrCreate();
1511
+ {
1512
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1513
+ expect6(sleepCount).toBe(0);
1514
+ expect6(startCount).toBe(1);
1515
+ }
1516
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1517
+ {
1518
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1519
+ expect6(sleepCount).toBe(1);
1520
+ expect6(startCount).toBe(2);
1521
+ }
1522
+ });
1523
+ test6("actor automatically sleeps after timeout with connect", async (c) => {
1524
+ const { client } = await setupDriverTest(c, driverTestConfig);
1525
+ const sleepActor = client.sleep.getOrCreate().connect();
1526
+ {
1527
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1528
+ expect6(sleepCount).toBe(0);
1529
+ expect6(startCount).toBe(1);
1530
+ }
1531
+ await sleepActor.dispose();
1532
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1533
+ const sleepActor2 = client.sleep.getOrCreate();
1534
+ {
1535
+ const { startCount, sleepCount } = await sleepActor2.getCounts();
1536
+ expect6(sleepCount).toBe(1);
1537
+ expect6(startCount).toBe(2);
1538
+ }
1539
+ });
1540
+ test6("rpc calls keep actor awake", async (c) => {
1541
+ const { client } = await setupDriverTest(c, driverTestConfig);
1542
+ const sleepActor = client.sleep.getOrCreate();
1543
+ {
1544
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1545
+ expect6(sleepCount).toBe(0);
1546
+ expect6(startCount).toBe(1);
1547
+ }
1548
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT - 100);
1549
+ {
1550
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1551
+ expect6(sleepCount).toBe(0);
1552
+ expect6(startCount).toBe(1);
1553
+ }
1554
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT - 100);
1555
+ {
1556
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1557
+ expect6(sleepCount).toBe(0);
1558
+ expect6(startCount).toBe(1);
1559
+ }
1560
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1561
+ {
1562
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1563
+ expect6(sleepCount).toBe(1);
1564
+ expect6(startCount).toBe(2);
1565
+ }
1566
+ });
1567
+ test6("alarms keep actor awake", async (c) => {
1568
+ const { client } = await setupDriverTest(c, driverTestConfig);
1569
+ const sleepActor = client.sleep.getOrCreate();
1570
+ {
1571
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1572
+ expect6(sleepCount).toBe(0);
1573
+ expect6(startCount).toBe(1);
1574
+ }
1575
+ await sleepActor.setAlarm(SLEEP_TIMEOUT - 100);
1576
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1577
+ {
1578
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1579
+ expect6(sleepCount).toBe(0);
1580
+ expect6(startCount).toBe(1);
1581
+ }
1582
+ });
1583
+ test6("alarms wake actors", async (c) => {
1584
+ const { client } = await setupDriverTest(c, driverTestConfig);
1585
+ const sleepActor = client.sleep.getOrCreate();
1586
+ {
1587
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1588
+ expect6(sleepCount).toBe(0);
1589
+ expect6(startCount).toBe(1);
1590
+ }
1591
+ await sleepActor.setAlarm(SLEEP_TIMEOUT + 100);
1592
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 200);
1593
+ {
1594
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1595
+ expect6(sleepCount).toBe(1);
1596
+ expect6(startCount).toBe(2);
1597
+ }
1598
+ });
1599
+ test6("long running rpcs keep actor awake", async (c) => {
1600
+ const { client } = await setupDriverTest(c, driverTestConfig);
1601
+ const sleepActor = client.sleepWithLongRpc.getOrCreate().connect();
1602
+ {
1603
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1604
+ expect6(sleepCount).toBe(0);
1605
+ expect6(startCount).toBe(1);
1606
+ }
1607
+ const waitPromise = new Promise(
1608
+ (resolve2) => sleepActor.once("waiting", resolve2)
1609
+ );
1610
+ const longRunningPromise = sleepActor.longRunningRpc();
1611
+ await waitPromise;
1612
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1613
+ await sleepActor.finishLongRunningRpc();
1614
+ await longRunningPromise;
1615
+ {
1616
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1617
+ expect6(sleepCount).toBe(0);
1618
+ expect6(startCount).toBe(1);
1619
+ }
1620
+ await sleepActor.dispose();
1621
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1622
+ const sleepActor2 = client.sleepWithLongRpc.getOrCreate();
1623
+ {
1624
+ const { startCount, sleepCount } = await sleepActor2.getCounts();
1625
+ expect6(sleepCount).toBe(1);
1626
+ expect6(startCount).toBe(2);
1627
+ }
1628
+ });
1629
+ test6("active raw websockets keep actor awake", async (c) => {
1630
+ const { client, endpoint: baseUrl } = await setupDriverTest(
1631
+ c,
1632
+ driverTestConfig
1633
+ );
1634
+ const sleepActor = client.sleepWithRawWebSocket.getOrCreate();
1635
+ {
1636
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1637
+ expect6(sleepCount).toBe(0);
1638
+ expect6(startCount).toBe(1);
1639
+ }
1640
+ const ws = await sleepActor.websocket();
1641
+ await new Promise((resolve2, reject) => {
1642
+ ws.onopen = () => resolve2();
1643
+ ws.onerror = reject;
1644
+ });
1645
+ await new Promise((resolve2) => {
1646
+ ws.onmessage = (event) => {
1647
+ const data = JSON.parse(event.data);
1648
+ if (data.type === "connected") {
1649
+ resolve2();
1650
+ }
1651
+ };
1652
+ });
1653
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1654
+ ws.send(JSON.stringify({ type: "getCounts" }));
1655
+ const counts = await new Promise((resolve2) => {
1656
+ ws.onmessage = (event) => {
1657
+ const data = JSON.parse(event.data);
1658
+ if (data.type === "counts") {
1659
+ resolve2(data);
1660
+ }
1661
+ };
1662
+ });
1663
+ expect6(counts.sleepCount).toBe(0);
1664
+ expect6(counts.startCount).toBe(1);
1665
+ ws.close();
1666
+ await new Promise((resolve2) => setTimeout(resolve2, 100));
1667
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1668
+ {
1669
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1670
+ expect6(sleepCount).toBe(1);
1671
+ expect6(startCount).toBe(2);
1672
+ }
1673
+ });
1674
+ test6("active raw fetch requests keep actor awake", async (c) => {
1675
+ const { client, endpoint: baseUrl } = await setupDriverTest(
1676
+ c,
1677
+ driverTestConfig
1678
+ );
1679
+ const sleepActor = client.sleepWithRawHttp.getOrCreate();
1680
+ {
1681
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1682
+ expect6(sleepCount).toBe(0);
1683
+ expect6(startCount).toBe(1);
1684
+ }
1685
+ const fetchDuration = SLEEP_TIMEOUT + 100;
1686
+ const fetchPromise = sleepActor.fetch(
1687
+ `long-request?duration=${fetchDuration}`
1688
+ );
1689
+ const response = await fetchPromise;
1690
+ const result = await response.json();
1691
+ expect6(result.completed).toBe(true);
1692
+ {
1693
+ const { startCount, sleepCount, requestCount } = await sleepActor.getCounts();
1694
+ expect6(sleepCount).toBe(0);
1695
+ expect6(startCount).toBe(1);
1696
+ expect6(requestCount).toBe(1);
1697
+ }
1698
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1699
+ {
1700
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1701
+ expect6(sleepCount).toBe(1);
1702
+ expect6(startCount).toBe(2);
1703
+ }
1704
+ });
1705
+ test6("noSleep option disables sleeping", async (c) => {
1706
+ const { client } = await setupDriverTest(c, driverTestConfig);
1707
+ const sleepActor = client.sleepWithNoSleepOption.getOrCreate();
1708
+ {
1709
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1710
+ expect6(sleepCount).toBe(0);
1711
+ expect6(startCount).toBe(1);
1712
+ }
1713
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1714
+ {
1715
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1716
+ expect6(sleepCount).toBe(0);
1717
+ expect6(startCount).toBe(1);
1718
+ }
1719
+ await waitFor(driverTestConfig, SLEEP_TIMEOUT + 100);
1720
+ {
1721
+ const { startCount, sleepCount } = await sleepActor.getCounts();
1722
+ expect6(sleepCount).toBe(0);
1723
+ expect6(startCount).toBe(1);
1724
+ }
1725
+ });
1726
+ });
1727
+ }
1728
+
1729
+ // src/driver-test-suite/tests/actor-state.ts
1730
+ import { describe as describe7, expect as expect7, test as test7 } from "vitest";
1731
+ function runActorStateTests(driverTestConfig) {
1732
+ describe7("Actor State Tests", () => {
1733
+ describe7("State Persistence", () => {
1734
+ test7("persists state between actor instances", async (c) => {
1735
+ const { client } = await setupDriverTest(c, driverTestConfig);
1736
+ const counterInstance = client.counter.getOrCreate();
1737
+ const initialCount = await counterInstance.increment(5);
1738
+ expect7(initialCount).toBe(5);
1739
+ const sameInstance = client.counter.getOrCreate();
1740
+ const persistedCount = await sameInstance.increment(3);
1741
+ expect7(persistedCount).toBe(8);
1742
+ });
1743
+ test7("restores state after actor disconnect/reconnect", async (c) => {
1744
+ const { client } = await setupDriverTest(c, driverTestConfig);
1745
+ const counterInstance = client.counter.getOrCreate();
1746
+ await counterInstance.increment(5);
1747
+ const reconnectedInstance = client.counter.getOrCreate();
1748
+ const persistedCount = await reconnectedInstance.increment(0);
1749
+ expect7(persistedCount).toBe(5);
1750
+ });
1751
+ test7("maintains separate state for different actors", async (c) => {
1752
+ const { client } = await setupDriverTest(c, driverTestConfig);
1753
+ const counterA = client.counter.getOrCreate(["counter-a"]);
1754
+ await counterA.increment(5);
1755
+ const counterB = client.counter.getOrCreate(["counter-b"]);
1756
+ await counterB.increment(10);
1757
+ const countA = await counterA.increment(0);
1758
+ const countB = await counterB.increment(0);
1759
+ expect7(countA).toBe(5);
1760
+ expect7(countB).toBe(10);
1761
+ });
1762
+ });
1763
+ });
1764
+ }
1765
+
1766
+ // src/driver-test-suite/tests/actor-driver.ts
1767
+ function runActorDriverTests(driverTestConfig) {
1768
+ describe8("Actor Driver Tests", () => {
1769
+ runActorStateTests(driverTestConfig);
1770
+ runActorScheduleTests(driverTestConfig);
1771
+ });
1772
+ }
1773
+ function runActorDriverTestsWithTransport(driverTestConfig) {
1774
+ describe8("Actor Driver Tests", () => {
1775
+ runActorSleepTests(driverTestConfig);
1776
+ });
1777
+ }
1778
+
1779
+ // src/driver-test-suite/tests/actor-error-handling.ts
1780
+ import { describe as describe9, expect as expect8, test as test8 } from "vitest";
1781
+ function runActorErrorHandlingTests(driverTestConfig) {
1782
+ describe9("Actor Error Handling Tests", () => {
1783
+ describe9("UserError Handling", () => {
1784
+ test8("should handle simple UserError with message", async (c) => {
1785
+ const { client } = await setupDriverTest(c, driverTestConfig);
1786
+ const handle = client.errorHandlingActor.getOrCreate();
1787
+ try {
1788
+ await handle.throwSimpleError();
1789
+ expect8(true).toBe(false);
1790
+ } catch (error) {
1791
+ expect8(error.message).toBe("Simple error message");
1792
+ expect8(error.code).toBe("user_error");
1793
+ expect8(error.metadata).toBeUndefined();
1794
+ }
1795
+ });
1796
+ test8("should handle detailed UserError with code and metadata", async (c) => {
1797
+ const { client } = await setupDriverTest(c, driverTestConfig);
1798
+ const handle = client.errorHandlingActor.getOrCreate();
1799
+ try {
1800
+ await handle.throwDetailedError();
1801
+ expect8(true).toBe(false);
1802
+ } catch (error) {
1803
+ expect8(error.message).toBe("Detailed error message");
1804
+ expect8(error.code).toBe("detailed_error");
1805
+ expect8(error.metadata).toBeDefined();
1806
+ expect8(error.metadata.reason).toBe("test");
1807
+ expect8(error.metadata.timestamp).toBeDefined();
1808
+ }
1809
+ });
1810
+ });
1811
+ describe9("Internal Error Handling", () => {
1812
+ test8("should convert internal errors to safe format", async (c) => {
1813
+ const { client } = await setupDriverTest(c, driverTestConfig);
1814
+ const handle = client.errorHandlingActor.getOrCreate();
1815
+ try {
1816
+ await handle.throwInternalError();
1817
+ expect8(true).toBe(false);
1818
+ } catch (error) {
1819
+ if (driverTestConfig.clientType === "http") {
1820
+ expect8(error.code).toBe(INTERNAL_ERROR_CODE);
1821
+ expect8(error.message).toBe(INTERNAL_ERROR_DESCRIPTION);
1822
+ } else if (driverTestConfig.clientType === "inline") {
1823
+ expect8(error.code).toBe(INTERNAL_ERROR_CODE);
1824
+ expect8(error.message).toBe("This is an internal error");
1825
+ } else {
1826
+ assertUnreachable(driverTestConfig.clientType);
1827
+ }
1828
+ }
1829
+ });
1830
+ });
1831
+ describe9.skip("Action Timeout", () => {
1832
+ test8("should handle action timeouts with custom duration", async (c) => {
1833
+ const { client } = await setupDriverTest(c, driverTestConfig);
1834
+ const handle = client.errorHandlingActor.getOrCreate();
1835
+ const timeoutPromise = handle.timeoutAction();
1836
+ try {
1837
+ await timeoutPromise;
1838
+ expect8(true).toBe(false);
1839
+ } catch (error) {
1840
+ expect8(error.message).toMatch(/timed out/i);
1841
+ }
1842
+ });
1843
+ test8("should successfully run actions within timeout", async (c) => {
1844
+ const { client } = await setupDriverTest(c, driverTestConfig);
1845
+ const handle = client.errorHandlingActor.getOrCreate();
1846
+ const result = await handle.delayedAction(200);
1847
+ expect8(result).toBe("Completed after 200ms");
1848
+ });
1849
+ test8("should respect different timeouts for different actors", async (c) => {
1850
+ const { client } = await setupDriverTest(c, driverTestConfig);
1851
+ try {
1852
+ await client.customTimeoutActor.getOrCreate().slowAction();
1853
+ expect8(true).toBe(false);
1854
+ } catch (error) {
1855
+ expect8(error.message).toMatch(/timed out/i);
1856
+ }
1857
+ const quickResult = await client.customTimeoutActor.getOrCreate().quickAction();
1858
+ expect8(quickResult).toBe("Quick action completed");
1859
+ });
1860
+ });
1861
+ describe9("Error Recovery", () => {
1862
+ test8("should continue working after errors", async (c) => {
1863
+ const { client } = await setupDriverTest(c, driverTestConfig);
1864
+ const handle = client.errorHandlingActor.getOrCreate();
1865
+ try {
1866
+ await handle.throwSimpleError();
1867
+ } catch (error) {
1868
+ }
1869
+ const result = await handle.successfulAction();
1870
+ expect8(result).toBe("success");
1871
+ });
1872
+ });
1873
+ });
1874
+ }
1875
+
1876
+ // src/driver-test-suite/tests/actor-handle.ts
1877
+ import { describe as describe10, expect as expect9, test as test9 } from "vitest";
1878
+ function runActorHandleTests(driverTestConfig) {
1879
+ describe10("Actor Handle Tests", () => {
1880
+ describe10("Access Methods", () => {
1881
+ test9("should use .get() to access a actor", async (c) => {
1882
+ const { client } = await setupDriverTest(c, driverTestConfig);
1883
+ await client.counter.create(["test-get-handle"]);
1884
+ const handle = client.counter.get(["test-get-handle"]);
1885
+ const count = await handle.increment(5);
1886
+ expect9(count).toBe(5);
1887
+ const retrievedCount = await handle.getCount();
1888
+ expect9(retrievedCount).toBe(5);
1889
+ });
1890
+ test9("should use .getForId() to access a actor by ID", async (c) => {
1891
+ const { client } = await setupDriverTest(c, driverTestConfig);
1892
+ const handle = client.counter.getOrCreate(["test-get-for-id-handle"]);
1893
+ await handle.increment(3);
1894
+ const actorId = await handle.resolve();
1895
+ const idHandle = client.counter.getForId(actorId);
1896
+ const count = await idHandle.getCount();
1897
+ expect9(count).toBe(3);
1898
+ const newCount = await idHandle.increment(4);
1899
+ expect9(newCount).toBe(7);
1900
+ });
1901
+ test9("should use .getOrCreate() to access or create a actor", async (c) => {
1902
+ const { client } = await setupDriverTest(c, driverTestConfig);
1903
+ const handle = client.counter.getOrCreate([
1904
+ "test-get-or-create-handle"
1905
+ ]);
1906
+ const count = await handle.increment(7);
1907
+ expect9(count).toBe(7);
1908
+ const sameHandle = client.counter.getOrCreate([
1909
+ "test-get-or-create-handle"
1910
+ ]);
1911
+ const retrievedCount = await sameHandle.getCount();
1912
+ expect9(retrievedCount).toBe(7);
1913
+ });
1914
+ test9("should use (await create()) to create and return a handle", async (c) => {
1915
+ const { client } = await setupDriverTest(c, driverTestConfig);
1916
+ const handle = await client.counter.create(["test-create-handle"]);
1917
+ const count = await handle.increment(9);
1918
+ expect9(count).toBe(9);
1919
+ const retrievedCount = await handle.getCount();
1920
+ expect9(retrievedCount).toBe(9);
1921
+ });
1922
+ });
1923
+ describe10("Action Functionality", () => {
1924
+ test9("should call actions directly on the handle", async (c) => {
1925
+ const { client } = await setupDriverTest(c, driverTestConfig);
1926
+ const handle = client.counter.getOrCreate(["test-action-handle"]);
1927
+ const count1 = await handle.increment(3);
1928
+ expect9(count1).toBe(3);
1929
+ const count2 = await handle.increment(5);
1930
+ expect9(count2).toBe(8);
1931
+ const retrievedCount = await handle.getCount();
1932
+ expect9(retrievedCount).toBe(8);
1933
+ });
1934
+ test9("should handle independent handles to the same actor", async (c) => {
1935
+ const { client } = await setupDriverTest(c, driverTestConfig);
1936
+ const handle1 = client.counter.getOrCreate(["test-multiple-handles"]);
1937
+ const handle2 = client.counter.get(["test-multiple-handles"]);
1938
+ await handle1.increment(3);
1939
+ const count = await handle2.getCount();
1940
+ expect9(count).toBe(3);
1941
+ const finalCount = await handle2.increment(4);
1942
+ expect9(finalCount).toBe(7);
1943
+ const checkCount = await handle1.getCount();
1944
+ expect9(checkCount).toBe(7);
1945
+ });
1946
+ test9("should resolve a actor's ID", async (c) => {
1947
+ const { client } = await setupDriverTest(c, driverTestConfig);
1948
+ const handle = client.counter.getOrCreate(["test-resolve-id"]);
1949
+ await handle.increment(1);
1950
+ const actorId = await handle.resolve();
1951
+ expect9(typeof actorId).toBe("string");
1952
+ expect9(actorId).not.toBe("");
1953
+ const idHandle = client.counter.getForId(actorId);
1954
+ const count = await idHandle.getCount();
1955
+ expect9(count).toBe(1);
1956
+ });
1957
+ });
1958
+ describe10("Lifecycle Hooks", () => {
1959
+ test9("should trigger lifecycle hooks on actor creation", async (c) => {
1960
+ const { client } = await setupDriverTest(c, driverTestConfig);
1961
+ const handle = client.counterWithLifecycle.getOrCreate([
1962
+ "test-lifecycle-handle"
1963
+ ]);
1964
+ const initialEvents = await handle.getEvents();
1965
+ expect9(initialEvents).toContain("onStart");
1966
+ const sameHandle = client.counterWithLifecycle.getOrCreate([
1967
+ "test-lifecycle-handle"
1968
+ ]);
1969
+ const events = await sameHandle.getEvents();
1970
+ expect9(events).toContain("onStart");
1971
+ expect9(events.filter((e) => e === "onStart").length).toBe(1);
1972
+ });
1973
+ test9("should trigger lifecycle hooks for each Action call", async (c) => {
1974
+ const { client } = await setupDriverTest(c, driverTestConfig);
1975
+ const viewHandle = client.counterWithLifecycle.getOrCreate([
1976
+ "test-lifecycle-action"
1977
+ ]);
1978
+ const initialEvents = await viewHandle.getEvents();
1979
+ expect9(initialEvents).toContain("onStart");
1980
+ expect9(initialEvents).not.toContain("onBeforeConnect");
1981
+ expect9(initialEvents).not.toContain("onConnect");
1982
+ expect9(initialEvents).not.toContain("onDisconnect");
1983
+ const trackingHandle = client.counterWithLifecycle.getOrCreate(
1984
+ ["test-lifecycle-action"],
1985
+ { params: { trackLifecycle: true } }
1986
+ );
1987
+ await trackingHandle.increment(5);
1988
+ const eventsAfterAction = await viewHandle.getEvents();
1989
+ expect9(eventsAfterAction).toContain("onBeforeConnect");
1990
+ expect9(eventsAfterAction).toContain("onConnect");
1991
+ expect9(eventsAfterAction).toContain("onDisconnect");
1992
+ expect9(
1993
+ eventsAfterAction.filter((e) => e === "onBeforeConnect").length
1994
+ ).toBe(1);
1995
+ expect9(eventsAfterAction.filter((e) => e === "onConnect").length).toBe(
1996
+ 1
1997
+ );
1998
+ expect9(
1999
+ eventsAfterAction.filter((e) => e === "onDisconnect").length
2000
+ ).toBe(1);
2001
+ await trackingHandle.increment(10);
2002
+ const eventsAfterSecondAction = await viewHandle.getEvents();
2003
+ expect9(
2004
+ eventsAfterSecondAction.filter((e) => e === "onBeforeConnect").length
2005
+ ).toBe(2);
2006
+ expect9(
2007
+ eventsAfterSecondAction.filter((e) => e === "onConnect").length
2008
+ ).toBe(2);
2009
+ expect9(
2010
+ eventsAfterSecondAction.filter((e) => e === "onDisconnect").length
2011
+ ).toBe(2);
2012
+ });
2013
+ test9("should trigger lifecycle hooks for each Action call across multiple handles", async (c) => {
2014
+ const { client } = await setupDriverTest(c, driverTestConfig);
2015
+ const viewHandle = client.counterWithLifecycle.getOrCreate([
2016
+ "test-lifecycle-multi-handle"
2017
+ ]);
2018
+ const trackingHandle1 = client.counterWithLifecycle.getOrCreate(
2019
+ ["test-lifecycle-multi-handle"],
2020
+ { params: { trackLifecycle: true } }
2021
+ );
2022
+ const trackingHandle2 = client.counterWithLifecycle.getOrCreate(
2023
+ ["test-lifecycle-multi-handle"],
2024
+ { params: { trackLifecycle: true } }
2025
+ );
2026
+ await trackingHandle1.increment(5);
2027
+ await trackingHandle2.increment(10);
2028
+ const events = await viewHandle.getEvents();
2029
+ expect9(events.filter((e) => e === "onStart").length).toBe(1);
2030
+ expect9(events.filter((e) => e === "onBeforeConnect").length).toBe(2);
2031
+ expect9(events.filter((e) => e === "onConnect").length).toBe(2);
2032
+ expect9(events.filter((e) => e === "onDisconnect").length).toBe(2);
2033
+ });
2034
+ });
2035
+ });
2036
+ }
2037
+
2038
+ // src/driver-test-suite/tests/actor-inline-client.ts
2039
+ import { describe as describe11, expect as expect10, test as test10 } from "vitest";
2040
+ function runActorInlineClientTests(driverTestConfig) {
2041
+ describe11("Actor Inline Client Tests", () => {
2042
+ describe11("Stateless Client Calls", () => {
2043
+ test10("should make stateless calls to other actors", async (c) => {
2044
+ const { client } = await setupDriverTest(c, driverTestConfig);
2045
+ const inlineClientHandle = client.inlineClientActor.getOrCreate([
2046
+ "inline-client-test"
2047
+ ]);
2048
+ const result = await inlineClientHandle.callCounterIncrement(5);
2049
+ expect10(result).toBe(5);
2050
+ const counterState = await inlineClientHandle.getCounterState();
2051
+ expect10(counterState).toBe(5);
2052
+ const messages = await inlineClientHandle.getMessages();
2053
+ expect10(messages).toHaveLength(2);
2054
+ expect10(messages[0]).toContain("Called counter.increment(5), result: 5");
2055
+ expect10(messages[1]).toContain("Got counter state: 5");
2056
+ });
2057
+ test10("should handle multiple stateless calls", async (c) => {
2058
+ const { client } = await setupDriverTest(c, driverTestConfig);
2059
+ const inlineClientHandle = client.inlineClientActor.getOrCreate([
2060
+ "inline-client-multi"
2061
+ ]);
2062
+ await inlineClientHandle.clearMessages();
2063
+ const result1 = await inlineClientHandle.callCounterIncrement(3);
2064
+ const result2 = await inlineClientHandle.callCounterIncrement(7);
2065
+ const finalState = await inlineClientHandle.getCounterState();
2066
+ expect10(result1).toBe(3);
2067
+ expect10(result2).toBe(10);
2068
+ expect10(finalState).toBe(10);
2069
+ const messages = await inlineClientHandle.getMessages();
2070
+ expect10(messages).toHaveLength(3);
2071
+ expect10(messages[0]).toContain("Called counter.increment(3), result: 3");
2072
+ expect10(messages[1]).toContain(
2073
+ "Called counter.increment(7), result: 10"
2074
+ );
2075
+ expect10(messages[2]).toContain("Got counter state: 10");
2076
+ });
2077
+ });
2078
+ describe11("Stateful Client Calls", () => {
2079
+ test10("should connect to other actors and receive events", async (c) => {
2080
+ const { client } = await setupDriverTest(c, driverTestConfig);
2081
+ const inlineClientHandle = client.inlineClientActor.getOrCreate([
2082
+ "inline-client-stateful"
2083
+ ]);
2084
+ await inlineClientHandle.clearMessages();
2085
+ const result = await inlineClientHandle.connectToCounterAndIncrement(4);
2086
+ expect10(result.result1).toBe(4);
2087
+ expect10(result.result2).toBe(12);
2088
+ expect10(result.events).toEqual([4, 12]);
2089
+ const messages = await inlineClientHandle.getMessages();
2090
+ expect10(messages).toHaveLength(1);
2091
+ expect10(messages[0]).toContain(
2092
+ "Connected to counter, incremented by 4 and 8"
2093
+ );
2094
+ expect10(messages[0]).toContain("results: 4, 12");
2095
+ expect10(messages[0]).toContain("events: [4,12]");
2096
+ });
2097
+ test10("should handle stateful connection independently", async (c) => {
2098
+ const { client } = await setupDriverTest(c, driverTestConfig);
2099
+ const inlineClientHandle = client.inlineClientActor.getOrCreate([
2100
+ "inline-client-independent"
2101
+ ]);
2102
+ await inlineClientHandle.clearMessages();
2103
+ const result = await inlineClientHandle.connectToCounterAndIncrement(2);
2104
+ expect10(result.result1).toBe(2);
2105
+ expect10(result.result2).toBe(6);
2106
+ expect10(result.events).toEqual([2, 6]);
2107
+ const messages = await inlineClientHandle.getMessages();
2108
+ expect10(messages).toHaveLength(1);
2109
+ expect10(messages[0]).toContain(
2110
+ "Connected to counter, incremented by 2 and 4"
2111
+ );
2112
+ });
2113
+ });
2114
+ describe11("Mixed Client Usage", () => {
2115
+ test10("should handle both stateless and stateful calls", async (c) => {
2116
+ const { client } = await setupDriverTest(c, driverTestConfig);
2117
+ const inlineClientHandle = client.inlineClientActor.getOrCreate([
2118
+ "inline-client-mixed"
2119
+ ]);
2120
+ await inlineClientHandle.clearMessages();
2121
+ await inlineClientHandle.callCounterIncrement(1);
2122
+ const statelessResult = await inlineClientHandle.getCounterState();
2123
+ expect10(statelessResult).toBe(1);
2124
+ const statefulResult = await inlineClientHandle.connectToCounterAndIncrement(3);
2125
+ expect10(statefulResult.result1).toBe(3);
2126
+ expect10(statefulResult.result2).toBe(9);
2127
+ const messages = await inlineClientHandle.getMessages();
2128
+ expect10(messages).toHaveLength(3);
2129
+ expect10(messages[0]).toContain("Called counter.increment(1), result: 1");
2130
+ expect10(messages[1]).toContain("Got counter state: 1");
2131
+ expect10(messages[2]).toContain(
2132
+ "Connected to counter, incremented by 3 and 6"
2133
+ );
2134
+ });
2135
+ });
2136
+ });
2137
+ }
2138
+
2139
+ // src/driver-test-suite/tests/actor-inspector.ts
2140
+ import { describe as describe12, expect as expect11, test as test11 } from "vitest";
2141
+ function runActorInspectorTests(driverTestConfig) {
2142
+ describe12("Actor Inspector Tests", () => {
2143
+ describe12("Manager Inspector", () => {
2144
+ test11("should respond to ping", async (c) => {
2145
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
2146
+ const http = createManagerInspectorClient(`${endpoint}/inspect`, {
2147
+ headers: {
2148
+ Authorization: `Bearer token`
2149
+ }
2150
+ });
2151
+ const response = await http.ping.$get();
2152
+ expect11(response.status).toBe(200);
2153
+ const data = await response.json();
2154
+ expect11(data).toEqual({ message: "pong" });
2155
+ });
2156
+ test11("should get actors with pagination", async (c) => {
2157
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2158
+ await client.counter.create(["test-actor-1"]);
2159
+ await client.counter.create(["test-actor-2"]);
2160
+ const http = createManagerInspectorClient(`${endpoint}/inspect`, {
2161
+ headers: {
2162
+ Authorization: `Bearer token`
2163
+ }
2164
+ });
2165
+ const response = await http.actors.$get({
2166
+ query: { limit: "1" }
2167
+ });
2168
+ expect11(response.status).toBe(200);
2169
+ const data = await response.json();
2170
+ expect11(data).toEqual(
2171
+ expect11.arrayContaining([
2172
+ expect11.objectContaining({ key: ["test-actor-1"] })
2173
+ ])
2174
+ );
2175
+ expect11(data.length).toBe(1);
2176
+ });
2177
+ test11("should get all actors with pagination", async (c) => {
2178
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2179
+ const actorKey1 = ["test-cursor-1"];
2180
+ const actorKey2 = ["test-cursor-2"];
2181
+ await client.counter.create(actorKey1);
2182
+ await client.counter.create(actorKey2);
2183
+ const http = createManagerInspectorClient(`${endpoint}/inspect`, {
2184
+ headers: {
2185
+ Authorization: `Bearer token`
2186
+ }
2187
+ });
2188
+ const response = await http.actors.$get({
2189
+ query: { limit: "5" }
2190
+ });
2191
+ expect11(response.status).toBe(200);
2192
+ const data = await response.json();
2193
+ expect11(data).toEqual(
2194
+ expect11.arrayContaining([
2195
+ expect11.objectContaining({
2196
+ id: expect11.any(String),
2197
+ key: actorKey1
2198
+ }),
2199
+ expect11.objectContaining({
2200
+ id: expect11.any(String),
2201
+ key: actorKey2
2202
+ })
2203
+ ])
2204
+ );
2205
+ });
2206
+ test11("should handle invalid limit parameter", async (c) => {
2207
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
2208
+ const http = createManagerInspectorClient(`${endpoint}/inspect`, {
2209
+ headers: {
2210
+ Authorization: `Bearer token`
2211
+ }
2212
+ });
2213
+ const response = await http.actors.$get({
2214
+ query: { limit: "0" }
2215
+ });
2216
+ expect11(response.status).toBe(400);
2217
+ });
2218
+ test11("should create a new actor", async (c) => {
2219
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
2220
+ const http = createManagerInspectorClient(`${endpoint}/inspect`, {
2221
+ headers: {
2222
+ Authorization: `Bearer token`
2223
+ }
2224
+ });
2225
+ const response = await http.actors.$post({
2226
+ json: {
2227
+ name: "default",
2228
+ key: ["test-create-actor"],
2229
+ input: {}
2230
+ }
2231
+ });
2232
+ expect11(response.status).toBe(201);
2233
+ const data = await response.json();
2234
+ expect11(data).toEqual(
2235
+ expect11.objectContaining({
2236
+ id: expect11.any(String),
2237
+ name: "default",
2238
+ key: ["test-create-actor"]
2239
+ })
2240
+ );
2241
+ });
2242
+ test11("should get builds", async (c) => {
2243
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
2244
+ const http = createManagerInspectorClient(`${endpoint}/inspect`, {
2245
+ headers: {
2246
+ Authorization: `Bearer token`
2247
+ }
2248
+ });
2249
+ const response = await http.builds.$get();
2250
+ expect11(response.status).toBe(200);
2251
+ const data = await response.json();
2252
+ expect11(data).toEqual(
2253
+ expect11.arrayContaining([
2254
+ expect11.objectContaining({ name: expect11.any(String) })
2255
+ ])
2256
+ );
2257
+ });
2258
+ test11("should get actor by id", async (c) => {
2259
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2260
+ const handle = await client.counter.create(["test-get-by-id"]);
2261
+ const actorId = await handle.resolve();
2262
+ const http = createManagerInspectorClient(`${endpoint}/inspect`, {
2263
+ headers: {
2264
+ Authorization: `Bearer token`
2265
+ }
2266
+ });
2267
+ const response = await http.actor[":id"].$get({
2268
+ param: { id: actorId }
2269
+ });
2270
+ expect11(response.status).toBe(200);
2271
+ const data = await response.json();
2272
+ expect11(data).toHaveProperty("id", actorId);
2273
+ });
2274
+ test11("should return 404 for non-existent actor", async (c) => {
2275
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
2276
+ const http = createManagerInspectorClient(`${endpoint}/inspect`, {
2277
+ headers: {
2278
+ Authorization: `Bearer token`
2279
+ }
2280
+ });
2281
+ const response = await http.actor[":id"].$get({
2282
+ param: { id: "non-existent-id" }
2283
+ });
2284
+ expect11(response.status).toBe(404);
2285
+ const data = await response.json();
2286
+ expect11(data).toEqual({ error: "Actor not found" });
2287
+ });
2288
+ test11("should get bootstrap data", async (c) => {
2289
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2290
+ const handle = await client.counter.create(["test-bootstrap"]);
2291
+ await handle.resolve();
2292
+ const http = createManagerInspectorClient(`${endpoint}/inspect`, {
2293
+ headers: {
2294
+ Authorization: `Bearer token`
2295
+ }
2296
+ });
2297
+ const response = await http.bootstrap.$get();
2298
+ expect11(response.status).toBe(200);
2299
+ const data = await response.json();
2300
+ expect11(data.actors).toEqual(
2301
+ expect11.arrayContaining([
2302
+ expect11.objectContaining({
2303
+ key: ["test-bootstrap"],
2304
+ name: "counter"
2305
+ })
2306
+ ])
2307
+ );
2308
+ });
2309
+ });
2310
+ describe12("Actor Inspector", () => {
2311
+ test11("should handle actor not found", async (c) => {
2312
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
2313
+ const actorId = "non-existing";
2314
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2315
+ headers: {
2316
+ Authorization: `Bearer token`,
2317
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2318
+ getForId: { name: "counter", actorId }
2319
+ })
2320
+ }
2321
+ });
2322
+ const response = await http.ping.$get();
2323
+ expect11(response.ok).toBe(false);
2324
+ });
2325
+ test11("should respond to ping", async (c) => {
2326
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2327
+ const handle = await client.counter.create(["test-ping"]);
2328
+ const actorId = await handle.resolve();
2329
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2330
+ headers: {
2331
+ Authorization: `Bearer token`,
2332
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2333
+ getForId: { name: "counter", actorId }
2334
+ })
2335
+ }
2336
+ });
2337
+ const response = await http.ping.$get();
2338
+ expect11(response.status).toBe(200);
2339
+ const data = await response.json();
2340
+ expect11(data).toEqual({ message: "pong" });
2341
+ });
2342
+ test11("should get actor state", async (c) => {
2343
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2344
+ const handle = await client.counter.create(["test-state"]);
2345
+ const actorId = await handle.resolve();
2346
+ await handle.increment(5);
2347
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2348
+ headers: {
2349
+ Authorization: `Bearer token`,
2350
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2351
+ getForId: { name: "counter", actorId }
2352
+ })
2353
+ }
2354
+ });
2355
+ const response = await http.state.$get();
2356
+ expect11(response.status).toBe(200);
2357
+ const data = await response.json();
2358
+ expect11(data).toEqual({
2359
+ enabled: true,
2360
+ state: expect11.objectContaining({
2361
+ count: 5
2362
+ })
2363
+ });
2364
+ });
2365
+ test11("should update actor state with replace", async (c) => {
2366
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2367
+ const handle = await client.counter.create(["test-state-replace"]);
2368
+ const actorId = await handle.resolve();
2369
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2370
+ headers: {
2371
+ Authorization: `Bearer token`,
2372
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2373
+ getForId: { name: "counter", actorId }
2374
+ })
2375
+ }
2376
+ });
2377
+ const response = await http.state.$patch({
2378
+ json: {
2379
+ replace: { count: 10 }
2380
+ }
2381
+ });
2382
+ expect11(response.status).toBe(200);
2383
+ const data = await response.json();
2384
+ expect11(data).toEqual({
2385
+ enabled: true,
2386
+ state: { count: 10 }
2387
+ });
2388
+ });
2389
+ test11("should update actor state with patch", async (c) => {
2390
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2391
+ const handle = await client.counter.create(["test-state-patch"]);
2392
+ const actorId = await handle.resolve();
2393
+ await handle.increment(3);
2394
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2395
+ headers: {
2396
+ Authorization: `Bearer token`,
2397
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2398
+ getForId: { name: "counter", actorId }
2399
+ })
2400
+ }
2401
+ });
2402
+ const response = await http.state.$patch({
2403
+ json: {
2404
+ patch: [
2405
+ {
2406
+ op: "replace",
2407
+ path: "/count",
2408
+ value: 7
2409
+ }
2410
+ ]
2411
+ }
2412
+ });
2413
+ expect11(response.status).toBe(200);
2414
+ const data = await response.json();
2415
+ expect11(data).toEqual({
2416
+ enabled: true,
2417
+ state: expect11.objectContaining({
2418
+ count: 7
2419
+ })
2420
+ });
2421
+ });
2422
+ test11("should get actor connections", async (c) => {
2423
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2424
+ const handle = await client.counter.create(["test-connections"]);
2425
+ const actorId = await handle.resolve();
2426
+ handle.connect();
2427
+ await handle.increment(10);
2428
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2429
+ headers: {
2430
+ Authorization: `Bearer token`,
2431
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2432
+ getForId: { name: "counter", actorId }
2433
+ })
2434
+ }
2435
+ });
2436
+ const response = await http.connections.$get();
2437
+ expect11(response.status).toBe(200);
2438
+ const data = await response.json();
2439
+ expect11(data.connections).toEqual(
2440
+ expect11.arrayContaining([
2441
+ expect11.objectContaining({
2442
+ id: expect11.any(String)
2443
+ })
2444
+ ])
2445
+ );
2446
+ });
2447
+ test11("should get actor events", async (c) => {
2448
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2449
+ const handle = await client.counter.create(["test-events"]);
2450
+ const actorId = await handle.resolve();
2451
+ handle.connect();
2452
+ await handle.increment(10);
2453
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2454
+ headers: {
2455
+ Authorization: `Bearer token`,
2456
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2457
+ getForId: { name: "counter", actorId }
2458
+ })
2459
+ }
2460
+ });
2461
+ const response = await http.events.$get();
2462
+ expect11(response.status).toBe(200);
2463
+ const data = await response.json();
2464
+ expect11(data.events).toEqual(
2465
+ expect11.arrayContaining([
2466
+ expect11.objectContaining({
2467
+ type: "broadcast",
2468
+ id: expect11.any(String)
2469
+ })
2470
+ ])
2471
+ );
2472
+ });
2473
+ test11("should clear actor events", async (c) => {
2474
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2475
+ const handle = await client.counter.create(["test-events-clear"]);
2476
+ const actorId = await handle.resolve();
2477
+ handle.connect();
2478
+ await handle.increment(10);
2479
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2480
+ headers: {
2481
+ Authorization: `Bearer token`,
2482
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2483
+ getForId: { name: "counter", actorId }
2484
+ })
2485
+ }
2486
+ });
2487
+ {
2488
+ const response2 = await http.events.$get();
2489
+ expect11(response2.status).toBe(200);
2490
+ const data = await response2.json();
2491
+ expect11(data.events).toEqual(
2492
+ expect11.arrayContaining([
2493
+ expect11.objectContaining({
2494
+ type: "broadcast",
2495
+ id: expect11.any(String)
2496
+ })
2497
+ ])
2498
+ );
2499
+ }
2500
+ const response = await http.events.clear.$post();
2501
+ expect11(response.status).toBe(200);
2502
+ });
2503
+ test11("should get actor rpcs", async (c) => {
2504
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2505
+ const handle = await client.counter.create(["test-rpcs"]);
2506
+ const actorId = await handle.resolve();
2507
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2508
+ headers: {
2509
+ Authorization: `Bearer token`,
2510
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2511
+ getForId: { name: "counter", actorId }
2512
+ })
2513
+ }
2514
+ });
2515
+ const response = await http.rpcs.$get();
2516
+ expect11(response.status).toBe(200);
2517
+ const data = await response.json();
2518
+ expect11(data).toEqual(
2519
+ expect11.objectContaining({
2520
+ rpcs: expect11.arrayContaining(["increment", "getCount"])
2521
+ })
2522
+ );
2523
+ });
2524
+ test11.skip("should get actor database info", async (c) => {
2525
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2526
+ const handle = await client.counter.create(["test-db"]);
2527
+ const actorId = await handle.resolve();
2528
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2529
+ headers: {
2530
+ Authorization: `Bearer token`,
2531
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2532
+ getForId: { name: "counter", actorId }
2533
+ })
2534
+ }
2535
+ });
2536
+ const response = await http.db.$get();
2537
+ expect11(response.status).toBe(200);
2538
+ const data = await response.json();
2539
+ expect11(data).toHaveProperty("enabled");
2540
+ expect11(typeof data.enabled).toBe("boolean");
2541
+ if (data.enabled) {
2542
+ expect11(data).toHaveProperty("db");
2543
+ expect11(Array.isArray(data.db)).toBe(true);
2544
+ } else {
2545
+ expect11(data.db).toBe(null);
2546
+ }
2547
+ });
2548
+ test11.skip("should execute database query when database is enabled", async (c) => {
2549
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
2550
+ const handle = await client.counter.create(["test-db-query"]);
2551
+ const actorId = await handle.resolve();
2552
+ const http = createActorInspectorClient(`${endpoint}/actors/inspect`, {
2553
+ headers: {
2554
+ Authorization: `Bearer token`,
2555
+ [HEADER_ACTOR_QUERY]: JSON.stringify({
2556
+ getForId: { name: "counter", actorId }
2557
+ })
2558
+ }
2559
+ });
2560
+ const dbInfoResponse = await http.db.$get();
2561
+ const dbInfo = await dbInfoResponse.json();
2562
+ if (dbInfo.enabled) {
2563
+ const queryResponse = await http.db.$post({
2564
+ json: {
2565
+ query: "SELECT 1 as test",
2566
+ params: []
2567
+ }
2568
+ });
2569
+ expect11(queryResponse.status).toBe(200);
2570
+ const queryData = await queryResponse.json();
2571
+ expect11(queryData).toHaveProperty("result");
2572
+ } else {
2573
+ const queryResponse = await http.db.$post({
2574
+ json: {
2575
+ query: "SELECT 1 as test",
2576
+ params: []
2577
+ }
2578
+ });
2579
+ expect11(queryResponse.status).toBe(200);
2580
+ const queryData = await queryResponse.json();
2581
+ expect11(queryData).toEqual({ enabled: false });
2582
+ }
2583
+ });
2584
+ });
2585
+ });
2586
+ }
2587
+
2588
+ // src/driver-test-suite/tests/actor-metadata.ts
2589
+ import { describe as describe13, expect as expect12, test as test12 } from "vitest";
2590
+ function runActorMetadataTests(driverTestConfig) {
2591
+ describe13("Actor Metadata Tests", () => {
2592
+ describe13("Actor Name", () => {
2593
+ test12("should provide access to actor name", async (c) => {
2594
+ const { client } = await setupDriverTest(c, driverTestConfig);
2595
+ const handle = client.metadataActor.getOrCreate();
2596
+ const actorName = await handle.getActorName();
2597
+ expect12(actorName).toBe("metadataActor");
2598
+ });
2599
+ test12("should preserve actor name in state during onStart", async (c) => {
2600
+ const { client } = await setupDriverTest(c, driverTestConfig);
2601
+ const handle = client.metadataActor.getOrCreate();
2602
+ const storedName = await handle.getStoredActorName();
2603
+ expect12(storedName).toBe("metadataActor");
2604
+ });
2605
+ });
2606
+ describe13("Actor Tags", () => {
2607
+ test12("should provide access to tags", async (c) => {
2608
+ const { client } = await setupDriverTest(c, driverTestConfig);
2609
+ const handle = client.metadataActor.getOrCreate();
2610
+ await handle.setupTestTags({
2611
+ env: "test",
2612
+ purpose: "metadata-test"
2613
+ });
2614
+ const tags = await handle.getTags();
2615
+ expect12(tags).toHaveProperty("env");
2616
+ expect12(tags.env).toBe("test");
2617
+ expect12(tags).toHaveProperty("purpose");
2618
+ expect12(tags.purpose).toBe("metadata-test");
2619
+ });
2620
+ test12("should allow accessing individual tags", async (c) => {
2621
+ const { client } = await setupDriverTest(c, driverTestConfig);
2622
+ const handle = client.metadataActor.getOrCreate();
2623
+ await handle.setupTestTags({
2624
+ category: "test-actor",
2625
+ version: "1.0"
2626
+ });
2627
+ const category = await handle.getTag("category");
2628
+ const version = await handle.getTag("version");
2629
+ const nonexistent = await handle.getTag("nonexistent");
2630
+ expect12(category).toBe("test-actor");
2631
+ expect12(version).toBe("1.0");
2632
+ expect12(nonexistent).toBeNull();
2633
+ });
2634
+ });
2635
+ describe13("Metadata Structure", () => {
2636
+ test12("should provide complete metadata object", async (c) => {
2637
+ const { client } = await setupDriverTest(c, driverTestConfig);
2638
+ const handle = client.metadataActor.getOrCreate();
2639
+ await handle.setupTestTags({ type: "metadata-test" });
2640
+ await handle.setupTestRegion("us-west-1");
2641
+ const metadata = await handle.getMetadata();
2642
+ expect12(metadata).toHaveProperty("name");
2643
+ expect12(metadata.name).toBe("metadataActor");
2644
+ expect12(metadata).toHaveProperty("tags");
2645
+ expect12(metadata.tags).toHaveProperty("type");
2646
+ expect12(metadata.tags.type).toBe("metadata-test");
2647
+ expect12(metadata).toHaveProperty("region");
2648
+ expect12(metadata.region).toBe("us-west-1");
2649
+ });
2650
+ });
2651
+ describe13("Region Information", () => {
2652
+ test12("should retrieve region information", async (c) => {
2653
+ const { client } = await setupDriverTest(c, driverTestConfig);
2654
+ const handle = client.metadataActor.getOrCreate();
2655
+ await handle.setupTestRegion("eu-central-1");
2656
+ const region = await handle.getRegion();
2657
+ expect12(region).toBe("eu-central-1");
2658
+ });
2659
+ });
2660
+ });
2661
+ }
2662
+
2663
+ // src/driver-test-suite/tests/actor-onstatechange.ts
2664
+ import { describe as describe14, expect as expect13, test as test13 } from "vitest";
2665
+ function runActorOnStateChangeTests(driverTestConfig) {
2666
+ describe14("Actor onStateChange Tests", () => {
2667
+ test13("triggers onStateChange when state is modified", async (c) => {
2668
+ const { client } = await setupDriverTest(c, driverTestConfig);
2669
+ const actor2 = client.onStateChangeActor.getOrCreate();
2670
+ await actor2.setValue(10);
2671
+ const changeCount = await actor2.getChangeCount();
2672
+ expect13(changeCount).toBe(1);
2673
+ });
2674
+ test13("triggers onChange multiple times for multiple state changes", async (c) => {
2675
+ const { client } = await setupDriverTest(c, driverTestConfig);
2676
+ const actor2 = client.onStateChangeActor.getOrCreate();
2677
+ await actor2.incrementMultiple(3);
2678
+ const changeCount = await actor2.getChangeCount();
2679
+ expect13(changeCount).toBe(3);
2680
+ });
2681
+ test13("does NOT trigger onChange for read-only actions", async (c) => {
2682
+ const { client } = await setupDriverTest(c, driverTestConfig);
2683
+ const actor2 = client.onStateChangeActor.getOrCreate();
2684
+ await actor2.setValue(5);
2685
+ const value = await actor2.getValue();
2686
+ expect13(value).toBe(5);
2687
+ const changeCount = await actor2.getChangeCount();
2688
+ expect13(changeCount).toBe(1);
2689
+ });
2690
+ test13("does NOT trigger onChange for computed values", async (c) => {
2691
+ const { client } = await setupDriverTest(c, driverTestConfig);
2692
+ const actor2 = client.onStateChangeActor.getOrCreate();
2693
+ await actor2.setValue(3);
2694
+ {
2695
+ const changeCount = await actor2.getChangeCount();
2696
+ expect13(changeCount).toBe(1);
2697
+ }
2698
+ const doubled = await actor2.getDoubled();
2699
+ expect13(doubled).toBe(6);
2700
+ {
2701
+ const changeCount = await actor2.getChangeCount();
2702
+ expect13(changeCount).toBe(1);
2703
+ }
2704
+ });
2705
+ test13("simple: connect, call action, dispose does NOT trigger onChange", async (c) => {
2706
+ const { client } = await setupDriverTest(c, driverTestConfig);
2707
+ const actor2 = client.onStateChangeActor.getOrCreate();
2708
+ const connection = await actor2.connect();
2709
+ const value = await connection.getValue();
2710
+ expect13(value).toBe(0);
2711
+ await connection.dispose();
2712
+ const changeCount = await actor2.getChangeCount();
2713
+ expect13(changeCount).toBe(0);
2714
+ });
2715
+ });
2716
+ }
2717
+
2718
+ // src/driver-test-suite/tests/actor-vars.ts
2719
+ import { describe as describe15, expect as expect14, test as test14 } from "vitest";
2720
+ function runActorVarsTests(driverTestConfig) {
2721
+ describe15("Actor Variables", () => {
2722
+ describe15("Static vars", () => {
2723
+ test14("should provide access to static vars", async (c) => {
2724
+ const { client } = await setupDriverTest(c, driverTestConfig);
2725
+ const instance = client.staticVarActor.getOrCreate();
2726
+ const result = await instance.getVars();
2727
+ expect14(result).toEqual({ counter: 42, name: "test-actor" });
2728
+ const name = await instance.getName();
2729
+ expect14(name).toBe("test-actor");
2730
+ });
2731
+ });
2732
+ describe15("Deep cloning of static vars", () => {
2733
+ test14("should deep clone static vars between actor instances", async (c) => {
2734
+ const { client } = await setupDriverTest(c, driverTestConfig);
2735
+ const instance1 = client.nestedVarActor.getOrCreate(["instance1"]);
2736
+ const instance2 = client.nestedVarActor.getOrCreate(["instance2"]);
2737
+ const modifiedVars = await instance1.modifyNested();
2738
+ expect14(modifiedVars.nested.value).toBe("modified");
2739
+ expect14(modifiedVars.nested.array).toContain(4);
2740
+ expect14(modifiedVars.nested.obj.key).toBe("new-value");
2741
+ const instance2Vars = await instance2.getVars();
2742
+ expect14(instance2Vars.nested.value).toBe("original");
2743
+ expect14(instance2Vars.nested.array).toEqual([1, 2, 3]);
2744
+ expect14(instance2Vars.nested.obj.key).toBe("value");
2745
+ });
2746
+ });
2747
+ describe15("createVars", () => {
2748
+ test14("should support dynamic vars creation", async (c) => {
2749
+ const { client } = await setupDriverTest(c, driverTestConfig);
2750
+ const instance = client.dynamicVarActor.getOrCreate();
2751
+ const vars = await instance.getVars();
2752
+ expect14(vars).toHaveProperty("random");
2753
+ expect14(vars).toHaveProperty("computed");
2754
+ expect14(typeof vars.random).toBe("number");
2755
+ expect14(typeof vars.computed).toBe("string");
2756
+ expect14(vars.computed).toMatch(/^Actor-\d+$/);
2757
+ });
2758
+ test14("should create different vars for different instances", async (c) => {
2759
+ const { client } = await setupDriverTest(c, driverTestConfig);
2760
+ const instance1 = client.uniqueVarActor.getOrCreate(["test1"]);
2761
+ const instance2 = client.uniqueVarActor.getOrCreate(["test2"]);
2762
+ const vars1 = await instance1.getVars();
2763
+ const vars2 = await instance2.getVars();
2764
+ expect14(vars1.id).not.toBe(vars2.id);
2765
+ });
2766
+ });
2767
+ describe15("Driver Context", () => {
2768
+ test14("should provide access to driver context", async (c) => {
2769
+ const { client } = await setupDriverTest(c, driverTestConfig);
2770
+ const instance = client.driverCtxActor.getOrCreate();
2771
+ const vars = await instance.getVars();
2772
+ expect14(vars).toHaveProperty("hasDriverCtx");
2773
+ });
2774
+ });
2775
+ });
2776
+ }
2777
+
2778
+ // src/driver-test-suite/tests/manager-driver.ts
2779
+ import { describe as describe16, expect as expect15, test as test15 } from "vitest";
2780
+ function runManagerDriverTests(driverTestConfig) {
2781
+ describe16("Manager Driver Tests", () => {
2782
+ describe16("Client Connection Methods", () => {
2783
+ test15("connect() - finds or creates a actor", async (c) => {
2784
+ const { client } = await setupDriverTest(c, driverTestConfig);
2785
+ const counterA = client.counter.getOrCreate();
2786
+ await counterA.increment(5);
2787
+ const counterAAgain = client.counter.getOrCreate();
2788
+ const count = await counterAAgain.increment(0);
2789
+ expect15(count).toBe(5);
2790
+ const counterB = client.counter.getOrCreate(["counter-b", "testing"]);
2791
+ await counterB.increment(10);
2792
+ const countB = await counterB.increment(0);
2793
+ expect15(countB).toBe(10);
2794
+ });
2795
+ test15("throws ActorAlreadyExists when creating duplicate actors", async (c) => {
2796
+ const { client } = await setupDriverTest(c, driverTestConfig);
2797
+ const uniqueKey = ["duplicate-actor-test", crypto.randomUUID()];
2798
+ const counter = client.counter.getOrCreate(uniqueKey);
2799
+ await counter.increment(5);
2800
+ try {
2801
+ await client.counter.create(uniqueKey);
2802
+ expect15.fail("did not error on duplicate create");
2803
+ } catch (err) {
2804
+ expect15(err.code).toBe("actor_already_exists");
2805
+ }
2806
+ const count = await counter.increment(0);
2807
+ expect15(count).toBe(5);
2808
+ });
2809
+ });
2810
+ describe16("Connection Options", () => {
2811
+ test15("get without create prevents actor creation", async (c) => {
2812
+ const { client } = await setupDriverTest(c, driverTestConfig);
2813
+ const nonexistentId = `nonexistent-${crypto.randomUUID()}`;
2814
+ try {
2815
+ await client.counter.get([nonexistentId]).resolve();
2816
+ expect15.fail("did not error for get");
2817
+ } catch (err) {
2818
+ expect15(err.code).toBe("actor_not_found");
2819
+ }
2820
+ const createdCounter = client.counter.getOrCreate(nonexistentId);
2821
+ await createdCounter.increment(3);
2822
+ const retrievedCounter = client.counter.get(nonexistentId);
2823
+ const count = await retrievedCounter.increment(0);
2824
+ expect15(count).toBe(3);
2825
+ });
2826
+ test15("connection params are passed to actors", async (c) => {
2827
+ const { client } = await setupDriverTest(c, driverTestConfig);
2828
+ const counter = client.counter.getOrCreate(void 0, {
2829
+ params: {
2830
+ userId: "user-123",
2831
+ authToken: "token-abc",
2832
+ settings: { increment: 5 }
2833
+ }
2834
+ });
2835
+ await counter.increment(1);
2836
+ const count = await counter.increment(0);
2837
+ expect15(count).toBe(1);
2838
+ });
2839
+ });
2840
+ describe16("Actor Creation & Retrieval", () => {
2841
+ test15("creates and retrieves actors by ID", async (c) => {
2842
+ const { client } = await setupDriverTest(c, driverTestConfig);
2843
+ const uniqueId = `test-counter-${crypto.randomUUID()}`;
2844
+ const counter = client.counter.getOrCreate([uniqueId]);
2845
+ await counter.increment(10);
2846
+ const retrievedCounter = client.counter.getOrCreate([uniqueId]);
2847
+ const count = await retrievedCounter.increment(0);
2848
+ expect15(count).toBe(10);
2849
+ });
2850
+ test15("passes input to actor during creation", async (c) => {
2851
+ const { client } = await setupDriverTest(c, driverTestConfig);
2852
+ const testInput = {
2853
+ name: "test-actor",
2854
+ value: 42,
2855
+ nested: { foo: "bar" }
2856
+ };
2857
+ const actor2 = await client.inputActor.create(void 0, {
2858
+ input: testInput
2859
+ });
2860
+ const inputs = await actor2.getInputs();
2861
+ expect15(inputs.initialInput).toEqual(testInput);
2862
+ expect15(inputs.onCreateInput).toEqual(testInput);
2863
+ });
2864
+ test15("input is undefined when not provided", async (c) => {
2865
+ const { client } = await setupDriverTest(c, driverTestConfig);
2866
+ const actor2 = await client.inputActor.create();
2867
+ const inputs = await actor2.getInputs();
2868
+ expect15(inputs.initialInput).toBeUndefined();
2869
+ expect15(inputs.onCreateInput).toBeUndefined();
2870
+ });
2871
+ test15("getOrCreate passes input to actor during creation", async (c) => {
2872
+ const { client } = await setupDriverTest(c, driverTestConfig);
2873
+ const uniqueKey = [`input-test-${crypto.randomUUID()}`];
2874
+ const testInput = {
2875
+ name: "getorcreate-test",
2876
+ value: 100,
2877
+ nested: { baz: "qux" }
2878
+ };
2879
+ const actor2 = client.inputActor.getOrCreate(uniqueKey, {
2880
+ createWithInput: testInput
2881
+ });
2882
+ const inputs = await actor2.getInputs();
2883
+ expect15(inputs.initialInput).toEqual(testInput);
2884
+ expect15(inputs.onCreateInput).toEqual(testInput);
2885
+ const existingActor = client.inputActor.getOrCreate(uniqueKey);
2886
+ const existingInputs = await existingActor.getInputs();
2887
+ expect15(existingInputs.initialInput).toEqual(testInput);
2888
+ expect15(existingInputs.onCreateInput).toEqual(testInput);
2889
+ });
2890
+ });
2891
+ describe16("Key Matching", () => {
2892
+ test15("matches actors only with exactly the same keys", async (c) => {
2893
+ const { client } = await setupDriverTest(c, driverTestConfig);
2894
+ const originalCounter = client.counter.getOrCreate([
2895
+ "counter-match",
2896
+ "test",
2897
+ "us-east"
2898
+ ]);
2899
+ await originalCounter.increment(10);
2900
+ const exactMatchCounter = client.counter.getOrCreate([
2901
+ "counter-match",
2902
+ "test",
2903
+ "us-east"
2904
+ ]);
2905
+ const exactMatchCount = await exactMatchCounter.increment(0);
2906
+ expect15(exactMatchCount).toBe(10);
2907
+ const subsetMatchCounter = client.counter.getOrCreate([
2908
+ "counter-match",
2909
+ "test"
2910
+ ]);
2911
+ const subsetMatchCount = await subsetMatchCounter.increment(0);
2912
+ expect15(subsetMatchCount).toBe(0);
2913
+ const singleKeyCounter = client.counter.getOrCreate(["counter-match"]);
2914
+ const singleKeyCount = await singleKeyCounter.increment(0);
2915
+ expect15(singleKeyCount).toBe(0);
2916
+ });
2917
+ test15("string key matches array with single string key", async (c) => {
2918
+ const { client } = await setupDriverTest(c, driverTestConfig);
2919
+ const stringKeyCounter = client.counter.getOrCreate("string-key-test");
2920
+ await stringKeyCounter.increment(7);
2921
+ const arrayKeyCounter = client.counter.getOrCreate(["string-key-test"]);
2922
+ const count = await arrayKeyCounter.increment(0);
2923
+ expect15(count).toBe(7);
2924
+ });
2925
+ test15("undefined key matches empty array key and no key", async (c) => {
2926
+ const { client } = await setupDriverTest(c, driverTestConfig);
2927
+ const undefinedKeyCounter = client.counter.getOrCreate(void 0);
2928
+ await undefinedKeyCounter.increment(12);
2929
+ const emptyArrayKeyCounter = client.counter.getOrCreate([]);
2930
+ const emptyArrayCount = await emptyArrayKeyCounter.increment(0);
2931
+ expect15(emptyArrayCount).toBe(12);
2932
+ const noKeyCounter = client.counter.getOrCreate();
2933
+ const noKeyCount = await noKeyCounter.increment(0);
2934
+ expect15(noKeyCount).toBe(12);
2935
+ });
2936
+ test15("no keys does not match actors with keys", async (c) => {
2937
+ const { client } = await setupDriverTest(c, driverTestConfig);
2938
+ const keyedCounter = client.counter.getOrCreate([
2939
+ "counter-with-keys",
2940
+ "special"
2941
+ ]);
2942
+ await keyedCounter.increment(15);
2943
+ const noKeysCounter = client.counter.getOrCreate();
2944
+ const count = await noKeysCounter.increment(10);
2945
+ expect15(count).toBe(10);
2946
+ });
2947
+ test15("actors with keys match actors with no keys", async (c) => {
2948
+ const { client } = await setupDriverTest(c, driverTestConfig);
2949
+ const noKeysCounter = client.counter.getOrCreate();
2950
+ await noKeysCounter.increment(25);
2951
+ const keyedCounter = client.counter.getOrCreate([
2952
+ "new-counter",
2953
+ "prod"
2954
+ ]);
2955
+ const keyedCount = await keyedCounter.increment(0);
2956
+ expect15(keyedCount).toBe(0);
2957
+ });
2958
+ });
2959
+ describe16("Multiple Actor Instances", () => {
2960
+ test15("creates multiple actor instances of the same type", async (c) => {
2961
+ const { client } = await setupDriverTest(c, driverTestConfig);
2962
+ const instance1 = client.counter.getOrCreate(["multi-1"]);
2963
+ const instance2 = client.counter.getOrCreate(["multi-2"]);
2964
+ const instance3 = client.counter.getOrCreate(["multi-3"]);
2965
+ await instance1.increment(1);
2966
+ await instance2.increment(2);
2967
+ await instance3.increment(3);
2968
+ const retrieved1 = client.counter.getOrCreate(["multi-1"]);
2969
+ const retrieved2 = client.counter.getOrCreate(["multi-2"]);
2970
+ const retrieved3 = client.counter.getOrCreate(["multi-3"]);
2971
+ expect15(await retrieved1.increment(0)).toBe(1);
2972
+ expect15(await retrieved2.increment(0)).toBe(2);
2973
+ expect15(await retrieved3.increment(0)).toBe(3);
2974
+ });
2975
+ test15("handles default instance with no explicit ID", async (c) => {
2976
+ const { client } = await setupDriverTest(c, driverTestConfig);
2977
+ const defaultCounter = client.counter.getOrCreate();
2978
+ await defaultCounter.increment(5);
2979
+ const sameDefaultCounter = client.counter.getOrCreate();
2980
+ const count = await sameDefaultCounter.increment(0);
2981
+ expect15(count).toBe(5);
2982
+ });
2983
+ });
2984
+ });
2985
+ }
2986
+
2987
+ // src/driver-test-suite/tests/raw-http.ts
2988
+ import { describe as describe17, expect as expect16, test as test16 } from "vitest";
2989
+ function runRawHttpTests(driverTestConfig) {
2990
+ describe17("raw http", () => {
2991
+ test16("should handle raw HTTP GET requests", async (c) => {
2992
+ const { client } = await setupDriverTest(c, driverTestConfig);
2993
+ const actor2 = client.rawHttpActor.getOrCreate(["test"]);
2994
+ const helloResponse = await actor2.fetch("api/hello");
2995
+ expect16(helloResponse.ok).toBe(true);
2996
+ const helloData = await helloResponse.json();
2997
+ expect16(helloData).toEqual({ message: "Hello from actor!" });
2998
+ });
2999
+ test16("should handle raw HTTP POST requests with echo", async (c) => {
3000
+ const { client } = await setupDriverTest(c, driverTestConfig);
3001
+ const actor2 = client.rawHttpActor.getOrCreate(["test"]);
3002
+ const testData = { test: "data", number: 123 };
3003
+ const echoResponse = await actor2.fetch("api/echo", {
3004
+ method: "POST",
3005
+ headers: {
3006
+ "Content-Type": "application/json"
3007
+ },
3008
+ body: JSON.stringify(testData)
3009
+ });
3010
+ expect16(echoResponse.ok).toBe(true);
3011
+ const echoData = await echoResponse.json();
3012
+ expect16(echoData).toEqual(testData);
3013
+ });
3014
+ test16("should track state across raw HTTP requests", async (c) => {
3015
+ const { client } = await setupDriverTest(c, driverTestConfig);
3016
+ const actor2 = client.rawHttpActor.getOrCreate(["state-test"]);
3017
+ await actor2.fetch("api/hello");
3018
+ await actor2.fetch("api/hello");
3019
+ await actor2.fetch("api/state");
3020
+ const stateResponse = await actor2.fetch("api/state");
3021
+ expect16(stateResponse.ok).toBe(true);
3022
+ const stateData = await stateResponse.json();
3023
+ expect16(stateData.requestCount).toBe(4);
3024
+ });
3025
+ test16("should pass headers correctly", async (c) => {
3026
+ const { client } = await setupDriverTest(c, driverTestConfig);
3027
+ const actor2 = client.rawHttpActor.getOrCreate(["headers-test"]);
3028
+ const customHeaders = {
3029
+ "X-Custom-Header": "test-value",
3030
+ "X-Another-Header": "another-value"
3031
+ };
3032
+ const response = await actor2.fetch("api/headers", {
3033
+ headers: customHeaders
3034
+ });
3035
+ expect16(response.ok).toBe(true);
3036
+ const headers = await response.json();
3037
+ expect16(headers["x-custom-header"]).toBe("test-value");
3038
+ expect16(headers["x-another-header"]).toBe("another-value");
3039
+ });
3040
+ test16("should return 404 for unhandled paths", async (c) => {
3041
+ const { client } = await setupDriverTest(c, driverTestConfig);
3042
+ const actor2 = client.rawHttpActor.getOrCreate(["404-test"]);
3043
+ const response = await actor2.fetch("api/nonexistent");
3044
+ expect16(response.ok).toBe(false);
3045
+ expect16(response.status).toBe(404);
3046
+ });
3047
+ test16("should return 404 when no onFetch handler defined", async (c) => {
3048
+ const { client } = await setupDriverTest(c, driverTestConfig);
3049
+ const actor2 = client.rawHttpNoHandlerActor.getOrCreate(["no-handler"]);
3050
+ const response = await actor2.fetch("api/anything");
3051
+ expect16(response.ok).toBe(false);
3052
+ expect16(response.status).toBe(404);
3053
+ });
3054
+ test16("should return 500 error when onFetch returns void", async (c) => {
3055
+ const { client } = await setupDriverTest(c, driverTestConfig);
3056
+ const actor2 = client.rawHttpVoidReturnActor.getOrCreate(["void-return"]);
3057
+ const response = await actor2.fetch("api/anything");
3058
+ expect16(response.ok).toBe(false);
3059
+ expect16(response.status).toBe(500);
3060
+ try {
3061
+ const errorData = await response.json();
3062
+ expect16(errorData.message).toContain(
3063
+ "onFetch handler must return a Response"
3064
+ );
3065
+ } catch {
3066
+ }
3067
+ });
3068
+ test16("should handle different HTTP methods", async (c) => {
3069
+ const { client } = await setupDriverTest(c, driverTestConfig);
3070
+ const actor2 = client.rawHttpActor.getOrCreate(["methods-test"]);
3071
+ const methods = ["GET", "POST", "PUT", "DELETE", "PATCH"];
3072
+ for (const method of methods) {
3073
+ const response = await actor2.fetch("api/echo", {
3074
+ method,
3075
+ body: ["POST", "PUT", "PATCH"].includes(method) ? JSON.stringify({ method }) : void 0
3076
+ });
3077
+ if (method === "POST") {
3078
+ expect16(response.ok).toBe(true);
3079
+ const data = await response.json();
3080
+ expect16(data).toEqual({ method });
3081
+ } else if (method === "GET") {
3082
+ expect16(response.status).toBe(404);
3083
+ } else {
3084
+ expect16(response.status).toBe(404);
3085
+ }
3086
+ }
3087
+ });
3088
+ test16("should handle binary data", async (c) => {
3089
+ const { client } = await setupDriverTest(c, driverTestConfig);
3090
+ const actor2 = client.rawHttpActor.getOrCreate(["binary-test"]);
3091
+ const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
3092
+ const response = await actor2.fetch("api/echo", {
3093
+ method: "POST",
3094
+ headers: {
3095
+ "Content-Type": "application/octet-stream"
3096
+ },
3097
+ body: binaryData
3098
+ });
3099
+ expect16(response.ok).toBe(true);
3100
+ const responseBuffer = await response.arrayBuffer();
3101
+ const responseArray = new Uint8Array(responseBuffer);
3102
+ expect16(Array.from(responseArray)).toEqual([1, 2, 3, 4, 5]);
3103
+ });
3104
+ test16("should work with Hono router using createVars", async (c) => {
3105
+ const { client } = await setupDriverTest(c, driverTestConfig);
3106
+ const actor2 = client.rawHttpHonoActor.getOrCreate(["hono-test"]);
3107
+ const rootResponse = await actor2.fetch("/");
3108
+ expect16(rootResponse.ok).toBe(true);
3109
+ const rootData = await rootResponse.json();
3110
+ expect16(rootData).toEqual({ message: "Welcome to Hono actor!" });
3111
+ const usersResponse = await actor2.fetch("/users");
3112
+ expect16(usersResponse.ok).toBe(true);
3113
+ const users = await usersResponse.json();
3114
+ expect16(users).toEqual([
3115
+ { id: 1, name: "Alice" },
3116
+ { id: 2, name: "Bob" }
3117
+ ]);
3118
+ const userResponse = await actor2.fetch("/users/1");
3119
+ expect16(userResponse.ok).toBe(true);
3120
+ const user = await userResponse.json();
3121
+ expect16(user).toEqual({ id: 1, name: "Alice" });
3122
+ const newUser = { name: "Charlie" };
3123
+ const createResponse = await actor2.fetch("/users", {
3124
+ method: "POST",
3125
+ headers: { "Content-Type": "application/json" },
3126
+ body: JSON.stringify(newUser)
3127
+ });
3128
+ expect16(createResponse.ok).toBe(true);
3129
+ expect16(createResponse.status).toBe(201);
3130
+ const createdUser = await createResponse.json();
3131
+ expect16(createdUser).toEqual({ id: 3, name: "Charlie" });
3132
+ const updateData = { name: "Alice Updated" };
3133
+ const updateResponse = await actor2.fetch("/users/1", {
3134
+ method: "PUT",
3135
+ headers: { "Content-Type": "application/json" },
3136
+ body: JSON.stringify(updateData)
3137
+ });
3138
+ expect16(updateResponse.ok).toBe(true);
3139
+ const updatedUser = await updateResponse.json();
3140
+ expect16(updatedUser).toEqual({ id: 1, name: "Alice Updated" });
3141
+ const deleteResponse = await actor2.fetch("/users/2", {
3142
+ method: "DELETE"
3143
+ });
3144
+ expect16(deleteResponse.ok).toBe(true);
3145
+ const deleteResult = await deleteResponse.json();
3146
+ expect16(deleteResult).toEqual({ message: "User 2 deleted" });
3147
+ const notFoundResponse = await actor2.fetch("/api/unknown");
3148
+ expect16(notFoundResponse.ok).toBe(false);
3149
+ expect16(notFoundResponse.status).toBe(404);
3150
+ });
3151
+ test16("should handle paths with and without leading slashes", async (c) => {
3152
+ const { client } = await setupDriverTest(c, driverTestConfig);
3153
+ const actor2 = client.rawHttpActor.getOrCreate(["path-test"]);
3154
+ const responseWithoutSlash = await actor2.fetch("api/hello");
3155
+ expect16(responseWithoutSlash.ok).toBe(true);
3156
+ const dataWithoutSlash = await responseWithoutSlash.json();
3157
+ expect16(dataWithoutSlash).toEqual({ message: "Hello from actor!" });
3158
+ const responseWithSlash = await actor2.fetch("/api/hello");
3159
+ expect16(responseWithSlash.ok).toBe(true);
3160
+ const dataWithSlash = await responseWithSlash.json();
3161
+ expect16(dataWithSlash).toEqual({ message: "Hello from actor!" });
3162
+ });
3163
+ test16("should not create double slashes in request URLs", async (c) => {
3164
+ const { client } = await setupDriverTest(c, driverTestConfig);
3165
+ const actor2 = client.rawHttpHonoActor.getOrCreate(["url-test"]);
3166
+ const response = await actor2.fetch("/users");
3167
+ expect16(response.ok).toBe(true);
3168
+ const data = await response.json();
3169
+ expect16(data).toEqual([
3170
+ { id: 1, name: "Alice" },
3171
+ { id: 2, name: "Bob" }
3172
+ ]);
3173
+ });
3174
+ test16("should handle forwarded requests correctly without double slashes", async (c) => {
3175
+ const { client } = await setupDriverTest(c, driverTestConfig);
3176
+ const actor2 = client.rawHttpHonoActor.getOrCreate(["forward-test"]);
3177
+ const truncatedPath = "/users";
3178
+ const url = new URL(truncatedPath, "http://example.com");
3179
+ const newRequest = new Request(url, {
3180
+ method: "GET"
3181
+ });
3182
+ const response = await actor2.fetch(truncatedPath, newRequest);
3183
+ expect16(response.ok).toBe(true);
3184
+ const users = await response.json();
3185
+ expect16(users).toEqual([
3186
+ { id: 1, name: "Alice" },
3187
+ { id: 2, name: "Bob" }
3188
+ ]);
3189
+ });
3190
+ test16("example fix: should properly forward requests using just Request object", async (c) => {
3191
+ const { client } = await setupDriverTest(c, driverTestConfig);
3192
+ const actor2 = client.rawHttpHonoActor.getOrCreate(["forward-fix"]);
3193
+ const truncatedPath = "/users/1";
3194
+ const url = new URL(truncatedPath, "http://example.com");
3195
+ const newRequest = new Request(url, {
3196
+ method: "GET"
3197
+ });
3198
+ const response = await actor2.fetch(newRequest);
3199
+ expect16(response.ok).toBe(true);
3200
+ const user = await response.json();
3201
+ expect16(user).toEqual({ id: 1, name: "Alice" });
3202
+ });
3203
+ test16("should support standard fetch API with URL and Request objects", async (c) => {
3204
+ const { client } = await setupDriverTest(c, driverTestConfig);
3205
+ const actor2 = client.rawHttpActor.getOrCreate(["fetch-api-test"]);
3206
+ const url = new URL("/api/echo", "http://example.com");
3207
+ const urlResponse = await actor2.fetch(url, {
3208
+ method: "POST",
3209
+ headers: { "Content-Type": "application/json" },
3210
+ body: JSON.stringify({ from: "URL object" })
3211
+ });
3212
+ expect16(urlResponse.ok).toBe(true);
3213
+ const urlData = await urlResponse.json();
3214
+ expect16(urlData).toEqual({ from: "URL object" });
3215
+ const request = new Request("http://example.com/api/echo", {
3216
+ method: "POST",
3217
+ headers: { "Content-Type": "application/json" },
3218
+ body: JSON.stringify({ from: "Request object" })
3219
+ });
3220
+ const requestResponse = await actor2.fetch(request);
3221
+ expect16(requestResponse.ok).toBe(true);
3222
+ const requestData = await requestResponse.json();
3223
+ expect16(requestData).toEqual({ from: "Request object" });
3224
+ const request2 = new Request("http://example.com/api/headers", {
3225
+ method: "GET",
3226
+ headers: { "X-Original": "request-header" }
3227
+ });
3228
+ const overrideResponse = await actor2.fetch(request2, {
3229
+ headers: { "X-Override": "init-header" }
3230
+ });
3231
+ expect16(overrideResponse.ok).toBe(true);
3232
+ const headers = await overrideResponse.json();
3233
+ expect16(headers["x-override"]).toBe("init-header");
3234
+ expect16(headers["x-original"]).toBe("request-header");
3235
+ });
3236
+ });
3237
+ }
3238
+
3239
+ // src/driver-test-suite/tests/raw-http-direct-registry.ts
3240
+ import { describe as describe18, expect as expect17, test as test17 } from "vitest";
3241
+ function runRawHttpDirectRegistryTests(driverTestConfig) {
3242
+ describe18("raw http - direct registry access", () => {
3243
+ test17("should handle direct fetch requests to registry with proper headers", async (c) => {
3244
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
3245
+ const actorQuery = {
3246
+ getOrCreateForKey: {
3247
+ name: "rawHttpActor",
3248
+ key: ["direct-test"]
3249
+ }
3250
+ };
3251
+ const response = await fetch(
3252
+ `${endpoint}/registry/actors/raw/http/api/hello`,
3253
+ {
3254
+ method: "GET",
3255
+ headers: {
3256
+ [HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery)
3257
+ }
3258
+ }
3259
+ );
3260
+ expect17(response.ok).toBe(true);
3261
+ expect17(response.status).toBe(200);
3262
+ const data = await response.json();
3263
+ expect17(data).toEqual({ message: "Hello from actor!" });
3264
+ });
3265
+ test17("should handle POST requests with body to registry", async (c) => {
3266
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
3267
+ const actorQuery = {
3268
+ getOrCreateForKey: {
3269
+ name: "rawHttpActor",
3270
+ key: ["direct-post-test"]
3271
+ }
3272
+ };
3273
+ const testData = { test: "direct", number: 456 };
3274
+ const response = await fetch(
3275
+ `${endpoint}/registry/actors/raw/http/api/echo`,
3276
+ {
3277
+ method: "POST",
3278
+ headers: {
3279
+ [HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery),
3280
+ "Content-Type": "application/json"
3281
+ },
3282
+ body: JSON.stringify(testData)
3283
+ }
3284
+ );
3285
+ expect17(response.ok).toBe(true);
3286
+ expect17(response.status).toBe(200);
3287
+ const data = await response.json();
3288
+ expect17(data).toEqual(testData);
3289
+ });
3290
+ test17("should pass custom headers through to actor", async (c) => {
3291
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
3292
+ const actorQuery = {
3293
+ getOrCreateForKey: {
3294
+ name: "rawHttpActor",
3295
+ key: ["direct-headers-test"]
3296
+ }
3297
+ };
3298
+ const customHeaders = {
3299
+ "X-Custom-Header": "direct-test-value",
3300
+ "X-Another-Header": "another-direct-value"
3301
+ };
3302
+ const response = await fetch(
3303
+ `${endpoint}/registry/actors/raw/http/api/headers`,
3304
+ {
3305
+ method: "GET",
3306
+ headers: {
3307
+ [HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery),
3308
+ ...customHeaders
3309
+ }
3310
+ }
3311
+ );
3312
+ expect17(response.ok).toBe(true);
3313
+ const headers = await response.json();
3314
+ expect17(headers["x-custom-header"]).toBe("direct-test-value");
3315
+ expect17(headers["x-another-header"]).toBe("another-direct-value");
3316
+ });
3317
+ test17("should handle connection parameters for authentication", async (c) => {
3318
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
3319
+ const actorQuery = {
3320
+ getOrCreateForKey: {
3321
+ name: "rawHttpActor",
3322
+ key: ["direct-auth-test"]
3323
+ }
3324
+ };
3325
+ const connParams = { token: "test-auth-token", userId: "user123" };
3326
+ const response = await fetch(
3327
+ `${endpoint}/registry/actors/raw/http/api/hello`,
3328
+ {
3329
+ method: "GET",
3330
+ headers: {
3331
+ [HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery),
3332
+ [HEADER_CONN_PARAMS]: JSON.stringify(connParams)
3333
+ }
3334
+ }
3335
+ );
3336
+ expect17(response.ok).toBe(true);
3337
+ const data = await response.json();
3338
+ expect17(data).toEqual({ message: "Hello from actor!" });
3339
+ });
3340
+ test17("should return 404 for actors without onFetch handler", async (c) => {
3341
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
3342
+ const actorQuery = {
3343
+ getOrCreateForKey: {
3344
+ name: "rawHttpNoHandlerActor",
3345
+ key: ["direct-no-handler"]
3346
+ }
3347
+ };
3348
+ const response = await fetch(
3349
+ `${endpoint}/registry/actors/raw/http/api/anything`,
3350
+ {
3351
+ method: "GET",
3352
+ headers: {
3353
+ [HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery)
3354
+ }
3355
+ }
3356
+ );
3357
+ expect17(response.ok).toBe(false);
3358
+ expect17(response.status).toBe(404);
3359
+ });
3360
+ test17("should handle different HTTP methods", async (c) => {
3361
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
3362
+ const actorQuery = {
3363
+ getOrCreateForKey: {
3364
+ name: "rawHttpActor",
3365
+ key: ["direct-methods-test"]
3366
+ }
3367
+ };
3368
+ const methods = ["GET", "POST", "PUT", "DELETE", "PATCH"];
3369
+ for (const method of methods) {
3370
+ const response = await fetch(
3371
+ `${endpoint}/registry/actors/raw/http/api/echo`,
3372
+ {
3373
+ method,
3374
+ headers: {
3375
+ [HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery),
3376
+ ...method !== "GET" ? { "Content-Type": "application/json" } : {}
3377
+ },
3378
+ body: ["POST", "PUT", "PATCH"].includes(method) ? JSON.stringify({ method }) : void 0
3379
+ }
3380
+ );
3381
+ if (method === "POST") {
3382
+ expect17(response.ok).toBe(true);
3383
+ const data = await response.json();
3384
+ expect17(data).toEqual({ method });
3385
+ } else {
3386
+ expect17(response.status).toBe(404);
3387
+ }
3388
+ }
3389
+ });
3390
+ test17("should handle binary data", async (c) => {
3391
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
3392
+ const actorQuery = {
3393
+ getOrCreateForKey: {
3394
+ name: "rawHttpActor",
3395
+ key: ["direct-binary-test"]
3396
+ }
3397
+ };
3398
+ const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
3399
+ const response = await fetch(
3400
+ `${endpoint}/registry/actors/raw/http/api/echo`,
3401
+ {
3402
+ method: "POST",
3403
+ headers: {
3404
+ [HEADER_ACTOR_QUERY]: JSON.stringify(actorQuery),
3405
+ "Content-Type": "application/octet-stream"
3406
+ },
3407
+ body: binaryData
3408
+ }
3409
+ );
3410
+ expect17(response.ok).toBe(true);
3411
+ const responseBuffer = await response.arrayBuffer();
3412
+ const responseArray = new Uint8Array(responseBuffer);
3413
+ expect17(Array.from(responseArray)).toEqual([1, 2, 3, 4, 5]);
3414
+ });
3415
+ });
3416
+ }
3417
+
3418
+ // src/driver-test-suite/tests/raw-http-request-properties.ts
3419
+ import { describe as describe19, expect as expect18, test as test18 } from "vitest";
3420
+ function runRawHttpRequestPropertiesTests(driverTestConfig) {
3421
+ describe19("raw http request properties", () => {
3422
+ test18("should pass all Request properties correctly to onFetch", async (c) => {
3423
+ const { client } = await setupDriverTest(c, driverTestConfig);
3424
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3425
+ const response = await actor2.fetch("test/path?foo=bar&baz=qux", {
3426
+ method: "POST",
3427
+ headers: {
3428
+ "Content-Type": "application/json",
3429
+ "X-Custom-Header": "custom-value",
3430
+ Authorization: "Bearer test-token"
3431
+ },
3432
+ body: JSON.stringify({ test: "data" })
3433
+ });
3434
+ expect18(response.ok).toBe(true);
3435
+ const data = await response.json();
3436
+ expect18(data.url).toContain("/test/path?foo=bar&baz=qux");
3437
+ expect18(data.pathname).toBe("/test/path");
3438
+ expect18(data.search).toBe("?foo=bar&baz=qux");
3439
+ expect18(data.searchParams).toEqual({
3440
+ foo: "bar",
3441
+ baz: "qux"
3442
+ });
3443
+ expect18(data.method).toBe("POST");
3444
+ expect18(data.headers["content-type"]).toBe("application/json");
3445
+ expect18(data.headers["x-custom-header"]).toBe("custom-value");
3446
+ expect18(data.headers["authorization"]).toBe("Bearer test-token");
3447
+ expect18(data.body).toEqual({ test: "data" });
3448
+ });
3449
+ test18("should handle GET requests with no body", async (c) => {
3450
+ const { client } = await setupDriverTest(c, driverTestConfig);
3451
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3452
+ const response = await actor2.fetch("test/get", {
3453
+ method: "GET"
3454
+ });
3455
+ expect18(response.ok).toBe(true);
3456
+ const data = await response.json();
3457
+ expect18(data.method).toBe("GET");
3458
+ expect18(data.body).toBeNull();
3459
+ });
3460
+ test18("should handle different content types", async (c) => {
3461
+ const { client } = await setupDriverTest(c, driverTestConfig);
3462
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3463
+ const formData = new URLSearchParams();
3464
+ formData.append("field1", "value1");
3465
+ formData.append("field2", "value2");
3466
+ const formResponse = await actor2.fetch("test/form", {
3467
+ method: "POST",
3468
+ headers: {
3469
+ "Content-Type": "application/x-www-form-urlencoded"
3470
+ },
3471
+ body: formData.toString()
3472
+ });
3473
+ expect18(formResponse.ok).toBe(true);
3474
+ const formResult = await formResponse.json();
3475
+ expect18(formResult.headers["content-type"]).toBe(
3476
+ "application/x-www-form-urlencoded"
3477
+ );
3478
+ expect18(formResult.bodyText).toBe("field1=value1&field2=value2");
3479
+ const textResponse = await actor2.fetch("test/text", {
3480
+ method: "POST",
3481
+ headers: {
3482
+ "Content-Type": "text/plain"
3483
+ },
3484
+ body: "Hello, World!"
3485
+ });
3486
+ expect18(textResponse.ok).toBe(true);
3487
+ const textResult = await textResponse.json();
3488
+ expect18(textResult.headers["content-type"]).toBe("text/plain");
3489
+ expect18(textResult.bodyText).toBe("Hello, World!");
3490
+ });
3491
+ test18("should preserve all header casing and values", async (c) => {
3492
+ const { client } = await setupDriverTest(c, driverTestConfig);
3493
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3494
+ const response = await actor2.fetch("test/headers", {
3495
+ headers: {
3496
+ Accept: "application/json",
3497
+ "Accept-Language": "en-US,en;q=0.9",
3498
+ "Cache-Control": "no-cache",
3499
+ "User-Agent": "RivetKit-Test/1.0",
3500
+ "X-Request-ID": "12345"
3501
+ }
3502
+ });
3503
+ expect18(response.ok).toBe(true);
3504
+ const data = await response.json();
3505
+ expect18(data.headers["accept"]).toBe("application/json");
3506
+ expect18(data.headers["accept-language"]).toBe("en-US,en;q=0.9");
3507
+ expect18(data.headers["cache-control"]).toBe("no-cache");
3508
+ expect18(data.headers["user-agent"]).toBeTruthy();
3509
+ expect18(data.headers["x-request-id"]).toBe("12345");
3510
+ });
3511
+ test18("should handle empty and special URL paths", async (c) => {
3512
+ const { client } = await setupDriverTest(c, driverTestConfig);
3513
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3514
+ const rootResponse = await actor2.fetch("");
3515
+ expect18(rootResponse.ok).toBe(true);
3516
+ const rootData = await rootResponse.json();
3517
+ expect18(rootData.pathname).toBe("/");
3518
+ const specialResponse = await actor2.fetch(
3519
+ "test/path%20with%20spaces/and%2Fslashes"
3520
+ );
3521
+ expect18(specialResponse.ok).toBe(true);
3522
+ const specialData = await specialResponse.json();
3523
+ expect18(specialData.pathname).toMatch(/path.*with.*spaces.*and.*slashes/);
3524
+ const fragmentResponse = await actor2.fetch("test/path#fragment");
3525
+ expect18(fragmentResponse.ok).toBe(true);
3526
+ const fragmentData = await fragmentResponse.json();
3527
+ expect18(fragmentData.pathname).toBe("/test/path");
3528
+ expect18(fragmentData.hash).toBe("");
3529
+ });
3530
+ test18("should handle request properties for all HTTP methods", async (c) => {
3531
+ const { client } = await setupDriverTest(c, driverTestConfig);
3532
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3533
+ const methods = [
3534
+ "GET",
3535
+ "POST",
3536
+ "PUT",
3537
+ "DELETE",
3538
+ "PATCH",
3539
+ "HEAD",
3540
+ "OPTIONS"
3541
+ ];
3542
+ for (const method of methods) {
3543
+ const response = await actor2.fetch(`test/${method.toLowerCase()}`, {
3544
+ method,
3545
+ // Only include body for methods that support it
3546
+ body: ["POST", "PUT", "PATCH"].includes(method) ? JSON.stringify({ method }) : void 0
3547
+ });
3548
+ if (method === "HEAD") {
3549
+ expect18(response.status).toBe(200);
3550
+ const text = await response.text();
3551
+ expect18(text).toBe("");
3552
+ } else if (method === "OPTIONS") {
3553
+ expect18(response.status).toBe(204);
3554
+ const text = await response.text();
3555
+ expect18(text).toBe("");
3556
+ } else {
3557
+ expect18(response.ok).toBe(true);
3558
+ const data = await response.json();
3559
+ expect18(data.method).toBe(method);
3560
+ }
3561
+ }
3562
+ });
3563
+ test18("should handle complex query parameters", async (c) => {
3564
+ const { client } = await setupDriverTest(c, driverTestConfig);
3565
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3566
+ const response = await actor2.fetch(
3567
+ "test?key=value1&key=value2&array[]=1&array[]=2&nested[prop]=val"
3568
+ );
3569
+ expect18(response.ok).toBe(true);
3570
+ const data = await response.json();
3571
+ expect18(data.searchParams.key).toBe("value2");
3572
+ expect18(data.searchParams["array[]"]).toBe("2");
3573
+ expect18(data.searchParams["nested[prop]"]).toBe("val");
3574
+ });
3575
+ test18("should handle multipart form data", async (c) => {
3576
+ const { client } = await setupDriverTest(c, driverTestConfig);
3577
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3578
+ const boundary = "----RivetKitBoundary";
3579
+ const body = [
3580
+ `------${boundary}`,
3581
+ 'Content-Disposition: form-data; name="field1"',
3582
+ "",
3583
+ "value1",
3584
+ `------${boundary}`,
3585
+ 'Content-Disposition: form-data; name="field2"',
3586
+ "",
3587
+ "value2",
3588
+ `------${boundary}--`
3589
+ ].join("\r\n");
3590
+ const response = await actor2.fetch("test/multipart", {
3591
+ method: "POST",
3592
+ headers: {
3593
+ "Content-Type": `multipart/form-data; boundary=----${boundary}`
3594
+ },
3595
+ body
3596
+ });
3597
+ expect18(response.ok).toBe(true);
3598
+ const data = await response.json();
3599
+ expect18(data.headers["content-type"]).toContain("multipart/form-data");
3600
+ expect18(data.bodyText).toContain("field1");
3601
+ expect18(data.bodyText).toContain("value1");
3602
+ });
3603
+ test18("should handle very long URLs", async (c) => {
3604
+ const { client } = await setupDriverTest(c, driverTestConfig);
3605
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3606
+ const longValue = "x".repeat(1e3);
3607
+ const response = await actor2.fetch(`test/long?param=${longValue}`);
3608
+ expect18(response.ok).toBe(true);
3609
+ const data = await response.json();
3610
+ expect18(data.searchParams.param).toBe(longValue);
3611
+ expect18(data.search.length).toBeGreaterThan(1e3);
3612
+ });
3613
+ test18("should handle large request bodies", async (c) => {
3614
+ const { client } = await setupDriverTest(c, driverTestConfig);
3615
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3616
+ const largeArray = new Array(1e4).fill({
3617
+ id: 1,
3618
+ name: "Test",
3619
+ description: "This is a test object with some data"
3620
+ });
3621
+ const response = await actor2.fetch("test/large", {
3622
+ method: "POST",
3623
+ headers: {
3624
+ "Content-Type": "application/json"
3625
+ },
3626
+ body: JSON.stringify(largeArray)
3627
+ });
3628
+ expect18(response.ok).toBe(true);
3629
+ const data = await response.json();
3630
+ expect18(data.body).toHaveLength(1e4);
3631
+ });
3632
+ test18("should handle missing content-type header", async (c) => {
3633
+ const { client } = await setupDriverTest(c, driverTestConfig);
3634
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3635
+ const response = await actor2.fetch("test/no-content-type", {
3636
+ method: "POST",
3637
+ body: "plain text without content-type"
3638
+ });
3639
+ expect18(response.ok).toBe(true);
3640
+ const data = await response.json();
3641
+ expect18(data.bodyText).toBe("plain text without content-type");
3642
+ });
3643
+ test18("should handle empty request body", async (c) => {
3644
+ const { client } = await setupDriverTest(c, driverTestConfig);
3645
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3646
+ const response = await actor2.fetch("test/empty", {
3647
+ method: "POST",
3648
+ headers: {
3649
+ "Content-Type": "application/json"
3650
+ },
3651
+ body: ""
3652
+ });
3653
+ expect18(response.ok).toBe(true);
3654
+ const data = await response.json();
3655
+ expect18(data.body).toBeNull();
3656
+ expect18(data.bodyText).toBe("");
3657
+ });
3658
+ test18("should handle custom HTTP methods", async (c) => {
3659
+ const { client } = await setupDriverTest(c, driverTestConfig);
3660
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3661
+ try {
3662
+ const response = await actor2.fetch("test/custom", {
3663
+ method: "CUSTOM"
3664
+ });
3665
+ if (response.ok) {
3666
+ const data = await response.json();
3667
+ expect18(data.method).toBe("CUSTOM");
3668
+ }
3669
+ } catch (error) {
3670
+ }
3671
+ });
3672
+ test18("should handle cookies in headers", async (c) => {
3673
+ const { client } = await setupDriverTest(c, driverTestConfig);
3674
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3675
+ const response = await actor2.fetch("test/cookies", {
3676
+ headers: {
3677
+ Cookie: "session=abc123; user=test; preferences=dark_mode"
3678
+ }
3679
+ });
3680
+ expect18(response.ok).toBe(true);
3681
+ const data = await response.json();
3682
+ expect18(data.headers.cookie).toBe(
3683
+ "session=abc123; user=test; preferences=dark_mode"
3684
+ );
3685
+ });
3686
+ test18("should handle URL encoding properly", async (c) => {
3687
+ const { client } = await setupDriverTest(c, driverTestConfig);
3688
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3689
+ const response = await actor2.fetch(
3690
+ "test/encoded?special=%20%21%40%23%24%25%5E%26&unicode=%E2%9C%93&email=test%40example.com"
3691
+ );
3692
+ expect18(response.ok).toBe(true);
3693
+ const data = await response.json();
3694
+ expect18(data.searchParams.special).toBe(" !@#$%^&");
3695
+ expect18(data.searchParams.unicode).toBe("\u2713");
3696
+ expect18(data.searchParams.email).toBe("test@example.com");
3697
+ });
3698
+ test18("should handle concurrent requests maintaining separate contexts", async (c) => {
3699
+ const { client } = await setupDriverTest(c, driverTestConfig);
3700
+ const actor2 = client.rawHttpRequestPropertiesActor.getOrCreate(["test"]);
3701
+ const requests = [
3702
+ actor2.fetch("test/concurrent?id=1", {
3703
+ method: "POST",
3704
+ headers: { "Content-Type": "application/json" },
3705
+ body: JSON.stringify({ request: 1 })
3706
+ }),
3707
+ actor2.fetch("test/concurrent?id=2", {
3708
+ method: "PUT",
3709
+ headers: { "Content-Type": "application/json" },
3710
+ body: JSON.stringify({ request: 2 })
3711
+ }),
3712
+ actor2.fetch("test/concurrent?id=3", {
3713
+ method: "DELETE"
3714
+ })
3715
+ ];
3716
+ const responses = await Promise.all(requests);
3717
+ const results = await Promise.all(
3718
+ responses.map((r) => r.json())
3719
+ );
3720
+ expect18(results[0].searchParams.id).toBe("1");
3721
+ expect18(results[0].method).toBe("POST");
3722
+ expect18(results[0].body).toEqual({ request: 1 });
3723
+ expect18(results[1].searchParams.id).toBe("2");
3724
+ expect18(results[1].method).toBe("PUT");
3725
+ expect18(results[1].body).toEqual({ request: 2 });
3726
+ expect18(results[2].searchParams.id).toBe("3");
3727
+ expect18(results[2].method).toBe("DELETE");
3728
+ expect18(results[2].body).toBeNull();
3729
+ });
3730
+ });
3731
+ }
3732
+
3733
+ // src/driver-test-suite/tests/raw-websocket.ts
3734
+ import { describe as describe20, expect as expect19, test as test19 } from "vitest";
3735
+ function runRawWebSocketTests(driverTestConfig) {
3736
+ describe20("raw websocket", () => {
3737
+ test19("should establish raw WebSocket connection", async (c) => {
3738
+ const { client } = await setupDriverTest(c, driverTestConfig);
3739
+ const actor2 = client.rawWebSocketActor.getOrCreate(["basic"]);
3740
+ const ws = await actor2.websocket();
3741
+ await new Promise((resolve2) => {
3742
+ if (ws.readyState === WebSocket.OPEN) {
3743
+ resolve2();
3744
+ } else {
3745
+ ws.addEventListener(
3746
+ "open",
3747
+ () => {
3748
+ resolve2();
3749
+ },
3750
+ { once: true }
3751
+ );
3752
+ }
3753
+ });
3754
+ const welcomeMessage = await new Promise((resolve2, reject) => {
3755
+ ws.addEventListener(
3756
+ "message",
3757
+ (event) => {
3758
+ resolve2(JSON.parse(event.data));
3759
+ },
3760
+ { once: true }
3761
+ );
3762
+ ws.addEventListener("close", reject);
3763
+ });
3764
+ expect19(welcomeMessage.type).toBe("welcome");
3765
+ expect19(welcomeMessage.connectionCount).toBe(1);
3766
+ ws.close();
3767
+ });
3768
+ test19("should echo messages", async (c) => {
3769
+ const { client } = await setupDriverTest(c, driverTestConfig);
3770
+ const actor2 = client.rawWebSocketActor.getOrCreate(["echo"]);
3771
+ const ws = await actor2.websocket();
3772
+ if (ws.readyState !== WebSocket.OPEN) {
3773
+ await new Promise((resolve2, reject) => {
3774
+ ws.addEventListener("open", () => resolve2(), { once: true });
3775
+ ws.addEventListener("close", reject);
3776
+ });
3777
+ }
3778
+ await new Promise((resolve2, reject) => {
3779
+ ws.addEventListener("message", () => resolve2(), { once: true });
3780
+ ws.addEventListener("close", reject);
3781
+ });
3782
+ const testMessage = { test: "data", timestamp: Date.now() };
3783
+ ws.send(JSON.stringify(testMessage));
3784
+ const echoMessage = await new Promise((resolve2, reject) => {
3785
+ ws.addEventListener(
3786
+ "message",
3787
+ (event) => {
3788
+ resolve2(JSON.parse(event.data));
3789
+ },
3790
+ { once: true }
3791
+ );
3792
+ ws.addEventListener("close", reject);
3793
+ });
3794
+ expect19(echoMessage).toEqual(testMessage);
3795
+ ws.close();
3796
+ });
3797
+ test19("should handle ping/pong protocol", async (c) => {
3798
+ const { client } = await setupDriverTest(c, driverTestConfig);
3799
+ const actor2 = client.rawWebSocketActor.getOrCreate(["ping"]);
3800
+ const ws = await actor2.websocket();
3801
+ if (ws.readyState !== WebSocket.OPEN) {
3802
+ await new Promise((resolve2, reject) => {
3803
+ ws.addEventListener("open", () => resolve2(), { once: true });
3804
+ ws.addEventListener("close", reject);
3805
+ });
3806
+ }
3807
+ await new Promise((resolve2, reject) => {
3808
+ ws.addEventListener("message", () => resolve2(), { once: true });
3809
+ ws.addEventListener("close", reject);
3810
+ });
3811
+ ws.send(JSON.stringify({ type: "ping" }));
3812
+ const pongMessage = await new Promise((resolve2, reject) => {
3813
+ ws.addEventListener("message", (event) => {
3814
+ const data = JSON.parse(event.data);
3815
+ if (data.type === "pong") {
3816
+ resolve2(data);
3817
+ }
3818
+ });
3819
+ ws.addEventListener("close", reject);
3820
+ });
3821
+ expect19(pongMessage.type).toBe("pong");
3822
+ expect19(pongMessage.timestamp).toBeDefined();
3823
+ ws.close();
3824
+ });
3825
+ test19("should track stats across connections", async (c) => {
3826
+ const { client } = await setupDriverTest(c, driverTestConfig);
3827
+ const actor1 = client.rawWebSocketActor.getOrCreate(["stats"]);
3828
+ const ws1 = await actor1.websocket();
3829
+ const ws1MessagePromise = new Promise((resolve2, reject) => {
3830
+ ws1.addEventListener("message", () => resolve2(), { once: true });
3831
+ ws1.addEventListener("close", reject);
3832
+ });
3833
+ await ws1MessagePromise;
3834
+ const actor2 = client.rawWebSocketActor.get(["stats"]);
3835
+ const ws2 = await actor2.websocket();
3836
+ const ws2MessagePromise = new Promise((resolve2, reject) => {
3837
+ ws2.addEventListener("message", () => resolve2(), { once: true });
3838
+ ws2.addEventListener("close", reject);
3839
+ });
3840
+ await Promise.all([ws1MessagePromise, ws2MessagePromise]);
3841
+ const pingPromise = new Promise((resolve2, reject) => {
3842
+ ws2.addEventListener("message", (event) => {
3843
+ const data = JSON.parse(event.data);
3844
+ if (data.type === "pong") {
3845
+ resolve2(void 0);
3846
+ }
3847
+ });
3848
+ ws2.addEventListener("close", reject);
3849
+ });
3850
+ ws1.send(JSON.stringify({ data: "test1" }));
3851
+ ws1.send(JSON.stringify({ data: "test3" }));
3852
+ ws2.send(JSON.stringify({ type: "ping" }));
3853
+ await pingPromise;
3854
+ const statsPromise = new Promise((resolve2, reject) => {
3855
+ ws1.addEventListener("message", (event) => {
3856
+ const data = JSON.parse(event.data);
3857
+ if (data.type === "stats") {
3858
+ resolve2(data);
3859
+ }
3860
+ });
3861
+ ws1.addEventListener("close", reject);
3862
+ });
3863
+ ws1.send(JSON.stringify({ type: "getStats" }));
3864
+ const stats = await statsPromise;
3865
+ expect19(stats.connectionCount).toBe(2);
3866
+ expect19(stats.messageCount).toBe(4);
3867
+ const actionStats = await actor1.getStats();
3868
+ expect19(actionStats.connectionCount).toBe(2);
3869
+ expect19(actionStats.messageCount).toBe(4);
3870
+ ws1.close();
3871
+ ws2.close();
3872
+ });
3873
+ test19("should handle binary data", async (c) => {
3874
+ const { client } = await setupDriverTest(c, driverTestConfig);
3875
+ const actor2 = client.rawWebSocketBinaryActor.getOrCreate(["binary"]);
3876
+ const ws = await actor2.websocket();
3877
+ if (ws.readyState !== WebSocket.OPEN) {
3878
+ await new Promise((resolve2, reject) => {
3879
+ ws.addEventListener("open", () => resolve2(), { once: true });
3880
+ ws.addEventListener("close", reject);
3881
+ });
3882
+ }
3883
+ const receiveBinaryMessage = async () => {
3884
+ const response = await new Promise(
3885
+ (resolve2, reject) => {
3886
+ ws.addEventListener(
3887
+ "message",
3888
+ (event) => {
3889
+ resolve2(event.data);
3890
+ },
3891
+ { once: true }
3892
+ );
3893
+ ws.addEventListener("close", reject);
3894
+ }
3895
+ );
3896
+ const buffer = response instanceof Blob ? await response.arrayBuffer() : response;
3897
+ return new Uint8Array(buffer);
3898
+ };
3899
+ const smallData = new Uint8Array([1, 2, 3, 4, 5]);
3900
+ ws.send(smallData);
3901
+ const smallReversed = await receiveBinaryMessage();
3902
+ expect19(Array.from(smallReversed)).toEqual([5, 4, 3, 2, 1]);
3903
+ const largeData = new Uint8Array(1024);
3904
+ for (let i = 0; i < largeData.length; i++) {
3905
+ largeData[i] = i % 256;
3906
+ }
3907
+ ws.send(largeData);
3908
+ const largeReversed = await receiveBinaryMessage();
3909
+ for (let i = 0; i < largeData.length; i++) {
3910
+ expect19(largeReversed[i]).toBe(largeData[largeData.length - 1 - i]);
3911
+ }
3912
+ ws.close();
3913
+ });
3914
+ test19("should work with custom paths", async (c) => {
3915
+ const { client } = await setupDriverTest(c, driverTestConfig);
3916
+ const actor2 = client.rawWebSocketActor.getOrCreate(["paths"]);
3917
+ const ws = await actor2.websocket("custom/path");
3918
+ await new Promise((resolve2, reject) => {
3919
+ ws.addEventListener("open", () => {
3920
+ resolve2();
3921
+ });
3922
+ ws.addEventListener("error", reject);
3923
+ ws.addEventListener("close", reject);
3924
+ });
3925
+ const welcomeMessage = await new Promise((resolve2) => {
3926
+ ws.addEventListener(
3927
+ "message",
3928
+ (event) => {
3929
+ resolve2(JSON.parse(event.data));
3930
+ },
3931
+ { once: true }
3932
+ );
3933
+ });
3934
+ expect19(welcomeMessage.type).toBe("welcome");
3935
+ ws.close();
3936
+ });
3937
+ test19("should pass connection parameters through subprotocols", async (c) => {
3938
+ const { client } = await setupDriverTest(c, driverTestConfig);
3939
+ const testParams = { userId: "test123", role: "admin" };
3940
+ const actor2 = client.rawWebSocketActor.getOrCreate(["params"], {
3941
+ params: testParams
3942
+ });
3943
+ const ws = await actor2.websocket();
3944
+ await new Promise((resolve2) => {
3945
+ ws.addEventListener("open", () => resolve2(), { once: true });
3946
+ });
3947
+ ws.send(JSON.stringify({ type: "getAuthData" }));
3948
+ const response = await new Promise((resolve2, reject) => {
3949
+ ws.addEventListener("message", (event) => {
3950
+ const data = JSON.parse(event.data);
3951
+ if (data.type === "authData") {
3952
+ resolve2(data);
3953
+ }
3954
+ });
3955
+ ws.addEventListener("close", reject);
3956
+ });
3957
+ expect19(response).toBeDefined();
3958
+ ws.close();
3959
+ });
3960
+ test19("should handle connection close properly", async (c) => {
3961
+ const { client } = await setupDriverTest(c, driverTestConfig);
3962
+ const actor2 = client.rawWebSocketActor.getOrCreate(["close-test"]);
3963
+ const ws = await actor2.websocket();
3964
+ if (ws.readyState !== WebSocket.OPEN) {
3965
+ await new Promise((resolve2, reject) => {
3966
+ ws.addEventListener("open", () => resolve2(), { once: true });
3967
+ ws.addEventListener("close", reject);
3968
+ });
3969
+ }
3970
+ const initialStats = await actor2.getStats();
3971
+ expect19(initialStats.connectionCount).toBe(1);
3972
+ const closePromise = new Promise((resolve2) => {
3973
+ ws.addEventListener("close", () => resolve2(), { once: true });
3974
+ });
3975
+ ws.close();
3976
+ await closePromise;
3977
+ let finalStats;
3978
+ for (let i = 0; i < 20; i++) {
3979
+ finalStats = await actor2.getStats();
3980
+ if (finalStats.connectionCount === 0) {
3981
+ break;
3982
+ }
3983
+ await new Promise((resolve2) => setTimeout(resolve2, 50));
3984
+ }
3985
+ expect19(finalStats == null ? void 0 : finalStats.connectionCount).toBe(0);
3986
+ });
3987
+ test19("should properly handle onWebSocket open and close events", async (c) => {
3988
+ const { client } = await setupDriverTest(c, driverTestConfig);
3989
+ const actor2 = client.rawWebSocketActor.getOrCreate(["open-close-test"]);
3990
+ const ws1 = await actor2.websocket();
3991
+ await new Promise((resolve2, reject) => {
3992
+ ws1.addEventListener("open", () => resolve2(), { once: true });
3993
+ ws1.addEventListener("close", reject);
3994
+ });
3995
+ const welcome1 = await new Promise((resolve2, reject) => {
3996
+ ws1.addEventListener(
3997
+ "message",
3998
+ (event) => {
3999
+ resolve2(JSON.parse(event.data));
4000
+ },
4001
+ { once: true }
4002
+ );
4003
+ ws1.addEventListener("close", reject);
4004
+ });
4005
+ expect19(welcome1.type).toBe("welcome");
4006
+ expect19(welcome1.connectionCount).toBe(1);
4007
+ const ws2 = await actor2.websocket();
4008
+ await new Promise((resolve2, reject) => {
4009
+ ws2.addEventListener("open", () => resolve2(), { once: true });
4010
+ ws2.addEventListener("close", reject);
4011
+ });
4012
+ const welcome2 = await new Promise((resolve2, reject) => {
4013
+ ws2.addEventListener(
4014
+ "message",
4015
+ (event) => {
4016
+ resolve2(JSON.parse(event.data));
4017
+ },
4018
+ { once: true }
4019
+ );
4020
+ ws2.addEventListener("close", reject);
4021
+ });
4022
+ expect19(welcome2.type).toBe("welcome");
4023
+ expect19(welcome2.connectionCount).toBe(2);
4024
+ const midStats = await actor2.getStats();
4025
+ expect19(midStats.connectionCount).toBe(2);
4026
+ ws1.close();
4027
+ await new Promise((resolve2) => {
4028
+ ws1.addEventListener("close", () => resolve2(), { once: true });
4029
+ });
4030
+ let afterFirstClose;
4031
+ for (let i = 0; i < 20; i++) {
4032
+ afterFirstClose = await actor2.getStats();
4033
+ if (afterFirstClose.connectionCount === 1) {
4034
+ break;
4035
+ }
4036
+ await new Promise((resolve2) => setTimeout(resolve2, 50));
4037
+ }
4038
+ expect19(afterFirstClose == null ? void 0 : afterFirstClose.connectionCount).toBe(1);
4039
+ ws2.close();
4040
+ await new Promise((resolve2) => {
4041
+ ws2.addEventListener("close", () => resolve2(), { once: true });
4042
+ });
4043
+ let finalStats;
4044
+ for (let i = 0; i < 20; i++) {
4045
+ finalStats = await actor2.getStats();
4046
+ if (finalStats.connectionCount === 0) {
4047
+ break;
4048
+ }
4049
+ await new Promise((resolve2) => setTimeout(resolve2, 50));
4050
+ }
4051
+ expect19(finalStats == null ? void 0 : finalStats.connectionCount).toBe(0);
4052
+ });
4053
+ test19("should handle query parameters in websocket paths", async (c) => {
4054
+ const { client } = await setupDriverTest(c, driverTestConfig);
4055
+ const actor2 = client.rawWebSocketActor.getOrCreate(["query-params"]);
4056
+ const ws = await actor2.websocket("api/v1/stream?token=abc123&user=test");
4057
+ await new Promise((resolve2, reject) => {
4058
+ ws.addEventListener("open", () => resolve2(), { once: true });
4059
+ ws.addEventListener("error", reject);
4060
+ });
4061
+ const requestInfoPromise = new Promise((resolve2, reject) => {
4062
+ ws.addEventListener("message", (event) => {
4063
+ const data = JSON.parse(event.data);
4064
+ if (data.type === "requestInfo") {
4065
+ resolve2(data);
4066
+ }
4067
+ });
4068
+ ws.addEventListener("close", reject);
4069
+ });
4070
+ ws.send(JSON.stringify({ type: "getRequestInfo" }));
4071
+ const requestInfo = await requestInfoPromise;
4072
+ expect19(requestInfo.url).toContain("api/v1/stream");
4073
+ expect19(requestInfo.url).toContain("token=abc123");
4074
+ expect19(requestInfo.url).toContain("user=test");
4075
+ ws.close();
4076
+ });
4077
+ });
4078
+ }
4079
+
4080
+ // src/driver-test-suite/tests/raw-websocket-direct-registry.ts
4081
+ import { describe as describe21, expect as expect20, test as test20 } from "vitest";
4082
+ function runRawWebSocketDirectRegistryTests(driverTestConfig) {
4083
+ describe21("raw websocket - direct registry access", () => {
4084
+ test20("should establish vanilla WebSocket connection with proper subprotocols", async (c) => {
4085
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
4086
+ const WebSocket2 = await importWebSocket();
4087
+ const actorQuery = {
4088
+ getOrCreateForKey: {
4089
+ name: "rawWebSocketActor",
4090
+ key: ["vanilla-test"]
4091
+ }
4092
+ };
4093
+ const queryProtocol = `query.${encodeURIComponent(JSON.stringify(actorQuery))}`;
4094
+ const wsEndpoint = endpoint.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
4095
+ const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
4096
+ const ws = new WebSocket2(wsUrl, [
4097
+ queryProtocol,
4098
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
4099
+ "rivetkit"
4100
+ ]);
4101
+ await new Promise((resolve2, reject) => {
4102
+ ws.addEventListener("open", () => {
4103
+ resolve2();
4104
+ });
4105
+ ws.addEventListener("error", reject);
4106
+ ws.addEventListener("close", reject);
4107
+ });
4108
+ const welcomeMessage = await new Promise((resolve2, reject) => {
4109
+ ws.addEventListener(
4110
+ "message",
4111
+ (event) => {
4112
+ resolve2(JSON.parse(event.data));
4113
+ },
4114
+ { once: true }
4115
+ );
4116
+ ws.addEventListener("close", reject);
4117
+ });
4118
+ expect20(welcomeMessage.type).toBe("welcome");
4119
+ expect20(welcomeMessage.connectionCount).toBe(1);
4120
+ ws.close();
4121
+ });
4122
+ test20("should echo messages with vanilla WebSocket", async (c) => {
4123
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
4124
+ const WebSocket2 = await importWebSocket();
4125
+ const actorQuery = {
4126
+ getOrCreateForKey: {
4127
+ name: "rawWebSocketActor",
4128
+ key: ["vanilla-echo"]
4129
+ }
4130
+ };
4131
+ const queryProtocol = `query.${encodeURIComponent(JSON.stringify(actorQuery))}`;
4132
+ const wsEndpoint = endpoint.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
4133
+ const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
4134
+ const ws = new WebSocket2(wsUrl, [
4135
+ queryProtocol,
4136
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
4137
+ "rivetkit"
4138
+ ]);
4139
+ await new Promise((resolve2, reject) => {
4140
+ ws.addEventListener("open", () => resolve2(), { once: true });
4141
+ ws.addEventListener("close", reject);
4142
+ });
4143
+ await new Promise((resolve2, reject) => {
4144
+ ws.addEventListener("message", () => resolve2(), { once: true });
4145
+ ws.addEventListener("close", reject);
4146
+ });
4147
+ const testMessage = { test: "vanilla", timestamp: Date.now() };
4148
+ ws.send(JSON.stringify(testMessage));
4149
+ const echoMessage = await new Promise((resolve2, reject) => {
4150
+ ws.addEventListener(
4151
+ "message",
4152
+ (event) => {
4153
+ resolve2(JSON.parse(event.data));
4154
+ },
4155
+ { once: true }
4156
+ );
4157
+ ws.addEventListener("close", reject);
4158
+ });
4159
+ expect20(echoMessage).toEqual(testMessage);
4160
+ ws.close();
4161
+ });
4162
+ test20("should handle connection parameters for authentication", async (c) => {
4163
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
4164
+ const WebSocket2 = await importWebSocket();
4165
+ const actorQuery = {
4166
+ getOrCreateForKey: {
4167
+ name: "rawWebSocketActor",
4168
+ key: ["vanilla-auth"]
4169
+ }
4170
+ };
4171
+ const connParams = { token: "ws-auth-token", userId: "ws-user123" };
4172
+ const queryProtocol = `query.${encodeURIComponent(JSON.stringify(actorQuery))}`;
4173
+ const connParamsProtocol = `conn_params.${encodeURIComponent(JSON.stringify(connParams))}`;
4174
+ const wsEndpoint = endpoint.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
4175
+ const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
4176
+ const ws = new WebSocket2(wsUrl, [
4177
+ queryProtocol,
4178
+ connParamsProtocol,
4179
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
4180
+ "rivetkit"
4181
+ ]);
4182
+ await new Promise((resolve2, reject) => {
4183
+ ws.addEventListener("open", () => {
4184
+ resolve2();
4185
+ });
4186
+ ws.addEventListener("error", reject);
4187
+ ws.addEventListener("close", reject);
4188
+ });
4189
+ const welcomeMessage = await new Promise((resolve2, reject) => {
4190
+ ws.addEventListener(
4191
+ "message",
4192
+ (event) => {
4193
+ resolve2(JSON.parse(event.data));
4194
+ },
4195
+ { once: true }
4196
+ );
4197
+ ws.addEventListener("close", reject);
4198
+ });
4199
+ expect20(welcomeMessage.type).toBe("welcome");
4200
+ ws.close();
4201
+ });
4202
+ test20("should handle custom user protocols alongside rivetkit protocols", async (c) => {
4203
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
4204
+ const WebSocket2 = await importWebSocket();
4205
+ const actorQuery = {
4206
+ getOrCreateForKey: {
4207
+ name: "rawWebSocketActor",
4208
+ key: ["vanilla-protocols"]
4209
+ }
4210
+ };
4211
+ const queryProtocol = `query.${encodeURIComponent(JSON.stringify(actorQuery))}`;
4212
+ const userProtocol1 = "chat-v1";
4213
+ const userProtocol2 = "custom-protocol";
4214
+ const wsEndpoint = endpoint.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
4215
+ const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
4216
+ const ws = new WebSocket2(wsUrl, [
4217
+ queryProtocol,
4218
+ userProtocol1,
4219
+ userProtocol2,
4220
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
4221
+ "rivetkit"
4222
+ ]);
4223
+ await new Promise((resolve2, reject) => {
4224
+ ws.addEventListener("open", () => {
4225
+ resolve2();
4226
+ });
4227
+ ws.addEventListener("error", reject);
4228
+ ws.addEventListener("close", reject);
4229
+ });
4230
+ const welcomeMessage = await new Promise((resolve2, reject) => {
4231
+ ws.addEventListener(
4232
+ "message",
4233
+ (event) => {
4234
+ resolve2(JSON.parse(event.data));
4235
+ },
4236
+ { once: true }
4237
+ );
4238
+ ws.addEventListener("close", reject);
4239
+ });
4240
+ expect20(welcomeMessage.type).toBe("welcome");
4241
+ ws.close();
4242
+ });
4243
+ test20("should handle different paths for WebSocket routes", async (c) => {
4244
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
4245
+ const WebSocket2 = await importWebSocket();
4246
+ const actorQuery = {
4247
+ getOrCreateForKey: {
4248
+ name: "rawWebSocketActor",
4249
+ key: ["vanilla-paths"]
4250
+ }
4251
+ };
4252
+ const queryProtocol = `query.${encodeURIComponent(JSON.stringify(actorQuery))}`;
4253
+ const wsEndpoint = endpoint.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
4254
+ const paths = ["chat/room1", "updates/feed", "stream/events"];
4255
+ for (const path of paths) {
4256
+ const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/${path}`;
4257
+ const ws = new WebSocket2(wsUrl, [
4258
+ queryProtocol,
4259
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
4260
+ "rivetkit"
4261
+ ]);
4262
+ await new Promise((resolve2, reject) => {
4263
+ ws.addEventListener("open", () => {
4264
+ resolve2();
4265
+ });
4266
+ ws.addEventListener("error", reject);
4267
+ });
4268
+ const welcomeMessage = await new Promise((resolve2, reject) => {
4269
+ ws.addEventListener(
4270
+ "message",
4271
+ (event) => {
4272
+ resolve2(JSON.parse(event.data));
4273
+ },
4274
+ { once: true }
4275
+ );
4276
+ ws.addEventListener("close", reject);
4277
+ });
4278
+ expect20(welcomeMessage.type).toBe("welcome");
4279
+ ws.close();
4280
+ }
4281
+ });
4282
+ test20("should return error for actors without onWebSocket handler", async (c) => {
4283
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
4284
+ const WebSocket2 = await importWebSocket();
4285
+ const actorQuery = {
4286
+ getOrCreateForKey: {
4287
+ name: "rawWebSocketNoHandlerActor",
4288
+ key: ["vanilla-no-handler"]
4289
+ }
4290
+ };
4291
+ const queryProtocol = `query.${encodeURIComponent(JSON.stringify(actorQuery))}`;
4292
+ const wsEndpoint = endpoint.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
4293
+ const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
4294
+ const ws = new WebSocket2(wsUrl, [
4295
+ queryProtocol,
4296
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
4297
+ "rivetkit"
4298
+ ]);
4299
+ await new Promise((resolve2) => {
4300
+ ws.addEventListener("error", () => resolve2(), { once: true });
4301
+ ws.addEventListener("close", () => resolve2(), { once: true });
4302
+ });
4303
+ expect20(ws.readyState).toBe(ws.CLOSED || 3);
4304
+ });
4305
+ test20("should handle binary data over vanilla WebSocket", async (c) => {
4306
+ const { endpoint } = await setupDriverTest(c, driverTestConfig);
4307
+ const WebSocket2 = await importWebSocket();
4308
+ const actorQuery = {
4309
+ getOrCreateForKey: {
4310
+ name: "rawWebSocketActor",
4311
+ key: ["vanilla-binary"]
4312
+ }
4313
+ };
4314
+ const queryProtocol = `query.${encodeURIComponent(JSON.stringify(actorQuery))}`;
4315
+ const wsEndpoint = endpoint.replace(/^http:/, "ws:").replace(/^https:/, "wss:");
4316
+ const wsUrl = `${wsEndpoint}/registry/actors/raw/websocket/`;
4317
+ const ws = new WebSocket2(wsUrl, [
4318
+ queryProtocol,
4319
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
4320
+ "rivetkit"
4321
+ ]);
4322
+ ws.binaryType = "arraybuffer";
4323
+ await new Promise((resolve2, reject) => {
4324
+ ws.addEventListener("open", () => resolve2(), { once: true });
4325
+ ws.addEventListener("close", reject);
4326
+ });
4327
+ await new Promise((resolve2, reject) => {
4328
+ ws.addEventListener("message", () => resolve2(), { once: true });
4329
+ ws.addEventListener("close", reject);
4330
+ });
4331
+ const binaryData = new Uint8Array([1, 2, 3, 4, 5]);
4332
+ ws.send(binaryData.buffer);
4333
+ const echoedData = await new Promise((resolve2, reject) => {
4334
+ ws.addEventListener(
4335
+ "message",
4336
+ (event) => {
4337
+ resolve2(event.data);
4338
+ },
4339
+ { once: true }
4340
+ );
4341
+ ws.addEventListener("close", reject);
4342
+ });
4343
+ const echoedArray = new Uint8Array(echoedData);
4344
+ expect20(Array.from(echoedArray)).toEqual([1, 2, 3, 4, 5]);
4345
+ ws.send(JSON.stringify({ type: "binary-test", size: binaryData.length }));
4346
+ const echoMessage = await new Promise((resolve2, reject) => {
4347
+ ws.addEventListener(
4348
+ "message",
4349
+ (event) => {
4350
+ resolve2(JSON.parse(event.data));
4351
+ },
4352
+ { once: true }
4353
+ );
4354
+ ws.addEventListener("close", reject);
4355
+ });
4356
+ expect20(echoMessage.type).toBe("binary-test");
4357
+ expect20(echoMessage.size).toBe(5);
4358
+ ws.close();
4359
+ });
4360
+ });
4361
+ }
4362
+
4363
+ // src/driver-test-suite/tests/request-access.ts
4364
+ import { describe as describe22, expect as expect21, test as test21 } from "vitest";
4365
+ function runRequestAccessTests(driverTestConfig) {
4366
+ describe22("Request Access in Lifecycle Hooks", () => {
4367
+ test21("should have access to request object in onBeforeConnect and createConnState", async (c) => {
4368
+ const { client } = await setupDriverTest(c, driverTestConfig);
4369
+ const handle = client.requestAccessActor.getOrCreate(["test-request"], {
4370
+ params: { trackRequest: true }
4371
+ });
4372
+ const connection = handle.connect();
4373
+ const requestInfo = await connection.getRequestInfo();
4374
+ if (driverTestConfig.clientType === "http") {
4375
+ expect21(requestInfo.onBeforeConnect.hasRequest).toBe(true);
4376
+ expect21(requestInfo.onBeforeConnect.requestUrl).toBeDefined();
4377
+ expect21(requestInfo.onBeforeConnect.requestMethod).toBeDefined();
4378
+ expect21(requestInfo.onBeforeConnect.requestHeaders).toBeDefined();
4379
+ expect21(requestInfo.createConnState.hasRequest).toBe(true);
4380
+ expect21(requestInfo.createConnState.requestUrl).toBeDefined();
4381
+ expect21(requestInfo.createConnState.requestMethod).toBeDefined();
4382
+ expect21(requestInfo.createConnState.requestHeaders).toBeDefined();
4383
+ } else {
4384
+ }
4385
+ await connection.dispose();
4386
+ });
4387
+ test21("should not have request when trackRequest is false", async (c) => {
4388
+ const { client } = await setupDriverTest(c, driverTestConfig);
4389
+ const handle = client.requestAccessActor.getOrCreate(
4390
+ ["test-no-request"],
4391
+ {
4392
+ params: { trackRequest: false }
4393
+ }
4394
+ );
4395
+ const connection = handle.connect();
4396
+ const requestInfo = await connection.getRequestInfo();
4397
+ expect21(requestInfo.onBeforeConnect.hasRequest).toBe(false);
4398
+ expect21(requestInfo.onBeforeConnect.requestUrl).toBeNull();
4399
+ expect21(requestInfo.onBeforeConnect.requestMethod).toBeNull();
4400
+ expect21(
4401
+ Object.keys(requestInfo.onBeforeConnect.requestHeaders)
4402
+ ).toHaveLength(0);
4403
+ expect21(requestInfo.createConnState.hasRequest).toBe(false);
4404
+ expect21(requestInfo.createConnState.requestUrl).toBeNull();
4405
+ expect21(requestInfo.createConnState.requestMethod).toBeNull();
4406
+ expect21(
4407
+ Object.keys(requestInfo.createConnState.requestHeaders)
4408
+ ).toHaveLength(0);
4409
+ await connection.dispose();
4410
+ });
4411
+ test21("should capture request headers and method", async (c) => {
4412
+ const { client } = await setupDriverTest(c, driverTestConfig);
4413
+ const handle = client.requestAccessActor.getOrCreate(["test-headers"], {
4414
+ params: { trackRequest: true }
4415
+ });
4416
+ const connection = handle.connect();
4417
+ const requestInfo = await connection.getRequestInfo();
4418
+ if (driverTestConfig.clientType === "http") {
4419
+ expect21(requestInfo.onBeforeConnect.hasRequest).toBe(true);
4420
+ expect21(requestInfo.onBeforeConnect.requestMethod).toBeTruthy();
4421
+ expect21(requestInfo.onBeforeConnect.requestUrl).toBeTruthy();
4422
+ expect21(requestInfo.onBeforeConnect.requestHeaders).toBeTruthy();
4423
+ expect21(typeof requestInfo.onBeforeConnect.requestHeaders).toBe(
4424
+ "object"
4425
+ );
4426
+ expect21(requestInfo.createConnState.hasRequest).toBe(true);
4427
+ expect21(requestInfo.createConnState.requestMethod).toBeTruthy();
4428
+ expect21(requestInfo.createConnState.requestUrl).toBeTruthy();
4429
+ expect21(requestInfo.createConnState.requestHeaders).toBeTruthy();
4430
+ expect21(typeof requestInfo.createConnState.requestHeaders).toBe(
4431
+ "object"
4432
+ );
4433
+ } else {
4434
+ }
4435
+ await connection.dispose();
4436
+ });
4437
+ test21("should have access to request object in onAuth", async (c) => {
4438
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
4439
+ if (driverTestConfig.clientType === "http") {
4440
+ console.log("Skipping onAuth test - requires public endpoint setup");
4441
+ }
4442
+ });
4443
+ test21("should have access to request object in onFetch", async (c) => {
4444
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
4445
+ const handle = client.requestAccessActor.getOrCreate(["test-fetch"]);
4446
+ await handle.resolve();
4447
+ const actorQuery = {
4448
+ getOrCreateForKey: {
4449
+ name: "requestAccessActor",
4450
+ key: ["test-fetch"]
4451
+ }
4452
+ };
4453
+ const url = `${endpoint}/registry/actors/raw/http/test-path`;
4454
+ const response = await fetch(url, {
4455
+ method: "POST",
4456
+ headers: {
4457
+ "Content-Type": "application/json",
4458
+ "X-Test-Header": "test-value",
4459
+ "X-RivetKit-Query": JSON.stringify(actorQuery)
4460
+ },
4461
+ body: JSON.stringify({ test: "data" })
4462
+ });
4463
+ if (!response.ok) {
4464
+ const errorText = await response.text();
4465
+ console.error(
4466
+ `HTTP request failed: ${response.status} ${response.statusText}`,
4467
+ errorText
4468
+ );
4469
+ }
4470
+ expect21(response.ok).toBe(true);
4471
+ const data = await response.json();
4472
+ expect21(data.hasRequest).toBe(true);
4473
+ expect21(data.requestUrl).toContain("/test-path");
4474
+ expect21(data.requestMethod).toBe("POST");
4475
+ expect21(data.requestHeaders).toBeDefined();
4476
+ expect21(data.requestHeaders["content-type"]).toBe(
4477
+ "application/json"
4478
+ );
4479
+ expect21(data.requestHeaders["x-test-header"]).toBe("test-value");
4480
+ });
4481
+ test21("should have access to request object in onWebSocket", async (c) => {
4482
+ const { client, endpoint } = await setupDriverTest(c, driverTestConfig);
4483
+ if (typeof WebSocket !== "undefined") {
4484
+ const handle = client.requestAccessActor.getOrCreate([
4485
+ "test-websocket"
4486
+ ]);
4487
+ await handle.resolve();
4488
+ const actorQuery = {
4489
+ getOrCreateForKey: {
4490
+ name: "requestAccessActor",
4491
+ key: ["test-websocket"]
4492
+ }
4493
+ };
4494
+ const queryProtocol = `query.${encodeURIComponent(JSON.stringify(actorQuery))}`;
4495
+ const wsUrl = endpoint.replace("http://", "ws://").replace("https://", "wss://");
4496
+ const ws = new WebSocket(
4497
+ `${wsUrl}/registry/actors/raw/websocket/test-path`,
4498
+ [
4499
+ queryProtocol,
4500
+ "rivetkit"
4501
+ // Required protocol
4502
+ ]
4503
+ );
4504
+ await new Promise((resolve2, reject) => {
4505
+ ws.onopen = () => {
4506
+ };
4507
+ ws.onmessage = (event) => {
4508
+ try {
4509
+ const data = JSON.parse(event.data);
4510
+ expect21(data.hasRequest).toBe(true);
4511
+ expect21(data.requestUrl).toContain("/test-path");
4512
+ expect21(data.requestMethod).toBe("GET");
4513
+ expect21(data.requestHeaders).toBeDefined();
4514
+ ws.close();
4515
+ resolve2();
4516
+ } catch (error) {
4517
+ reject(error);
4518
+ }
4519
+ };
4520
+ ws.onerror = (error) => {
4521
+ reject(error);
4522
+ };
4523
+ });
4524
+ }
4525
+ });
4526
+ });
4527
+ }
4528
+
4529
+ // src/driver-test-suite/mod.ts
4530
+ function runDriverTests(driverTestConfigPartial) {
4531
+ for (const clientType of ["http", "inline"]) {
4532
+ const driverTestConfig = {
4533
+ ...driverTestConfigPartial,
4534
+ clientType
4535
+ };
4536
+ describe23(`client type (${clientType})`, () => {
4537
+ runActorDriverTests(driverTestConfig);
4538
+ runManagerDriverTests(driverTestConfig);
4539
+ for (const transport of ["websocket", "sse"]) {
4540
+ describe23(`transport (${transport})`, () => {
4541
+ runActorConnTests({
4542
+ ...driverTestConfig,
4543
+ transport
4544
+ });
4545
+ runActorConnStateTests({ ...driverTestConfig, transport });
4546
+ runRequestAccessTests({ ...driverTestConfig, transport });
4547
+ runActorDriverTestsWithTransport({ ...driverTestConfig, transport });
4548
+ });
4549
+ }
4550
+ runActorHandleTests(driverTestConfig);
4551
+ runActionFeaturesTests(driverTestConfig);
4552
+ runActorVarsTests(driverTestConfig);
4553
+ runActorMetadataTests(driverTestConfig);
4554
+ runActorOnStateChangeTests(driverTestConfig);
4555
+ runActorErrorHandlingTests(driverTestConfig);
4556
+ runActorAuthTests(driverTestConfig);
4557
+ runActorInlineClientTests(driverTestConfig);
4558
+ runRawHttpTests(driverTestConfig);
4559
+ runRawHttpRequestPropertiesTests(driverTestConfig);
4560
+ runRawWebSocketTests(driverTestConfig);
4561
+ runRawHttpDirectRegistryTests(driverTestConfig);
4562
+ runRawWebSocketDirectRegistryTests(driverTestConfig);
4563
+ runActorInspectorTests(driverTestConfig);
4564
+ });
4565
+ }
4566
+ }
4567
+ async function createTestRuntime(registryPath, driverFactory) {
4568
+ const {
4569
+ mod: { registry }
4570
+ } = await bundleRequire({
4571
+ filepath: registryPath
4572
+ });
4573
+ registry.config.test.enabled = true;
4574
+ const { driver, cleanup: driverCleanup } = await driverFactory(registry);
4575
+ let injectWebSocket;
4576
+ let upgradeWebSocket;
4577
+ const config = RunConfigSchema.parse({
4578
+ driver,
4579
+ getUpgradeWebSocket: () => upgradeWebSocket,
4580
+ inspector: {
4581
+ enabled: true,
4582
+ token: () => "token"
4583
+ }
4584
+ });
4585
+ const managerDriver = driver.manager(registry.config, config);
4586
+ const inlineDriver = createInlineClientDriver(managerDriver);
4587
+ const { router } = createManagerRouter(
4588
+ registry.config,
4589
+ config,
4590
+ inlineDriver,
4591
+ managerDriver,
4592
+ false
4593
+ );
4594
+ const nodeWebSocket = createNodeWebSocket({ app: router });
4595
+ upgradeWebSocket = nodeWebSocket.upgradeWebSocket;
4596
+ injectWebSocket = nodeWebSocket.injectWebSocket;
4597
+ const port = await getPort();
4598
+ const server = honoServe({
4599
+ fetch: router.fetch,
4600
+ hostname: "127.0.0.1",
4601
+ port
4602
+ });
4603
+ invariant(injectWebSocket !== void 0, "should have injectWebSocket");
4604
+ injectWebSocket(server);
4605
+ const endpoint = `http://127.0.0.1:${port}`;
4606
+ const cleanup = async () => {
4607
+ await new Promise((resolve2) => server.close(() => resolve2(void 0)));
4608
+ await (driverCleanup == null ? void 0 : driverCleanup());
4609
+ };
4610
+ return {
4611
+ endpoint,
4612
+ cleanup
4613
+ };
4614
+ }
4615
+ export {
4616
+ createTestRuntime,
4617
+ runDriverTests
4618
+ };
4619
+ //# sourceMappingURL=mod.js.map