sonamu 0.11.15 → 0.12.0
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/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +12 -7
- package/dist/bin/build-config.d.ts +3 -1
- package/dist/bin/build-config.d.ts.map +1 -1
- package/dist/bin/build-config.js +17 -6
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/stream/__tests__/ws-test-helpers.d.ts +108 -0
- package/dist/stream/__tests__/ws-test-helpers.d.ts.map +1 -0
- package/dist/stream/__tests__/ws-test-helpers.js +260 -0
- package/dist/stream/index.d.ts +1 -0
- package/dist/stream/index.d.ts.map +1 -1
- package/dist/stream/index.js +4 -2
- package/dist/stream/ws-audience-resolver.d.ts +8 -5
- package/dist/stream/ws-audience-resolver.d.ts.map +1 -1
- package/dist/stream/ws-audience-resolver.js +16 -13
- package/dist/stream/ws-cluster-bus.d.ts +9 -4
- package/dist/stream/ws-cluster-bus.d.ts.map +1 -1
- package/dist/stream/ws-cluster-bus.js +1 -1
- package/dist/stream/ws-core.d.ts +10 -0
- package/dist/stream/ws-core.d.ts.map +1 -1
- package/dist/stream/ws-delivery.d.ts +30 -4
- package/dist/stream/ws-delivery.d.ts.map +1 -1
- package/dist/stream/ws-delivery.js +199 -52
- package/dist/stream/ws-frame.d.ts +15 -0
- package/dist/stream/ws-frame.d.ts.map +1 -0
- package/dist/stream/ws-frame.js +29 -0
- package/dist/stream/ws-local-connection-store.d.ts +4 -4
- package/dist/stream/ws-local-connection-store.d.ts.map +1 -1
- package/dist/stream/ws-local-connection-store.js +2 -2
- package/dist/stream/ws-presence-index.d.ts +36 -0
- package/dist/stream/ws-presence-index.d.ts.map +1 -0
- package/dist/stream/ws-presence-index.js +177 -0
- package/dist/stream/ws-presence-store.d.ts +39 -39
- package/dist/stream/ws-presence-store.d.ts.map +1 -1
- package/dist/stream/ws-presence-store.js +22 -152
- package/dist/stream/ws-registry.d.ts +45 -17
- package/dist/stream/ws-registry.d.ts.map +1 -1
- package/dist/stream/ws-registry.js +169 -60
- package/dist/stream/ws-session-id.d.ts +14 -0
- package/dist/stream/ws-session-id.d.ts.map +1 -0
- package/dist/stream/ws-session-id.js +37 -0
- package/dist/stream/ws.d.ts +20 -10
- package/dist/stream/ws.d.ts.map +1 -1
- package/dist/stream/ws.js +59 -36
- package/package.json +1 -1
- package/src/api/__tests__/sonamu.websocket-routes.test.ts +234 -0
- package/src/api/__tests__/sonamu.websocket.test.ts +241 -20
- package/src/api/sonamu.ts +20 -7
- package/src/bin/__tests__/build-web-command.test.ts +57 -0
- package/src/bin/__tests__/zod-compiler-build.test.ts +5 -3
- package/src/bin/build-config.ts +19 -7
- package/src/index.ts +1 -0
- package/src/stream/__tests__/ws-contracts.test.ts +483 -265
- package/src/stream/__tests__/ws-multinode.test.ts +326 -0
- package/src/stream/__tests__/ws-registry-async.test.ts +855 -0
- package/src/stream/__tests__/ws-test-helpers.ts +360 -0
- package/src/stream/__tests__/ws.test.ts +342 -145
- package/src/stream/index.ts +1 -0
- package/src/stream/ws-audience-resolver.ts +21 -19
- package/src/stream/ws-cluster-bus.ts +12 -4
- package/src/stream/ws-core.ts +14 -0
- package/src/stream/ws-delivery.ts +321 -97
- package/src/stream/ws-frame.ts +39 -0
- package/src/stream/ws-local-connection-store.ts +10 -9
- package/src/stream/ws-presence-index.ts +273 -0
- package/src/stream/ws-presence-store.ts +64 -284
- package/src/stream/ws-registry.ts +272 -85
- package/src/stream/ws-session-id.ts +39 -0
- package/src/stream/ws.ts +91 -50
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 기본 노드 ID를 만든다. 형식은 `${hostname()}-${process.pid}-${짧은 랜덤}`이다.
|
|
3
|
+
* 컨테이너 재시작 뒤 hostname과 pid가 같아도 이전 노드의 stale 상태를 물려받지 않도록 랜덤 접미사를 붙인다.
|
|
4
|
+
*/
|
|
5
|
+
export declare function createWebSocketNodeId(): string;
|
|
6
|
+
/**
|
|
7
|
+
* 노드 ID를 포함한 세션 ID를 만든다. `connections` audience는 이 ID만으로 대상 노드를 찾으므로 store 조회가 필요 없다.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createWebSocketSessionId(nodeId: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* 세션 ID에서 노드 ID를 복원한다. Sonamu가 만든 형식이 아니면 undefined를 반환한다.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parseWebSocketSessionNodeId(sessionId: string): string | undefined;
|
|
14
|
+
//# sourceMappingURL=ws-session-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ws-session-id.d.ts","sourceRoot":"","sources":["../../src/stream/ws-session-id.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAE/D;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAYjF"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { __esmMin } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { randomBytes, randomUUID } from "node:crypto";
|
|
3
|
+
import { hostname } from "node:os";
|
|
4
|
+
//#region src/stream/ws-session-id.ts
|
|
5
|
+
/**
|
|
6
|
+
* 기본 노드 ID를 만든다. 형식은 `${hostname()}-${process.pid}-${짧은 랜덤}`이다.
|
|
7
|
+
* 컨테이너 재시작 뒤 hostname과 pid가 같아도 이전 노드의 stale 상태를 물려받지 않도록 랜덤 접미사를 붙인다.
|
|
8
|
+
*/
|
|
9
|
+
function createWebSocketNodeId() {
|
|
10
|
+
return `${hostname()}-${process.pid}-${randomBytes(6).toString("base64url")}`;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 노드 ID를 포함한 세션 ID를 만든다. `connections` audience는 이 ID만으로 대상 노드를 찾으므로 store 조회가 필요 없다.
|
|
14
|
+
*/
|
|
15
|
+
function createWebSocketSessionId(nodeId) {
|
|
16
|
+
return `${nodeId}${SESSION_ID_SEPARATOR}${randomUUID()}`;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* 세션 ID에서 노드 ID를 복원한다. Sonamu가 만든 형식이 아니면 undefined를 반환한다.
|
|
20
|
+
*/
|
|
21
|
+
function parseWebSocketSessionNodeId(sessionId) {
|
|
22
|
+
const separatorIndex = sessionId.lastIndexOf(SESSION_ID_SEPARATOR);
|
|
23
|
+
if (separatorIndex < 0) return;
|
|
24
|
+
const suffix = sessionId.slice(separatorIndex + SESSION_ID_SEPARATOR.length);
|
|
25
|
+
if (!SESSION_SUFFIX_PATTERN.test(suffix)) return;
|
|
26
|
+
return sessionId.slice(0, separatorIndex);
|
|
27
|
+
}
|
|
28
|
+
var SESSION_ID_SEPARATOR, SESSION_SUFFIX_PATTERN;
|
|
29
|
+
var init_ws_session_id = __esmMin((() => {
|
|
30
|
+
SESSION_ID_SEPARATOR = ":";
|
|
31
|
+
SESSION_SUFFIX_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
32
|
+
}));
|
|
33
|
+
//#endregion
|
|
34
|
+
init_ws_session_id();
|
|
35
|
+
export { createWebSocketNodeId, createWebSocketSessionId, init_ws_session_id, parseWebSocketSessionNodeId };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid3Mtc2Vzc2lvbi1pZC5qcyIsIm5hbWVzIjpbXSwic291cmNlcyI6WyIuLi8uLi9zcmMvc3RyZWFtL3dzLXNlc3Npb24taWQudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgcmFuZG9tQnl0ZXMsIHJhbmRvbVVVSUQgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IGhvc3RuYW1lIH0gZnJvbSBcIm5vZGU6b3NcIjtcblxuLy8g7IS47IWYIElE64qUIGAke25vZGVJZH06JHt1dWlkfWAg7ZiV7Iud7J2064ukLiB1dWlk7JeQ64qUICc6J+qwgCDsl4bsnLzrr4DroZwg66eI7KeA66eJICc6J+uhnCDrgpjriITrqbRcbi8vIOuFuOuTnCBJROyXkCAnOicg6rCZ7J2AIOq1rOu2hOyekOqwgCDrk6TslrQg7J6I7Ja064+EIOq3uOuMgOuhnCDrs7Xsm5DrkJzri6RcbmNvbnN0IFNFU1NJT05fSURfU0VQQVJBVE9SID0gXCI6XCI7XG5jb25zdCBTRVNTSU9OX1NVRkZJWF9QQVRURVJOID0gL15bMC05YS1mXXs4fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXsxMn0kLztcblxuLyoqXG4gKiDquLDrs7gg64W465OcIElE66W8IOunjOuToOuLpC4g7ZiV7Iud7J2AIGAke2hvc3RuYW1lKCl9LSR7cHJvY2Vzcy5waWR9LSR77Ken7J2AIOuenOuNpH1g7J2064ukLlxuICog7Luo7YWM7J2064SIIOyerOyLnOyekSDrkqQgaG9zdG5hbWXqs7wgcGlk6rCAIOqwmeyVhOuPhCDsnbTsoIQg64W465Oc7J2YIHN0YWxlIOyDge2DnOulvCDrrLzroKTrsJvsp4Ag7JWK64+E66GdIOuenOuNpCDsoJHrr7jsgqzrpbwg67aZ7J2464ukLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlV2ViU29ja2V0Tm9kZUlkKCk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtob3N0bmFtZSgpfS0ke3Byb2Nlc3MucGlkfS0ke3JhbmRvbUJ5dGVzKDYpLnRvU3RyaW5nKFwiYmFzZTY0dXJsXCIpfWA7XG59XG5cbi8qKlxuICog64W465OcIElE66W8IO2PrO2VqO2VnCDshLjshZggSUTrpbwg66eM65Og64ukLiBgY29ubmVjdGlvbnNgIGF1ZGllbmNl64qUIOydtCBJROunjOycvOuhnCDrjIDsg4Eg64W465Oc66W8IOywvuycvOuvgOuhnCBzdG9yZSDsobDtmozqsIAg7ZWE7JqUIOyXhuuLpC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVdlYlNvY2tldFNlc3Npb25JZChub2RlSWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtub2RlSWR9JHtTRVNTSU9OX0lEX1NFUEFSQVRPUn0ke3JhbmRvbVVVSUQoKX1gO1xufVxuXG4vKipcbiAqIOyEuOyFmCBJROyXkOyEnCDrhbjrk5wgSUTrpbwg67O17JuQ7ZWc64ukLiBTb25hbXXqsIAg66eM65OgIO2YleyLneydtCDslYTri4jrqbQgdW5kZWZpbmVk66W8IOuwmO2ZmO2VnOuLpC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlV2ViU29ja2V0U2Vzc2lvbk5vZGVJZChzZXNzaW9uSWQ6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHNlcGFyYXRvckluZGV4ID0gc2Vzc2lvbklkLmxhc3RJbmRleE9mKFNFU1NJT05fSURfU0VQQVJBVE9SKTtcbiAgaWYgKHNlcGFyYXRvckluZGV4IDwgMCkge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBjb25zdCBzdWZmaXggPSBzZXNzaW9uSWQuc2xpY2Uoc2VwYXJhdG9ySW5kZXggKyBTRVNTSU9OX0lEX1NFUEFSQVRPUi5sZW5ndGgpO1xuICBpZiAoIVNFU1NJT05fU1VGRklYX1BBVFRFUk4udGVzdChzdWZmaXgpKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIHJldHVybiBzZXNzaW9uSWQuc2xpY2UoMCwgc2VwYXJhdG9ySW5kZXgpO1xufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7OztBQVlBLFNBQWdCLHdCQUFnQztDQUM5QyxPQUFPLEdBQUcsU0FBUyxFQUFFLEdBQUcsUUFBUSxJQUFJLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxTQUFTLFdBQVc7QUFDNUU7Ozs7QUFLQSxTQUFnQix5QkFBeUIsUUFBd0I7Q0FDL0QsT0FBTyxHQUFHLFNBQVMsdUJBQXVCLFdBQVc7QUFDdkQ7Ozs7QUFLQSxTQUFnQiw0QkFBNEIsV0FBdUM7Q0FDakYsTUFBTSxpQkFBaUIsVUFBVSxZQUFZLG9CQUFvQjtDQUNqRSxJQUFJLGlCQUFpQixHQUNuQjtDQUdGLE1BQU0sU0FBUyxVQUFVLE1BQU0saUJBQWlCLHFCQUFxQixNQUFNO0NBQzNFLElBQUksQ0FBQyx1QkFBdUIsS0FBSyxNQUFNLEdBQ3JDO0NBR0YsT0FBTyxVQUFVLE1BQU0sR0FBRyxjQUFjO0FBQzFDOzs7Q0FqQ00sdUJBQXVCO0NBQ3ZCLHlCQUF5QiJ9
|
package/dist/stream/ws.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { type WebSocket } from "ws";
|
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
import { type WebSocketAudience } from "./ws-audience";
|
|
5
5
|
import { type WebSocketClusterBus } from "./ws-cluster-bus";
|
|
6
|
+
import { type WebSocketRouteDefinition } from "./ws-delivery";
|
|
6
7
|
import { type WebSocketPresenceStore } from "./ws-presence-store";
|
|
7
8
|
import { type ManagedWebSocketConnection, WebSocketRegistry, type WebSocketRoomId, type WebSocketUserId } from "./ws-registry";
|
|
8
9
|
import { type WebSocketTelemetryConnectionContext, type WebSocketTelemetryController, type WebSocketTelemetryOptions } from "./ws-telemetry";
|
|
@@ -23,13 +24,14 @@ export interface WebSocketConnection<TOut extends object = WebSocketEventMap, TI
|
|
|
23
24
|
onMessage<K extends keyof WebSocketInEvents<TIn>>(event: K, handler: MessageHandler<WebSocketInEvents<TIn>[K]>): void;
|
|
24
25
|
publish<K extends keyof WebSocketOutEvents<TOut>>(event: K, data: WebSocketOutEvents<TOut>[K]): void;
|
|
25
26
|
waitForClose(): Promise<void>;
|
|
26
|
-
join(roomId: WebSocketRoomId): void
|
|
27
|
-
leave(roomId: WebSocketRoomId): void
|
|
28
|
-
setUserId(userId: WebSocketUserId): void
|
|
29
|
-
clearUserId(): void
|
|
27
|
+
join(roomId: WebSocketRoomId): Promise<void>;
|
|
28
|
+
leave(roomId: WebSocketRoomId): Promise<void>;
|
|
29
|
+
setUserId(userId: WebSocketUserId): Promise<void>;
|
|
30
|
+
clearUserId(): Promise<void>;
|
|
30
31
|
}
|
|
31
32
|
export type AnyWebSocketConnection = WebSocketConnection<object, object>;
|
|
32
33
|
type WebSocketConnectionOptions<TOut extends WebSocketEventFields, TIn extends WebSocketEventFields> = {
|
|
34
|
+
routeKey?: string;
|
|
33
35
|
namespace?: string;
|
|
34
36
|
heartbeat?: number;
|
|
35
37
|
active?: boolean;
|
|
@@ -47,17 +49,25 @@ export type WebSocketRuntimeOptions = {
|
|
|
47
49
|
presenceStore?: WebSocketPresenceStore;
|
|
48
50
|
clusterBus?: WebSocketClusterBus;
|
|
49
51
|
telemetry?: boolean | WebSocketTelemetryOptions;
|
|
52
|
+
drainTimeoutMs?: number;
|
|
50
53
|
};
|
|
51
54
|
export declare class WebSocketRuntime {
|
|
52
55
|
readonly registry: WebSocketRegistry;
|
|
53
56
|
readonly telemetryController: WebSocketTelemetryController;
|
|
54
57
|
constructor(options?: WebSocketRuntimeOptions);
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
58
|
+
registerRoute(routeKey: string, route: {
|
|
59
|
+
outEvents: z.ZodObject;
|
|
60
|
+
}): void;
|
|
61
|
+
replaceRoutes(routes: WebSocketRouteDefinition[]): void;
|
|
62
|
+
/**
|
|
63
|
+
* 소켓 리스너를 동기로 붙이고 registry에 등록한다. store.register가 끝나면(실패해도) resolve한다.
|
|
64
|
+
*/
|
|
65
|
+
registerConnection<TOutSchema extends WebSocketEventFields, TInSchema extends WebSocketEventFields>(socket: WebSocketTransport, options: Omit<WebSocketConnectionOptions<TOutSchema, TInSchema>, "registry" | "telemetryController">): Promise<WebSocketConnection<InferWebSocketEventMap<TOutSchema>, InferWebSocketEventMap<TInSchema>>>;
|
|
66
|
+
activateConnection(connectionId: string): Promise<void>;
|
|
67
|
+
broadcast<Data>(event: string, data: Data, namespace?: string): Promise<void>;
|
|
68
|
+
publishToRoom<Data>(roomId: WebSocketRoomId, event: string, data: Data, namespace?: string): Promise<void>;
|
|
69
|
+
publishToUser<Data>(userId: WebSocketUserId, event: string, data: Data, namespace?: string): Promise<void>;
|
|
70
|
+
publishToAudience<Data>(audience: WebSocketAudience, event: string, data: Data): Promise<void>;
|
|
61
71
|
shutdown(code?: number, reason?: string): Promise<void>;
|
|
62
72
|
}
|
|
63
73
|
export declare function createWebSocketRuntime(options?: WebSocketRuntimeOptions): WebSocketRuntime;
|
package/dist/stream/ws.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/stream/ws.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ws.d.ts","sourceRoot":"","sources":["../../src/stream/ws.ts"],"names":[],"mappings":"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"}
|