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,297 @@
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
+
22
+ export const TransportSchema = z.enum(["websocket", "sse"]);
23
+
24
+ /**
25
+ * Transport mechanism used to communicate between client & actor.
26
+ */
27
+ export type Transport = z.infer<typeof TransportSchema>;
28
+
29
+ interface MessageEventOpts {
30
+ encoding: Encoding;
31
+ maxIncomingMessageSize: number;
32
+ }
33
+
34
+ function getValueLength(value: InputData): number {
35
+ if (typeof value === "string") {
36
+ return value.length;
37
+ } else if (value instanceof Blob) {
38
+ return value.size;
39
+ } else if (
40
+ value instanceof ArrayBuffer ||
41
+ value instanceof SharedArrayBuffer ||
42
+ value instanceof Uint8Array
43
+ ) {
44
+ return value.byteLength;
45
+ } else {
46
+ assertUnreachable(value);
47
+ }
48
+ }
49
+
50
+ export async function inputDataToBuffer(
51
+ data: InputData,
52
+ ): Promise<Uint8Array | string> {
53
+ if (typeof data === "string") {
54
+ return data;
55
+ } else if (data instanceof Blob) {
56
+ const arrayBuffer = await data.arrayBuffer();
57
+ return new Uint8Array(arrayBuffer);
58
+ } else if (data instanceof Uint8Array) {
59
+ return data;
60
+ } else if (data instanceof ArrayBuffer || data instanceof SharedArrayBuffer) {
61
+ return new Uint8Array(data);
62
+ } else {
63
+ throw new errors.MalformedMessage();
64
+ }
65
+ }
66
+
67
+ export async function parseMessage(
68
+ value: InputData,
69
+ opts: MessageEventOpts,
70
+ ): Promise<protocol.ToServer> {
71
+ // Validate value length
72
+ const length = getValueLength(value);
73
+ if (length > opts.maxIncomingMessageSize) {
74
+ throw new errors.MessageTooLong();
75
+ }
76
+
77
+ // Convert value
78
+ let buffer = await inputDataToBuffer(value);
79
+
80
+ // HACK: For some reason, the output buffer needs to be cloned when using BARE encoding
81
+ //
82
+ // THis is likely because the input data is of type `Buffer` and there is an inconsistency in implementation that I am not aware of
83
+ if (buffer instanceof Buffer) {
84
+ buffer = new Uint8Array(buffer);
85
+ }
86
+
87
+ // Deserialize message
88
+ return deserializeWithEncoding(opts.encoding, buffer, TO_SERVER_VERSIONED);
89
+ }
90
+
91
+ export interface ProcessMessageHandler<
92
+ S,
93
+ CP,
94
+ CS,
95
+ V,
96
+ I,
97
+ DB extends AnyDatabaseProvider,
98
+ > {
99
+ onExecuteAction?: (
100
+ ctx: ActionContext<S, CP, CS, V, I, DB>,
101
+ name: string,
102
+ args: unknown[],
103
+ ) => Promise<unknown>;
104
+ onSubscribe?: (
105
+ eventName: string,
106
+ conn: Conn<S, CP, CS, V, I, DB>,
107
+ ) => Promise<void>;
108
+ onUnsubscribe?: (
109
+ eventName: string,
110
+ conn: Conn<S, CP, CS, V, I, DB>,
111
+ ) => Promise<void>;
112
+ }
113
+
114
+ export async function processMessage<
115
+ S,
116
+ CP,
117
+ CS,
118
+ V,
119
+ I,
120
+ DB extends AnyDatabaseProvider,
121
+ >(
122
+ message: protocol.ToServer,
123
+ actor: ActorInstance<S, CP, CS, V, I, DB>,
124
+ conn: Conn<S, CP, CS, V, I, DB>,
125
+ handler: ProcessMessageHandler<S, CP, CS, V, I, DB>,
126
+ ) {
127
+ let actionId: bigint | undefined;
128
+ let actionName: string | undefined;
129
+
130
+ try {
131
+ if (message.body.tag === "ActionRequest") {
132
+ // Action request
133
+
134
+ if (handler.onExecuteAction === undefined) {
135
+ throw new errors.Unsupported("Action");
136
+ }
137
+
138
+ const { id, name, args: argsRaw } = message.body.val;
139
+ actionId = id;
140
+ actionName = name;
141
+ const args = cbor.decode(new Uint8Array(argsRaw));
142
+
143
+ actor.rLog.debug({
144
+ msg: "processing action request",
145
+ actionId: id,
146
+ actionName: name,
147
+ });
148
+
149
+ const ctx = new ActionContext<S, CP, CS, V, I, DB>(
150
+ actor.actorContext,
151
+ conn,
152
+ );
153
+
154
+ // Process the action request and wait for the result
155
+ // This will wait for async actions to complete
156
+ const output = await handler.onExecuteAction(ctx, name, args);
157
+
158
+ actor.rLog.debug({
159
+ msg: "sending action response",
160
+ actionId: id,
161
+ actionName: name,
162
+ outputType: typeof output,
163
+ isPromise: output instanceof Promise,
164
+ });
165
+
166
+ // Send the response back to the client
167
+ conn._sendMessage(
168
+ new CachedSerializer<protocol.ToClient>(
169
+ {
170
+ body: {
171
+ tag: "ActionResponse",
172
+ val: {
173
+ id: id,
174
+ output: bufferToArrayBuffer(cbor.encode(output)),
175
+ },
176
+ },
177
+ },
178
+ TO_CLIENT_VERSIONED,
179
+ ),
180
+ );
181
+
182
+ actor.rLog.debug({ msg: "action response sent", id, name: name });
183
+ } else if (message.body.tag === "SubscriptionRequest") {
184
+ // Subscription request
185
+
186
+ if (
187
+ handler.onSubscribe === undefined ||
188
+ handler.onUnsubscribe === undefined
189
+ ) {
190
+ throw new errors.Unsupported("Subscriptions");
191
+ }
192
+
193
+ const { eventName, subscribe } = message.body.val;
194
+ actor.rLog.debug({
195
+ msg: "processing subscription request",
196
+ eventName,
197
+ subscribe,
198
+ });
199
+
200
+ if (subscribe) {
201
+ await handler.onSubscribe(eventName, conn);
202
+ } else {
203
+ await handler.onUnsubscribe(eventName, conn);
204
+ }
205
+
206
+ actor.rLog.debug({
207
+ msg: "subscription request completed",
208
+ eventName,
209
+ subscribe,
210
+ });
211
+ } else {
212
+ assertUnreachable(message.body);
213
+ }
214
+ } catch (error) {
215
+ const { group, code, message, metadata } = deconstructError(
216
+ error,
217
+ actor.rLog,
218
+ {
219
+ connectionId: conn.id,
220
+ actionId,
221
+ actionName,
222
+ },
223
+ );
224
+
225
+ actor.rLog.debug({
226
+ msg: "sending error response",
227
+ actionId,
228
+ actionName,
229
+ code,
230
+ message,
231
+ });
232
+
233
+ // Build response
234
+ conn._sendMessage(
235
+ new CachedSerializer<protocol.ToClient>(
236
+ {
237
+ body: {
238
+ tag: "Error",
239
+ val: {
240
+ group,
241
+ code,
242
+ message,
243
+ metadata: bufferToArrayBuffer(cbor.encode(metadata)),
244
+ actionId: actionId ?? null,
245
+ },
246
+ },
247
+ },
248
+ TO_CLIENT_VERSIONED,
249
+ ),
250
+ );
251
+
252
+ actor.rLog.debug({ msg: "error response sent", actionId, actionName });
253
+ }
254
+ }
255
+
256
+ ///**
257
+ // * Use `CachedSerializer` if serializing the same data repeatedly.
258
+ // */
259
+ //export function serialize<T>(value: T, encoding: Encoding): OutputData {
260
+ // if (encoding === "json") {
261
+ // return JSON.stringify(value);
262
+ // } else if (encoding === "cbor") {
263
+ // // TODO: Remove this hack, but cbor-x can't handle anything extra in data structures
264
+ // const cleanValue = JSON.parse(JSON.stringify(value));
265
+ // return cbor.encode(cleanValue);
266
+ // } else {
267
+ // assertUnreachable(encoding);
268
+ // }
269
+ //}
270
+ //
271
+ //export async function deserialize(data: InputData, encoding: Encoding) {
272
+ // if (encoding === "json") {
273
+ // if (typeof data !== "string") {
274
+ // actor.rLog.warn("received non-string for json parse");
275
+ // throw new errors.MalformedMessage();
276
+ // } else {
277
+ // return JSON.parse(data);
278
+ // }
279
+ // } else if (encoding === "cbor") {
280
+ // if (data instanceof Blob) {
281
+ // const arrayBuffer = await data.arrayBuffer();
282
+ // return cbor.decode(new Uint8Array(arrayBuffer));
283
+ // } else if (data instanceof Uint8Array) {
284
+ // return cbor.decode(data);
285
+ // } else if (
286
+ // data instanceof ArrayBuffer ||
287
+ // data instanceof SharedArrayBuffer
288
+ // ) {
289
+ // return cbor.decode(new Uint8Array(data));
290
+ // } else {
291
+ // actor.rLog.warn("received non-binary type for cbor parse");
292
+ // throw new errors.MalformedMessage();
293
+ // }
294
+ // } else {
295
+ // assertUnreachable(encoding);
296
+ // }
297
+ //}
@@ -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 { loggerWithoutContext } 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
+ }