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.
- package/dist/schemas/actor-persist/v1.ts +228 -0
- package/dist/schemas/client-protocol/v1.ts +429 -0
- package/dist/schemas/file-system-driver/v1.ts +102 -0
- package/dist/tsup/actor/errors.cjs +69 -0
- package/dist/tsup/actor/errors.cjs.map +1 -0
- package/dist/tsup/actor/errors.d.cts +143 -0
- package/dist/tsup/actor/errors.d.ts +143 -0
- package/dist/tsup/actor/errors.js +69 -0
- package/dist/tsup/actor/errors.js.map +1 -0
- package/dist/tsup/chunk-2CRLFV6Z.cjs +202 -0
- package/dist/tsup/chunk-2CRLFV6Z.cjs.map +1 -0
- package/dist/tsup/chunk-3H7O2A7I.js +525 -0
- package/dist/tsup/chunk-3H7O2A7I.js.map +1 -0
- package/dist/tsup/chunk-42I3OZ3Q.js +15 -0
- package/dist/tsup/chunk-42I3OZ3Q.js.map +1 -0
- package/dist/tsup/chunk-4NSUQZ2H.js +1790 -0
- package/dist/tsup/chunk-4NSUQZ2H.js.map +1 -0
- package/dist/tsup/chunk-6PDXBYI5.js +132 -0
- package/dist/tsup/chunk-6PDXBYI5.js.map +1 -0
- package/dist/tsup/chunk-6WKQDDUD.cjs +1790 -0
- package/dist/tsup/chunk-6WKQDDUD.cjs.map +1 -0
- package/dist/tsup/chunk-CTBOSFUH.cjs +116 -0
- package/dist/tsup/chunk-CTBOSFUH.cjs.map +1 -0
- package/dist/tsup/chunk-EGVZZFE2.js +2857 -0
- package/dist/tsup/chunk-EGVZZFE2.js.map +1 -0
- package/dist/tsup/chunk-FCCPJNMA.cjs +132 -0
- package/dist/tsup/chunk-FCCPJNMA.cjs.map +1 -0
- package/dist/tsup/chunk-FLMTTN27.js +244 -0
- package/dist/tsup/chunk-FLMTTN27.js.map +1 -0
- package/dist/tsup/chunk-GIR3AFFI.cjs +315 -0
- package/dist/tsup/chunk-GIR3AFFI.cjs.map +1 -0
- package/dist/tsup/chunk-INGJP237.js +315 -0
- package/dist/tsup/chunk-INGJP237.js.map +1 -0
- package/dist/tsup/chunk-KJCJLKRM.js +116 -0
- package/dist/tsup/chunk-KJCJLKRM.js.map +1 -0
- package/dist/tsup/chunk-KUPQZYUQ.cjs +15 -0
- package/dist/tsup/chunk-KUPQZYUQ.cjs.map +1 -0
- package/dist/tsup/chunk-O2MBYIXO.cjs +2857 -0
- package/dist/tsup/chunk-O2MBYIXO.cjs.map +1 -0
- package/dist/tsup/chunk-OGAPU3UG.cjs +525 -0
- package/dist/tsup/chunk-OGAPU3UG.cjs.map +1 -0
- package/dist/tsup/chunk-OV6AYD4S.js +4406 -0
- package/dist/tsup/chunk-OV6AYD4S.js.map +1 -0
- package/dist/tsup/chunk-PO4VLDWA.js +47 -0
- package/dist/tsup/chunk-PO4VLDWA.js.map +1 -0
- package/dist/tsup/chunk-R2OPSKIV.cjs +244 -0
- package/dist/tsup/chunk-R2OPSKIV.cjs.map +1 -0
- package/dist/tsup/chunk-TZJKSBUQ.cjs +47 -0
- package/dist/tsup/chunk-TZJKSBUQ.cjs.map +1 -0
- package/dist/tsup/chunk-UBUC5C3G.cjs +189 -0
- package/dist/tsup/chunk-UBUC5C3G.cjs.map +1 -0
- package/dist/tsup/chunk-UIM22YJL.cjs +4406 -0
- package/dist/tsup/chunk-UIM22YJL.cjs.map +1 -0
- package/dist/tsup/chunk-URVFQMYI.cjs +230 -0
- package/dist/tsup/chunk-URVFQMYI.cjs.map +1 -0
- package/dist/tsup/chunk-UVUPOS46.js +230 -0
- package/dist/tsup/chunk-UVUPOS46.js.map +1 -0
- package/dist/tsup/chunk-VRRHBNJC.js +189 -0
- package/dist/tsup/chunk-VRRHBNJC.js.map +1 -0
- package/dist/tsup/chunk-XFSS33EQ.js +202 -0
- package/dist/tsup/chunk-XFSS33EQ.js.map +1 -0
- package/dist/tsup/client/mod.cjs +32 -0
- package/dist/tsup/client/mod.cjs.map +1 -0
- package/dist/tsup/client/mod.d.cts +26 -0
- package/dist/tsup/client/mod.d.ts +26 -0
- package/dist/tsup/client/mod.js +32 -0
- package/dist/tsup/client/mod.js.map +1 -0
- package/dist/tsup/common/log.cjs +13 -0
- package/dist/tsup/common/log.cjs.map +1 -0
- package/dist/tsup/common/log.d.cts +20 -0
- package/dist/tsup/common/log.d.ts +20 -0
- package/dist/tsup/common/log.js +13 -0
- package/dist/tsup/common/log.js.map +1 -0
- package/dist/tsup/common/websocket.cjs +10 -0
- package/dist/tsup/common/websocket.cjs.map +1 -0
- package/dist/tsup/common/websocket.d.cts +3 -0
- package/dist/tsup/common/websocket.d.ts +3 -0
- package/dist/tsup/common/websocket.js +10 -0
- package/dist/tsup/common/websocket.js.map +1 -0
- package/dist/tsup/common-CpqORuCq.d.cts +218 -0
- package/dist/tsup/common-CpqORuCq.d.ts +218 -0
- package/dist/tsup/connection-BR_Ve4ku.d.cts +2117 -0
- package/dist/tsup/connection-BwUMoe6n.d.ts +2117 -0
- package/dist/tsup/driver-helpers/mod.cjs +33 -0
- package/dist/tsup/driver-helpers/mod.cjs.map +1 -0
- package/dist/tsup/driver-helpers/mod.d.cts +18 -0
- package/dist/tsup/driver-helpers/mod.d.ts +18 -0
- package/dist/tsup/driver-helpers/mod.js +33 -0
- package/dist/tsup/driver-helpers/mod.js.map +1 -0
- package/dist/tsup/driver-test-suite/mod.cjs +4619 -0
- package/dist/tsup/driver-test-suite/mod.cjs.map +1 -0
- package/dist/tsup/driver-test-suite/mod.d.cts +57 -0
- package/dist/tsup/driver-test-suite/mod.d.ts +57 -0
- package/dist/tsup/driver-test-suite/mod.js +4619 -0
- package/dist/tsup/driver-test-suite/mod.js.map +1 -0
- package/dist/tsup/inspector/mod.cjs +53 -0
- package/dist/tsup/inspector/mod.cjs.map +1 -0
- package/dist/tsup/inspector/mod.d.cts +408 -0
- package/dist/tsup/inspector/mod.d.ts +408 -0
- package/dist/tsup/inspector/mod.js +53 -0
- package/dist/tsup/inspector/mod.js.map +1 -0
- package/dist/tsup/mod.cjs +73 -0
- package/dist/tsup/mod.cjs.map +1 -0
- package/dist/tsup/mod.d.cts +100 -0
- package/dist/tsup/mod.d.ts +100 -0
- package/dist/tsup/mod.js +73 -0
- package/dist/tsup/mod.js.map +1 -0
- package/dist/tsup/router-endpoints-AYkXG8Tl.d.cts +66 -0
- package/dist/tsup/router-endpoints-DAbqVFx2.d.ts +66 -0
- package/dist/tsup/test/mod.cjs +21 -0
- package/dist/tsup/test/mod.cjs.map +1 -0
- package/dist/tsup/test/mod.d.cts +27 -0
- package/dist/tsup/test/mod.d.ts +27 -0
- package/dist/tsup/test/mod.js +21 -0
- package/dist/tsup/test/mod.js.map +1 -0
- package/dist/tsup/utils-CT0cv4jd.d.cts +17 -0
- package/dist/tsup/utils-CT0cv4jd.d.ts +17 -0
- package/dist/tsup/utils.cjs +26 -0
- package/dist/tsup/utils.cjs.map +1 -0
- package/dist/tsup/utils.d.cts +36 -0
- package/dist/tsup/utils.d.ts +36 -0
- package/dist/tsup/utils.js +26 -0
- package/dist/tsup/utils.js.map +1 -0
- package/package.json +208 -5
- package/src/actor/action.ts +182 -0
- package/src/actor/config.ts +765 -0
- package/src/actor/connection.ts +260 -0
- package/src/actor/context.ts +171 -0
- package/src/actor/database.ts +23 -0
- package/src/actor/definition.ts +86 -0
- package/src/actor/driver.ts +84 -0
- package/src/actor/errors.ts +360 -0
- package/src/actor/generic-conn-driver.ts +234 -0
- package/src/actor/instance.ts +1800 -0
- package/src/actor/log.ts +15 -0
- package/src/actor/mod.ts +113 -0
- package/src/actor/persisted.ts +42 -0
- package/src/actor/protocol/old.ts +281 -0
- package/src/actor/protocol/serde.ts +131 -0
- package/src/actor/router-endpoints.ts +685 -0
- package/src/actor/router.ts +263 -0
- package/src/actor/schedule.ts +17 -0
- package/src/actor/unstable-react.ts +110 -0
- package/src/actor/utils.ts +98 -0
- package/src/client/actor-common.ts +30 -0
- package/src/client/actor-conn.ts +804 -0
- package/src/client/actor-handle.ts +208 -0
- package/src/client/client.ts +623 -0
- package/src/client/errors.ts +41 -0
- package/src/client/http-client-driver.ts +326 -0
- package/src/client/log.ts +7 -0
- package/src/client/mod.ts +56 -0
- package/src/client/raw-utils.ts +92 -0
- package/src/client/test.ts +44 -0
- package/src/client/utils.ts +150 -0
- package/src/common/eventsource-interface.ts +47 -0
- package/src/common/eventsource.ts +80 -0
- package/src/common/fake-event-source.ts +266 -0
- package/src/common/inline-websocket-adapter2.ts +445 -0
- package/src/common/log-levels.ts +27 -0
- package/src/common/log.ts +139 -0
- package/src/common/logfmt.ts +228 -0
- package/src/common/network.ts +2 -0
- package/src/common/router.ts +87 -0
- package/src/common/utils.ts +322 -0
- package/src/common/versioned-data.ts +95 -0
- package/src/common/websocket-interface.ts +49 -0
- package/src/common/websocket.ts +43 -0
- package/src/driver-helpers/mod.ts +22 -0
- package/src/driver-helpers/utils.ts +17 -0
- package/src/driver-test-suite/log.ts +7 -0
- package/src/driver-test-suite/mod.ts +213 -0
- package/src/driver-test-suite/test-inline-client-driver.ts +402 -0
- package/src/driver-test-suite/tests/action-features.ts +136 -0
- package/src/driver-test-suite/tests/actor-auth.ts +591 -0
- package/src/driver-test-suite/tests/actor-conn-state.ts +249 -0
- package/src/driver-test-suite/tests/actor-conn.ts +349 -0
- package/src/driver-test-suite/tests/actor-driver.ts +25 -0
- package/src/driver-test-suite/tests/actor-error-handling.ts +158 -0
- package/src/driver-test-suite/tests/actor-handle.ts +259 -0
- package/src/driver-test-suite/tests/actor-inline-client.ts +152 -0
- package/src/driver-test-suite/tests/actor-inspector.ts +570 -0
- package/src/driver-test-suite/tests/actor-metadata.ts +116 -0
- package/src/driver-test-suite/tests/actor-onstatechange.ts +95 -0
- package/src/driver-test-suite/tests/actor-schedule.ts +108 -0
- package/src/driver-test-suite/tests/actor-sleep.ts +413 -0
- package/src/driver-test-suite/tests/actor-state.ts +54 -0
- package/src/driver-test-suite/tests/actor-vars.ts +93 -0
- package/src/driver-test-suite/tests/manager-driver.ts +365 -0
- package/src/driver-test-suite/tests/raw-http-direct-registry.ts +226 -0
- package/src/driver-test-suite/tests/raw-http-request-properties.ts +414 -0
- package/src/driver-test-suite/tests/raw-http.ts +347 -0
- package/src/driver-test-suite/tests/raw-websocket-direct-registry.ts +392 -0
- package/src/driver-test-suite/tests/raw-websocket.ts +484 -0
- package/src/driver-test-suite/tests/request-access.ts +244 -0
- package/src/driver-test-suite/utils.ts +68 -0
- package/src/drivers/default.ts +31 -0
- package/src/drivers/engine/actor-driver.ts +360 -0
- package/src/drivers/engine/api-endpoints.ts +128 -0
- package/src/drivers/engine/api-utils.ts +70 -0
- package/src/drivers/engine/config.ts +39 -0
- package/src/drivers/engine/keys.test.ts +266 -0
- package/src/drivers/engine/keys.ts +89 -0
- package/src/drivers/engine/kv.ts +3 -0
- package/src/drivers/engine/log.ts +7 -0
- package/src/drivers/engine/manager-driver.ts +391 -0
- package/src/drivers/engine/mod.ts +36 -0
- package/src/drivers/engine/ws-proxy.ts +170 -0
- package/src/drivers/file-system/actor.ts +91 -0
- package/src/drivers/file-system/global-state.ts +673 -0
- package/src/drivers/file-system/log.ts +7 -0
- package/src/drivers/file-system/manager.ts +306 -0
- package/src/drivers/file-system/mod.ts +48 -0
- package/src/drivers/file-system/utils.ts +109 -0
- package/src/globals.d.ts +6 -0
- package/src/inline-client-driver/log.ts +7 -0
- package/src/inline-client-driver/mod.ts +385 -0
- package/src/inspector/actor.ts +298 -0
- package/src/inspector/config.ts +83 -0
- package/src/inspector/log.ts +5 -0
- package/src/inspector/manager.ts +86 -0
- package/src/inspector/mod.ts +2 -0
- package/src/inspector/protocol/actor.ts +10 -0
- package/src/inspector/protocol/common.ts +196 -0
- package/src/inspector/protocol/manager.ts +10 -0
- package/src/inspector/protocol/mod.ts +2 -0
- package/src/inspector/utils.ts +76 -0
- package/src/manager/auth.ts +121 -0
- package/src/manager/driver.ts +80 -0
- package/src/manager/hono-websocket-adapter.ts +333 -0
- package/src/manager/log.ts +7 -0
- package/src/manager/mod.ts +2 -0
- package/src/manager/protocol/mod.ts +24 -0
- package/src/manager/protocol/query.ts +89 -0
- package/src/manager/router.ts +1792 -0
- package/src/mod.ts +20 -0
- package/src/registry/config.ts +32 -0
- package/src/registry/log.ts +7 -0
- package/src/registry/mod.ts +124 -0
- package/src/registry/run-config.ts +54 -0
- package/src/registry/serve.ts +53 -0
- package/src/schemas/actor-persist/mod.ts +1 -0
- package/src/schemas/actor-persist/versioned.ts +25 -0
- package/src/schemas/client-protocol/mod.ts +1 -0
- package/src/schemas/client-protocol/versioned.ts +63 -0
- package/src/schemas/file-system-driver/mod.ts +1 -0
- package/src/schemas/file-system-driver/versioned.ts +28 -0
- package/src/serde.ts +84 -0
- package/src/test/config.ts +16 -0
- package/src/test/log.ts +7 -0
- package/src/test/mod.ts +153 -0
- package/src/utils.ts +172 -0
- 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
|
+
}
|