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,422 @@
1
+ import type { DeconstructedError } from "@/common/utils";
2
+
3
+ export const INTERNAL_ERROR_CODE = "internal_error";
4
+ export const INTERNAL_ERROR_DESCRIPTION =
5
+ "Internal error. Read the server logs for more details.";
6
+ export type InternalErrorMetadata = {};
7
+
8
+ export const USER_ERROR_CODE = "user_error";
9
+
10
+ interface ActorErrorOptions extends ErrorOptions {
11
+ /** Error data can safely be serialized in a response to the client. */
12
+ public?: boolean;
13
+ /** Metadata associated with this error. This will be sent to clients. */
14
+ metadata?: unknown;
15
+ }
16
+
17
+ export class ActorError extends Error {
18
+ __type = "ActorError";
19
+
20
+ public public: boolean;
21
+ public metadata?: unknown;
22
+ public statusCode = 500;
23
+ public readonly group: string;
24
+ public readonly code: string;
25
+
26
+ public static isActorError(
27
+ error: unknown,
28
+ ): error is ActorError | DeconstructedError {
29
+ return (
30
+ typeof error === "object" &&
31
+ (error as ActorError | DeconstructedError).__type === "ActorError"
32
+ );
33
+ }
34
+
35
+ constructor(
36
+ group: string,
37
+ code: string,
38
+ message: string,
39
+ opts?: ActorErrorOptions,
40
+ ) {
41
+ super(message, { cause: opts?.cause });
42
+ this.group = group;
43
+ this.code = code;
44
+ this.public = opts?.public ?? false;
45
+ this.metadata = opts?.metadata;
46
+
47
+ // Set status code based on error type
48
+ if (opts?.public) {
49
+ this.statusCode = 400; // Bad request for public errors
50
+ }
51
+ }
52
+
53
+ toString() {
54
+ // Force stringify to return the message
55
+ return this.message;
56
+ }
57
+
58
+ /**
59
+ * Serialize error for HTTP response
60
+ */
61
+ serializeForHttp() {
62
+ return {
63
+ type: this.code,
64
+ message: this.message,
65
+ metadata: this.metadata,
66
+ };
67
+ }
68
+ }
69
+
70
+ export class InternalError extends ActorError {
71
+ constructor(message: string) {
72
+ super("actor", INTERNAL_ERROR_CODE, message);
73
+ }
74
+ }
75
+
76
+ export class Unreachable extends InternalError {
77
+ constructor(x: never) {
78
+ super(`Unreachable case: ${x}`);
79
+ }
80
+ }
81
+
82
+ export class StateNotEnabled extends ActorError {
83
+ constructor() {
84
+ super(
85
+ "actor",
86
+ "state_not_enabled",
87
+ "State not enabled. Must implement `createState` or `state` to use state. (https://www.rivet.dev/docs/actors/state/#initializing-state)",
88
+ );
89
+ }
90
+ }
91
+
92
+ export class ConnStateNotEnabled extends ActorError {
93
+ constructor() {
94
+ super(
95
+ "actor",
96
+ "conn_state_not_enabled",
97
+ "Connection state not enabled. Must implement `createConnectionState` or `connectionState` to use connection state. (https://www.rivet.dev/docs/actors/connections/#connection-state)",
98
+ );
99
+ }
100
+ }
101
+
102
+ export class VarsNotEnabled extends ActorError {
103
+ constructor() {
104
+ super(
105
+ "actor",
106
+ "vars_not_enabled",
107
+ "Variables not enabled. Must implement `createVars` or `vars` to use state. (https://www.rivet.dev/docs/actors/ephemeral-variables/#initializing-variables)",
108
+ );
109
+ }
110
+ }
111
+
112
+ export class ActionTimedOut extends ActorError {
113
+ constructor() {
114
+ super(
115
+ "action",
116
+ "timed_out",
117
+ "Action timed out. This can be increased with: `actor({ options: { action: { timeout: ... } } })`",
118
+ { public: true },
119
+ );
120
+ }
121
+ }
122
+
123
+ export class ActionNotFound extends ActorError {
124
+ constructor(name: string) {
125
+ super(
126
+ "action",
127
+ "not_found",
128
+ `Action '${name}' not found. Validate the action exists on your actor.`,
129
+ { public: true },
130
+ );
131
+ }
132
+ }
133
+
134
+ export class InvalidEncoding extends ActorError {
135
+ constructor(format?: string) {
136
+ super(
137
+ "encoding",
138
+ "invalid",
139
+ `Invalid encoding \`${format}\`. (https://www.rivet.dev/docs/actors/clients/#actor-client)`,
140
+ {
141
+ public: true,
142
+ },
143
+ );
144
+ }
145
+ }
146
+
147
+ export class ConnNotFound extends ActorError {
148
+ constructor(id?: string) {
149
+ super("connection", "not_found", `Connection not found for ID: ${id}`, {
150
+ public: true,
151
+ });
152
+ }
153
+ }
154
+
155
+ export class IncorrectConnToken extends ActorError {
156
+ constructor() {
157
+ super("connection", "incorrect_token", "Incorrect connection token.", {
158
+ public: true,
159
+ });
160
+ }
161
+ }
162
+
163
+ export class MessageTooLong extends ActorError {
164
+ constructor() {
165
+ super(
166
+ "message",
167
+ "too_long",
168
+ "Message too long. This can be configured with: `registry.runServer({ maxIncomingMessageSize: ... })`",
169
+ { public: true },
170
+ );
171
+ }
172
+ }
173
+
174
+ export class MalformedMessage extends ActorError {
175
+ constructor(cause?: unknown) {
176
+ super("message", "malformed", `Malformed message: ${cause}`, {
177
+ public: true,
178
+ cause,
179
+ });
180
+ }
181
+ }
182
+
183
+ export interface InvalidStateTypeOptions {
184
+ path?: unknown;
185
+ }
186
+
187
+ export class InvalidStateType extends ActorError {
188
+ constructor(opts?: InvalidStateTypeOptions) {
189
+ let msg = "";
190
+ if (opts?.path) {
191
+ msg += `Attempted to set invalid state at path \`${opts.path}\`.`;
192
+ } else {
193
+ msg += "Attempted to set invalid state.";
194
+ }
195
+ msg +=
196
+ " Valid types include: null, undefined, boolean, string, number, BigInt, Date, RegExp, Error, typed arrays (Uint8Array, Int8Array, Float32Array, etc.), Map, Set, Array, and plain objects. (https://www.rivet.dev/docs/actors/state/#limitations)";
197
+ super("state", "invalid_type", msg);
198
+ }
199
+ }
200
+
201
+ export class Unsupported extends ActorError {
202
+ constructor(feature: string) {
203
+ super("feature", "unsupported", `Unsupported feature: ${feature}`);
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Options for the UserError class.
209
+ */
210
+ export interface UserErrorOptions extends ErrorOptions {
211
+ /**
212
+ * Machine readable code for this error. Useful for catching different types of errors in try-catch.
213
+ */
214
+ code?: string;
215
+
216
+ /**
217
+ * Additional metadata related to the error. Useful for understanding context about the error.
218
+ */
219
+ metadata?: unknown;
220
+ }
221
+
222
+ /** Error that can be safely returned to the user. */
223
+ export class UserError extends ActorError {
224
+ /**
225
+ * Constructs a new UserError instance.
226
+ *
227
+ * @param message - The error message to be displayed.
228
+ * @param opts - Optional parameters for the error, including a machine-readable code and additional metadata.
229
+ */
230
+ constructor(message: string, opts?: UserErrorOptions) {
231
+ super("user", opts?.code ?? USER_ERROR_CODE, message, {
232
+ public: true,
233
+ metadata: opts?.metadata,
234
+ });
235
+ }
236
+ }
237
+
238
+ export class InvalidQueryJSON extends ActorError {
239
+ constructor(error?: unknown) {
240
+ super("request", "invalid_query_json", `Invalid query JSON: ${error}`, {
241
+ public: true,
242
+ cause: error,
243
+ });
244
+ }
245
+ }
246
+
247
+ export class InvalidRequest extends ActorError {
248
+ constructor(error?: unknown) {
249
+ super("request", "invalid", `Invalid request: ${error}`, {
250
+ public: true,
251
+ cause: error,
252
+ });
253
+ }
254
+ }
255
+
256
+ export class ActorNotFound extends ActorError {
257
+ constructor(identifier?: string) {
258
+ super(
259
+ "actor",
260
+ "not_found",
261
+ identifier
262
+ ? `Actor not found: ${identifier} (https://www.rivet.dev/docs/actors/clients/#actor-client)`
263
+ : "Actor not found (https://www.rivet.dev/docs/actors/clients/#actor-client)",
264
+ { public: true },
265
+ );
266
+ }
267
+ }
268
+
269
+ export class ActorAlreadyExists extends ActorError {
270
+ constructor(name: string, key: string[]) {
271
+ super(
272
+ "actor",
273
+ "already_exists",
274
+ `Actor already exists with name '${name}' and key '${JSON.stringify(key)}' (https://www.rivet.dev/docs/actors/clients/#actor-client)`,
275
+ { public: true },
276
+ );
277
+ }
278
+ }
279
+
280
+ export class ProxyError extends ActorError {
281
+ constructor(operation: string, error?: unknown) {
282
+ super(
283
+ "proxy",
284
+ "error",
285
+ `Error proxying ${operation}, this is likely an internal error: ${error}`,
286
+ {
287
+ public: true,
288
+ cause: error,
289
+ },
290
+ );
291
+ }
292
+ }
293
+
294
+ export class InvalidActionRequest extends ActorError {
295
+ constructor(message: string) {
296
+ super("action", "invalid_request", message, { public: true });
297
+ }
298
+ }
299
+
300
+ export class InvalidParams extends ActorError {
301
+ constructor(message: string) {
302
+ super("params", "invalid", message, { public: true });
303
+ }
304
+ }
305
+
306
+ export class Unauthorized extends ActorError {
307
+ constructor(message?: string) {
308
+ super(
309
+ "auth",
310
+ "unauthorized",
311
+ message ??
312
+ "Unauthorized. Access denied. (https://www.rivet.dev/docs/actors/authentication/)",
313
+ {
314
+ public: true,
315
+ },
316
+ );
317
+ this.statusCode = 401;
318
+ }
319
+ }
320
+
321
+ export class Forbidden extends ActorError {
322
+ constructor(message?: string, opts?: { metadata?: unknown }) {
323
+ super(
324
+ "auth",
325
+ "forbidden",
326
+ message ??
327
+ "Forbidden. Access denied. (https://www.rivet.dev/docs/actors/authentication/)",
328
+ {
329
+ public: true,
330
+ metadata: opts?.metadata,
331
+ },
332
+ );
333
+ this.statusCode = 403;
334
+ }
335
+ }
336
+
337
+ export class DatabaseNotEnabled extends ActorError {
338
+ constructor() {
339
+ super(
340
+ "database",
341
+ "not_enabled",
342
+ "Database not enabled. Must implement `database` to use database.",
343
+ );
344
+ }
345
+ }
346
+
347
+ export class FetchHandlerNotDefined extends ActorError {
348
+ constructor() {
349
+ super(
350
+ "handler",
351
+ "fetch_not_defined",
352
+ "Raw HTTP handler not defined. Actor must implement `onFetch` to handle raw HTTP requests. (https://www.rivet.dev/docs/actors/fetch-and-websocket-handler/)",
353
+ { public: true },
354
+ );
355
+ this.statusCode = 404;
356
+ }
357
+ }
358
+
359
+ export class WebSocketHandlerNotDefined extends ActorError {
360
+ constructor() {
361
+ super(
362
+ "handler",
363
+ "websocket_not_defined",
364
+ "Raw WebSocket handler not defined. Actor must implement `onWebSocket` to handle raw WebSocket connections. (https://www.rivet.dev/docs/actors/fetch-and-websocket-handler/)",
365
+ { public: true },
366
+ );
367
+ this.statusCode = 404;
368
+ }
369
+ }
370
+
371
+ export class InvalidFetchResponse extends ActorError {
372
+ constructor() {
373
+ super(
374
+ "handler",
375
+ "invalid_fetch_response",
376
+ "Actor's onFetch handler must return a Response object. Returning void/undefined is not allowed. (https://www.rivet.dev/docs/actors/fetch-and-websocket-handler/)",
377
+ { public: true },
378
+ );
379
+ this.statusCode = 500;
380
+ }
381
+ }
382
+
383
+ // Manager-specific errors
384
+ export class MissingActorHeader extends ActorError {
385
+ constructor() {
386
+ super(
387
+ "request",
388
+ "missing_actor_header",
389
+ "Missing x-rivet-actor header when x-rivet-target=actor",
390
+ { public: true },
391
+ );
392
+ this.statusCode = 400;
393
+ }
394
+ }
395
+
396
+ export class WebSocketsNotEnabled extends ActorError {
397
+ constructor() {
398
+ super(
399
+ "driver",
400
+ "websockets_not_enabled",
401
+ "WebSockets are not enabled for this driver",
402
+ { public: true },
403
+ );
404
+ this.statusCode = 400;
405
+ }
406
+ }
407
+
408
+ export class FeatureNotImplemented extends ActorError {
409
+ constructor(feature: string) {
410
+ super("feature", "not_implemented", `${feature} is not implemented`, {
411
+ public: true,
412
+ });
413
+ this.statusCode = 501;
414
+ }
415
+ }
416
+
417
+ export class RouteNotFound extends ActorError {
418
+ constructor() {
419
+ super("route", "not_found", "Route not found", { public: true });
420
+ this.statusCode = 404;
421
+ }
422
+ }
@@ -0,0 +1,246 @@
1
+ import type { SSEStreamingApi } from "hono/streaming";
2
+ import type { WSContext } from "hono/ws";
3
+ import type { WebSocket } from "ws";
4
+ import {
5
+ type AnyConn,
6
+ CONNECTION_DRIVER_HTTP,
7
+ CONNECTION_DRIVER_SSE,
8
+ CONNECTION_DRIVER_WEBSOCKET,
9
+ } from "@/actor/connection";
10
+ import {
11
+ type ConnDriver,
12
+ type ConnectionDriversMap,
13
+ ConnectionReadyState,
14
+ } from "@/actor/driver";
15
+ import type { AnyActorInstance } from "@/actor/instance";
16
+ import type { CachedSerializer, Encoding } from "@/actor/protocol/serde";
17
+ import { encodeDataToString } from "@/actor/protocol/serde";
18
+ import type * as protocol from "@/schemas/client-protocol/mod";
19
+ import { loggerWithoutContext } from "./log";
20
+
21
+ // This state is different than `PersistedConn` state since the connection-specific state is persisted & must be serializable. This is also part of the connection driver, not part of the core actor.
22
+ //
23
+ // This holds the actual connections, which are not serializable.
24
+ //
25
+ // This is scoped to each actor. Do not share between multiple actors.
26
+ export class GenericConnGlobalState {
27
+ websockets = new Map<string, WSContext>();
28
+ sseStreams = new Map<string, SSEStreamingApi>();
29
+ }
30
+
31
+ /**
32
+ * Exposes connection drivers for platforms that support vanilla WebSocket, SSE, and HTTP.
33
+ */
34
+ export function createGenericConnDrivers(
35
+ globalState: GenericConnGlobalState,
36
+ ): ConnectionDriversMap {
37
+ return {
38
+ [CONNECTION_DRIVER_WEBSOCKET]: createGenericWebSocketDriver(globalState),
39
+ [CONNECTION_DRIVER_SSE]: createGenericSseDriver(globalState),
40
+ [CONNECTION_DRIVER_HTTP]: createGenericHttpDriver(),
41
+ };
42
+ }
43
+
44
+ // MARK: WebSocket
45
+ export interface GenericWebSocketDriverState {
46
+ encoding: Encoding;
47
+ }
48
+
49
+ export function createGenericWebSocketDriver(
50
+ globalState: GenericConnGlobalState,
51
+ ): ConnDriver<GenericWebSocketDriverState> {
52
+ return {
53
+ sendMessage: (
54
+ actor: AnyActorInstance,
55
+ conn: AnyConn,
56
+ state: GenericWebSocketDriverState,
57
+ message: CachedSerializer<protocol.ToClient>,
58
+ ) => {
59
+ const ws = globalState.websockets.get(conn.id);
60
+ if (!ws) {
61
+ actor.rLog.warn({
62
+ msg: "missing ws for sendMessage",
63
+ actorId: actor.id,
64
+ connId: conn.id,
65
+ totalCount: globalState.websockets.size,
66
+ });
67
+ return;
68
+ }
69
+
70
+ const serialized = message.serialize(state.encoding);
71
+
72
+ actor.rLog.debug({
73
+ msg: "sending websocket message",
74
+ encoding: state.encoding,
75
+ dataType: typeof serialized,
76
+ isUint8Array: serialized instanceof Uint8Array,
77
+ isArrayBuffer: serialized instanceof ArrayBuffer,
78
+ dataLength:
79
+ (serialized as any).byteLength || (serialized as any).length,
80
+ });
81
+
82
+ // Convert Uint8Array to ArrayBuffer for proper transmission
83
+ if (serialized instanceof Uint8Array) {
84
+ const buffer = serialized.buffer.slice(
85
+ serialized.byteOffset,
86
+ serialized.byteOffset + serialized.byteLength,
87
+ );
88
+ // Handle SharedArrayBuffer case
89
+ if (buffer instanceof SharedArrayBuffer) {
90
+ const arrayBuffer = new ArrayBuffer(buffer.byteLength);
91
+ new Uint8Array(arrayBuffer).set(new Uint8Array(buffer));
92
+ actor.rLog.debug({
93
+ msg: "converted SharedArrayBuffer to ArrayBuffer",
94
+ byteLength: arrayBuffer.byteLength,
95
+ });
96
+ ws.send(arrayBuffer);
97
+ } else {
98
+ actor.rLog.debug({
99
+ msg: "sending ArrayBuffer",
100
+ byteLength: buffer.byteLength,
101
+ });
102
+ ws.send(buffer);
103
+ }
104
+ } else {
105
+ actor.rLog.debug({
106
+ msg: "sending string data",
107
+ length: (serialized as string).length,
108
+ });
109
+ ws.send(serialized);
110
+ }
111
+ },
112
+
113
+ disconnect: async (
114
+ actor: AnyActorInstance,
115
+ conn: AnyConn,
116
+ _state: GenericWebSocketDriverState,
117
+ reason?: string,
118
+ ) => {
119
+ const ws = globalState.websockets.get(conn.id);
120
+ if (!ws) {
121
+ actor.rLog.warn({
122
+ msg: "missing ws for disconnect",
123
+ actorId: actor.id,
124
+ connId: conn.id,
125
+ totalCount: globalState.websockets.size,
126
+ });
127
+ return;
128
+ }
129
+ const raw = ws.raw as WebSocket;
130
+ if (!raw) {
131
+ actor.rLog.warn({ msg: "ws.raw does not exist" });
132
+ return;
133
+ }
134
+
135
+ // Create promise to wait for socket to close gracefully
136
+ const { promise, resolve } = Promise.withResolvers<void>();
137
+ raw.addEventListener("close", () => resolve());
138
+
139
+ // Close socket
140
+ ws.close(1000, reason);
141
+
142
+ await promise;
143
+ },
144
+
145
+ getConnectionReadyState: (
146
+ actor: AnyActorInstance,
147
+ conn: AnyConn,
148
+ ): ConnectionReadyState | undefined => {
149
+ const ws = globalState.websockets.get(conn.id);
150
+ if (!ws) {
151
+ actor.rLog.warn({
152
+ msg: "missing ws for getConnectionReadyState",
153
+ connId: conn.id,
154
+ });
155
+ return undefined;
156
+ }
157
+
158
+ const raw = ws.raw as WebSocket;
159
+
160
+ return raw.readyState as ConnectionReadyState;
161
+ },
162
+ };
163
+ }
164
+
165
+ // MARK: SSE
166
+ export interface GenericSseDriverState {
167
+ encoding: Encoding;
168
+ }
169
+
170
+ export function createGenericSseDriver(
171
+ globalState: GenericConnGlobalState,
172
+ ): ConnDriver<GenericSseDriverState> {
173
+ return {
174
+ sendMessage: (
175
+ actor: AnyActorInstance,
176
+ conn: AnyConn,
177
+ state: GenericSseDriverState,
178
+ message: CachedSerializer<protocol.ToClient>,
179
+ ) => {
180
+ const stream = globalState.sseStreams.get(conn.id);
181
+ if (!stream) {
182
+ actor.rLog.warn({
183
+ msg: "missing sse stream for sendMessage",
184
+ connId: conn.id,
185
+ });
186
+ return;
187
+ }
188
+ stream.writeSSE({
189
+ data: encodeDataToString(message.serialize(state.encoding)),
190
+ });
191
+ },
192
+
193
+ disconnect: async (
194
+ actor: AnyActorInstance,
195
+ conn: AnyConn,
196
+ _state: GenericSseDriverState,
197
+ _reason?: string,
198
+ ) => {
199
+ const stream = globalState.sseStreams.get(conn.id);
200
+ if (!stream) {
201
+ actor.rLog.warn({
202
+ msg: "missing sse stream for disconnect",
203
+ connId: conn.id,
204
+ });
205
+ return;
206
+ }
207
+
208
+ stream.close();
209
+ },
210
+
211
+ getConnectionReadyState: (
212
+ actor: AnyActorInstance,
213
+ conn: AnyConn,
214
+ ): ConnectionReadyState | undefined => {
215
+ const stream = globalState.sseStreams.get(conn.id);
216
+ if (!stream) {
217
+ actor.rLog.warn({
218
+ msg: "missing sse stream for getConnectionReadyState",
219
+ connId: conn.id,
220
+ });
221
+ return undefined;
222
+ }
223
+
224
+ if (stream.aborted || stream.closed) {
225
+ return ConnectionReadyState.CLOSED;
226
+ }
227
+
228
+ return ConnectionReadyState.OPEN;
229
+ },
230
+ };
231
+ }
232
+
233
+ // MARK: HTTP
234
+ export type GenericHttpDriverState = Record<never, never>;
235
+
236
+ export function createGenericHttpDriver(): ConnDriver<GenericHttpDriverState> {
237
+ return {
238
+ getConnectionReadyState(_actor, _conn) {
239
+ // TODO: This might not be the correct logic
240
+ return ConnectionReadyState.OPEN;
241
+ },
242
+ disconnect: async () => {
243
+ // Noop
244
+ },
245
+ };
246
+ }