rivetkit 2.0.1 → 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,445 @@
1
+ import { WSContext } from "hono/ws";
2
+ import type {
3
+ RivetCloseEvent,
4
+ RivetEvent,
5
+ RivetMessageEvent,
6
+ UniversalWebSocket,
7
+ } from "@/common/websocket-interface";
8
+ import { getLogger } from "./log";
9
+
10
+ export const LOGGER_NAME = "fake-event-source2";
11
+
12
+ export function logger() {
13
+ return getLogger(LOGGER_NAME);
14
+ }
15
+
16
+ // TODO: Merge with ConnectWebSocketOutput interface
17
+ export interface UpgradeWebSocketArgs {
18
+ onOpen: (event: any, ws: WSContext) => void;
19
+ onMessage: (event: any, ws: WSContext) => void;
20
+ onClose: (event: any, ws: WSContext) => void;
21
+ onError: (error: any, ws: WSContext) => void;
22
+ }
23
+
24
+ // TODO: Remove `2` suffix
25
+ /**
26
+ * InlineWebSocketAdapter implements a WebSocket-like interface
27
+ * that connects to a UpgradeWebSocketArgs handler
28
+ */
29
+ export class InlineWebSocketAdapter2 implements UniversalWebSocket {
30
+ // WebSocket readyState values
31
+ readonly CONNECTING = 0 as const;
32
+ readonly OPEN = 1 as const;
33
+ readonly CLOSING = 2 as const;
34
+ readonly CLOSED = 3 as const;
35
+
36
+ // Private properties
37
+ #handler: UpgradeWebSocketArgs;
38
+ #wsContext: WSContext;
39
+ #readyState: 0 | 1 | 2 | 3 = 0; // Start in CONNECTING state
40
+ #queuedMessages: Array<string | ArrayBuffer | Uint8Array> = [];
41
+ // Event buffering is needed since events can be fired
42
+ // before JavaScript has a chance to add event listeners (e.g. within the same tick)
43
+ #bufferedEvents: Array<{
44
+ type: string;
45
+ event: any;
46
+ }> = [];
47
+
48
+ // Event listeners with buffering
49
+ #eventListeners: Map<string, ((ev: any) => void)[]> = new Map();
50
+
51
+ constructor(handler: UpgradeWebSocketArgs) {
52
+ this.#handler = handler;
53
+
54
+ // Create a fake WSContext to pass to the handler
55
+ this.#wsContext = new WSContext({
56
+ raw: this,
57
+ send: (data: string | ArrayBuffer | Uint8Array) => {
58
+ logger().debug("WSContext.send called");
59
+ this.#handleMessage(data);
60
+ },
61
+ close: (code?: number, reason?: string) => {
62
+ logger().debug("WSContext.close called", { code, reason });
63
+ this.#handleClose(code || 1000, reason || "");
64
+ },
65
+ // Set readyState to 1 (OPEN) since handlers expect an open connection
66
+ readyState: 1,
67
+ });
68
+
69
+ // Initialize the connection
70
+ this.#initialize();
71
+ }
72
+
73
+ get readyState(): 0 | 1 | 2 | 3 {
74
+ return this.#readyState;
75
+ }
76
+
77
+ get binaryType(): "arraybuffer" | "blob" {
78
+ return "arraybuffer";
79
+ }
80
+
81
+ set binaryType(value: "arraybuffer" | "blob") {
82
+ // Ignored for now - always use arraybuffer
83
+ }
84
+
85
+ get bufferedAmount(): number {
86
+ return 0; // Not tracked in InlineWebSocketAdapter
87
+ }
88
+
89
+ get extensions(): string {
90
+ return ""; // Not available in InlineWebSocketAdapter
91
+ }
92
+
93
+ get protocol(): string {
94
+ return ""; // Not available in InlineWebSocketAdapter
95
+ }
96
+
97
+ get url(): string {
98
+ return ""; // Not available in InlineWebSocketAdapter
99
+ }
100
+
101
+ send(data: string | ArrayBufferLike | Blob | ArrayBufferView): void {
102
+ logger().debug("send called", { readyState: this.readyState });
103
+
104
+ if (this.readyState !== this.OPEN) {
105
+ const error = new Error("WebSocket is not open");
106
+ logger().warn("cannot send message, websocket not open", {
107
+ readyState: this.readyState,
108
+ dataType: typeof data,
109
+ dataLength: typeof data === "string" ? data.length : "binary",
110
+ error,
111
+ });
112
+ this.#fireError(error);
113
+ return;
114
+ }
115
+
116
+ this.#handler.onMessage({ data }, this.#wsContext);
117
+ }
118
+
119
+ /**
120
+ * Closes the connection
121
+ */
122
+ close(code = 1000, reason = ""): void {
123
+ if (this.readyState === this.CLOSED || this.readyState === this.CLOSING) {
124
+ return;
125
+ }
126
+
127
+ logger().debug("closing fake websocket", { code, reason });
128
+
129
+ this.#readyState = this.CLOSING;
130
+
131
+ // Call the handler's onClose method
132
+ try {
133
+ this.#handler.onClose({ code, reason, wasClean: true }, this.#wsContext);
134
+ } catch (err) {
135
+ logger().error("error closing websocket", { error: err });
136
+ } finally {
137
+ this.#readyState = this.CLOSED;
138
+
139
+ // Fire the close event
140
+ // Create a close event object since CloseEvent is not available in Node.js
141
+ const closeEvent = {
142
+ type: "close",
143
+ wasClean: code === 1000,
144
+ code,
145
+ reason,
146
+ target: this,
147
+ currentTarget: this,
148
+ } as unknown as RivetCloseEvent;
149
+
150
+ this.#fireClose(closeEvent);
151
+ }
152
+ }
153
+
154
+ /**
155
+ * Initialize the connection with the handler
156
+ */
157
+ async #initialize(): Promise<void> {
158
+ try {
159
+ logger().debug("fake websocket initializing");
160
+
161
+ // Call the handler's onOpen method
162
+ logger().debug("calling handler.onOpen with WSContext");
163
+ this.#handler.onOpen(undefined, this.#wsContext);
164
+
165
+ // Update the ready state and fire events
166
+ this.#readyState = this.OPEN;
167
+ logger().debug("fake websocket initialized and now OPEN");
168
+
169
+ // Fire the open event
170
+ this.#fireOpen();
171
+
172
+ // Delay processing queued messages slightly to allow event handlers to be set up
173
+ if (this.#queuedMessages.length > 0) {
174
+ if (this.readyState !== this.OPEN) {
175
+ logger().warn("socket no longer open, dropping queued messages");
176
+ return;
177
+ }
178
+
179
+ logger().debug(
180
+ `now processing ${this.#queuedMessages.length} queued messages`,
181
+ );
182
+
183
+ // Create a copy to avoid issues if new messages arrive during processing
184
+ const messagesToProcess = [...this.#queuedMessages];
185
+ this.#queuedMessages = [];
186
+
187
+ // Process each queued message
188
+ for (const message of messagesToProcess) {
189
+ logger().debug("processing queued message");
190
+ this.#handleMessage(message);
191
+ }
192
+ }
193
+ } catch (err) {
194
+ logger().error("error opening fake websocket", {
195
+ error: err,
196
+ errorMessage: err instanceof Error ? err.message : String(err),
197
+ stack: err instanceof Error ? err.stack : undefined,
198
+ });
199
+ this.#fireError(err);
200
+ this.close(1011, "Internal error during initialization");
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Handle messages received from the server via the WSContext
206
+ */
207
+ #handleMessage(data: string | ArrayBuffer | Uint8Array): void {
208
+ // Store messages that arrive before the socket is fully initialized
209
+ if (this.readyState !== this.OPEN) {
210
+ logger().debug("message received before socket is OPEN, queuing", {
211
+ readyState: this.readyState,
212
+ dataType: typeof data,
213
+ dataLength:
214
+ typeof data === "string"
215
+ ? data.length
216
+ : data instanceof ArrayBuffer
217
+ ? data.byteLength
218
+ : data instanceof Uint8Array
219
+ ? data.byteLength
220
+ : "unknown",
221
+ });
222
+
223
+ // Queue the message to be processed once the socket is open
224
+ this.#queuedMessages.push(data);
225
+ return;
226
+ }
227
+
228
+ // Log message received from server
229
+ logger().debug("fake websocket received message from server", {
230
+ dataType: typeof data,
231
+ dataLength:
232
+ typeof data === "string"
233
+ ? data.length
234
+ : data instanceof ArrayBuffer
235
+ ? data.byteLength
236
+ : data instanceof Uint8Array
237
+ ? data.byteLength
238
+ : "unknown",
239
+ });
240
+
241
+ // Create a MessageEvent-like object
242
+ const event = {
243
+ type: "message",
244
+ data,
245
+ target: this,
246
+ currentTarget: this,
247
+ } as unknown as RivetMessageEvent;
248
+
249
+ // Dispatch the event
250
+ this.#dispatchEvent("message", event);
251
+ }
252
+
253
+ #handleClose(code: number, reason: string): void {
254
+ if (this.readyState === this.CLOSED) return;
255
+
256
+ this.#readyState = this.CLOSED;
257
+
258
+ // Create a CloseEvent-like object
259
+ const event = {
260
+ type: "close",
261
+ code,
262
+ reason,
263
+ wasClean: code === 1000,
264
+ target: this,
265
+ currentTarget: this,
266
+ } as unknown as RivetCloseEvent;
267
+
268
+ // Dispatch the event
269
+ this.#dispatchEvent("close", event);
270
+ }
271
+
272
+ addEventListener(type: string, listener: (ev: any) => void): void {
273
+ if (!this.#eventListeners.has(type)) {
274
+ this.#eventListeners.set(type, []);
275
+ }
276
+ this.#eventListeners.get(type)!.push(listener);
277
+
278
+ // Flush any buffered events for this type
279
+ this.#flushBufferedEvents(type);
280
+ }
281
+
282
+ removeEventListener(type: string, listener: (ev: any) => void): void {
283
+ const listeners = this.#eventListeners.get(type);
284
+ if (listeners) {
285
+ const index = listeners.indexOf(listener);
286
+ if (index !== -1) {
287
+ listeners.splice(index, 1);
288
+ }
289
+ }
290
+ }
291
+
292
+ #dispatchEvent(type: string, event: any): void {
293
+ const listeners = this.#eventListeners.get(type);
294
+ if (listeners && listeners.length > 0) {
295
+ logger().debug(
296
+ `dispatching ${type} event to ${listeners.length} listeners`,
297
+ );
298
+ for (const listener of listeners) {
299
+ try {
300
+ listener(event);
301
+ } catch (err) {
302
+ logger().error(`error in ${type} event listener`, { error: err });
303
+ }
304
+ }
305
+ } else {
306
+ logger().debug(`no ${type} listeners registered, buffering event`);
307
+ this.#bufferedEvents.push({ type, event });
308
+ }
309
+
310
+ // Also check for on* properties
311
+ switch (type) {
312
+ case "open":
313
+ if (this.#onopen) {
314
+ try {
315
+ this.#onopen(event);
316
+ } catch (error) {
317
+ logger().error("error in onopen handler", { error });
318
+ }
319
+ }
320
+ break;
321
+ case "close":
322
+ if (this.#onclose) {
323
+ try {
324
+ this.#onclose(event);
325
+ } catch (error) {
326
+ logger().error("error in onclose handler", { error });
327
+ }
328
+ }
329
+ break;
330
+ case "error":
331
+ if (this.#onerror) {
332
+ try {
333
+ this.#onerror(event);
334
+ } catch (error) {
335
+ logger().error("error in onerror handler", { error });
336
+ }
337
+ }
338
+ break;
339
+ case "message":
340
+ if (this.#onmessage) {
341
+ try {
342
+ this.#onmessage(event);
343
+ } catch (error) {
344
+ logger().error("error in onmessage handler", { error });
345
+ }
346
+ }
347
+ break;
348
+ }
349
+ }
350
+
351
+ dispatchEvent(event: RivetEvent): boolean {
352
+ this.#dispatchEvent(event.type, event);
353
+ return true;
354
+ }
355
+
356
+ #flushBufferedEvents(type: string): void {
357
+ const eventsToFlush = this.#bufferedEvents.filter(
358
+ (buffered) => buffered.type === type,
359
+ );
360
+ this.#bufferedEvents = this.#bufferedEvents.filter(
361
+ (buffered) => buffered.type !== type,
362
+ );
363
+
364
+ for (const { event } of eventsToFlush) {
365
+ this.#dispatchEvent(type, event);
366
+ }
367
+ }
368
+
369
+ #fireOpen(): void {
370
+ try {
371
+ // Create an Event-like object since Event constructor may not be available
372
+ const event = {
373
+ type: "open",
374
+ target: this,
375
+ currentTarget: this,
376
+ } as unknown as RivetEvent;
377
+
378
+ this.#dispatchEvent("open", event);
379
+ } catch (err) {
380
+ logger().error("error in open event", { error: err });
381
+ }
382
+ }
383
+
384
+ #fireClose(event: RivetCloseEvent): void {
385
+ try {
386
+ this.#dispatchEvent("close", event);
387
+ } catch (err) {
388
+ logger().error("error in close event", { error: err });
389
+ }
390
+ }
391
+
392
+ #fireError(error: unknown): void {
393
+ try {
394
+ // Create an Event-like object for error
395
+ const event = {
396
+ type: "error",
397
+ target: this,
398
+ currentTarget: this,
399
+ error,
400
+ message: error instanceof Error ? error.message : String(error),
401
+ } as unknown as RivetEvent;
402
+
403
+ this.#dispatchEvent("error", event);
404
+ } catch (err) {
405
+ logger().error("error in error event", { error: err });
406
+ }
407
+
408
+ // Log the error
409
+ logger().error("websocket error", { error });
410
+ }
411
+
412
+ // Event handler properties with getters/setters
413
+ #onopen: ((event: RivetEvent) => void) | null = null;
414
+ #onclose: ((event: RivetCloseEvent) => void) | null = null;
415
+ #onerror: ((event: RivetEvent) => void) | null = null;
416
+ #onmessage: ((event: RivetMessageEvent) => void) | null = null;
417
+
418
+ get onopen(): ((event: RivetEvent) => void) | null {
419
+ return this.#onopen;
420
+ }
421
+ set onopen(handler: ((event: RivetEvent) => void) | null) {
422
+ this.#onopen = handler;
423
+ }
424
+
425
+ get onclose(): ((event: RivetCloseEvent) => void) | null {
426
+ return this.#onclose;
427
+ }
428
+ set onclose(handler: ((event: RivetCloseEvent) => void) | null) {
429
+ this.#onclose = handler;
430
+ }
431
+
432
+ get onerror(): ((event: RivetEvent) => void) | null {
433
+ return this.#onerror;
434
+ }
435
+ set onerror(handler: ((event: RivetEvent) => void) | null) {
436
+ this.#onerror = handler;
437
+ }
438
+
439
+ get onmessage(): ((event: RivetMessageEvent) => void) | null {
440
+ return this.#onmessage;
441
+ }
442
+ set onmessage(handler: ((event: RivetMessageEvent) => void) | null) {
443
+ this.#onmessage = handler;
444
+ }
445
+ }
@@ -0,0 +1,27 @@
1
+ export type LogLevel =
2
+ | "TRACE"
3
+ | "DEBUG"
4
+ | "INFO"
5
+ | "WARN"
6
+ | "ERROR"
7
+ | "CRITICAL";
8
+
9
+ export const LogLevels: Record<LogLevel, LevelIndex> = {
10
+ TRACE: 0,
11
+ DEBUG: 1,
12
+ INFO: 2,
13
+ WARN: 3,
14
+ ERROR: 4,
15
+ CRITICAL: 5,
16
+ } as const;
17
+
18
+ export const LevelNameMap: Record<number, LogLevel> = {
19
+ 0: "TRACE",
20
+ 1: "DEBUG",
21
+ 2: "INFO",
22
+ 3: "WARN",
23
+ 4: "ERROR",
24
+ 5: "CRITICAL",
25
+ };
26
+
27
+ export type LevelIndex = number;
@@ -0,0 +1,139 @@
1
+ import { getEnvUniversal } from "@/utils";
2
+ import {
3
+ type LevelIndex,
4
+ LevelNameMap,
5
+ type LogLevel,
6
+ LogLevels,
7
+ } from "./log-levels";
8
+ import {
9
+ castToLogValue,
10
+ formatTimestamp,
11
+ type LogEntry,
12
+ stringify,
13
+ } from "./logfmt";
14
+
15
+ interface LogRecord {
16
+ args: unknown[];
17
+ datetime: Date;
18
+ level: number;
19
+ levelName: string;
20
+ loggerName: string;
21
+ msg: string;
22
+ }
23
+
24
+ export class Logger {
25
+ name: string;
26
+ level: LogLevel;
27
+
28
+ constructor(name: string, level: LogLevel) {
29
+ this.name = name;
30
+ this.level = level;
31
+ }
32
+
33
+ log(level: LevelIndex, message: string, ...args: unknown[]): void {
34
+ const record: LogRecord = {
35
+ msg: message,
36
+ args,
37
+ level,
38
+ loggerName: this.name,
39
+ datetime: new Date(),
40
+ levelName: LevelNameMap[level],
41
+ };
42
+
43
+ if (this.#shouldLog(level)) {
44
+ this.#logRecord(record);
45
+ }
46
+ }
47
+
48
+ #shouldLog(level: LevelIndex): boolean {
49
+ return level >= LogLevels[this.level];
50
+ }
51
+
52
+ #logRecord(record: LogRecord): void {
53
+ console.log(formatter(record));
54
+ }
55
+
56
+ trace(message: string, ...args: unknown[]): void {
57
+ this.log(LogLevels.TRACE, message, ...args);
58
+ }
59
+
60
+ debug(message: string, ...args: unknown[]): void {
61
+ this.log(LogLevels.DEBUG, message, ...args);
62
+ }
63
+
64
+ info(message: string, ...args: unknown[]): void {
65
+ this.log(LogLevels.INFO, message, ...args);
66
+ }
67
+
68
+ warn(message: string, ...args: unknown[]): void {
69
+ this.log(LogLevels.WARN, message, ...args);
70
+ }
71
+
72
+ error(message: string, ...args: unknown[]): void {
73
+ this.log(LogLevels.ERROR, message, ...args);
74
+ }
75
+
76
+ critical(message: string, ...args: unknown[]): void {
77
+ this.log(LogLevels.CRITICAL, message, ...args);
78
+ }
79
+ }
80
+
81
+ const loggers: Record<string, Logger> = {};
82
+
83
+ export function getLogger(name = "default"): Logger {
84
+ const defaultLogLevelEnv: LogLevel | undefined = getEnvUniversal(
85
+ "_LOG_LEVEL",
86
+ ) as LogLevel | undefined;
87
+
88
+ const defaultLogLevel: LogLevel = defaultLogLevelEnv ?? "INFO";
89
+ if (!loggers[name]) {
90
+ loggers[name] = new Logger(name, defaultLogLevel);
91
+ }
92
+ return loggers[name];
93
+ }
94
+
95
+ function formatter(log: LogRecord): string {
96
+ const args: LogEntry[] = [];
97
+ for (let i = 0; i < log.args.length; i++) {
98
+ const logArg = log.args[i];
99
+ if (logArg && typeof logArg === "object") {
100
+ // Spread object
101
+ for (const k in logArg) {
102
+ // biome-ignore lint/suspicious/noExplicitAny: Unknown type
103
+ const v = (logArg as any)[k];
104
+
105
+ pushArg(k, v, args);
106
+ }
107
+ } else {
108
+ pushArg(`arg${i}`, logArg, args);
109
+ }
110
+ }
111
+
112
+ const logTs = getEnvUniversal("_LOG_TIMESTAMP") === "1";
113
+ const logTarget = getEnvUniversal("_LOG_TARGET") === "1";
114
+
115
+ return stringify(
116
+ ...(logTs ? [["ts", formatTimestamp(new Date())] as LogEntry] : []),
117
+ ["level", LevelNameMap[log.level]],
118
+ ...(logTarget ? [["target", log.loggerName] as LogEntry] : []),
119
+ ["msg", log.msg],
120
+ ...args,
121
+ );
122
+ }
123
+
124
+ function pushArg(k: string, v: unknown, args: LogEntry[]) {
125
+ args.push([k, castToLogValue(v)]);
126
+ }
127
+
128
+ // function getEnv(name: string): string | undefined {
129
+ // if (typeof window !== "undefined" && window.localStorage) {
130
+ // return window.localStorage.getItem(name) || undefined;
131
+ // }
132
+ // return undefined;
133
+ // // TODO(ACTR-9): Add back env config once node compat layer works
134
+ // //return crossGetEnv(name);
135
+ // }
136
+
137
+ export function setupLogging() {
138
+ // Do nothing for now
139
+ }