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,15 @@
1
+ import { getLogger } from "@/common//log";
2
+
3
+ /** Logger for this library. */
4
+ export const RUNTIME_LOGGER_NAME = "actor-runtime";
5
+
6
+ /** Logger used for logs from the actor instance itself. */
7
+ export const ACTOR_LOGGER_NAME = "actor";
8
+
9
+ export function logger() {
10
+ return getLogger(RUNTIME_LOGGER_NAME);
11
+ }
12
+
13
+ export function instanceLogger() {
14
+ return getLogger(ACTOR_LOGGER_NAME);
15
+ }
@@ -0,0 +1,113 @@
1
+ import {
2
+ type Actions,
3
+ type ActorConfig,
4
+ type ActorConfigInput,
5
+ ActorConfigSchema,
6
+ ActorTypes,
7
+ } from "./config";
8
+ import type { AnyDatabaseProvider } from "./database";
9
+ import { ActorDefinition } from "./definition";
10
+
11
+ export function actor<
12
+ TState,
13
+ TConnParams,
14
+ TConnState,
15
+ TVars,
16
+ TInput,
17
+ TAuthData,
18
+ TDatabase extends AnyDatabaseProvider,
19
+ TActions extends Actions<
20
+ TState,
21
+ TConnParams,
22
+ TConnState,
23
+ TVars,
24
+ TInput,
25
+ TAuthData,
26
+ TDatabase
27
+ >,
28
+ >(
29
+ input: ActorConfigInput<
30
+ TState,
31
+ TConnParams,
32
+ TConnState,
33
+ TVars,
34
+ TInput,
35
+ TAuthData,
36
+ TDatabase,
37
+ TActions
38
+ >,
39
+ ): ActorDefinition<
40
+ TState,
41
+ TConnParams,
42
+ TConnState,
43
+ TVars,
44
+ TInput,
45
+ TAuthData,
46
+ TDatabase,
47
+ TActions
48
+ > {
49
+ const config = ActorConfigSchema.parse(input) as ActorConfig<
50
+ TState,
51
+ TConnParams,
52
+ TConnState,
53
+ TVars,
54
+ TInput,
55
+ TAuthData,
56
+ TDatabase
57
+ >;
58
+ return new ActorDefinition(config);
59
+ }
60
+ export type { Encoding } from "@/actor/protocol/serde";
61
+ export type {
62
+ UniversalErrorEvent,
63
+ UniversalEvent,
64
+ UniversalEventSource,
65
+ UniversalMessageEvent,
66
+ } from "@/common/eventsource-interface";
67
+ export type { UpgradeWebSocketArgs } from "@/common/inline-websocket-adapter2";
68
+ export type {
69
+ RivetCloseEvent,
70
+ RivetEvent,
71
+ RivetMessageEvent,
72
+ UniversalWebSocket,
73
+ } from "@/common/websocket-interface";
74
+ export type { ActorKey } from "@/manager/protocol/query";
75
+ export type { ActionContext } from "./action";
76
+ export type * from "./config";
77
+ export type {
78
+ Conn,
79
+ ConnectionDriver,
80
+ ConnectionStatus,
81
+ generateConnId,
82
+ generateConnToken,
83
+ } from "./connection";
84
+ export {
85
+ CONNECTION_DRIVER_HTTP,
86
+ CONNECTION_DRIVER_SSE,
87
+ CONNECTION_DRIVER_WEBSOCKET,
88
+ } from "./connection";
89
+ export type { ActorContext } from "./context";
90
+ export type {
91
+ ActionContextOf,
92
+ ActorContextOf,
93
+ ActorDefinition,
94
+ AnyActorDefinition,
95
+ } from "./definition";
96
+ export { lookupInRegistry } from "./definition";
97
+ export { UserError, type UserErrorOptions } from "./errors";
98
+ export {
99
+ createGenericConnDrivers,
100
+ GenericConnGlobalState,
101
+ } from "./generic-conn-driver";
102
+ export type { AnyActorInstance } from "./instance";
103
+ export {
104
+ type ActorRouter,
105
+ createActorRouter,
106
+ PATH_CONNECT_WEBSOCKET,
107
+ PATH_RAW_WEBSOCKET_PREFIX,
108
+ } from "./router";
109
+ export {
110
+ ALLOWED_PUBLIC_HEADERS,
111
+ handleRawWebSocketHandler,
112
+ handleWebSocketConnect,
113
+ } from "./router-endpoints";
@@ -0,0 +1,42 @@
1
+ import type { ConnectionDriver } from "./connection";
2
+
3
+ /** State object that gets automatically persisted to storage. */
4
+ export interface PersistedActor<S, CP, CS, I> {
5
+ input?: I;
6
+ hasInitiated: boolean;
7
+ state: S;
8
+ connections: PersistedConn<CP, CS>[];
9
+ scheduledEvents: PersistedScheduleEvent[];
10
+ }
11
+
12
+ /** Object representing connection that gets persisted to storage. */
13
+ export interface PersistedConn<CP, CS> {
14
+ connId: string;
15
+ token: string;
16
+ connDriver: ConnectionDriver;
17
+ connDriverState: unknown;
18
+ params: CP;
19
+ state: CS;
20
+ authData?: unknown;
21
+ subscriptions: PersistedSubscription[];
22
+ lastSeen: number;
23
+ }
24
+
25
+ export interface PersistedSubscription {
26
+ eventName: string;
27
+ }
28
+
29
+ export interface GenericPersistedScheduleEvent {
30
+ actionName: string;
31
+ args: ArrayBuffer | null;
32
+ }
33
+
34
+ export type PersistedScheduleEventKind = {
35
+ generic: GenericPersistedScheduleEvent;
36
+ };
37
+
38
+ export interface PersistedScheduleEvent {
39
+ eventId: string;
40
+ timestamp: number;
41
+ kind: PersistedScheduleEventKind;
42
+ }
@@ -0,0 +1,281 @@
1
+ import * as cbor from "cbor-x";
2
+ import { z } from "zod";
3
+ import type { AnyDatabaseProvider } from "@/actor/database";
4
+ import * as errors from "@/actor/errors";
5
+ import {
6
+ CachedSerializer,
7
+ type Encoding,
8
+ type InputData,
9
+ } from "@/actor/protocol/serde";
10
+ import { deconstructError } from "@/common/utils";
11
+ import type * as protocol from "@/schemas/client-protocol/mod";
12
+ import {
13
+ TO_CLIENT_VERSIONED,
14
+ TO_SERVER_VERSIONED,
15
+ } from "@/schemas/client-protocol/versioned";
16
+ import { deserializeWithEncoding } from "@/serde";
17
+ import { assertUnreachable, bufferToArrayBuffer } from "../../utils";
18
+ import { ActionContext } from "../action";
19
+ import type { Conn } from "../connection";
20
+ import type { ActorInstance } from "../instance";
21
+ import { logger } from "../log";
22
+
23
+ export const TransportSchema = z.enum(["websocket", "sse"]);
24
+
25
+ /**
26
+ * Transport mechanism used to communicate between client & actor.
27
+ */
28
+ export type Transport = z.infer<typeof TransportSchema>;
29
+
30
+ interface MessageEventOpts {
31
+ encoding: Encoding;
32
+ maxIncomingMessageSize: number;
33
+ }
34
+
35
+ function getValueLength(value: InputData): number {
36
+ if (typeof value === "string") {
37
+ return value.length;
38
+ } else if (value instanceof Blob) {
39
+ return value.size;
40
+ } else if (
41
+ value instanceof ArrayBuffer ||
42
+ value instanceof SharedArrayBuffer ||
43
+ value instanceof Uint8Array
44
+ ) {
45
+ return value.byteLength;
46
+ } else {
47
+ assertUnreachable(value);
48
+ }
49
+ }
50
+
51
+ export async function inputDataToBuffer(
52
+ data: InputData,
53
+ ): Promise<Uint8Array | string> {
54
+ if (typeof data === "string") {
55
+ return data;
56
+ } else if (data instanceof Blob) {
57
+ const arrayBuffer = await data.arrayBuffer();
58
+ return new Uint8Array(arrayBuffer);
59
+ } else if (data instanceof Uint8Array) {
60
+ return data;
61
+ } else if (data instanceof ArrayBuffer || data instanceof SharedArrayBuffer) {
62
+ return new Uint8Array(data);
63
+ } else {
64
+ throw new errors.MalformedMessage();
65
+ }
66
+ }
67
+
68
+ export async function parseMessage(
69
+ value: InputData,
70
+ opts: MessageEventOpts,
71
+ ): Promise<protocol.ToServer> {
72
+ // Validate value length
73
+ const length = getValueLength(value);
74
+ if (length > opts.maxIncomingMessageSize) {
75
+ throw new errors.MessageTooLong();
76
+ }
77
+
78
+ // Parse & validate message
79
+ const buffer = await inputDataToBuffer(value);
80
+ return deserializeWithEncoding(opts.encoding, buffer, TO_SERVER_VERSIONED);
81
+ }
82
+
83
+ export interface ProcessMessageHandler<
84
+ S,
85
+ CP,
86
+ CS,
87
+ V,
88
+ I,
89
+ AD,
90
+ DB extends AnyDatabaseProvider,
91
+ > {
92
+ onExecuteAction?: (
93
+ ctx: ActionContext<S, CP, CS, V, I, AD, DB>,
94
+ name: string,
95
+ args: unknown[],
96
+ ) => Promise<unknown>;
97
+ onSubscribe?: (
98
+ eventName: string,
99
+ conn: Conn<S, CP, CS, V, I, AD, DB>,
100
+ ) => Promise<void>;
101
+ onUnsubscribe?: (
102
+ eventName: string,
103
+ conn: Conn<S, CP, CS, V, I, AD, DB>,
104
+ ) => Promise<void>;
105
+ }
106
+
107
+ export async function processMessage<
108
+ S,
109
+ CP,
110
+ CS,
111
+ V,
112
+ I,
113
+ AD,
114
+ DB extends AnyDatabaseProvider,
115
+ >(
116
+ message: protocol.ToServer,
117
+ actor: ActorInstance<S, CP, CS, V, I, AD, DB>,
118
+ conn: Conn<S, CP, CS, V, I, AD, DB>,
119
+ handler: ProcessMessageHandler<S, CP, CS, V, I, AD, DB>,
120
+ ) {
121
+ let actionId: bigint | undefined;
122
+ let actionName: string | undefined;
123
+
124
+ try {
125
+ if (message.body.tag === "ActionRequest") {
126
+ // Action request
127
+
128
+ if (handler.onExecuteAction === undefined) {
129
+ throw new errors.Unsupported("Action");
130
+ }
131
+
132
+ const { id, name, args: argsRaw } = message.body.val;
133
+ actionId = id;
134
+ actionName = name;
135
+ const args = cbor.decode(new Uint8Array(argsRaw));
136
+
137
+ logger().debug("processing action request", {
138
+ actionId: id,
139
+ actionName: name,
140
+ });
141
+
142
+ const ctx = new ActionContext<S, CP, CS, V, I, AD, DB>(
143
+ actor.actorContext,
144
+ conn,
145
+ );
146
+
147
+ // Process the action request and wait for the result
148
+ // This will wait for async actions to complete
149
+ const output = await handler.onExecuteAction(ctx, name, args);
150
+
151
+ logger().debug("sending action response", {
152
+ actionId: id,
153
+ actionName: name,
154
+ outputType: typeof output,
155
+ isPromise: output instanceof Promise,
156
+ });
157
+
158
+ // Send the response back to the client
159
+ conn._sendMessage(
160
+ new CachedSerializer<protocol.ToClient>(
161
+ {
162
+ body: {
163
+ tag: "ActionResponse",
164
+ val: {
165
+ id: id,
166
+ output: bufferToArrayBuffer(cbor.encode(output)),
167
+ },
168
+ },
169
+ },
170
+ TO_CLIENT_VERSIONED,
171
+ ),
172
+ );
173
+
174
+ logger().debug("action response sent", { id, name: name });
175
+ } else if (message.body.tag === "SubscriptionRequest") {
176
+ // Subscription request
177
+
178
+ if (
179
+ handler.onSubscribe === undefined ||
180
+ handler.onUnsubscribe === undefined
181
+ ) {
182
+ throw new errors.Unsupported("Subscriptions");
183
+ }
184
+
185
+ const { eventName, subscribe } = message.body.val;
186
+ logger().debug("processing subscription request", {
187
+ eventName,
188
+ subscribe,
189
+ });
190
+
191
+ if (subscribe) {
192
+ await handler.onSubscribe(eventName, conn);
193
+ } else {
194
+ await handler.onUnsubscribe(eventName, conn);
195
+ }
196
+
197
+ logger().debug("subscription request completed", {
198
+ eventName,
199
+ subscribe,
200
+ });
201
+ } else {
202
+ assertUnreachable(message.body);
203
+ }
204
+ } catch (error) {
205
+ const { code, message, metadata } = deconstructError(error, logger(), {
206
+ connectionId: conn.id,
207
+ actionId,
208
+ actionName,
209
+ });
210
+
211
+ logger().debug("sending error response", {
212
+ actionId,
213
+ actionName,
214
+ code,
215
+ message,
216
+ });
217
+
218
+ // Build response
219
+ conn._sendMessage(
220
+ new CachedSerializer<protocol.ToClient>(
221
+ {
222
+ body: {
223
+ tag: "Error",
224
+ val: {
225
+ code,
226
+ message,
227
+ metadata: bufferToArrayBuffer(cbor.encode(metadata)),
228
+ actionId: actionId ?? null,
229
+ },
230
+ },
231
+ },
232
+ TO_CLIENT_VERSIONED,
233
+ ),
234
+ );
235
+
236
+ logger().debug("error response sent", { actionId, actionName });
237
+ }
238
+ }
239
+
240
+ ///**
241
+ // * Use `CachedSerializer` if serializing the same data repeatedly.
242
+ // */
243
+ //export function serialize<T>(value: T, encoding: Encoding): OutputData {
244
+ // if (encoding === "json") {
245
+ // return JSON.stringify(value);
246
+ // } else if (encoding === "cbor") {
247
+ // // TODO: Remove this hack, but cbor-x can't handle anything extra in data structures
248
+ // const cleanValue = JSON.parse(JSON.stringify(value));
249
+ // return cbor.encode(cleanValue);
250
+ // } else {
251
+ // assertUnreachable(encoding);
252
+ // }
253
+ //}
254
+ //
255
+ //export async function deserialize(data: InputData, encoding: Encoding) {
256
+ // if (encoding === "json") {
257
+ // if (typeof data !== "string") {
258
+ // logger().warn("received non-string for json parse");
259
+ // throw new errors.MalformedMessage();
260
+ // } else {
261
+ // return JSON.parse(data);
262
+ // }
263
+ // } else if (encoding === "cbor") {
264
+ // if (data instanceof Blob) {
265
+ // const arrayBuffer = await data.arrayBuffer();
266
+ // return cbor.decode(new Uint8Array(arrayBuffer));
267
+ // } else if (data instanceof Uint8Array) {
268
+ // return cbor.decode(data);
269
+ // } else if (
270
+ // data instanceof ArrayBuffer ||
271
+ // data instanceof SharedArrayBuffer
272
+ // ) {
273
+ // return cbor.decode(new Uint8Array(data));
274
+ // } else {
275
+ // logger().warn("received non-binary type for cbor parse");
276
+ // throw new errors.MalformedMessage();
277
+ // }
278
+ // } else {
279
+ // assertUnreachable(encoding);
280
+ // }
281
+ //}
@@ -0,0 +1,131 @@
1
+ import * as cbor from "cbor-x";
2
+ import { z } from "zod";
3
+ import * as errors from "@/actor/errors";
4
+ import type { VersionedDataHandler } from "@/common/versioned-data";
5
+ import { serializeWithEncoding } from "@/serde";
6
+ import { logger } from "../log";
7
+ import { assertUnreachable } from "../utils";
8
+
9
+ /** Data that can be deserialized. */
10
+ export type InputData = string | Buffer | Blob | ArrayBufferLike | Uint8Array;
11
+
12
+ /** Data that's been serialized. */
13
+ export type OutputData = string | Uint8Array;
14
+
15
+ export const EncodingSchema = z.enum(["json", "cbor", "bare"]);
16
+
17
+ /**
18
+ * Encoding used to communicate between the client & actor.
19
+ */
20
+ export type Encoding = z.infer<typeof EncodingSchema>;
21
+
22
+ /**
23
+ * Helper class that helps serialize data without re-serializing for the same encoding.
24
+ */
25
+ export class CachedSerializer<T> {
26
+ #data: T;
27
+ #cache = new Map<Encoding, OutputData>();
28
+ #versionedDataHandler: VersionedDataHandler<T>;
29
+
30
+ constructor(data: T, versionedDataHandler: VersionedDataHandler<T>) {
31
+ this.#data = data;
32
+ this.#versionedDataHandler = versionedDataHandler;
33
+ }
34
+
35
+ public get rawData(): T {
36
+ return this.#data;
37
+ }
38
+
39
+ public serialize(encoding: Encoding): OutputData {
40
+ const cached = this.#cache.get(encoding);
41
+ if (cached) {
42
+ return cached;
43
+ } else {
44
+ const serialized = serializeWithEncoding(
45
+ encoding,
46
+ this.#data,
47
+ this.#versionedDataHandler,
48
+ );
49
+ this.#cache.set(encoding, serialized);
50
+ return serialized;
51
+ }
52
+ }
53
+ }
54
+
55
+ ///**
56
+ // * Use `CachedSerializer` if serializing the same data repeatedly.
57
+ // */
58
+ //export function serialize<T>(value: T, encoding: Encoding): OutputData {
59
+ // if (encoding === "json") {
60
+ // return JSON.stringify(value);
61
+ // } else if (encoding === "cbor") {
62
+ // // TODO: Remove this hack, but cbor-x can't handle anything extra in data structures
63
+ // const cleanValue = JSON.parse(JSON.stringify(value));
64
+ // return cbor.encode(cleanValue);
65
+ // } else {
66
+ // assertUnreachable(encoding);
67
+ // }
68
+ //}
69
+ //
70
+ //export async function deserialize(data: InputData, encoding: Encoding) {
71
+ // if (encoding === "json") {
72
+ // if (typeof data !== "string") {
73
+ // logger().warn("received non-string for json parse");
74
+ // throw new errors.MalformedMessage();
75
+ // } else {
76
+ // return JSON.parse(data);
77
+ // }
78
+ // } else if (encoding === "cbor") {
79
+ // if (data instanceof Blob) {
80
+ // const arrayBuffer = await data.arrayBuffer();
81
+ // return cbor.decode(new Uint8Array(arrayBuffer));
82
+ // } else if (data instanceof Uint8Array) {
83
+ // return cbor.decode(data);
84
+ // } else if (
85
+ // data instanceof ArrayBuffer ||
86
+ // data instanceof SharedArrayBuffer
87
+ // ) {
88
+ // return cbor.decode(new Uint8Array(data));
89
+ // } else {
90
+ // logger().warn("received non-binary type for cbor parse");
91
+ // throw new errors.MalformedMessage();
92
+ // }
93
+ // } else {
94
+ // assertUnreachable(encoding);
95
+ // }
96
+ //}
97
+
98
+ // TODO: Encode base 128
99
+ function base64EncodeUint8Array(uint8Array: Uint8Array): string {
100
+ let binary = "";
101
+ const len = uint8Array.byteLength;
102
+ for (let i = 0; i < len; i++) {
103
+ binary += String.fromCharCode(uint8Array[i]);
104
+ }
105
+ return btoa(binary);
106
+ }
107
+
108
+ function base64EncodeArrayBuffer(arrayBuffer: ArrayBuffer): string {
109
+ const uint8Array = new Uint8Array(arrayBuffer);
110
+ return base64EncodeUint8Array(uint8Array);
111
+ }
112
+
113
+ /** Converts data that was encoded to a string. Some formats (like SSE) don't support raw binary data. */
114
+ export function encodeDataToString(message: OutputData): string {
115
+ if (typeof message === "string") {
116
+ return message;
117
+ } else if (message instanceof ArrayBuffer) {
118
+ return base64EncodeArrayBuffer(message);
119
+ } else if (message instanceof Uint8Array) {
120
+ return base64EncodeUint8Array(message);
121
+ } else {
122
+ assertUnreachable(message);
123
+ }
124
+ }
125
+
126
+ /** Stringifies with compat for values that BARE & CBOR supports. */
127
+ export function jsonStringifyCompat(input: any): string {
128
+ return JSON.stringify(input, (_key, value) =>
129
+ typeof value === "bigint" ? value.toString() : value,
130
+ );
131
+ }