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,402 @@
1
+ import * as cbor from "cbor-x";
2
+ import type { Context as HonoContext } from "hono";
3
+ import type { WebSocket } from "ws";
4
+ import type { Encoding } from "@/actor/protocol/serde";
5
+ import {
6
+ HEADER_ACTOR_QUERY,
7
+ HEADER_CONN_PARAMS,
8
+ HEADER_ENCODING,
9
+ } from "@/actor/router-endpoints";
10
+ import { assertUnreachable } from "@/actor/utils";
11
+ import type { ClientDriver } from "@/client/client";
12
+ import { ActorError as ClientActorError } from "@/client/errors";
13
+ import type { Transport } from "@/client/mod";
14
+ import type { UniversalEventSource } from "@/common/eventsource-interface";
15
+ import { importWebSocket } from "@/common/websocket";
16
+ import type { ActorQuery } from "@/manager/protocol/query";
17
+ import type {
18
+ TestInlineDriverCallRequest,
19
+ TestInlineDriverCallResponse,
20
+ } from "@/manager/router";
21
+ import type * as protocol from "@/schemas/client-protocol/mod";
22
+ import { logger } from "./log";
23
+
24
+ /**
25
+ * Creates a client driver used for testing the inline client driver. This will send a request to the HTTP server which will then internally call the internal client and return the response.
26
+ */
27
+ export function createTestInlineClientDriver(
28
+ endpoint: string,
29
+ transport: Transport,
30
+ ): ClientDriver {
31
+ return {
32
+ action: async <Args extends Array<unknown> = unknown[], Response = unknown>(
33
+ _c: HonoContext | undefined,
34
+ actorQuery: ActorQuery,
35
+ encoding: Encoding,
36
+ params: unknown,
37
+ name: string,
38
+ args: Args,
39
+ ): Promise<Response> => {
40
+ return makeInlineRequest<Response>(
41
+ endpoint,
42
+ encoding,
43
+ transport,
44
+ "action",
45
+ [undefined, actorQuery, encoding, params, name, args],
46
+ );
47
+ },
48
+
49
+ resolveActorId: async (
50
+ _c: HonoContext | undefined,
51
+ actorQuery: ActorQuery,
52
+ encodingKind: Encoding,
53
+ params: unknown,
54
+ ): Promise<string> => {
55
+ return makeInlineRequest<string>(
56
+ endpoint,
57
+ encodingKind,
58
+ transport,
59
+ "resolveActorId",
60
+ [undefined, actorQuery, encodingKind, params],
61
+ );
62
+ },
63
+
64
+ connectWebSocket: async (
65
+ _c: HonoContext | undefined,
66
+ actorQuery: ActorQuery,
67
+ encodingKind: Encoding,
68
+ params: unknown,
69
+ ): Promise<WebSocket> => {
70
+ const WebSocket = await importWebSocket();
71
+
72
+ logger().debug("creating websocket connection via test inline driver", {
73
+ actorQuery,
74
+ encodingKind,
75
+ });
76
+
77
+ // Create WebSocket connection to the test endpoint
78
+ const wsUrl = new URL(
79
+ `${endpoint}/registry/.test/inline-driver/connect-websocket`,
80
+ );
81
+ wsUrl.searchParams.set("actorQuery", JSON.stringify(actorQuery));
82
+ if (params !== undefined)
83
+ wsUrl.searchParams.set("params", JSON.stringify(params));
84
+ wsUrl.searchParams.set("encodingKind", encodingKind);
85
+
86
+ // Convert http/https to ws/wss
87
+ const wsProtocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
88
+ const finalWsUrl = `${wsProtocol}//${wsUrl.host}${wsUrl.pathname}${wsUrl.search}`;
89
+
90
+ logger().debug("connecting to websocket", { url: finalWsUrl });
91
+
92
+ // Create and return the WebSocket
93
+ // Node & browser WebSocket types are incompatible
94
+ const ws = new WebSocket(finalWsUrl, [
95
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
96
+ "rivetkit",
97
+ ]) as any;
98
+
99
+ return ws;
100
+ },
101
+
102
+ connectSse: async (
103
+ _c: HonoContext | undefined,
104
+ actorQuery: ActorQuery,
105
+ encodingKind: Encoding,
106
+ params: unknown,
107
+ ): Promise<UniversalEventSource> => {
108
+ logger().debug("creating sse connection via test inline driver", {
109
+ actorQuery,
110
+ encodingKind,
111
+ params,
112
+ });
113
+
114
+ // Dynamically import EventSource if needed
115
+ const EventSourceImport = await import("eventsource");
116
+ // Handle both ES modules (default) and CommonJS export patterns
117
+ const EventSourceConstructor =
118
+ (EventSourceImport as any).default || EventSourceImport;
119
+
120
+ // Encode parameters for the URL
121
+ const actorQueryParam = encodeURIComponent(JSON.stringify(actorQuery));
122
+ const encodingParam = encodeURIComponent(encodingKind);
123
+ const paramsParam = params
124
+ ? encodeURIComponent(JSON.stringify(params))
125
+ : null;
126
+
127
+ // Create SSE connection URL
128
+ const sseUrl = new URL(
129
+ `${endpoint}/registry/.test/inline-driver/connect-sse`,
130
+ );
131
+ sseUrl.searchParams.set("actorQueryRaw", actorQueryParam);
132
+ sseUrl.searchParams.set("encodingKind", encodingParam);
133
+ if (paramsParam) {
134
+ sseUrl.searchParams.set("params", paramsParam);
135
+ }
136
+
137
+ logger().debug("connecting to sse", { url: sseUrl.toString() });
138
+
139
+ // Create and return the EventSource
140
+ const eventSource = new EventSourceConstructor(sseUrl.toString());
141
+
142
+ // Wait for the connection to be established before returning
143
+ await new Promise<void>((resolve, reject) => {
144
+ eventSource.onopen = () => {
145
+ logger().debug("sse connection established");
146
+ resolve();
147
+ };
148
+
149
+ eventSource.onerror = (event: Event) => {
150
+ logger().error("sse connection failed", { event });
151
+ reject(new Error("Failed to establish SSE connection"));
152
+ };
153
+
154
+ // Set a timeout in case the connection never establishes
155
+ setTimeout(() => {
156
+ if (eventSource.readyState !== EventSourceConstructor.OPEN) {
157
+ reject(new Error("SSE connection timed out"));
158
+ }
159
+ }, 10000); // 10 second timeout
160
+ });
161
+
162
+ return eventSource as UniversalEventSource;
163
+ },
164
+
165
+ sendHttpMessage: async (
166
+ _c: HonoContext | undefined,
167
+ actorId: string,
168
+ encoding: Encoding,
169
+ connectionId: string,
170
+ connectionToken: string,
171
+ message: protocol.ToServer,
172
+ ): Promise<void> => {
173
+ logger().debug("sending http message via test inline driver", {
174
+ actorId,
175
+ encoding,
176
+ connectionId,
177
+ transport,
178
+ });
179
+
180
+ const result = await fetch(
181
+ `${endpoint}/registry/.test/inline-driver/call`,
182
+ {
183
+ method: "POST",
184
+ headers: {
185
+ "Content-Type": "application/json",
186
+ },
187
+ body: JSON.stringify({
188
+ encoding,
189
+ transport,
190
+ method: "sendHttpMessage",
191
+ args: [
192
+ undefined,
193
+ actorId,
194
+ encoding,
195
+ connectionId,
196
+ connectionToken,
197
+ message,
198
+ ],
199
+ } satisfies TestInlineDriverCallRequest),
200
+ },
201
+ );
202
+
203
+ if (!result.ok) {
204
+ throw new Error(`Failed to send HTTP message: ${result.statusText}`);
205
+ }
206
+
207
+ // Discard response
208
+ await result.body?.cancel();
209
+ },
210
+
211
+ rawHttpRequest: async (
212
+ _c: HonoContext | undefined,
213
+ actorQuery: ActorQuery,
214
+ encoding: Encoding,
215
+ params: unknown,
216
+ path: string,
217
+ init: RequestInit,
218
+ ): Promise<Response> => {
219
+ // Normalize path to match other drivers
220
+ const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
221
+
222
+ logger().debug("sending raw http request via test inline driver", {
223
+ actorQuery,
224
+ encoding,
225
+ path: normalizedPath,
226
+ });
227
+
228
+ // Use the dedicated raw HTTP endpoint
229
+ const url = `${endpoint}/registry/.test/inline-driver/raw-http/${normalizedPath}`;
230
+
231
+ logger().debug("rewriting http url", {
232
+ from: path,
233
+ to: url,
234
+ });
235
+
236
+ // Merge headers with our metadata
237
+ const headers = new Headers(init.headers);
238
+ headers.set(HEADER_ACTOR_QUERY, JSON.stringify(actorQuery));
239
+ headers.set(HEADER_ENCODING, encoding);
240
+ if (params !== undefined) {
241
+ headers.set(HEADER_CONN_PARAMS, JSON.stringify(params));
242
+ }
243
+
244
+ // Forward the request directly
245
+ const response = await fetch(url, {
246
+ ...init,
247
+ headers,
248
+ });
249
+
250
+ // Check if it's an error response from our handler
251
+ if (
252
+ !response.ok &&
253
+ response.headers.get("content-type")?.includes("application/json")
254
+ ) {
255
+ try {
256
+ // Clone the response to avoid consuming the body
257
+ const clonedResponse = response.clone();
258
+ const errorData = (await clonedResponse.json()) as any;
259
+ if (errorData.error) {
260
+ // Handle both error formats:
261
+ // 1. { error: { code, message, metadata } } - structured format
262
+ // 2. { error: "message" } - simple string format (from custom onFetch handlers)
263
+ if (typeof errorData.error === "object") {
264
+ throw new ClientActorError(
265
+ errorData.error.code,
266
+ errorData.error.message,
267
+ errorData.error.metadata,
268
+ );
269
+ }
270
+ // For simple string errors, just return the response as-is
271
+ // This allows custom onFetch handlers to return their own error formats
272
+ }
273
+ } catch (e) {
274
+ // If it's not our error format, just return the response as-is
275
+ if (!(e instanceof ClientActorError)) {
276
+ return response;
277
+ }
278
+ throw e;
279
+ }
280
+ }
281
+
282
+ return response;
283
+ },
284
+
285
+ rawWebSocket: async (
286
+ _c: HonoContext | undefined,
287
+ actorQuery: ActorQuery,
288
+ encoding: Encoding,
289
+ params: unknown,
290
+ path: string,
291
+ protocols: string | string[] | undefined,
292
+ ): Promise<WebSocket> => {
293
+ logger().debug("test inline driver rawWebSocket called");
294
+ const WebSocket = await importWebSocket();
295
+
296
+ // Normalize path to match other drivers
297
+ const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
298
+
299
+ logger().debug(
300
+ "creating raw websocket connection via test inline driver",
301
+ {
302
+ actorQuery,
303
+ encoding,
304
+ path: normalizedPath,
305
+ protocols,
306
+ },
307
+ );
308
+
309
+ // Create WebSocket connection to the test endpoint
310
+ const wsUrl = new URL(
311
+ `${endpoint}/registry/.test/inline-driver/raw-websocket`,
312
+ );
313
+ wsUrl.searchParams.set("actorQuery", JSON.stringify(actorQuery));
314
+ if (params !== undefined)
315
+ wsUrl.searchParams.set("params", JSON.stringify(params));
316
+ wsUrl.searchParams.set("encodingKind", encoding);
317
+ wsUrl.searchParams.set("path", normalizedPath);
318
+ if (protocols !== undefined)
319
+ wsUrl.searchParams.set("protocols", JSON.stringify(protocols));
320
+
321
+ // Convert http/https to ws/wss
322
+ const wsProtocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
323
+ const finalWsUrl = `${wsProtocol}//${wsUrl.host}${wsUrl.pathname}${wsUrl.search}`;
324
+
325
+ logger().debug("connecting to raw websocket", { url: finalWsUrl });
326
+
327
+ logger().debug("rewriting websocket url", {
328
+ from: path,
329
+ to: finalWsUrl,
330
+ });
331
+
332
+ // Create and return the WebSocket
333
+ // Node & browser WebSocket types are incompatible
334
+ const ws = new WebSocket(finalWsUrl, [
335
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
336
+ "rivetkit",
337
+ ]) as any;
338
+
339
+ logger().debug("test inline driver created websocket", {
340
+ readyState: ws.readyState,
341
+ url: ws.url,
342
+ });
343
+
344
+ return ws;
345
+ },
346
+ };
347
+ }
348
+
349
+ async function makeInlineRequest<T>(
350
+ endpoint: string,
351
+ encoding: Encoding,
352
+ transport: Transport,
353
+ method: string,
354
+ args: unknown[],
355
+ ): Promise<T> {
356
+ logger().debug("sending inline request", {
357
+ encoding,
358
+ transport,
359
+ method,
360
+ args,
361
+ });
362
+
363
+ // Call driver
364
+ const response = await fetch(
365
+ `${endpoint}/registry/.test/inline-driver/call`,
366
+ {
367
+ method: "POST",
368
+ headers: {
369
+ "Content-Type": "application/json",
370
+ },
371
+ body: cbor.encode({
372
+ encoding,
373
+ transport,
374
+ method,
375
+ args,
376
+ } satisfies TestInlineDriverCallRequest),
377
+ },
378
+ );
379
+
380
+ if (!response.ok) {
381
+ throw new Error(`Failed to call inline ${method}: ${response.statusText}`);
382
+ }
383
+
384
+ // Parse response
385
+ const buffer = await response.arrayBuffer();
386
+ const callResponse: TestInlineDriverCallResponse<T> = cbor.decode(
387
+ new Uint8Array(buffer),
388
+ );
389
+
390
+ // Throw or OK
391
+ if ("ok" in callResponse) {
392
+ return callResponse.ok;
393
+ } else if ("err" in callResponse) {
394
+ throw new ClientActorError(
395
+ callResponse.err.code,
396
+ callResponse.err.message,
397
+ callResponse.err.metadata,
398
+ );
399
+ } else {
400
+ assertUnreachable(callResponse);
401
+ }
402
+ }
@@ -0,0 +1,136 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import type { ActorError } from "@/client/errors";
3
+ import type { DriverTestConfig } from "../mod";
4
+ import { setupDriverTest } from "../utils";
5
+
6
+ export function runActionFeaturesTests(driverTestConfig: DriverTestConfig) {
7
+ describe("Action Features", () => {
8
+ // TODO: These do not work with fake timers
9
+ describe("Action Timeouts", () => {
10
+ const usesFakeTimers = !driverTestConfig.useRealTimers;
11
+
12
+ test("should timeout actions that exceed the configured timeout", async (c) => {
13
+ const { client } = await setupDriverTest(c, driverTestConfig);
14
+
15
+ // The quick action should complete successfully
16
+ const quickResult = await client.shortTimeoutActor
17
+ .getOrCreate()
18
+ .quickAction();
19
+ expect(quickResult).toBe("quick response");
20
+
21
+ // The slow action should throw a timeout error
22
+ await expect(
23
+ client.shortTimeoutActor.getOrCreate().slowAction(),
24
+ ).rejects.toThrow("Action timed out");
25
+ });
26
+
27
+ test("should respect the default timeout", async (c) => {
28
+ const { client } = await setupDriverTest(c, driverTestConfig);
29
+
30
+ // This action should complete within the default timeout
31
+ const result = await client.defaultTimeoutActor
32
+ .getOrCreate()
33
+ .normalAction();
34
+ expect(result).toBe("normal response");
35
+ });
36
+
37
+ test("non-promise action results should not be affected by timeout", async (c) => {
38
+ const { client } = await setupDriverTest(c, driverTestConfig);
39
+
40
+ // Synchronous action should not be affected by timeout
41
+ const result = await client.syncTimeoutActor.getOrCreate().syncAction();
42
+ expect(result).toBe("sync response");
43
+ });
44
+
45
+ test("should allow configuring different timeouts for different actors", async (c) => {
46
+ const { client } = await setupDriverTest(c, driverTestConfig);
47
+
48
+ // The short timeout actor should fail
49
+ await expect(
50
+ client.shortTimeoutActor.getOrCreate().slowAction(),
51
+ ).rejects.toThrow("Action timed out");
52
+
53
+ // The longer timeout actor should succeed
54
+ const result = await client.longTimeoutActor
55
+ .getOrCreate()
56
+ .delayedAction();
57
+ expect(result).toBe("delayed response");
58
+ });
59
+ });
60
+
61
+ describe("Action Sync & Async", () => {
62
+ test("should support synchronous actions", async (c) => {
63
+ const { client } = await setupDriverTest(c, driverTestConfig);
64
+
65
+ const instance = client.syncActionActor.getOrCreate();
66
+
67
+ // Test increment action
68
+ let result = await instance.increment(5);
69
+ expect(result).toBe(5);
70
+
71
+ result = await instance.increment(3);
72
+ expect(result).toBe(8);
73
+
74
+ // Test getInfo action
75
+ const info = await instance.getInfo();
76
+ expect(info.currentValue).toBe(8);
77
+ expect(typeof info.timestamp).toBe("number");
78
+
79
+ // Test reset action (void return)
80
+ await instance.reset();
81
+ result = await instance.increment(0);
82
+ expect(result).toBe(0);
83
+ });
84
+
85
+ test("should support asynchronous actions", async (c) => {
86
+ const { client } = await setupDriverTest(c, driverTestConfig);
87
+
88
+ const instance = client.asyncActionActor.getOrCreate();
89
+
90
+ // Test delayed increment
91
+ const result = await instance.delayedIncrement(5);
92
+ expect(result).toBe(5);
93
+
94
+ // Test fetch data
95
+ const data = await instance.fetchData("test-123");
96
+ expect(data.id).toBe("test-123");
97
+ expect(typeof data.timestamp).toBe("number");
98
+
99
+ // Test successful async operation
100
+ const success = await instance.asyncWithError(false);
101
+ expect(success).toBe("Success");
102
+
103
+ // Test error in async operation
104
+ try {
105
+ await instance.asyncWithError(true);
106
+ expect.fail("did not error");
107
+ } catch (error) {
108
+ expect((error as ActorError).message).toBe("Intentional error");
109
+ }
110
+ });
111
+
112
+ test("should handle promises returned from actions correctly", async (c) => {
113
+ const { client } = await setupDriverTest(c, driverTestConfig);
114
+
115
+ const instance = client.promiseActor.getOrCreate();
116
+
117
+ // Test resolved promise
118
+ const resolvedValue = await instance.resolvedPromise();
119
+ expect(resolvedValue).toBe("resolved value");
120
+
121
+ // Test delayed promise
122
+ const delayedValue = await instance.delayedPromise();
123
+ expect(delayedValue).toBe("delayed value");
124
+
125
+ // Test rejected promise
126
+ await expect(instance.rejectedPromise()).rejects.toThrow(
127
+ "promised rejection",
128
+ );
129
+
130
+ // Check state was updated by the delayed promise
131
+ const results = await instance.getResults();
132
+ expect(results).toContain("delayed");
133
+ });
134
+ });
135
+ });
136
+ }