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,336 @@
1
+ import type { Next } from "hono";
2
+ import type { ContentfulStatusCode } from "hono/utils/http-status";
3
+ import * as errors from "@/actor/errors";
4
+ import { getEnvUniversal } from "@/utils";
5
+ import type { Logger } from "./log";
6
+
7
+ export function assertUnreachable(x: never): never {
8
+ throw new Error(`Unreachable case: ${x}`);
9
+ }
10
+
11
+ /**
12
+ * Safely stringifies an object, ensuring that the stringified object is under a certain size.
13
+ * @param obj any object to stringify
14
+ * @param maxSize maximum size of the stringified object in bytes
15
+ * @returns stringified object
16
+ */
17
+ export function safeStringify(obj: unknown, maxSize: number) {
18
+ let size = 0;
19
+
20
+ function replacer(key: string, value: unknown) {
21
+ if (value === null || value === undefined) return value;
22
+ const valueSize =
23
+ typeof value === "string" ? value.length : JSON.stringify(value).length;
24
+ size += key.length + valueSize;
25
+
26
+ if (size > maxSize) {
27
+ throw new Error(`JSON object exceeds size limit of ${maxSize} bytes.`);
28
+ }
29
+
30
+ return value;
31
+ }
32
+
33
+ return JSON.stringify(obj, replacer);
34
+ }
35
+
36
+ // TODO: Instead of doing this, use a temp var for state and attempt to write
37
+ // it. Roll back state if fails to serialize.
38
+
39
+ /**
40
+ * Check if a value is CBOR serializable.
41
+ * Optionally pass an onInvalid callback to receive the path to invalid values.
42
+ *
43
+ * For a complete list of supported CBOR tags, see:
44
+ * https://github.com/kriszyp/cbor-x/blob/cc1cf9df8ba72288c7842af1dd374d73e34cdbc1/README.md#list-of-supported-tags-for-decoding
45
+ */
46
+ export function isCborSerializable(
47
+ value: unknown,
48
+ onInvalid?: (path: string) => void,
49
+ currentPath = "",
50
+ ): boolean {
51
+ // Handle primitive types directly
52
+ if (value === null || value === undefined) {
53
+ return true;
54
+ }
55
+
56
+ if (typeof value === "number") {
57
+ if (!Number.isFinite(value)) {
58
+ onInvalid?.(currentPath);
59
+ return false;
60
+ }
61
+ return true;
62
+ }
63
+
64
+ if (typeof value === "boolean" || typeof value === "string") {
65
+ return true;
66
+ }
67
+
68
+ // Handle BigInt (CBOR tags 2 and 3)
69
+ if (typeof value === "bigint") {
70
+ return true;
71
+ }
72
+
73
+ // Handle Date objects (CBOR tags 0 and 1)
74
+ if (value instanceof Date) {
75
+ return true;
76
+ }
77
+
78
+ // Handle typed arrays (CBOR tags 64-82)
79
+ if (
80
+ value instanceof Uint8Array ||
81
+ value instanceof Uint8ClampedArray ||
82
+ value instanceof Uint16Array ||
83
+ value instanceof Uint32Array ||
84
+ value instanceof BigUint64Array ||
85
+ value instanceof Int8Array ||
86
+ value instanceof Int16Array ||
87
+ value instanceof Int32Array ||
88
+ value instanceof BigInt64Array ||
89
+ value instanceof Float32Array ||
90
+ value instanceof Float64Array
91
+ ) {
92
+ return true;
93
+ }
94
+
95
+ // Handle Map (CBOR tag 259)
96
+ if (value instanceof Map) {
97
+ for (const [key, val] of value.entries()) {
98
+ const keyPath = currentPath
99
+ ? `${currentPath}.key(${String(key)})`
100
+ : `key(${String(key)})`;
101
+ const valPath = currentPath
102
+ ? `${currentPath}.value(${String(key)})`
103
+ : `value(${String(key)})`;
104
+ if (
105
+ !isCborSerializable(key, onInvalid, keyPath) ||
106
+ !isCborSerializable(val, onInvalid, valPath)
107
+ ) {
108
+ return false;
109
+ }
110
+ }
111
+ return true;
112
+ }
113
+
114
+ // Handle Set (CBOR tag 258)
115
+ if (value instanceof Set) {
116
+ let index = 0;
117
+ for (const item of value.values()) {
118
+ const itemPath = currentPath
119
+ ? `${currentPath}.set[${index}]`
120
+ : `set[${index}]`;
121
+ if (!isCborSerializable(item, onInvalid, itemPath)) {
122
+ return false;
123
+ }
124
+ index++;
125
+ }
126
+ return true;
127
+ }
128
+
129
+ // Handle RegExp (CBOR tag 27)
130
+ if (value instanceof RegExp) {
131
+ return true;
132
+ }
133
+
134
+ // Handle Error objects (CBOR tag 27)
135
+ if (value instanceof Error) {
136
+ return true;
137
+ }
138
+
139
+ // Handle arrays
140
+ if (Array.isArray(value)) {
141
+ for (let i = 0; i < value.length; i++) {
142
+ const itemPath = currentPath ? `${currentPath}[${i}]` : `[${i}]`;
143
+ if (!isCborSerializable(value[i], onInvalid, itemPath)) {
144
+ return false;
145
+ }
146
+ }
147
+ return true;
148
+ }
149
+
150
+ // Handle plain objects and records (CBOR tags 105, 51, 57344-57599)
151
+ if (typeof value === "object") {
152
+ // Allow plain objects and objects with prototypes (for records and named objects)
153
+ const proto = Object.getPrototypeOf(value);
154
+ if (proto !== null && proto !== Object.prototype) {
155
+ // Check if it's a known serializable object type
156
+ const protoConstructor = value.constructor;
157
+ if (protoConstructor && typeof protoConstructor.name === "string") {
158
+ // Allow objects with named constructors (records, named objects)
159
+ // This includes user-defined classes and built-in objects
160
+ // that CBOR can serialize with tag 27 or record tags
161
+ }
162
+ }
163
+
164
+ // Check all properties recursively
165
+ for (const key in value) {
166
+ const propPath = currentPath ? `${currentPath}.${key}` : key;
167
+ if (
168
+ !isCborSerializable(
169
+ value[key as keyof typeof value],
170
+ onInvalid,
171
+ propPath,
172
+ )
173
+ ) {
174
+ return false;
175
+ }
176
+ }
177
+ return true;
178
+ }
179
+
180
+ // Not serializable
181
+ onInvalid?.(currentPath);
182
+ return false;
183
+ }
184
+
185
+ export interface DeconstructedError {
186
+ __type: "ActorError";
187
+ statusCode: ContentfulStatusCode;
188
+ public: boolean;
189
+ group: string;
190
+ code: string;
191
+ message: string;
192
+ metadata?: unknown;
193
+ }
194
+
195
+ /** Deconstructs error in to components that are used to build responses. */
196
+ export function deconstructError(
197
+ error: unknown,
198
+ logger: Logger,
199
+ extraLog: Record<string, unknown>,
200
+ exposeInternalError = false,
201
+ ): DeconstructedError {
202
+ // Build response error information. Only return errors if flagged as public in order to prevent leaking internal behavior.
203
+ //
204
+ // We log the error here instead of after generating the code & message because we need to log the original error, not the masked internal error.
205
+ let statusCode: ContentfulStatusCode;
206
+ let public_: boolean;
207
+ let group: string;
208
+ let code: string;
209
+ let message: string;
210
+ let metadata: unknown;
211
+ if (errors.ActorError.isActorError(error) && error.public) {
212
+ // Check if error has statusCode (could be ActorError instance or DeconstructedError)
213
+ statusCode = (
214
+ "statusCode" in error && error.statusCode ? error.statusCode : 400
215
+ ) as ContentfulStatusCode;
216
+ public_ = true;
217
+ group = error.group;
218
+ code = error.code;
219
+ message = getErrorMessage(error);
220
+ metadata = error.metadata;
221
+
222
+ logger.info({
223
+ msg: "public error",
224
+ group,
225
+ code,
226
+ message,
227
+ issues: "https://github.com/rivet-dev/rivetkit/issues",
228
+ support: "https://rivet.dev/discord",
229
+ ...extraLog,
230
+ });
231
+ } else if (exposeInternalError) {
232
+ if (errors.ActorError.isActorError(error)) {
233
+ statusCode = 500;
234
+ public_ = false;
235
+ group = error.group;
236
+ code = error.code;
237
+ message = getErrorMessage(error);
238
+ metadata = error.metadata;
239
+
240
+ logger.info({
241
+ msg: "internal error",
242
+ group,
243
+ code,
244
+ message,
245
+ issues: "https://github.com/rivet-dev/rivetkit/issues",
246
+ support: "https://rivet.dev/discord",
247
+ ...extraLog,
248
+ });
249
+ } else {
250
+ statusCode = 500;
251
+ public_ = false;
252
+ group = "internal";
253
+ code = errors.INTERNAL_ERROR_CODE;
254
+ message = getErrorMessage(error);
255
+
256
+ logger.info({
257
+ msg: "internal error",
258
+ group,
259
+ code,
260
+ message,
261
+ issues: "https://github.com/rivet-dev/rivetkit/issues",
262
+ support: "https://rivet.dev/discord",
263
+ ...extraLog,
264
+ });
265
+ }
266
+ } else {
267
+ statusCode = 500;
268
+ public_ = false;
269
+ group = "internal";
270
+ code = errors.INTERNAL_ERROR_CODE;
271
+ message = errors.INTERNAL_ERROR_DESCRIPTION;
272
+ metadata = {
273
+ //url: `https://hub.rivet.dev/projects/${actorMetadata.project.slug}/environments/${actorMetadata.environment.slug}/actors?actorId=${actorMetadata.actor.id}`,
274
+ } satisfies errors.InternalErrorMetadata;
275
+
276
+ logger.warn({
277
+ msg: "internal error",
278
+ error: getErrorMessage(error),
279
+ stack: (error as Error)?.stack,
280
+ issues: "https://github.com/rivet-dev/rivetkit/issues",
281
+ support: "https://rivet.dev/discord",
282
+ ...extraLog,
283
+ });
284
+ }
285
+
286
+ return {
287
+ __type: "ActorError",
288
+ statusCode,
289
+ public: public_,
290
+ group,
291
+ code,
292
+ message,
293
+ metadata,
294
+ };
295
+ }
296
+
297
+ export function stringifyError(error: unknown): string {
298
+ if (error instanceof Error) {
299
+ if (
300
+ typeof process !== "undefined" &&
301
+ getEnvUniversal("_RIVETKIT_ERROR_STACK") === "1"
302
+ ) {
303
+ return `${error.name}: ${error.message}${error.stack ? `\n${error.stack}` : ""}`;
304
+ } else {
305
+ return `${error.name}: ${error.message}`;
306
+ }
307
+ } else if (typeof error === "string") {
308
+ return error;
309
+ } else if (typeof error === "object" && error !== null) {
310
+ try {
311
+ return `${JSON.stringify(error)}`;
312
+ } catch {
313
+ return "[cannot stringify error]";
314
+ }
315
+ } else {
316
+ return `Unknown error: ${getErrorMessage(error)}`;
317
+ }
318
+ }
319
+
320
+ function getErrorMessage(err: unknown): string {
321
+ if (
322
+ err &&
323
+ typeof err === "object" &&
324
+ "message" in err &&
325
+ typeof err.message === "string"
326
+ ) {
327
+ return err.message;
328
+ } else {
329
+ return String(err);
330
+ }
331
+ }
332
+
333
+ /** Generates a `Next` handler to pass to middleware in order to be able to call arbitrary middleware. */
334
+ export function noopNext(): Next {
335
+ return async () => {};
336
+ }
@@ -0,0 +1,95 @@
1
+ export interface VersionedData<T> {
2
+ version: number;
3
+ data: T;
4
+ }
5
+
6
+ export type MigrationFn<TFrom, TTo> = (data: TFrom) => TTo;
7
+
8
+ export interface VersionedDataConfig<T> {
9
+ currentVersion: number;
10
+ migrations: Map<number, MigrationFn<any, any>>;
11
+ serializeVersion: (data: T) => Uint8Array;
12
+ deserializeVersion: (bytes: Uint8Array) => T;
13
+ }
14
+
15
+ export class VersionedDataHandler<T> {
16
+ constructor(private config: VersionedDataConfig<T>) {}
17
+
18
+ serializeWithEmbeddedVersion(data: T): Uint8Array {
19
+ const versioned: VersionedData<Uint8Array> = {
20
+ version: this.config.currentVersion,
21
+ data: this.config.serializeVersion(data),
22
+ };
23
+
24
+ return this.embedVersion(versioned);
25
+ }
26
+
27
+ deserializeWithEmbeddedVersion(bytes: Uint8Array): T {
28
+ const versioned = this.extractVersion(bytes);
29
+ return this.deserialize(versioned.data, versioned.version);
30
+ }
31
+
32
+ serialize(data: T, version: number): Uint8Array {
33
+ return this.config.serializeVersion(data);
34
+ }
35
+
36
+ deserialize(bytes: Uint8Array, version: number): T {
37
+ if (version === this.config.currentVersion) {
38
+ return this.config.deserializeVersion(bytes);
39
+ }
40
+
41
+ if (version > this.config.currentVersion) {
42
+ throw new Error(
43
+ `Cannot decode data from version ${version}, current version is ${this.config.currentVersion}`,
44
+ );
45
+ }
46
+
47
+ let currentData: any = this.config.deserializeVersion(bytes);
48
+ let currentVersion = version;
49
+
50
+ while (currentVersion < this.config.currentVersion) {
51
+ const migration = this.config.migrations.get(currentVersion);
52
+ if (!migration) {
53
+ throw new Error(
54
+ `No migration found from version ${currentVersion} to ${currentVersion + 1}`,
55
+ );
56
+ }
57
+
58
+ currentData = migration(currentData);
59
+ currentVersion++;
60
+ }
61
+
62
+ return currentData;
63
+ }
64
+
65
+ private embedVersion(data: VersionedData<Uint8Array>): Uint8Array {
66
+ const versionBytes = new Uint8Array(4);
67
+ new DataView(versionBytes.buffer).setUint32(0, data.version, true);
68
+
69
+ const result = new Uint8Array(versionBytes.length + data.data.length);
70
+ result.set(versionBytes);
71
+ result.set(data.data, versionBytes.length);
72
+
73
+ return result;
74
+ }
75
+
76
+ private extractVersion(bytes: Uint8Array): VersionedData<Uint8Array> {
77
+ if (bytes.length < 4) {
78
+ throw new Error("Invalid versioned data: too short");
79
+ }
80
+
81
+ const version = new DataView(bytes.buffer, bytes.byteOffset).getUint32(
82
+ 0,
83
+ true,
84
+ );
85
+ const data = bytes.slice(4);
86
+
87
+ return { version, data };
88
+ }
89
+ }
90
+
91
+ export function createVersionedDataHandler<T>(
92
+ config: VersionedDataConfig<T>,
93
+ ): VersionedDataHandler<T> {
94
+ return new VersionedDataHandler(config);
95
+ }
@@ -0,0 +1,49 @@
1
+ // Define minimal event interfaces to avoid conflicts between different WebSocket implementations
2
+ export interface RivetEvent {
3
+ type: string;
4
+ target?: any;
5
+ currentTarget?: any;
6
+ }
7
+
8
+ export interface RivetMessageEvent extends RivetEvent {
9
+ data: any;
10
+ }
11
+
12
+ export interface RivetCloseEvent extends RivetEvent {
13
+ code: number;
14
+ reason: string;
15
+ wasClean: boolean;
16
+ }
17
+
18
+ /**
19
+ * Common WebSocket interface that can be implemented by different WebSocket-like classes
20
+ * This is compatible with the standard WebSocket API but allows for custom implementations
21
+ */
22
+ export interface UniversalWebSocket {
23
+ // WebSocket readyState values
24
+ readonly CONNECTING: 0;
25
+ readonly OPEN: 1;
26
+ readonly CLOSING: 2;
27
+ readonly CLOSED: 3;
28
+
29
+ // Properties
30
+ readonly readyState: 0 | 1 | 2 | 3;
31
+ binaryType: "arraybuffer" | "blob";
32
+ readonly bufferedAmount: number;
33
+ readonly extensions: string;
34
+ readonly protocol: string;
35
+ readonly url: string;
36
+
37
+ // Methods
38
+ send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void;
39
+ close(code?: number, reason?: string): void;
40
+ addEventListener(type: string, listener: (event: any) => void): void;
41
+ removeEventListener(type: string, listener: (event: any) => void): void;
42
+ dispatchEvent(event: RivetEvent): boolean;
43
+
44
+ // Event handlers (optional)
45
+ onopen?: ((event: RivetEvent) => void) | null;
46
+ onclose?: ((event: RivetCloseEvent) => void) | null;
47
+ onerror?: ((event: RivetEvent) => void) | null;
48
+ onmessage?: ((event: RivetMessageEvent) => void) | null;
49
+ }
@@ -0,0 +1,42 @@
1
+ import { logger } from "@/client/log";
2
+
3
+ // Global singleton promise that will be reused for subsequent calls
4
+ let webSocketPromise: Promise<typeof WebSocket> | null = null;
5
+
6
+ export async function importWebSocket(): Promise<typeof WebSocket> {
7
+ // Return existing promise if we already started loading
8
+ if (webSocketPromise !== null) {
9
+ return webSocketPromise;
10
+ }
11
+
12
+ // Create and store the promise
13
+ webSocketPromise = (async () => {
14
+ let _WebSocket: typeof WebSocket;
15
+
16
+ if (typeof WebSocket !== "undefined") {
17
+ // Browser environment
18
+ _WebSocket = WebSocket as unknown as typeof WebSocket;
19
+ } else {
20
+ // Node.js environment
21
+ try {
22
+ const ws = await import("ws");
23
+ _WebSocket = ws.default as unknown as typeof WebSocket;
24
+ logger().debug("using websocket from npm");
25
+ } catch {
26
+ // WS not available
27
+ _WebSocket = class MockWebSocket {
28
+ constructor() {
29
+ throw new Error(
30
+ 'WebSocket support requires installing the "ws" peer dependency.',
31
+ );
32
+ }
33
+ } as unknown as typeof WebSocket;
34
+ logger().debug("using mock websocket");
35
+ }
36
+ }
37
+
38
+ return _WebSocket;
39
+ })();
40
+
41
+ return webSocketPromise;
42
+ }
@@ -0,0 +1,22 @@
1
+ export type { ActorDriver } from "@/actor/driver";
2
+ export type { ActorInstance, AnyActorInstance } from "@/actor/instance";
3
+ export {
4
+ HEADER_ACTOR_ID,
5
+ HEADER_ACTOR_QUERY,
6
+ HEADER_AUTH_DATA,
7
+ HEADER_CONN_ID,
8
+ HEADER_CONN_PARAMS,
9
+ HEADER_CONN_TOKEN,
10
+ HEADER_ENCODING,
11
+ } from "@/actor/router-endpoints";
12
+ export type {
13
+ ActorOutput,
14
+ CreateInput,
15
+ GetForIdInput,
16
+ GetOrCreateWithKeyInput,
17
+ GetWithKeyInput,
18
+ ManagerDisplayInformation,
19
+ ManagerDriver,
20
+ } from "@/manager/driver";
21
+ export { DriverConfigSchema, RunConfigSchema } from "@/registry/run-config";
22
+ export { serializeEmptyPersistData } from "./utils";
@@ -0,0 +1,17 @@
1
+ import * as cbor from "cbor-x";
2
+ import type * as schema from "@/schemas/actor-persist/mod";
3
+ import { PERSISTED_ACTOR_VERSIONED } from "@/schemas/actor-persist/versioned";
4
+ import { bufferToArrayBuffer } from "@/utils";
5
+
6
+ export function serializeEmptyPersistData(
7
+ input: unknown | undefined,
8
+ ): Uint8Array {
9
+ const persistData: schema.PersistedActor = {
10
+ input: input !== undefined ? bufferToArrayBuffer(cbor.encode(input)) : null,
11
+ hasInitialized: false,
12
+ state: bufferToArrayBuffer(cbor.encode(undefined)),
13
+ connections: [],
14
+ scheduledEvents: [],
15
+ };
16
+ return PERSISTED_ACTOR_VERSIONED.serializeWithEmbeddedVersion(persistData);
17
+ }
@@ -0,0 +1,5 @@
1
+ import { getLogger } from "@/common/log";
2
+
3
+ export function logger() {
4
+ return getLogger("test-suite");
5
+ }