rivetkit 2.0.4 → 2.0.6

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 (140) hide show
  1. package/dist/tsup/actor/errors.cjs +2 -2
  2. package/dist/tsup/actor/errors.js +1 -1
  3. package/dist/tsup/actor-router-consts-BK6arfy8.d.cts +17 -0
  4. package/dist/tsup/actor-router-consts-BK6arfy8.d.ts +17 -0
  5. package/dist/tsup/chunk-2K3JMDAN.js +232 -0
  6. package/dist/tsup/chunk-2K3JMDAN.js.map +1 -0
  7. package/dist/tsup/chunk-42I3OZ3Q.js +15 -0
  8. package/dist/tsup/chunk-42I3OZ3Q.js.map +1 -0
  9. package/dist/tsup/{chunk-XJQHKJ4P.js → chunk-4CKHQRXG.js} +1650 -4147
  10. package/dist/tsup/chunk-4CKHQRXG.js.map +1 -0
  11. package/dist/tsup/{chunk-6LJT3QRL.cjs → chunk-5JBFVV4C.cjs} +37 -12
  12. package/dist/tsup/chunk-5JBFVV4C.cjs.map +1 -0
  13. package/dist/tsup/{chunk-SBHHJ6QS.cjs → chunk-5QGQK44L.cjs} +2 -2
  14. package/dist/tsup/{chunk-SBHHJ6QS.cjs.map → chunk-5QGQK44L.cjs.map} +1 -1
  15. package/dist/tsup/{chunk-IH6CKNDW.cjs → chunk-6P6RA47N.cjs} +9 -9
  16. package/dist/tsup/{chunk-IH6CKNDW.cjs.map → chunk-6P6RA47N.cjs.map} +1 -1
  17. package/dist/tsup/chunk-7OUKNSTU.js +1043 -0
  18. package/dist/tsup/chunk-7OUKNSTU.js.map +1 -0
  19. package/dist/tsup/{chunk-LWNKVZG5.cjs → chunk-DIAYNQTE.cjs} +13 -25
  20. package/dist/tsup/chunk-DIAYNQTE.cjs.map +1 -0
  21. package/dist/tsup/{chunk-3F2YSRJL.js → chunk-G75SVQON.js} +4 -4
  22. package/dist/tsup/{chunk-QNNXFOQV.cjs → chunk-KG3C7MKR.cjs} +3 -3
  23. package/dist/tsup/{chunk-QNNXFOQV.cjs.map → chunk-KG3C7MKR.cjs.map} +1 -1
  24. package/dist/tsup/chunk-KUPQZYUQ.cjs +15 -0
  25. package/dist/tsup/chunk-KUPQZYUQ.cjs.map +1 -0
  26. package/dist/tsup/{chunk-4CXBCT26.cjs → chunk-MRRT2CZD.cjs} +7 -7
  27. package/dist/tsup/{chunk-4CXBCT26.cjs.map → chunk-MRRT2CZD.cjs.map} +1 -1
  28. package/dist/tsup/chunk-NTCUGYSD.cjs +1043 -0
  29. package/dist/tsup/chunk-NTCUGYSD.cjs.map +1 -0
  30. package/dist/tsup/{chunk-PQY7KKTL.js → chunk-RGQR2J7S.js} +32 -7
  31. package/dist/tsup/{chunk-PQY7KKTL.js.map → chunk-RGQR2J7S.js.map} +1 -1
  32. package/dist/tsup/chunk-TCUI5JFE.cjs +232 -0
  33. package/dist/tsup/chunk-TCUI5JFE.cjs.map +1 -0
  34. package/dist/tsup/chunk-TWGATZ3X.cjs +3676 -0
  35. package/dist/tsup/chunk-TWGATZ3X.cjs.map +1 -0
  36. package/dist/tsup/chunk-UFWAK3X2.cjs +3796 -0
  37. package/dist/tsup/chunk-UFWAK3X2.cjs.map +1 -0
  38. package/dist/tsup/chunk-UTI5NCES.cjs +20 -0
  39. package/dist/tsup/{chunk-4R73YDN3.cjs.map → chunk-UTI5NCES.cjs.map} +1 -1
  40. package/dist/tsup/{chunk-QK72M5JB.js → chunk-VCEHU56K.js} +2 -2
  41. package/dist/tsup/{chunk-HI3HWJRC.js → chunk-VPV4MWXR.js} +4 -4
  42. package/dist/tsup/{chunk-HI3HWJRC.js.map → chunk-VPV4MWXR.js.map} +1 -1
  43. package/dist/tsup/chunk-W6LN7AF5.js +3676 -0
  44. package/dist/tsup/chunk-W6LN7AF5.js.map +1 -0
  45. package/dist/tsup/{chunk-LV2S3OU3.js → chunk-WC2PSJWN.js} +2 -2
  46. package/dist/tsup/{chunk-NFU2BBT5.js → chunk-YPZFLUO6.js} +2 -2
  47. package/dist/tsup/chunk-YPZFLUO6.js.map +1 -0
  48. package/dist/tsup/{chunk-H26RP6GD.js → chunk-ZYLTS2EM.js} +3 -15
  49. package/dist/tsup/chunk-ZYLTS2EM.js.map +1 -0
  50. package/dist/tsup/client/mod.cjs +10 -10
  51. package/dist/tsup/client/mod.d.cts +2 -2
  52. package/dist/tsup/client/mod.d.ts +2 -2
  53. package/dist/tsup/client/mod.js +9 -9
  54. package/dist/tsup/common/log.cjs +4 -4
  55. package/dist/tsup/common/log.js +3 -3
  56. package/dist/tsup/common/websocket.cjs +5 -5
  57. package/dist/tsup/common/websocket.js +4 -4
  58. package/dist/tsup/{connection-BI-6UIBJ.d.ts → connection-BLemxi4f.d.ts} +23 -12
  59. package/dist/tsup/{connection-Dyd4NLGW.d.cts → connection-CpDIydXf.d.cts} +23 -12
  60. package/dist/tsup/driver-helpers/mod.cjs +6 -6
  61. package/dist/tsup/driver-helpers/mod.d.cts +2 -2
  62. package/dist/tsup/driver-helpers/mod.d.ts +2 -2
  63. package/dist/tsup/driver-helpers/mod.js +5 -5
  64. package/dist/tsup/driver-test-suite/mod.cjs +614 -140
  65. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -1
  66. package/dist/tsup/driver-test-suite/mod.d.cts +2 -2
  67. package/dist/tsup/driver-test-suite/mod.d.ts +2 -2
  68. package/dist/tsup/driver-test-suite/mod.js +575 -101
  69. package/dist/tsup/driver-test-suite/mod.js.map +1 -1
  70. package/dist/tsup/inspector/mod.cjs +8 -6
  71. package/dist/tsup/inspector/mod.cjs.map +1 -1
  72. package/dist/tsup/inspector/mod.js +10 -8
  73. package/dist/tsup/mod.cjs +12 -9
  74. package/dist/tsup/mod.cjs.map +1 -1
  75. package/dist/tsup/mod.d.cts +52 -7
  76. package/dist/tsup/mod.d.ts +52 -7
  77. package/dist/tsup/mod.js +18 -15
  78. package/dist/tsup/test/mod.cjs +12 -10
  79. package/dist/tsup/test/mod.cjs.map +1 -1
  80. package/dist/tsup/test/mod.d.cts +1 -1
  81. package/dist/tsup/test/mod.d.ts +1 -1
  82. package/dist/tsup/test/mod.js +11 -9
  83. package/dist/tsup/utils.cjs +5 -3
  84. package/dist/tsup/utils.cjs.map +1 -1
  85. package/dist/tsup/utils.d.cts +18 -1
  86. package/dist/tsup/utils.d.ts +18 -1
  87. package/dist/tsup/utils.js +4 -2
  88. package/package.json +4 -4
  89. package/src/actor/errors.ts +1 -1
  90. package/src/actor/mod.ts +5 -3
  91. package/src/actor/router-endpoints.ts +11 -33
  92. package/src/actor/router.ts +11 -9
  93. package/src/client/actor-conn.ts +9 -8
  94. package/src/client/actor-handle.ts +0 -1
  95. package/src/client/client.ts +1 -1
  96. package/src/client/mod.ts +1 -1
  97. package/src/client/raw-utils.ts +2 -2
  98. package/src/client/utils.ts +1 -1
  99. package/src/common/actor-router-consts.ts +38 -0
  100. package/src/driver-helpers/mod.ts +1 -1
  101. package/src/driver-test-suite/mod.ts +1 -1
  102. package/src/driver-test-suite/test-inline-client-driver.ts +588 -0
  103. package/src/driver-test-suite/tests/actor-error-handling.ts +4 -12
  104. package/src/driver-test-suite/tests/actor-inspector.ts +2 -1
  105. package/src/driver-test-suite/utils.ts +16 -10
  106. package/src/drivers/engine/actor-driver.ts +18 -17
  107. package/src/drivers/file-system/global-state.ts +3 -1
  108. package/src/drivers/file-system/manager.ts +16 -21
  109. package/src/manager/driver.ts +1 -1
  110. package/src/manager/protocol/query.ts +1 -1
  111. package/src/manager/router.ts +373 -5
  112. package/src/registry/mod.ts +36 -35
  113. package/src/registry/run-config.ts +16 -1
  114. package/src/registry/serve.ts +8 -3
  115. package/src/remote-manager-driver/actor-http-client.ts +3 -1
  116. package/src/remote-manager-driver/actor-websocket-client.ts +4 -3
  117. package/src/remote-manager-driver/api-utils.ts +4 -1
  118. package/src/remote-manager-driver/mod.ts +4 -6
  119. package/src/utils.ts +53 -0
  120. package/dist/tsup/chunk-4R73YDN3.cjs +0 -20
  121. package/dist/tsup/chunk-6LJT3QRL.cjs.map +0 -1
  122. package/dist/tsup/chunk-GICQ3YCU.cjs +0 -1792
  123. package/dist/tsup/chunk-GICQ3YCU.cjs.map +0 -1
  124. package/dist/tsup/chunk-H26RP6GD.js.map +0 -1
  125. package/dist/tsup/chunk-HLLF4B4Q.js +0 -1792
  126. package/dist/tsup/chunk-HLLF4B4Q.js.map +0 -1
  127. package/dist/tsup/chunk-LWNKVZG5.cjs.map +0 -1
  128. package/dist/tsup/chunk-NFU2BBT5.js.map +0 -1
  129. package/dist/tsup/chunk-TQ62L3X7.js +0 -325
  130. package/dist/tsup/chunk-TQ62L3X7.js.map +0 -1
  131. package/dist/tsup/chunk-VO7ZRVVD.cjs +0 -6293
  132. package/dist/tsup/chunk-VO7ZRVVD.cjs.map +0 -1
  133. package/dist/tsup/chunk-WHBPJNGW.cjs +0 -325
  134. package/dist/tsup/chunk-WHBPJNGW.cjs.map +0 -1
  135. package/dist/tsup/chunk-XJQHKJ4P.js.map +0 -1
  136. package/dist/tsup/router-endpoints-BTe_Rsdn.d.cts +0 -65
  137. package/dist/tsup/router-endpoints-CBSrKHmo.d.ts +0 -65
  138. /package/dist/tsup/{chunk-3F2YSRJL.js.map → chunk-G75SVQON.js.map} +0 -0
  139. /package/dist/tsup/{chunk-QK72M5JB.js.map → chunk-VCEHU56K.js.map} +0 -0
  140. /package/dist/tsup/{chunk-LV2S3OU3.js.map → chunk-WC2PSJWN.js.map} +0 -0
@@ -0,0 +1,588 @@
1
+ import * as cbor from "cbor-x";
2
+ import type { Context as HonoContext } from "hono";
3
+ import invariant from "invariant";
4
+ import type { WebSocket } from "ws";
5
+ import type { Encoding } from "@/actor/protocol/serde";
6
+ import { assertUnreachable } from "@/actor/utils";
7
+ import { ActorError as ClientActorError } from "@/client/errors";
8
+ import type { Transport } from "@/client/mod";
9
+ import {
10
+ HEADER_ACTOR_QUERY,
11
+ HEADER_CONN_PARAMS,
12
+ HEADER_ENCODING,
13
+ } from "@/common/actor-router-consts";
14
+ import type { UniversalEventSource } from "@/common/eventsource-interface";
15
+ import type { DeconstructedError } from "@/common/utils";
16
+ import { importWebSocket } from "@/common/websocket";
17
+ import {
18
+ type ActorOutput,
19
+ type CreateInput,
20
+ type GetForIdInput,
21
+ type GetOrCreateWithKeyInput,
22
+ type GetWithKeyInput,
23
+ HEADER_ACTOR_ID,
24
+ type ManagerDisplayInformation,
25
+ type ManagerDriver,
26
+ } from "@/driver-helpers/mod";
27
+ import type { ActorQuery } from "@/manager/protocol/query";
28
+ import type { UniversalWebSocket } from "@/mod";
29
+ import type * as protocol from "@/schemas/client-protocol/mod";
30
+ import { logger } from "./log";
31
+
32
+ export interface TestInlineDriverCallRequest {
33
+ encoding: Encoding;
34
+ transport: Transport;
35
+ method: string;
36
+ args: unknown[];
37
+ }
38
+
39
+ export type TestInlineDriverCallResponse<T> =
40
+ | {
41
+ ok: T;
42
+ }
43
+ | {
44
+ err: DeconstructedError;
45
+ };
46
+
47
+ /**
48
+ * 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.
49
+ */
50
+ export function createTestInlineClientDriver(
51
+ endpoint: string,
52
+ encoding: Encoding,
53
+ transport: Transport,
54
+ ): ManagerDriver {
55
+ return {
56
+ getForId(input: GetForIdInput): Promise<ActorOutput | undefined> {
57
+ return makeInlineRequest(endpoint, encoding, transport, "getForId", [
58
+ input,
59
+ ]);
60
+ },
61
+ getWithKey(input: GetWithKeyInput): Promise<ActorOutput | undefined> {
62
+ return makeInlineRequest(endpoint, encoding, transport, "getWithKey", [
63
+ input,
64
+ ]);
65
+ },
66
+ getOrCreateWithKey(input: GetOrCreateWithKeyInput): Promise<ActorOutput> {
67
+ return makeInlineRequest(
68
+ endpoint,
69
+ encoding,
70
+ transport,
71
+ "getOrCreateWithKey",
72
+ [input],
73
+ );
74
+ },
75
+ createActor(input: CreateInput): Promise<ActorOutput> {
76
+ return makeInlineRequest(endpoint, encoding, transport, "createActor", [
77
+ input,
78
+ ]);
79
+ },
80
+ async sendRequest(
81
+ actorId: string,
82
+ actorRequest: Request,
83
+ ): Promise<Response> {
84
+ // Normalize path to match other drivers
85
+ const oldUrl = new URL(actorRequest.url);
86
+ const normalizedPath = oldUrl.pathname.startsWith("/")
87
+ ? oldUrl.pathname.slice(1)
88
+ : oldUrl.pathname;
89
+ const pathWithQuery = normalizedPath + oldUrl.search;
90
+
91
+ logger().debug({
92
+ msg: "sending raw http request via test inline driver",
93
+ actorId,
94
+ encoding,
95
+ path: pathWithQuery,
96
+ });
97
+
98
+ // Use the dedicated raw HTTP endpoint
99
+ const url = `${endpoint}/.test/inline-driver/send-request/${pathWithQuery}`;
100
+
101
+ logger().debug({ msg: "rewriting http url", from: oldUrl, to: url });
102
+
103
+ // Merge headers with our metadata
104
+ const headers = new Headers(actorRequest.headers);
105
+ headers.set(HEADER_ACTOR_ID, actorId);
106
+
107
+ // Forward the request directly
108
+ const response = await fetch(
109
+ new Request(url, {
110
+ method: actorRequest.method,
111
+ headers,
112
+ body: actorRequest.body,
113
+ signal: actorRequest.signal,
114
+ }),
115
+ );
116
+
117
+ // Check if it's an error response from our handler
118
+ if (
119
+ !response.ok &&
120
+ response.headers.get("content-type")?.includes("application/json")
121
+ ) {
122
+ try {
123
+ // Clone the response to avoid consuming the body
124
+ const clonedResponse = response.clone();
125
+ const errorData = (await clonedResponse.json()) as any;
126
+ if (errorData.error) {
127
+ // Handle both error formats:
128
+ // 1. { error: { code, message, metadata } } - structured format
129
+ // 2. { error: "message" } - simple string format (from custom onFetch handlers)
130
+ if (typeof errorData.error === "object") {
131
+ throw new ClientActorError(
132
+ errorData.error.code,
133
+ errorData.error.message,
134
+ errorData.error.metadata,
135
+ );
136
+ }
137
+ // For simple string errors, just return the response as-is
138
+ // This allows custom onFetch handlers to return their own error formats
139
+ }
140
+ } catch (e) {
141
+ // If it's not our error format, just return the response as-is
142
+ if (!(e instanceof ClientActorError)) {
143
+ return response;
144
+ }
145
+ throw e;
146
+ }
147
+ }
148
+
149
+ return response;
150
+ },
151
+ async openWebSocket(
152
+ path: string,
153
+ actorId: string,
154
+ encoding: Encoding,
155
+ params: unknown,
156
+ ): Promise<UniversalWebSocket> {
157
+ const WebSocket = await importWebSocket();
158
+
159
+ // Normalize path to match other drivers
160
+ const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
161
+
162
+ logger().debug({
163
+ msg: "creating websocket connection via test inline driver",
164
+ });
165
+
166
+ // Create WebSocket connection to the test endpoint
167
+ // Use a placeholder path and pass the actual path as a query param to avoid mixing user query params with internal ones
168
+ const wsUrl = new URL(
169
+ `${endpoint}/.test/inline-driver/connect-websocket/ws`,
170
+ );
171
+ wsUrl.searchParams.set("path", normalizedPath);
172
+ wsUrl.searchParams.set("actorId", actorId);
173
+ if (params !== undefined)
174
+ wsUrl.searchParams.set("params", JSON.stringify(params));
175
+ wsUrl.searchParams.set("encodingKind", encoding);
176
+
177
+ // Convert http/https to ws/wss
178
+ const wsProtocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
179
+ const finalWsUrl = `${wsProtocol}//${wsUrl.host}${wsUrl.pathname}${wsUrl.search}`;
180
+
181
+ logger().debug({ msg: "connecting to websocket", url: finalWsUrl });
182
+
183
+ // Create and return the WebSocket
184
+ // Node & browser WebSocket types are incompatible
185
+ const ws = new WebSocket(finalWsUrl, [
186
+ // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
187
+ "rivetkit",
188
+ ]) as any;
189
+
190
+ return ws;
191
+ },
192
+ async proxyRequest(
193
+ c: HonoContext,
194
+ actorRequest: Request,
195
+ actorId: string,
196
+ ): Promise<Response> {
197
+ return await this.sendRequest(actorId, actorRequest);
198
+ },
199
+ proxyWebSocket(
200
+ _c: HonoContext,
201
+ _path: string,
202
+ _actorId: string,
203
+ _encoding: Encoding,
204
+ _params: unknown,
205
+ _authData: unknown,
206
+ ): Promise<Response> {
207
+ throw "UNIMPLEMENTED";
208
+ // const upgradeWebSocket = this.#runConfig.getUpgradeWebSocket?.();
209
+ // invariant(upgradeWebSocket, "missing getUpgradeWebSocket");
210
+ //
211
+ // const wsHandler = this.openWebSocket(path, actorId, encoding, connParams);
212
+ // return upgradeWebSocket(() => wsHandler)(c, noopNext());
213
+ },
214
+ displayInformation(): ManagerDisplayInformation {
215
+ return { name: "Test Inline", properties: {} };
216
+ },
217
+
218
+ // action: async <Args extends Array<unknown> = unknown[], Response = unknown>(
219
+ // _c: HonoContext | undefined,
220
+ // actorQuery: ActorQuery,
221
+ // encoding: Encoding,
222
+ // params: unknown,
223
+ // name: string,
224
+ // args: Args,
225
+ // ): Promise<Response> => {
226
+ // return makeInlineRequest<Response>(
227
+ // endpoint,
228
+ // encoding,
229
+ // transport,
230
+ // "action",
231
+ // [undefined, actorQuery, encoding, params, name, args],
232
+ // );
233
+ // },
234
+ //
235
+ // resolveActorId: async (
236
+ // _c: HonoContext | undefined,
237
+ // actorQuery: ActorQuery,
238
+ // encodingKind: Encoding,
239
+ // params: unknown,
240
+ // ): Promise<string> => {
241
+ // return makeInlineRequest<string>(
242
+ // endpoint,
243
+ // encodingKind,
244
+ // transport,
245
+ // "resolveActorId",
246
+ // [undefined, actorQuery, encodingKind, params],
247
+ // );
248
+ // },
249
+ //
250
+ // connectWebSocket: async (
251
+ // _c: HonoContext | undefined,
252
+ // actorQuery: ActorQuery,
253
+ // encodingKind: Encoding,
254
+ // params: unknown,
255
+ // ): Promise<WebSocket> => {
256
+ // const WebSocket = await importWebSocket();
257
+ //
258
+ // logger().debug({
259
+ // msg: "creating websocket connection via test inline driver",
260
+ // actorQuery,
261
+ // encodingKind,
262
+ // });
263
+ //
264
+ // // Create WebSocket connection to the test endpoint
265
+ // const wsUrl = new URL(
266
+ // `${endpoint}/registry/.test/inline-driver/connect-websocket`,
267
+ // );
268
+ // wsUrl.searchParams.set("actorQuery", JSON.stringify(actorQuery));
269
+ // if (params !== undefined)
270
+ // wsUrl.searchParams.set("params", JSON.stringify(params));
271
+ // wsUrl.searchParams.set("encodingKind", encodingKind);
272
+ //
273
+ // // Convert http/https to ws/wss
274
+ // const wsProtocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
275
+ // const finalWsUrl = `${wsProtocol}//${wsUrl.host}${wsUrl.pathname}${wsUrl.search}`;
276
+ //
277
+ // logger().debug({ msg: "connecting to websocket", url: finalWsUrl });
278
+ //
279
+ // // Create and return the WebSocket
280
+ // // Node & browser WebSocket types are incompatible
281
+ // const ws = new WebSocket(finalWsUrl, [
282
+ // // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
283
+ // "rivetkit",
284
+ // ]) as any;
285
+ //
286
+ // return ws;
287
+ // },
288
+ //
289
+ // connectSse: async (
290
+ // _c: HonoContext | undefined,
291
+ // actorQuery: ActorQuery,
292
+ // encodingKind: Encoding,
293
+ // params: unknown,
294
+ // ): Promise<UniversalEventSource> => {
295
+ // logger().debug({
296
+ // msg: "creating sse connection via test inline driver",
297
+ // actorQuery,
298
+ // encodingKind,
299
+ // params,
300
+ // });
301
+ //
302
+ // // Dynamically import EventSource if needed
303
+ // const EventSourceImport = await import("eventsource");
304
+ // // Handle both ES modules (default) and CommonJS export patterns
305
+ // const EventSourceConstructor =
306
+ // (EventSourceImport as any).default || EventSourceImport;
307
+ //
308
+ // // Encode parameters for the URL
309
+ // const actorQueryParam = encodeURIComponent(JSON.stringify(actorQuery));
310
+ // const encodingParam = encodeURIComponent(encodingKind);
311
+ // const paramsParam = params
312
+ // ? encodeURIComponent(JSON.stringify(params))
313
+ // : null;
314
+ //
315
+ // // Create SSE connection URL
316
+ // const sseUrl = new URL(
317
+ // `${endpoint}/registry/.test/inline-driver/connect-sse`,
318
+ // );
319
+ // sseUrl.searchParams.set("actorQueryRaw", actorQueryParam);
320
+ // sseUrl.searchParams.set("encodingKind", encodingParam);
321
+ // if (paramsParam) {
322
+ // sseUrl.searchParams.set("params", paramsParam);
323
+ // }
324
+ //
325
+ // logger().debug({ msg: "connecting to sse", url: sseUrl.toString() });
326
+ //
327
+ // // Create and return the EventSource
328
+ // const eventSource = new EventSourceConstructor(sseUrl.toString());
329
+ //
330
+ // // Wait for the connection to be established before returning
331
+ // await new Promise<void>((resolve, reject) => {
332
+ // eventSource.onopen = () => {
333
+ // logger().debug({ msg: "sse connection established" });
334
+ // resolve();
335
+ // };
336
+ //
337
+ // eventSource.onerror = (event: Event) => {
338
+ // logger().error({ msg: "sse connection failed", event });
339
+ // reject(new Error("Failed to establish SSE connection"));
340
+ // };
341
+ //
342
+ // // Set a timeout in case the connection never establishes
343
+ // setTimeout(() => {
344
+ // if (eventSource.readyState !== EventSourceConstructor.OPEN) {
345
+ // reject(new Error("SSE connection timed out"));
346
+ // }
347
+ // }, 10000); // 10 second timeout
348
+ // });
349
+ //
350
+ // return eventSource as UniversalEventSource;
351
+ // },
352
+ //
353
+ // sendHttpMessage: async (
354
+ // _c: HonoContext | undefined,
355
+ // actorId: string,
356
+ // encoding: Encoding,
357
+ // connectionId: string,
358
+ // connectionToken: string,
359
+ // message: protocol.ToServer,
360
+ // ): Promise<void> => {
361
+ // logger().debug({
362
+ // msg: "sending http message via test inline driver",
363
+ // actorId,
364
+ // encoding,
365
+ // connectionId,
366
+ // transport,
367
+ // });
368
+ //
369
+ // const result = await fetch(
370
+ // `${endpoint}/registry/.test/inline-driver/call`,
371
+ // {
372
+ // method: "POST",
373
+ // headers: {
374
+ // "Content-Type": "application/json",
375
+ // },
376
+ // body: JSON.stringify({
377
+ // encoding,
378
+ // transport,
379
+ // method: "sendHttpMessage",
380
+ // args: [
381
+ // undefined,
382
+ // actorId,
383
+ // encoding,
384
+ // connectionId,
385
+ // connectionToken,
386
+ // message,
387
+ // ],
388
+ // } satisfies TestInlineDriverCallRequest),
389
+ // },
390
+ // );
391
+ //
392
+ // if (!result.ok) {
393
+ // throw new Error(`Failed to send HTTP message: ${result.statusText}`);
394
+ // }
395
+ //
396
+ // // Discard response
397
+ // await result.body?.cancel();
398
+ // },
399
+ //
400
+ // rawHttpRequest: async (
401
+ // _c: HonoContext | undefined,
402
+ // actorQuery: ActorQuery,
403
+ // encoding: Encoding,
404
+ // params: unknown,
405
+ // path: string,
406
+ // init: RequestInit,
407
+ // ): Promise<Response> => {
408
+ // // Normalize path to match other drivers
409
+ // const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
410
+ //
411
+ // logger().debug({
412
+ // msg: "sending raw http request via test inline driver",
413
+ // actorQuery,
414
+ // encoding,
415
+ // path: normalizedPath,
416
+ // });
417
+ //
418
+ // // Use the dedicated raw HTTP endpoint
419
+ // const url = `${endpoint}/registry/.test/inline-driver/raw-http/${normalizedPath}`;
420
+ //
421
+ // logger().debug({ msg: "rewriting http url", from: path, to: url });
422
+ //
423
+ // // Merge headers with our metadata
424
+ // const headers = new Headers(init.headers);
425
+ // headers.set(HEADER_ACTOR_QUERY, JSON.stringify(actorQuery));
426
+ // headers.set(HEADER_ENCODING, encoding);
427
+ // if (params !== undefined) {
428
+ // headers.set(HEADER_CONN_PARAMS, JSON.stringify(params));
429
+ // }
430
+ //
431
+ // // Forward the request directly
432
+ // const response = await fetch(url, {
433
+ // ...init,
434
+ // headers,
435
+ // });
436
+ //
437
+ // // Check if it's an error response from our handler
438
+ // if (
439
+ // !response.ok &&
440
+ // response.headers.get("content-type")?.includes("application/json")
441
+ // ) {
442
+ // try {
443
+ // // Clone the response to avoid consuming the body
444
+ // const clonedResponse = response.clone();
445
+ // const errorData = (await clonedResponse.json()) as any;
446
+ // if (errorData.error) {
447
+ // // Handle both error formats:
448
+ // // 1. { error: { code, message, metadata } } - structured format
449
+ // // 2. { error: "message" } - simple string format (from custom onFetch handlers)
450
+ // if (typeof errorData.error === "object") {
451
+ // throw new ClientActorError(
452
+ // errorData.error.code,
453
+ // errorData.error.message,
454
+ // errorData.error.metadata,
455
+ // );
456
+ // }
457
+ // // For simple string errors, just return the response as-is
458
+ // // This allows custom onFetch handlers to return their own error formats
459
+ // }
460
+ // } catch (e) {
461
+ // // If it's not our error format, just return the response as-is
462
+ // if (!(e instanceof ClientActorError)) {
463
+ // return response;
464
+ // }
465
+ // throw e;
466
+ // }
467
+ // }
468
+ //
469
+ // return response;
470
+ // },
471
+ //
472
+ // rawWebSocket: async (
473
+ // _c: HonoContext | undefined,
474
+ // actorQuery: ActorQuery,
475
+ // encoding: Encoding,
476
+ // params: unknown,
477
+ // path: string,
478
+ // protocols: string | string[] | undefined,
479
+ // ): Promise<WebSocket> => {
480
+ // logger().debug({ msg: "test inline driver rawWebSocket called" });
481
+ // const WebSocket = await importWebSocket();
482
+ //
483
+ // // Normalize path to match other drivers
484
+ // const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
485
+ //
486
+ // logger().debug({
487
+ // msg: "creating raw websocket connection via test inline driver",
488
+ // actorQuery,
489
+ // encoding,
490
+ // path: normalizedPath,
491
+ // protocols,
492
+ // });
493
+ //
494
+ // // Create WebSocket connection to the test endpoint
495
+ // const wsUrl = new URL(
496
+ // `${endpoint}/registry/.test/inline-driver/raw-websocket`,
497
+ // );
498
+ // wsUrl.searchParams.set("actorQuery", JSON.stringify(actorQuery));
499
+ // if (params !== undefined)
500
+ // wsUrl.searchParams.set("params", JSON.stringify(params));
501
+ // wsUrl.searchParams.set("encodingKind", encoding);
502
+ // wsUrl.searchParams.set("path", normalizedPath);
503
+ // if (protocols !== undefined)
504
+ // wsUrl.searchParams.set("protocols", JSON.stringify(protocols));
505
+ //
506
+ // // Convert http/https to ws/wss
507
+ // const wsProtocol = wsUrl.protocol === "https:" ? "wss:" : "ws:";
508
+ // const finalWsUrl = `${wsProtocol}//${wsUrl.host}${wsUrl.pathname}${wsUrl.search}`;
509
+ //
510
+ // logger().debug({ msg: "connecting to raw websocket", url: finalWsUrl });
511
+ //
512
+ // logger().debug({
513
+ // msg: "rewriting websocket url",
514
+ // from: path,
515
+ // to: finalWsUrl,
516
+ // });
517
+ //
518
+ // // Create and return the WebSocket
519
+ // // Node & browser WebSocket types are incompatible
520
+ // const ws = new WebSocket(finalWsUrl, [
521
+ // // HACK: See packages/drivers/cloudflare-workers/src/websocket.ts
522
+ // "rivetkit",
523
+ // ]) as any;
524
+ //
525
+ // logger().debug({
526
+ // msg: "test inline driver created websocket",
527
+ // readyState: ws.readyState,
528
+ // url: ws.url,
529
+ // });
530
+ //
531
+ // return ws;
532
+ // },
533
+ } satisfies ManagerDriver;
534
+ }
535
+
536
+ async function makeInlineRequest<T>(
537
+ endpoint: string,
538
+ encoding: Encoding,
539
+ transport: Transport,
540
+ method: string,
541
+ args: unknown[],
542
+ ): Promise<T> {
543
+ logger().debug({
544
+ msg: "sending inline request",
545
+ encoding,
546
+ transport,
547
+ method,
548
+ args,
549
+ });
550
+
551
+ // Call driver
552
+ const response = await fetch(`${endpoint}/.test/inline-driver/call`, {
553
+ method: "POST",
554
+ headers: {
555
+ "Content-Type": "application/json",
556
+ },
557
+ body: cbor.encode({
558
+ encoding,
559
+ transport,
560
+ method,
561
+ args,
562
+ } satisfies TestInlineDriverCallRequest),
563
+ });
564
+
565
+ if (!response.ok) {
566
+ throw new Error(`Failed to call inline ${method}: ${response.statusText}`);
567
+ }
568
+
569
+ // Parse response
570
+ const buffer = await response.arrayBuffer();
571
+ const callResponse: TestInlineDriverCallResponse<T> = cbor.decode(
572
+ new Uint8Array(buffer),
573
+ );
574
+
575
+ // Throw or OK
576
+ if ("ok" in callResponse) {
577
+ return callResponse.ok;
578
+ } else if ("err" in callResponse) {
579
+ throw new ClientActorError(
580
+ callResponse.err.group,
581
+ callResponse.err.code,
582
+ callResponse.err.message,
583
+ callResponse.err.metadata,
584
+ );
585
+ } else {
586
+ assertUnreachable(callResponse);
587
+ }
588
+ }
@@ -63,18 +63,10 @@ export function runActorErrorHandlingTests(driverTestConfig: DriverTestConfig) {
63
63
  // If we get here, the test should fail
64
64
  expect(true).toBe(false); // This should not be reached
65
65
  } catch (error: any) {
66
- if (driverTestConfig.clientType === "http") {
67
- // Verify the error is converted to a safe format
68
- expect(error.code).toBe(INTERNAL_ERROR_CODE);
69
- // Original error details should not be exposed
70
- expect(error.message).toBe(INTERNAL_ERROR_DESCRIPTION);
71
- } else if (driverTestConfig.clientType === "inline") {
72
- // Verify that original error is preserved
73
- expect(error.code).toBe(INTERNAL_ERROR_CODE);
74
- expect(error.message).toBe("This is an internal error");
75
- } else {
76
- assertUnreachable(driverTestConfig.clientType);
77
- }
66
+ // Verify the error is converted to a safe format
67
+ expect(error.code).toBe(INTERNAL_ERROR_CODE);
68
+ // Original error details should not be exposed
69
+ expect(error.message).toBe(INTERNAL_ERROR_DESCRIPTION);
78
70
  }
79
71
  });
80
72
  });
@@ -9,7 +9,8 @@ import type { DriverTestConfig } from "../mod";
9
9
  import { setupDriverTest } from "../utils";
10
10
 
11
11
  export function runActorInspectorTests(driverTestConfig: DriverTestConfig) {
12
- describe("Actor Inspector Tests", () => {
12
+ // TODO: Add back
13
+ describe.skip("Actor Inspector Tests", () => {
13
14
  describe("Manager Inspector", () => {
14
15
  test("should respond to ping", async (c) => {
15
16
  const { endpoint } = await setupDriverTest(c, driverTestConfig);
@@ -1,9 +1,12 @@
1
- import { resolve } from "node:path";
1
+ import invariant from "invariant";
2
2
  import { type TestContext, vi } from "vitest";
3
3
  import { assertUnreachable } from "@/actor/utils";
4
4
  import { type Client, createClient } from "@/client/mod";
5
+ import { RunConfigSchema } from "@/driver-helpers/mod";
6
+ import { createClientWithDriver } from "@/mod";
5
7
  import type { registry } from "../../fixtures/driver-test-suite/registry";
6
8
  import type { DriverTestConfig } from "./mod";
9
+ import { createTestInlineClientDriver } from "./test-inline-client-driver";
7
10
 
8
11
  export const FAKE_TIME = new Date("2024-01-01T00:00:00.000Z");
9
12
 
@@ -21,9 +24,8 @@ export async function setupDriverTest(
21
24
  }
22
25
 
23
26
  // Build drivers
24
- const projectPath = resolve(__dirname, "../../fixtures/driver-test-suite");
25
27
  const { endpoint, namespace, runnerName, cleanup } =
26
- await driverTestConfig.start(projectPath);
28
+ await driverTestConfig.start();
27
29
  c.onTestFinished(cleanup);
28
30
 
29
31
  let client: Client<typeof registry>;
@@ -36,13 +38,17 @@ export async function setupDriverTest(
36
38
  transport: driverTestConfig.transport,
37
39
  });
38
40
  } else if (driverTestConfig.clientType === "inline") {
39
- throw "TODO";
40
- // // Use inline client from driver
41
- // const clientDriver = createTestInlineClientDriver(
42
- // endpoint,
43
- // driverTestConfig.transport ?? "websocket",
44
- // );
45
- // client = createClientWithDriver(clientDriver);
41
+ // Use inline client from driver
42
+ const managerDriver = createTestInlineClientDriver(
43
+ endpoint,
44
+ "bare",
45
+ driverTestConfig.transport ?? "websocket",
46
+ );
47
+ invariant(driverTestConfig.transport, "missing transport");
48
+ const runConfig = RunConfigSchema.parse({
49
+ transport: driverTestConfig.transport,
50
+ });
51
+ client = createClientWithDriver(managerDriver, runConfig);
46
52
  } else {
47
53
  assertUnreachable(driverTestConfig.clientType);
48
54
  }