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,685 @@
1
+ import * as cbor from "cbor-x";
2
+ import type { Context as HonoContext, HonoRequest } from "hono";
3
+ import { type SSEStreamingApi, streamSSE } from "hono/streaming";
4
+ import type { WSContext } from "hono/ws";
5
+ import { ActionContext } from "@/actor/action";
6
+ import type { AnyConn } from "@/actor/connection";
7
+ import {
8
+ CONNECTION_DRIVER_HTTP,
9
+ CONNECTION_DRIVER_SSE,
10
+ CONNECTION_DRIVER_WEBSOCKET,
11
+ generateConnId,
12
+ generateConnToken,
13
+ } from "@/actor/connection";
14
+ import * as errors from "@/actor/errors";
15
+ import type { AnyActorInstance } from "@/actor/instance";
16
+ import type { InputData } from "@/actor/protocol/serde";
17
+ import { type Encoding, EncodingSchema } from "@/actor/protocol/serde";
18
+ import type { UpgradeWebSocketArgs } from "@/common/inline-websocket-adapter2";
19
+ import { deconstructError, stringifyError } from "@/common/utils";
20
+ import type { UniversalWebSocket } from "@/common/websocket-interface";
21
+ import { HonoWebSocketAdapter } from "@/manager/hono-websocket-adapter";
22
+ import type { RunConfig } from "@/registry/run-config";
23
+ import type * as protocol from "@/schemas/client-protocol/mod";
24
+ import {
25
+ HTTP_ACTION_REQUEST_VERSIONED,
26
+ HTTP_ACTION_RESPONSE_VERSIONED,
27
+ TO_SERVER_VERSIONED,
28
+ } from "@/schemas/client-protocol/versioned";
29
+ import {
30
+ contentTypeForEncoding,
31
+ deserializeWithEncoding,
32
+ serializeWithEncoding,
33
+ } from "@/serde";
34
+ import { bufferToArrayBuffer } from "@/utils";
35
+ import type { ActorDriver } from "./driver";
36
+ import type {
37
+ GenericHttpDriverState,
38
+ GenericSseDriverState,
39
+ GenericWebSocketDriverState,
40
+ } from "./generic-conn-driver";
41
+ import { logger } from "./log";
42
+ import { parseMessage } from "./protocol/old";
43
+
44
+ export interface ConnectWebSocketOpts {
45
+ req?: HonoRequest;
46
+ encoding: Encoding;
47
+ actorId: string;
48
+ params: unknown;
49
+ authData: unknown;
50
+ }
51
+
52
+ export interface ConnectWebSocketOutput {
53
+ onOpen: (ws: WSContext) => void;
54
+ onMessage: (message: protocol.ToServer) => void;
55
+ onClose: () => void;
56
+ }
57
+
58
+ export interface ConnectSseOpts {
59
+ req?: HonoRequest;
60
+ encoding: Encoding;
61
+ params: unknown;
62
+ actorId: string;
63
+ authData: unknown;
64
+ }
65
+
66
+ export interface ConnectSseOutput {
67
+ onOpen: (stream: SSEStreamingApi) => void;
68
+ onClose: () => Promise<void>;
69
+ }
70
+
71
+ export interface ActionOpts {
72
+ req?: HonoRequest;
73
+ params: unknown;
74
+ actionName: string;
75
+ actionArgs: unknown[];
76
+ actorId: string;
77
+ authData: unknown;
78
+ }
79
+
80
+ export interface ActionOutput {
81
+ output: unknown;
82
+ }
83
+
84
+ export interface ConnsMessageOpts {
85
+ req?: HonoRequest;
86
+ connId: string;
87
+ connToken: string;
88
+ message: protocol.ToServer;
89
+ actorId: string;
90
+ }
91
+
92
+ export interface FetchOpts {
93
+ request: Request;
94
+ actorId: string;
95
+ authData: unknown;
96
+ }
97
+
98
+ export interface WebSocketOpts {
99
+ request: Request;
100
+ websocket: UniversalWebSocket;
101
+ actorId: string;
102
+ authData: unknown;
103
+ }
104
+
105
+ /**
106
+ * Creates a WebSocket connection handler
107
+ */
108
+ export async function handleWebSocketConnect(
109
+ req: Request | undefined,
110
+ runConfig: RunConfig,
111
+ actorDriver: ActorDriver,
112
+ actorId: string,
113
+ encoding: Encoding,
114
+ parameters: unknown,
115
+ authData: unknown,
116
+ ): Promise<UpgradeWebSocketArgs> {
117
+ const exposeInternalError = req ? getRequestExposeInternalError(req) : false;
118
+
119
+ // Setup promise for the init handlers since all other behavior depends on this
120
+ const {
121
+ promise: handlersPromise,
122
+ resolve: handlersResolve,
123
+ reject: handlersReject,
124
+ } = Promise.withResolvers<{
125
+ conn: AnyConn;
126
+ actor: AnyActorInstance;
127
+ connId: string;
128
+ }>();
129
+
130
+ // Pre-load the actor to catch errors early
131
+ let actor: AnyActorInstance;
132
+ try {
133
+ actor = await actorDriver.loadActor(actorId);
134
+ } catch (error) {
135
+ // Return handler that immediately closes with error
136
+ return {
137
+ onOpen: (_evt: any, ws: WSContext) => {
138
+ const { code } = deconstructError(
139
+ error,
140
+ logger(),
141
+ {
142
+ wsEvent: "open",
143
+ },
144
+ exposeInternalError,
145
+ );
146
+ ws.close(1011, code);
147
+ },
148
+ onMessage: (_evt: { data: any }, ws: WSContext) => {
149
+ ws.close(1011, "Actor not loaded");
150
+ },
151
+ onClose: (_event: any, _ws: WSContext) => {},
152
+ onError: (_error: unknown) => {},
153
+ };
154
+ }
155
+
156
+ return {
157
+ onOpen: (_evt: any, ws: WSContext) => {
158
+ logger().debug("websocket open");
159
+
160
+ // Run async operations in background
161
+ (async () => {
162
+ try {
163
+ const connId = generateConnId();
164
+ const connToken = generateConnToken();
165
+ const connState = await actor.prepareConn(parameters, req);
166
+
167
+ // Save socket
168
+ const connGlobalState =
169
+ actorDriver.getGenericConnGlobalState(actorId);
170
+ connGlobalState.websockets.set(connId, ws);
171
+ logger().debug("registered websocket for conn", {
172
+ actorId,
173
+ totalCount: connGlobalState.websockets.size,
174
+ });
175
+
176
+ // Create connection
177
+ const conn = await actor.createConn(
178
+ connId,
179
+ connToken,
180
+ parameters,
181
+ connState,
182
+ CONNECTION_DRIVER_WEBSOCKET,
183
+ { encoding } satisfies GenericWebSocketDriverState,
184
+ authData,
185
+ );
186
+
187
+ // Unblock other handlers
188
+ handlersResolve({ conn, actor, connId });
189
+ } catch (error) {
190
+ handlersReject(error);
191
+
192
+ const { code } = deconstructError(
193
+ error,
194
+ logger(),
195
+ {
196
+ wsEvent: "open",
197
+ },
198
+ exposeInternalError,
199
+ );
200
+ ws.close(1011, code);
201
+ }
202
+ })();
203
+ },
204
+ onMessage: (evt: { data: any }, ws: WSContext) => {
205
+ // Handle message asynchronously
206
+ handlersPromise
207
+ .then(({ conn, actor }) => {
208
+ logger().debug("received message");
209
+
210
+ const value = evt.data.valueOf() as InputData;
211
+ parseMessage(value, {
212
+ encoding: encoding,
213
+ maxIncomingMessageSize: runConfig.maxIncomingMessageSize,
214
+ })
215
+ .then((message) => {
216
+ actor.processMessage(message, conn).catch((error) => {
217
+ const { code } = deconstructError(
218
+ error,
219
+ logger(),
220
+ {
221
+ wsEvent: "message",
222
+ },
223
+ exposeInternalError,
224
+ );
225
+ ws.close(1011, code);
226
+ });
227
+ })
228
+ .catch((error) => {
229
+ const { code } = deconstructError(
230
+ error,
231
+ logger(),
232
+ {
233
+ wsEvent: "message",
234
+ },
235
+ exposeInternalError,
236
+ );
237
+ ws.close(1011, code);
238
+ });
239
+ })
240
+ .catch((error) => {
241
+ const { code } = deconstructError(
242
+ error,
243
+ logger(),
244
+ {
245
+ wsEvent: "message",
246
+ },
247
+ exposeInternalError,
248
+ );
249
+ ws.close(1011, code);
250
+ });
251
+ },
252
+ onClose: (
253
+ event: {
254
+ wasClean: boolean;
255
+ code: number;
256
+ reason: string;
257
+ },
258
+ ws: WSContext,
259
+ ) => {
260
+ if (event.wasClean) {
261
+ logger().info("websocket closed", {
262
+ code: event.code,
263
+ reason: event.reason,
264
+ wasClean: event.wasClean,
265
+ });
266
+ } else {
267
+ logger().warn("websocket closed", {
268
+ code: event.code,
269
+ reason: event.reason,
270
+ wasClean: event.wasClean,
271
+ });
272
+ }
273
+
274
+ // HACK: Close socket in order to fix bug with Cloudflare leaving WS in closing state
275
+ // https://github.com/cloudflare/workerd/issues/2569
276
+ ws.close(1000, "hack_force_close");
277
+
278
+ // Handle cleanup asynchronously
279
+ handlersPromise
280
+ .then(({ conn, actor, connId }) => {
281
+ const connGlobalState =
282
+ actorDriver.getGenericConnGlobalState(actorId);
283
+ const didDelete = connGlobalState.websockets.delete(connId);
284
+ if (didDelete) {
285
+ logger().info("removing websocket for conn", {
286
+ totalCount: connGlobalState.websockets.size,
287
+ });
288
+ } else {
289
+ logger().warn("websocket does not exist for conn", {
290
+ actorId,
291
+ totalCount: connGlobalState.websockets.size,
292
+ });
293
+ }
294
+
295
+ actor.__removeConn(conn);
296
+ })
297
+ .catch((error) => {
298
+ deconstructError(
299
+ error,
300
+ logger(),
301
+ { wsEvent: "close" },
302
+ exposeInternalError,
303
+ );
304
+ });
305
+ },
306
+ onError: (_error: unknown) => {
307
+ try {
308
+ // Actors don't need to know about this, since it's abstracted away
309
+ logger().warn("websocket error");
310
+ } catch (error) {
311
+ deconstructError(
312
+ error,
313
+ logger(),
314
+ { wsEvent: "error" },
315
+ exposeInternalError,
316
+ );
317
+ }
318
+ },
319
+ };
320
+ }
321
+
322
+ /**
323
+ * Creates an SSE connection handler
324
+ */
325
+ export async function handleSseConnect(
326
+ c: HonoContext,
327
+ _runConfig: RunConfig,
328
+ actorDriver: ActorDriver,
329
+ actorId: string,
330
+ authData: unknown,
331
+ ) {
332
+ const encoding = getRequestEncoding(c.req);
333
+ const parameters = getRequestConnParams(c.req);
334
+
335
+ // Return the main handler with all async work inside
336
+ return streamSSE(c, async (stream) => {
337
+ let actor: AnyActorInstance | undefined;
338
+ let connId: string | undefined;
339
+ let connToken: string | undefined;
340
+ let connState: unknown;
341
+ let conn: AnyConn | undefined;
342
+
343
+ try {
344
+ // Do all async work inside the handler
345
+ actor = await actorDriver.loadActor(actorId);
346
+ connId = generateConnId();
347
+ connToken = generateConnToken();
348
+ connState = await actor.prepareConn(parameters, c.req.raw);
349
+
350
+ logger().debug("sse open");
351
+
352
+ // Save stream
353
+ actorDriver
354
+ .getGenericConnGlobalState(actorId)
355
+ .sseStreams.set(connId, stream);
356
+
357
+ // Create connection
358
+ conn = await actor.createConn(
359
+ connId,
360
+ connToken,
361
+ parameters,
362
+ connState,
363
+ CONNECTION_DRIVER_SSE,
364
+ { encoding } satisfies GenericSseDriverState,
365
+ authData,
366
+ );
367
+
368
+ // Wait for close
369
+ const abortResolver = Promise.withResolvers();
370
+
371
+ // Handle stream abort (when client closes the connection)
372
+ stream.onAbort(async () => {
373
+ try {
374
+ logger().debug("sse stream aborted");
375
+
376
+ // Cleanup
377
+ if (connId) {
378
+ actorDriver
379
+ .getGenericConnGlobalState(actorId)
380
+ .sseStreams.delete(connId);
381
+ }
382
+ if (conn && actor) {
383
+ actor.__removeConn(conn);
384
+ }
385
+
386
+ abortResolver.resolve(undefined);
387
+ } catch (error) {
388
+ logger().error("error closing sse connection", { error });
389
+ abortResolver.resolve(undefined);
390
+ }
391
+ });
392
+
393
+ // HACK: Will throw if not configured
394
+ try {
395
+ c.executionCtx.waitUntil(abortResolver.promise);
396
+ } catch {}
397
+
398
+ // Wait until connection aborted
399
+ await abortResolver.promise;
400
+ } catch (error) {
401
+ logger().error("error in sse connection", { error });
402
+
403
+ // Cleanup on error
404
+ if (connId !== undefined) {
405
+ actorDriver
406
+ .getGenericConnGlobalState(actorId)
407
+ .sseStreams.delete(connId);
408
+ }
409
+ if (conn && actor !== undefined) {
410
+ actor.__removeConn(conn);
411
+ }
412
+
413
+ // Close the stream on error
414
+ stream.close();
415
+ }
416
+ });
417
+ }
418
+
419
+ /**
420
+ * Creates an action handler
421
+ */
422
+ export async function handleAction(
423
+ c: HonoContext,
424
+ _runConfig: RunConfig,
425
+ actorDriver: ActorDriver,
426
+ actionName: string,
427
+ actorId: string,
428
+ authData: unknown,
429
+ ) {
430
+ const encoding = getRequestEncoding(c.req);
431
+ const parameters = getRequestConnParams(c.req);
432
+
433
+ logger().debug("handling action", { actionName, encoding });
434
+
435
+ // Validate incoming request
436
+ const arrayBuffer = await c.req.arrayBuffer();
437
+ const request = deserializeWithEncoding(
438
+ encoding,
439
+ new Uint8Array(arrayBuffer),
440
+ HTTP_ACTION_REQUEST_VERSIONED,
441
+ );
442
+ const actionArgs = cbor.decode(new Uint8Array(request.args));
443
+
444
+ // Invoke the action
445
+ let actor: AnyActorInstance | undefined;
446
+ let conn: AnyConn | undefined;
447
+ let output: unknown | undefined;
448
+ try {
449
+ actor = await actorDriver.loadActor(actorId);
450
+
451
+ // Create conn
452
+ const connState = await actor.prepareConn(parameters, c.req.raw);
453
+ conn = await actor.createConn(
454
+ generateConnId(),
455
+ generateConnToken(),
456
+ parameters,
457
+ connState,
458
+ CONNECTION_DRIVER_HTTP,
459
+ {} satisfies GenericHttpDriverState,
460
+ authData,
461
+ );
462
+
463
+ // Call action
464
+ const ctx = new ActionContext(actor.actorContext!, conn!);
465
+ output = await actor.executeAction(ctx, actionName, actionArgs);
466
+ } finally {
467
+ if (conn) {
468
+ actor?.__removeConn(conn);
469
+ }
470
+ }
471
+
472
+ // Send response
473
+ const responseData: protocol.HttpActionResponse = {
474
+ output: bufferToArrayBuffer(cbor.encode(output)),
475
+ };
476
+ const serialized = serializeWithEncoding(
477
+ encoding,
478
+ responseData,
479
+ HTTP_ACTION_RESPONSE_VERSIONED,
480
+ );
481
+ return c.body(serialized as Uint8Array, 200, {
482
+ "Content-Type": contentTypeForEncoding(encoding),
483
+ });
484
+ }
485
+
486
+ /**
487
+ * Create a connection message handler
488
+ */
489
+ export async function handleConnectionMessage(
490
+ c: HonoContext,
491
+ _runConfig: RunConfig,
492
+ actorDriver: ActorDriver,
493
+ connId: string,
494
+ connToken: string,
495
+ actorId: string,
496
+ ) {
497
+ const encoding = getRequestEncoding(c.req);
498
+
499
+ // Validate incoming request
500
+ const arrayBuffer = await c.req.arrayBuffer();
501
+ const message = deserializeWithEncoding(
502
+ encoding,
503
+ new Uint8Array(arrayBuffer),
504
+ TO_SERVER_VERSIONED,
505
+ );
506
+
507
+ const actor = await actorDriver.loadActor(actorId);
508
+
509
+ // Find connection
510
+ const conn = actor.conns.get(connId);
511
+ if (!conn) {
512
+ throw new errors.ConnNotFound(connId);
513
+ }
514
+
515
+ // Authenticate connection
516
+ if (conn._token !== connToken) {
517
+ throw new errors.IncorrectConnToken();
518
+ }
519
+
520
+ // Process message
521
+ await actor.processMessage(message, conn);
522
+
523
+ return c.json({});
524
+ }
525
+
526
+ export async function handleRawWebSocketHandler(
527
+ req: Request | undefined,
528
+ path: string,
529
+ actorDriver: ActorDriver,
530
+ actorId: string,
531
+ authData: unknown,
532
+ ): Promise<UpgradeWebSocketArgs> {
533
+ const actor = await actorDriver.loadActor(actorId);
534
+
535
+ // Return WebSocket event handlers
536
+ return {
537
+ onOpen: (_evt: any, ws: any) => {
538
+ // Wrap the Hono WebSocket in our adapter
539
+ const adapter = new HonoWebSocketAdapter(ws);
540
+
541
+ // Store adapter reference on the WebSocket for event handlers
542
+ (ws as any).__adapter = adapter;
543
+
544
+ // Extract the path after prefix and preserve query parameters
545
+ // Use URL API for cleaner parsing
546
+ const url = new URL(path, "http://actor");
547
+ const pathname = url.pathname.replace(/^\/raw\/websocket/, "") || "/";
548
+ const normalizedPath = pathname + url.search;
549
+
550
+ let newRequest: Request;
551
+ if (req) {
552
+ newRequest = new Request(`http://actor${normalizedPath}`, req);
553
+ } else {
554
+ newRequest = new Request(`http://actor${normalizedPath}`, {
555
+ method: "GET",
556
+ });
557
+ }
558
+
559
+ logger().debug("rewriting websocket url", {
560
+ from: path,
561
+ to: newRequest.url,
562
+ });
563
+
564
+ // Call the actor's onWebSocket handler with the adapted WebSocket
565
+ actor.handleWebSocket(adapter, {
566
+ request: newRequest,
567
+ auth: authData,
568
+ });
569
+ },
570
+ onMessage: (event: any, ws: any) => {
571
+ // Find the adapter for this WebSocket
572
+ const adapter = (ws as any).__adapter;
573
+ if (adapter) {
574
+ adapter._handleMessage(event);
575
+ }
576
+ },
577
+ onClose: (evt: any, ws: any) => {
578
+ // Find the adapter for this WebSocket
579
+ const adapter = (ws as any).__adapter;
580
+ if (adapter) {
581
+ adapter._handleClose(evt?.code || 1006, evt?.reason || "");
582
+ }
583
+ },
584
+ onError: (error: any, ws: any) => {
585
+ // Find the adapter for this WebSocket
586
+ const adapter = (ws as any).__adapter;
587
+ if (adapter) {
588
+ adapter._handleError(error);
589
+ }
590
+ },
591
+ };
592
+ }
593
+
594
+ // Helper to get the connection encoding from a request
595
+ export function getRequestEncoding(req: HonoRequest): Encoding {
596
+ const encodingParam = req.header(HEADER_ENCODING);
597
+ if (!encodingParam) {
598
+ throw new errors.InvalidEncoding("undefined");
599
+ }
600
+
601
+ const result = EncodingSchema.safeParse(encodingParam);
602
+ if (!result.success) {
603
+ throw new errors.InvalidEncoding(encodingParam as string);
604
+ }
605
+
606
+ return result.data;
607
+ }
608
+
609
+ export function getRequestExposeInternalError(req: Request): boolean {
610
+ const param = req.headers.get(HEADER_EXPOSE_INTERNAL_ERROR);
611
+ if (!param) {
612
+ return false;
613
+ }
614
+
615
+ return param === "true";
616
+ }
617
+
618
+ export function getRequestQuery(c: HonoContext): unknown {
619
+ // Get query parameters for actor lookup
620
+ const queryParam = c.req.header(HEADER_ACTOR_QUERY);
621
+ if (!queryParam) {
622
+ logger().error("missing query parameter");
623
+ throw new errors.InvalidRequest("missing query");
624
+ }
625
+
626
+ // Parse the query JSON and validate with schema
627
+ try {
628
+ const parsed = JSON.parse(queryParam);
629
+ return parsed;
630
+ } catch (error) {
631
+ logger().error("invalid query json", { error });
632
+ throw new errors.InvalidQueryJSON(error);
633
+ }
634
+ }
635
+
636
+ export const HEADER_ACTOR_QUERY = "X-RivetKit-Query";
637
+
638
+ export const HEADER_ENCODING = "X-RivetKit-Encoding";
639
+
640
+ // Internal header
641
+ export const HEADER_EXPOSE_INTERNAL_ERROR = "X-RivetKit-Expose-Internal-Error";
642
+
643
+ // IMPORTANT: Params must be in headers or in an E2EE part of the request (i.e. NOT the URL or query string) in order to ensure that tokens can be securely passed in params.
644
+ export const HEADER_CONN_PARAMS = "X-RivetKit-Conn-Params";
645
+
646
+ // Internal header
647
+ export const HEADER_AUTH_DATA = "X-RivetKit-Auth-Data";
648
+
649
+ export const HEADER_ACTOR_ID = "X-RivetKit-Actor";
650
+
651
+ export const HEADER_CONN_ID = "X-RivetKit-Conn";
652
+
653
+ export const HEADER_CONN_TOKEN = "X-RivetKit-Conn-Token";
654
+
655
+ /**
656
+ * Headers that publics can send from public clients.
657
+ *
658
+ * Used for CORS.
659
+ **/
660
+ export const ALLOWED_PUBLIC_HEADERS = [
661
+ "Content-Type",
662
+ "User-Agent",
663
+ HEADER_ACTOR_QUERY,
664
+ HEADER_ENCODING,
665
+ HEADER_CONN_PARAMS,
666
+ HEADER_ACTOR_ID,
667
+ HEADER_CONN_ID,
668
+ HEADER_CONN_TOKEN,
669
+ ];
670
+
671
+ // Helper to get connection parameters for the request
672
+ export function getRequestConnParams(req: HonoRequest): unknown {
673
+ const paramsParam = req.header(HEADER_CONN_PARAMS);
674
+ if (!paramsParam) {
675
+ return null;
676
+ }
677
+
678
+ try {
679
+ return JSON.parse(paramsParam);
680
+ } catch (err) {
681
+ throw new errors.InvalidParams(
682
+ `Invalid params JSON: ${stringifyError(err)}`,
683
+ );
684
+ }
685
+ }