rivetkit 2.0.2 → 2.0.4

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 (246) hide show
  1. package/README.md +3 -5
  2. package/dist/schemas/actor-persist/v1.ts +225 -0
  3. package/dist/schemas/client-protocol/v1.ts +435 -0
  4. package/dist/schemas/file-system-driver/v1.ts +102 -0
  5. package/dist/tsup/actor/errors.cjs +77 -0
  6. package/dist/tsup/actor/errors.cjs.map +1 -0
  7. package/dist/tsup/actor/errors.d.cts +156 -0
  8. package/dist/tsup/actor/errors.d.ts +156 -0
  9. package/dist/tsup/actor/errors.js +77 -0
  10. package/dist/tsup/actor/errors.js.map +1 -0
  11. package/dist/tsup/chunk-3F2YSRJL.js +117 -0
  12. package/dist/tsup/chunk-3F2YSRJL.js.map +1 -0
  13. package/dist/tsup/chunk-4CXBCT26.cjs +250 -0
  14. package/dist/tsup/chunk-4CXBCT26.cjs.map +1 -0
  15. package/dist/tsup/chunk-4R73YDN3.cjs +20 -0
  16. package/dist/tsup/chunk-4R73YDN3.cjs.map +1 -0
  17. package/dist/tsup/chunk-6LJT3QRL.cjs +539 -0
  18. package/dist/tsup/chunk-6LJT3QRL.cjs.map +1 -0
  19. package/dist/tsup/chunk-GICQ3YCU.cjs +1792 -0
  20. package/dist/tsup/chunk-GICQ3YCU.cjs.map +1 -0
  21. package/dist/tsup/chunk-H26RP6GD.js +251 -0
  22. package/dist/tsup/chunk-H26RP6GD.js.map +1 -0
  23. package/dist/tsup/chunk-HI3HWJRC.js +20 -0
  24. package/dist/tsup/chunk-HI3HWJRC.js.map +1 -0
  25. package/dist/tsup/chunk-HLLF4B4Q.js +1792 -0
  26. package/dist/tsup/chunk-HLLF4B4Q.js.map +1 -0
  27. package/dist/tsup/chunk-IH6CKNDW.cjs +117 -0
  28. package/dist/tsup/chunk-IH6CKNDW.cjs.map +1 -0
  29. package/dist/tsup/chunk-LV2S3OU3.js +250 -0
  30. package/dist/tsup/chunk-LV2S3OU3.js.map +1 -0
  31. package/dist/tsup/chunk-LWNKVZG5.cjs +251 -0
  32. package/dist/tsup/chunk-LWNKVZG5.cjs.map +1 -0
  33. package/dist/tsup/chunk-NFU2BBT5.js +374 -0
  34. package/dist/tsup/chunk-NFU2BBT5.js.map +1 -0
  35. package/dist/tsup/chunk-PQY7KKTL.js +539 -0
  36. package/dist/tsup/chunk-PQY7KKTL.js.map +1 -0
  37. package/dist/tsup/chunk-QK72M5JB.js +45 -0
  38. package/dist/tsup/chunk-QK72M5JB.js.map +1 -0
  39. package/dist/tsup/chunk-QNNXFOQV.cjs +45 -0
  40. package/dist/tsup/chunk-QNNXFOQV.cjs.map +1 -0
  41. package/dist/tsup/chunk-SBHHJ6QS.cjs +374 -0
  42. package/dist/tsup/chunk-SBHHJ6QS.cjs.map +1 -0
  43. package/dist/tsup/chunk-TQ62L3X7.js +325 -0
  44. package/dist/tsup/chunk-TQ62L3X7.js.map +1 -0
  45. package/dist/tsup/chunk-VO7ZRVVD.cjs +6293 -0
  46. package/dist/tsup/chunk-VO7ZRVVD.cjs.map +1 -0
  47. package/dist/tsup/chunk-WHBPJNGW.cjs +325 -0
  48. package/dist/tsup/chunk-WHBPJNGW.cjs.map +1 -0
  49. package/dist/tsup/chunk-XJQHKJ4P.js +6293 -0
  50. package/dist/tsup/chunk-XJQHKJ4P.js.map +1 -0
  51. package/dist/tsup/client/mod.cjs +32 -0
  52. package/dist/tsup/client/mod.cjs.map +1 -0
  53. package/dist/tsup/client/mod.d.cts +20 -0
  54. package/dist/tsup/client/mod.d.ts +20 -0
  55. package/dist/tsup/client/mod.js +32 -0
  56. package/dist/tsup/client/mod.js.map +1 -0
  57. package/dist/tsup/common/log.cjs +21 -0
  58. package/dist/tsup/common/log.cjs.map +1 -0
  59. package/dist/tsup/common/log.d.cts +26 -0
  60. package/dist/tsup/common/log.d.ts +26 -0
  61. package/dist/tsup/common/log.js +21 -0
  62. package/dist/tsup/common/log.js.map +1 -0
  63. package/dist/tsup/common/websocket.cjs +10 -0
  64. package/dist/tsup/common/websocket.cjs.map +1 -0
  65. package/dist/tsup/common/websocket.d.cts +3 -0
  66. package/dist/tsup/common/websocket.d.ts +3 -0
  67. package/dist/tsup/common/websocket.js +10 -0
  68. package/dist/tsup/common/websocket.js.map +1 -0
  69. package/dist/tsup/common-CXCe7s6i.d.cts +218 -0
  70. package/dist/tsup/common-CXCe7s6i.d.ts +218 -0
  71. package/dist/tsup/connection-BI-6UIBJ.d.ts +2087 -0
  72. package/dist/tsup/connection-Dyd4NLGW.d.cts +2087 -0
  73. package/dist/tsup/driver-helpers/mod.cjs +30 -0
  74. package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
  75. package/dist/tsup/driver-helpers/mod.d.cts +17 -0
  76. package/dist/tsup/driver-helpers/mod.d.ts +17 -0
  77. package/dist/tsup/driver-helpers/mod.js +30 -0
  78. package/dist/tsup/driver-helpers/mod.js.map +1 -0
  79. package/dist/tsup/driver-test-suite/mod.cjs +3411 -0
  80. package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
  81. package/dist/tsup/driver-test-suite/mod.d.cts +63 -0
  82. package/dist/tsup/driver-test-suite/mod.d.ts +63 -0
  83. package/dist/tsup/driver-test-suite/mod.js +3411 -0
  84. package/dist/tsup/driver-test-suite/mod.js.map +1 -0
  85. package/dist/tsup/inspector/mod.cjs +51 -0
  86. package/dist/tsup/inspector/mod.cjs.map +1 -0
  87. package/dist/tsup/inspector/mod.d.cts +408 -0
  88. package/dist/tsup/inspector/mod.d.ts +408 -0
  89. package/dist/tsup/inspector/mod.js +51 -0
  90. package/dist/tsup/inspector/mod.js.map +1 -0
  91. package/dist/tsup/mod.cjs +67 -0
  92. package/dist/tsup/mod.cjs.map +1 -0
  93. package/dist/tsup/mod.d.cts +105 -0
  94. package/dist/tsup/mod.d.ts +105 -0
  95. package/dist/tsup/mod.js +67 -0
  96. package/dist/tsup/mod.js.map +1 -0
  97. package/dist/tsup/router-endpoints-BTe_Rsdn.d.cts +65 -0
  98. package/dist/tsup/router-endpoints-CBSrKHmo.d.ts +65 -0
  99. package/dist/tsup/test/mod.cjs +17 -0
  100. package/dist/tsup/test/mod.cjs.map +1 -0
  101. package/dist/tsup/test/mod.d.cts +26 -0
  102. package/dist/tsup/test/mod.d.ts +26 -0
  103. package/dist/tsup/test/mod.js +17 -0
  104. package/dist/tsup/test/mod.js.map +1 -0
  105. package/dist/tsup/utils-fwx3o3K9.d.cts +18 -0
  106. package/dist/tsup/utils-fwx3o3K9.d.ts +18 -0
  107. package/dist/tsup/utils.cjs +26 -0
  108. package/dist/tsup/utils.cjs.map +1 -0
  109. package/dist/tsup/utils.d.cts +36 -0
  110. package/dist/tsup/utils.d.ts +36 -0
  111. package/dist/tsup/utils.js +26 -0
  112. package/dist/tsup/utils.js.map +1 -0
  113. package/package.json +208 -5
  114. package/src/actor/action.ts +178 -0
  115. package/src/actor/config.ts +497 -0
  116. package/src/actor/connection.ts +257 -0
  117. package/src/actor/context.ts +168 -0
  118. package/src/actor/database.ts +23 -0
  119. package/src/actor/definition.ts +82 -0
  120. package/src/actor/driver.ts +84 -0
  121. package/src/actor/errors.ts +422 -0
  122. package/src/actor/generic-conn-driver.ts +246 -0
  123. package/src/actor/instance.ts +1844 -0
  124. package/src/actor/keys.test.ts +266 -0
  125. package/src/actor/keys.ts +89 -0
  126. package/src/actor/log.ts +6 -0
  127. package/src/actor/mod.ts +108 -0
  128. package/src/actor/persisted.ts +42 -0
  129. package/src/actor/protocol/old.ts +297 -0
  130. package/src/actor/protocol/serde.ts +131 -0
  131. package/src/actor/router-endpoints.ts +688 -0
  132. package/src/actor/router.ts +265 -0
  133. package/src/actor/schedule.ts +17 -0
  134. package/src/actor/unstable-react.ts +110 -0
  135. package/src/actor/utils.ts +102 -0
  136. package/src/client/actor-common.ts +30 -0
  137. package/src/client/actor-conn.ts +865 -0
  138. package/src/client/actor-handle.ts +268 -0
  139. package/src/client/actor-query.ts +65 -0
  140. package/src/client/client.ts +554 -0
  141. package/src/client/config.ts +44 -0
  142. package/src/client/errors.ts +42 -0
  143. package/src/client/log.ts +5 -0
  144. package/src/client/mod.ts +60 -0
  145. package/src/client/raw-utils.ts +149 -0
  146. package/src/client/test.ts +44 -0
  147. package/src/client/utils.ts +152 -0
  148. package/src/common/eventsource-interface.ts +47 -0
  149. package/src/common/eventsource.ts +80 -0
  150. package/src/common/fake-event-source.ts +267 -0
  151. package/src/common/inline-websocket-adapter2.ts +454 -0
  152. package/src/common/log-levels.ts +27 -0
  153. package/src/common/log.ts +214 -0
  154. package/src/common/logfmt.ts +219 -0
  155. package/src/common/network.ts +2 -0
  156. package/src/common/router.ts +80 -0
  157. package/src/common/utils.ts +336 -0
  158. package/src/common/versioned-data.ts +95 -0
  159. package/src/common/websocket-interface.ts +49 -0
  160. package/src/common/websocket.ts +42 -0
  161. package/src/driver-helpers/mod.ts +22 -0
  162. package/src/driver-helpers/utils.ts +17 -0
  163. package/src/driver-test-suite/log.ts +5 -0
  164. package/src/driver-test-suite/mod.ts +239 -0
  165. package/src/driver-test-suite/tests/action-features.ts +136 -0
  166. package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
  167. package/src/driver-test-suite/tests/actor-conn.ts +349 -0
  168. package/src/driver-test-suite/tests/actor-driver.ts +25 -0
  169. package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
  170. package/src/driver-test-suite/tests/actor-handle.ts +292 -0
  171. package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
  172. package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
  173. package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
  174. package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
  175. package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
  176. package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
  177. package/src/driver-test-suite/tests/actor-state.ts +54 -0
  178. package/src/driver-test-suite/tests/actor-vars.ts +93 -0
  179. package/src/driver-test-suite/tests/manager-driver.ts +367 -0
  180. package/src/driver-test-suite/tests/raw-http-direct-registry.ts +227 -0
  181. package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
  182. package/src/driver-test-suite/tests/raw-http.ts +347 -0
  183. package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +393 -0
  184. package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
  185. package/src/driver-test-suite/tests/request-access.ts +230 -0
  186. package/src/driver-test-suite/utils.ts +71 -0
  187. package/src/drivers/default.ts +34 -0
  188. package/src/drivers/engine/actor-driver.ts +369 -0
  189. package/src/drivers/engine/config.ts +31 -0
  190. package/src/drivers/engine/kv.ts +3 -0
  191. package/src/drivers/engine/log.ts +5 -0
  192. package/src/drivers/engine/mod.ts +35 -0
  193. package/src/drivers/file-system/actor.ts +91 -0
  194. package/src/drivers/file-system/global-state.ts +686 -0
  195. package/src/drivers/file-system/log.ts +5 -0
  196. package/src/drivers/file-system/manager.ts +329 -0
  197. package/src/drivers/file-system/mod.ts +48 -0
  198. package/src/drivers/file-system/utils.ts +109 -0
  199. package/src/globals.d.ts +6 -0
  200. package/src/inspector/actor.ts +298 -0
  201. package/src/inspector/config.ts +88 -0
  202. package/src/inspector/log.ts +5 -0
  203. package/src/inspector/manager.ts +86 -0
  204. package/src/inspector/mod.ts +2 -0
  205. package/src/inspector/protocol/actor.ts +10 -0
  206. package/src/inspector/protocol/common.ts +196 -0
  207. package/src/inspector/protocol/manager.ts +10 -0
  208. package/src/inspector/protocol/mod.ts +2 -0
  209. package/src/inspector/utils.ts +76 -0
  210. package/src/manager/driver.ts +88 -0
  211. package/src/manager/hono-websocket-adapter.ts +342 -0
  212. package/src/manager/log.ts +5 -0
  213. package/src/manager/mod.ts +2 -0
  214. package/src/manager/protocol/mod.ts +24 -0
  215. package/src/manager/protocol/query.ts +89 -0
  216. package/src/manager/router.ts +412 -0
  217. package/src/manager-api/routes/actors-create.ts +16 -0
  218. package/src/manager-api/routes/actors-delete.ts +4 -0
  219. package/src/manager-api/routes/actors-get-by-id.ts +7 -0
  220. package/src/manager-api/routes/actors-get-or-create-by-id.ts +29 -0
  221. package/src/manager-api/routes/actors-get.ts +7 -0
  222. package/src/manager-api/routes/common.ts +18 -0
  223. package/src/mod.ts +18 -0
  224. package/src/registry/config.ts +32 -0
  225. package/src/registry/log.ts +5 -0
  226. package/src/registry/mod.ts +157 -0
  227. package/src/registry/run-config.ts +52 -0
  228. package/src/registry/serve.ts +52 -0
  229. package/src/remote-manager-driver/actor-http-client.ts +72 -0
  230. package/src/remote-manager-driver/actor-websocket-client.ts +63 -0
  231. package/src/remote-manager-driver/api-endpoints.ts +79 -0
  232. package/src/remote-manager-driver/api-utils.ts +43 -0
  233. package/src/remote-manager-driver/log.ts +5 -0
  234. package/src/remote-manager-driver/mod.ts +274 -0
  235. package/src/remote-manager-driver/ws-proxy.ts +180 -0
  236. package/src/schemas/actor-persist/mod.ts +1 -0
  237. package/src/schemas/actor-persist/versioned.ts +25 -0
  238. package/src/schemas/client-protocol/mod.ts +1 -0
  239. package/src/schemas/client-protocol/versioned.ts +63 -0
  240. package/src/schemas/file-system-driver/mod.ts +1 -0
  241. package/src/schemas/file-system-driver/versioned.ts +28 -0
  242. package/src/serde.ts +90 -0
  243. package/src/test/config.ts +16 -0
  244. package/src/test/log.ts +5 -0
  245. package/src/test/mod.ts +154 -0
  246. package/src/utils.ts +172 -0
@@ -0,0 +1,149 @@
1
+ import invariant from "invariant";
2
+ import { PATH_RAW_WEBSOCKET_PREFIX } from "@/actor/router";
3
+ import { deconstructError } from "@/common/utils";
4
+ import { HEADER_CONN_PARAMS, type ManagerDriver } from "@/driver-helpers/mod";
5
+ import type { ActorQuery } from "@/manager/protocol/query";
6
+ import { queryActor } from "./actor-query";
7
+ import { ActorError } from "./errors";
8
+ import { logger } from "./log";
9
+
10
+ /**
11
+ * Shared implementation for raw HTTP fetch requests
12
+ */
13
+ export async function rawHttpFetch(
14
+ driver: ManagerDriver,
15
+ actorQuery: ActorQuery,
16
+ params: unknown,
17
+ input: string | URL | Request,
18
+ init?: RequestInit,
19
+ ): Promise<Response> {
20
+ // Extract path and merge init options
21
+ let path: string;
22
+ let mergedInit: RequestInit = init || {};
23
+
24
+ if (typeof input === "string") {
25
+ path = input;
26
+ } else if (input instanceof URL) {
27
+ path = input.pathname + input.search;
28
+ } else if (input instanceof Request) {
29
+ // Extract path from Request URL
30
+ const url = new URL(input.url);
31
+ path = url.pathname + url.search;
32
+ // Merge Request properties with init
33
+ const requestHeaders = new Headers(input.headers);
34
+ const initHeaders = new Headers(init?.headers || {});
35
+
36
+ // Merge headers - init headers override request headers
37
+ const mergedHeaders = new Headers(requestHeaders);
38
+ for (const [key, value] of initHeaders) {
39
+ mergedHeaders.set(key, value);
40
+ }
41
+
42
+ mergedInit = {
43
+ method: input.method,
44
+ body: input.body,
45
+ mode: input.mode,
46
+ credentials: input.credentials,
47
+ redirect: input.redirect,
48
+ referrer: input.referrer,
49
+ referrerPolicy: input.referrerPolicy,
50
+ integrity: input.integrity,
51
+ keepalive: input.keepalive,
52
+ signal: input.signal,
53
+ ...mergedInit, // init overrides Request properties
54
+ headers: mergedHeaders, // headers must be set after spread to ensure proper merge
55
+ };
56
+ // Add duplex if body is present
57
+ if (mergedInit.body) {
58
+ (mergedInit as any).duplex = "half";
59
+ }
60
+ } else {
61
+ throw new TypeError("Invalid input type for fetch");
62
+ }
63
+
64
+ try {
65
+ // Get the actor ID
66
+ const { actorId } = await queryActor(undefined, actorQuery, driver);
67
+ logger().debug({ msg: "found actor for raw http", actorId });
68
+ invariant(actorId, "Missing actor ID");
69
+
70
+ // Build the URL with normalized path
71
+ const normalizedPath = path.startsWith("/") ? path.slice(1) : path;
72
+ const url = new URL(`http://actor/raw/http/${normalizedPath}`);
73
+
74
+ // Forward conn params if provided
75
+ const proxyRequestHeaders = new Headers(mergedInit.headers);
76
+ if (params) {
77
+ proxyRequestHeaders.set(HEADER_CONN_PARAMS, JSON.stringify(params));
78
+ }
79
+
80
+ // Forward the request to the actor
81
+ const proxyRequest = new Request(url, {
82
+ ...init,
83
+ headers: proxyRequestHeaders,
84
+ });
85
+
86
+ return driver.sendRequest(actorId, proxyRequest);
87
+ } catch (err) {
88
+ // Standardize to ClientActorError instead of the native backend error
89
+ const { group, code, message, metadata } = deconstructError(
90
+ err,
91
+ logger(),
92
+ {},
93
+ true,
94
+ );
95
+ throw new ActorError(group, code, message, metadata);
96
+ }
97
+ }
98
+
99
+ /**
100
+ * Shared implementation for raw WebSocket connections
101
+ */
102
+ export async function rawWebSocket(
103
+ driver: ManagerDriver,
104
+ actorQuery: ActorQuery,
105
+ params: unknown,
106
+ path?: string,
107
+ // TODO: Supportp rotocols
108
+ protocols?: string | string[],
109
+ ): Promise<any> {
110
+ // TODO: Do we need encoding in rawWebSocket?
111
+ const encoding = "bare";
112
+
113
+ // Get the actor ID
114
+ const { actorId } = await queryActor(undefined, actorQuery, driver);
115
+ logger().debug({ msg: "found actor for action", actorId });
116
+ invariant(actorId, "Missing actor ID");
117
+
118
+ // Parse path and query parameters
119
+ let pathPortion = "";
120
+ let queryPortion = "";
121
+ if (path) {
122
+ const queryIndex = path.indexOf("?");
123
+ if (queryIndex !== -1) {
124
+ pathPortion = path.substring(0, queryIndex);
125
+ queryPortion = path.substring(queryIndex); // includes the '?'
126
+ } else {
127
+ pathPortion = path;
128
+ }
129
+ // Remove leading slash if present
130
+ if (pathPortion.startsWith("/")) {
131
+ pathPortion = pathPortion.slice(1);
132
+ }
133
+ }
134
+
135
+ const fullPath = `${PATH_RAW_WEBSOCKET_PREFIX}${pathPortion}${queryPortion}`;
136
+
137
+ logger().debug({
138
+ msg: "opening websocket",
139
+ actorId,
140
+ encoding,
141
+ path: fullPath,
142
+ });
143
+
144
+ // Open WebSocket
145
+ const ws = await driver.openWebSocket(fullPath, actorId, encoding, params);
146
+
147
+ // Node & browser WebSocket types are incompatible
148
+ return ws as any;
149
+ }
@@ -0,0 +1,44 @@
1
+ //import { exec as execCallback } from "node:child_process";
2
+ //import { setupLogging } from "@/common//log";
3
+ //import type { ClientOptions } from "./client";
4
+ //import { InternalError } from "./errors";
5
+ //import { Client } from "./mod.ts";
6
+ //
7
+ ///**
8
+ // * Uses the Rivet CLI to read the manager endpoint to connect to. This allows
9
+ // * for writing tests that run locally without hardcoding the manager endpoint.
10
+ // */
11
+ //export async function readEndpointFromCli(): Promise<string> {
12
+ // // Read endpoint
13
+ // const cliPath = process.env.RIVET_CLI_PATH ?? "rivet";
14
+ //
15
+ // try {
16
+ // const { stdout, stderr } = await new Promise<{
17
+ // stdout: string;
18
+ // stderr: string;
19
+ // }>((resolve, reject) => {
20
+ // execCallback(`${cliPath} manager endpoint`, (error, stdout, stderr) => {
21
+ // if (error) reject(error);
22
+ // else resolve({ stdout, stderr });
23
+ // });
24
+ // });
25
+ //
26
+ // if (stderr) {
27
+ // throw new Error(stderr);
28
+ // }
29
+ //
30
+ // // Decode output
31
+ // return stdout.trim();
32
+ // } catch (error) {
33
+ // throw new InternalError(`Read endpoint failed: ${error}`);
34
+ // }
35
+ //}
36
+ //
37
+ //export class TestClient extends Client {
38
+ // public constructor(opts?: ClientOptions) {
39
+ // // Setup logging automatically
40
+ // setupLogging();
41
+ //
42
+ // super(readEndpointFromCli(), opts);
43
+ // }
44
+ //}
@@ -0,0 +1,152 @@
1
+ import * as cbor from "cbor-x";
2
+ import invariant from "invariant";
3
+ import { assertUnreachable } from "@/common/utils";
4
+ import type { VersionedDataHandler } from "@/common/versioned-data";
5
+ import type { Encoding } from "@/mod";
6
+ import type { HttpResponseError } from "@/schemas/client-protocol/mod";
7
+ import { HTTP_RESPONSE_ERROR_VERSIONED } from "@/schemas/client-protocol/versioned";
8
+ import {
9
+ contentTypeForEncoding,
10
+ deserializeWithEncoding,
11
+ serializeWithEncoding,
12
+ } from "@/serde";
13
+ import { httpUserAgent } from "@/utils";
14
+ import { ActorError, HttpRequestError } from "./errors";
15
+ import { logger } from "./log";
16
+
17
+ export type WebSocketMessage = string | Blob | ArrayBuffer | Uint8Array;
18
+
19
+ export function messageLength(message: WebSocketMessage): number {
20
+ if (message instanceof Blob) {
21
+ return message.size;
22
+ }
23
+ if (message instanceof ArrayBuffer) {
24
+ return message.byteLength;
25
+ }
26
+ if (message instanceof Uint8Array) {
27
+ return message.byteLength;
28
+ }
29
+ if (typeof message === "string") {
30
+ return message.length;
31
+ }
32
+ assertUnreachable(message);
33
+ }
34
+
35
+ export interface HttpRequestOpts<RequestBody, ResponseBody> {
36
+ method: string;
37
+ url: string;
38
+ headers: Record<string, string>;
39
+ body?: RequestBody;
40
+ encoding: Encoding;
41
+ skipParseResponse?: boolean;
42
+ signal?: AbortSignal;
43
+ customFetch?: (req: Request) => Promise<Response>;
44
+ requestVersionedDataHandler: VersionedDataHandler<RequestBody> | undefined;
45
+ responseVersionedDataHandler: VersionedDataHandler<ResponseBody> | undefined;
46
+ }
47
+
48
+ export async function sendHttpRequest<
49
+ RequestBody = unknown,
50
+ ResponseBody = unknown,
51
+ >(opts: HttpRequestOpts<RequestBody, ResponseBody>): Promise<ResponseBody> {
52
+ logger().debug({
53
+ msg: "sending http request",
54
+ url: opts.url,
55
+ encoding: opts.encoding,
56
+ });
57
+
58
+ // Serialize body
59
+ let contentType: string | undefined;
60
+ let bodyData: string | Uint8Array | undefined;
61
+ if (opts.method === "POST" || opts.method === "PUT") {
62
+ invariant(opts.body !== undefined, "missing body");
63
+ contentType = contentTypeForEncoding(opts.encoding);
64
+ bodyData = serializeWithEncoding<RequestBody>(
65
+ opts.encoding,
66
+ opts.body,
67
+ opts.requestVersionedDataHandler,
68
+ );
69
+ }
70
+
71
+ // Send request
72
+ let response: Response;
73
+ try {
74
+ // Make the HTTP request
75
+ response = await (opts.customFetch ?? fetch)(
76
+ new Request(opts.url, {
77
+ method: opts.method,
78
+ headers: {
79
+ ...opts.headers,
80
+ ...(contentType
81
+ ? {
82
+ "Content-Type": contentType,
83
+ }
84
+ : {}),
85
+ "User-Agent": httpUserAgent(),
86
+ },
87
+ body: bodyData,
88
+ credentials: "include",
89
+ signal: opts.signal,
90
+ }),
91
+ );
92
+ } catch (error) {
93
+ throw new HttpRequestError(`Request failed: ${error}`, {
94
+ cause: error,
95
+ });
96
+ }
97
+
98
+ // Parse response error
99
+ if (!response.ok) {
100
+ // Attempt to parse structured data
101
+ const bufferResponse = await response.arrayBuffer();
102
+ let responseData: HttpResponseError;
103
+ try {
104
+ responseData = deserializeWithEncoding(
105
+ opts.encoding,
106
+ new Uint8Array(bufferResponse),
107
+ HTTP_RESPONSE_ERROR_VERSIONED,
108
+ );
109
+ } catch (error) {
110
+ //logger().warn("failed to cleanly parse error, this is likely because a non-structured response is being served", {
111
+ // error: stringifyError(error),
112
+ //});
113
+
114
+ // Error is not structured
115
+ const textResponse = new TextDecoder("utf-8", { fatal: false }).decode(
116
+ bufferResponse,
117
+ );
118
+ throw new HttpRequestError(
119
+ `${response.statusText} (${response.status}):\n${textResponse}`,
120
+ );
121
+ }
122
+
123
+ // Throw structured error
124
+ throw new ActorError(
125
+ responseData.group,
126
+ responseData.code,
127
+ responseData.message,
128
+ responseData.metadata
129
+ ? cbor.decode(new Uint8Array(responseData.metadata))
130
+ : undefined,
131
+ );
132
+ }
133
+
134
+ // Some requests don't need the success response to be parsed, so this can speed things up
135
+ if (opts.skipParseResponse) {
136
+ return undefined as ResponseBody;
137
+ }
138
+
139
+ // Parse the response based on encoding
140
+ try {
141
+ const buffer = new Uint8Array(await response.arrayBuffer());
142
+ return deserializeWithEncoding(
143
+ opts.encoding,
144
+ buffer,
145
+ opts.responseVersionedDataHandler,
146
+ );
147
+ } catch (error) {
148
+ throw new HttpRequestError(`Failed to parse response: ${error}`, {
149
+ cause: error,
150
+ });
151
+ }
152
+ }
@@ -0,0 +1,47 @@
1
+ // Define minimal event interfaces to avoid conflicts between different EventSource implementations
2
+ export interface UniversalEvent {
3
+ type: string;
4
+ target?: any;
5
+ currentTarget?: any;
6
+ }
7
+
8
+ export interface UniversalMessageEvent extends UniversalEvent {
9
+ data: string;
10
+ lastEventId: string;
11
+ origin: string;
12
+ }
13
+
14
+ export interface UniversalErrorEvent extends UniversalEvent {
15
+ message: string;
16
+ filename?: string;
17
+ lineno?: number;
18
+ colno?: number;
19
+ error?: any;
20
+ }
21
+
22
+ /**
23
+ * Common EventSource interface that can be implemented by different EventSource-like classes
24
+ * This is compatible with the standard EventSource API but allows for custom implementations
25
+ */
26
+ export interface UniversalEventSource {
27
+ // EventSource readyState values
28
+ readonly CONNECTING: 0;
29
+ readonly OPEN: 1;
30
+ readonly CLOSED: 2;
31
+
32
+ // Properties
33
+ readonly readyState: 0 | 1 | 2;
34
+ readonly url: string;
35
+ readonly withCredentials: boolean;
36
+
37
+ // Methods
38
+ close(): void;
39
+ addEventListener(type: string, listener: (event: any) => void): void;
40
+ removeEventListener(type: string, listener: (event: any) => void): void;
41
+ dispatchEvent(event: UniversalEvent): boolean;
42
+
43
+ // Event handlers (optional)
44
+ onopen?: ((event: UniversalEvent) => void) | null;
45
+ onmessage?: ((event: UniversalMessageEvent) => void) | null;
46
+ onerror?: ((event: UniversalErrorEvent) => void) | null;
47
+ }
@@ -0,0 +1,80 @@
1
+ import type { EventSource } from "eventsource";
2
+ import { logger } from "@/client/log";
3
+
4
+ // Global singleton promise that will be reused for subsequent calls
5
+ let eventSourcePromise: Promise<typeof EventSource> | null = null;
6
+
7
+ /**
8
+ * Import `eventsource` from the custom `eventsource` library. We need a custom implemnetation since we need to attach our own custom headers to the request.
9
+ **/
10
+ export async function importEventSource(): Promise<typeof EventSource> {
11
+ // Return existing promise if we already started loading
12
+ if (eventSourcePromise !== null) {
13
+ return eventSourcePromise;
14
+ }
15
+
16
+ // Create and store the promise
17
+ eventSourcePromise = (async () => {
18
+ let _EventSource: typeof EventSource;
19
+
20
+ // Node.js environment
21
+ try {
22
+ const es = await import("eventsource");
23
+ _EventSource = es.EventSource;
24
+ logger().debug("using eventsource from npm");
25
+ } catch (err) {
26
+ // EventSource not available
27
+ _EventSource = class MockEventSource {
28
+ constructor() {
29
+ throw new Error(
30
+ 'EventSource support requires installing the "eventsource" peer dependency.',
31
+ );
32
+ }
33
+ } as unknown as typeof EventSource;
34
+ logger().debug("using mock eventsource");
35
+ }
36
+
37
+ return _EventSource;
38
+ })();
39
+
40
+ return eventSourcePromise;
41
+ }
42
+
43
+ //export async function importEventSource(): Promise<typeof EventSource> {
44
+ // // Return existing promise if we already started loading
45
+ // if (eventSourcePromise !== null) {
46
+ // return eventSourcePromise;
47
+ // }
48
+ //
49
+ // // Create and store the promise
50
+ // eventSourcePromise = (async () => {
51
+ // let _EventSource: typeof EventSource;
52
+ //
53
+ // if (typeof EventSource !== "undefined") {
54
+ // // Browser environment
55
+ // _EventSource = EventSource;
56
+ // logger().debug("using native eventsource");
57
+ // } else {
58
+ // // Node.js environment
59
+ // try {
60
+ // const es = await import("eventsource");
61
+ // _EventSource = es.EventSource;
62
+ // logger().debug("using eventsource from npm");
63
+ // } catch (err) {
64
+ // // EventSource not available
65
+ // _EventSource = class MockEventSource {
66
+ // constructor() {
67
+ // throw new Error(
68
+ // 'EventSource support requires installing the "eventsource" peer dependency.',
69
+ // );
70
+ // }
71
+ // } as unknown as typeof EventSource;
72
+ // logger().debug("using mock eventsource");
73
+ // }
74
+ // }
75
+ //
76
+ // return _EventSource;
77
+ // })();
78
+ //
79
+ // return eventSourcePromise;
80
+ //}