@arcblock/ws 1.28.9 → 1.29.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.
@@ -0,0 +1,7 @@
1
+ import { createRequire } from "node:module";
2
+
3
+ //#region rolldown:runtime
4
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
5
+
6
+ //#endregion
7
+ export { __require };
@@ -0,0 +1,2 @@
1
+ import _default from "./client/browser.mjs";
2
+ export { _default as WsClient };
@@ -0,0 +1,3 @@
1
+ import browser_default from "./client/browser.mjs";
2
+
3
+ export { browser_default as WsClient };
@@ -0,0 +1,80 @@
1
+ import _default$1 from "../logger.mjs";
2
+
3
+ //#region src/client/base.d.ts
4
+ interface SocketConstructor {
5
+ new (endpoint: string, opts: object): SocketInstance;
6
+ }
7
+ interface SocketInstance {
8
+ channels: Channel[];
9
+ connect(): void;
10
+ disconnect(callback?: () => void, code?: number, reason?: string): void;
11
+ isConnected(): boolean;
12
+ onOpen(cb: () => void): void;
13
+ onClose(cb: () => void): void;
14
+ onError(cb: (err: {
15
+ error: Error;
16
+ }) => void): void;
17
+ onMessage(cb: (message: unknown) => void): void;
18
+ channel(topic: string, params?: object | (() => object)): Channel;
19
+ remove(channel: Channel): void;
20
+ }
21
+ interface Channel {
22
+ topic: string;
23
+ join(): ChannelPush;
24
+ leave(): ChannelPush;
25
+ on(event: string, callback: (data: {
26
+ status: string;
27
+ response: unknown;
28
+ }) => void): void;
29
+ off(event: string): void;
30
+ }
31
+ interface ChannelPush {
32
+ receive(status: string, callback: (data: unknown) => void): ChannelPush;
33
+ }
34
+ interface EventEmitterConstructor {
35
+ new (): EventEmitterInstance;
36
+ }
37
+ interface EventEmitterInstance {
38
+ on(event: string, handler: (data: unknown) => void): void;
39
+ off(event: string, handler?: (data: unknown) => void): void;
40
+ emit(event: string, data: unknown): void;
41
+ removeAllListeners(event: string): void;
42
+ listenerCount(event: string): number;
43
+ eventNames(): (string | symbol)[];
44
+ }
45
+ interface WsClientOptions {
46
+ silent?: boolean;
47
+ [key: string]: unknown;
48
+ }
49
+ declare const _default: (Socket: SocketConstructor, EventEmitter: EventEmitterConstructor, transport?: unknown) => {
50
+ new (endpoint: string, opts?: WsClientOptions): {
51
+ _logger: ReturnType<typeof _default$1>;
52
+ emitter: EventEmitterInstance;
53
+ on(event: string, handler: (data: unknown) => void, params?: object): void;
54
+ off(event: string, handler?: (data: unknown) => void): void;
55
+ disconnect(callback?: () => void, code?: number, reason?: string): void;
56
+ /**
57
+ * private
58
+ */
59
+ ensureJoinChannel(topic: string, params?: object): void;
60
+ /**
61
+ * private
62
+ */
63
+ ensureLeaveChannel(topic: string): void;
64
+ subscribe(topic: string, params?: object): Channel;
65
+ unsubscribe(topic: string): void;
66
+ channels: Channel[];
67
+ connect(): void;
68
+ isConnected(): boolean;
69
+ onOpen(cb: () => void): void;
70
+ onClose(cb: () => void): void;
71
+ onError(cb: (err: {
72
+ error: Error;
73
+ }) => void): void;
74
+ onMessage(cb: (message: unknown) => void): void;
75
+ channel(topic: string, params?: object | (() => object)): Channel;
76
+ remove(channel: Channel): void;
77
+ };
78
+ };
79
+ //#endregion
80
+ export { Channel, ChannelPush, EventEmitterConstructor, EventEmitterInstance, SocketConstructor, SocketInstance, WsClientOptions, _default as default };
@@ -0,0 +1,118 @@
1
+ import logger_default from "../logger.mjs";
2
+
3
+ //#region src/client/base.ts
4
+ var base_default = (Socket, EventEmitter, transport) => {
5
+ return class WsClient extends Socket {
6
+ constructor(endpoint, opts = {}) {
7
+ super(endpoint, {
8
+ transport,
9
+ ...opts
10
+ });
11
+ this._logger = logger_default("client", opts.silent);
12
+ this.emitter = new EventEmitter();
13
+ this.onOpen(() => {
14
+ this._logger.debug("socket open", endpoint);
15
+ });
16
+ this.onClose(() => {
17
+ this._logger.debug("socket close", endpoint);
18
+ });
19
+ this.onError((err) => {
20
+ this._logger.error("socket error", err.error);
21
+ });
22
+ this.onMessage((message) => {
23
+ this._logger.debug("socket message", message);
24
+ });
25
+ }
26
+ on(event, handler, params = {}) {
27
+ this.ensureJoinChannel(event, params);
28
+ this.emitter.on(event, handler);
29
+ }
30
+ off(event, handler) {
31
+ if (handler) this.emitter.off(event, handler);
32
+ else this.emitter.removeAllListeners(event);
33
+ this.ensureLeaveChannel(event);
34
+ }
35
+ disconnect(callback, code, reason) {
36
+ this.emitter.eventNames().forEach((event) => {
37
+ this.emitter.removeAllListeners(event);
38
+ });
39
+ super.disconnect(callback, code, reason);
40
+ }
41
+ /**
42
+ * private
43
+ */
44
+ ensureJoinChannel(topic, params = {}) {
45
+ if (this.emitter.listenerCount(topic) > 0) return;
46
+ const channel = this.channel(topic, params);
47
+ channel.join().receive("ok", (message) => {
48
+ this._logger.debug("join success", {
49
+ topic,
50
+ message
51
+ });
52
+ }).receive("error", (error) => {
53
+ this._logger.error("join error", {
54
+ topic,
55
+ error
56
+ });
57
+ }).receive("timeout", () => {
58
+ this._logger.debug("join timeout", { topic });
59
+ });
60
+ channel.on(topic, ({ status, response: data }) => {
61
+ if (status === "ok") this.emitter.emit(topic, data);
62
+ else this._logger.debug("response error", {
63
+ topic,
64
+ status,
65
+ data
66
+ });
67
+ });
68
+ }
69
+ /**
70
+ * private
71
+ */
72
+ ensureLeaveChannel(topic) {
73
+ if (this.emitter.listenerCount(topic) > 0) return;
74
+ const channel = this.channels.find((c) => c.topic === topic);
75
+ if (!channel) return;
76
+ this.remove(channel);
77
+ channel.leave().receive("ok", (message) => {
78
+ this._logger.debug("leave success", {
79
+ topic,
80
+ message
81
+ });
82
+ }).receive("error", (err) => {
83
+ this._logger.error("leave error", {
84
+ topic,
85
+ err
86
+ });
87
+ }).receive("timeout", () => {
88
+ this._logger.debug("leave timeout", { topic });
89
+ });
90
+ channel.off(topic);
91
+ }
92
+ subscribe(topic, params = {}) {
93
+ let channel = this.channels.find((c) => c.topic === topic);
94
+ if (channel) return channel;
95
+ channel = this.channel(topic, params);
96
+ channel.join().receive("ok", (message) => {
97
+ this._logger.debug("join success", {
98
+ topic,
99
+ message
100
+ });
101
+ }).receive("error", (error) => {
102
+ this._logger.error("join error", {
103
+ topic,
104
+ error
105
+ });
106
+ }).receive("timeout", () => {
107
+ this._logger.debug("join timeout", { topic });
108
+ });
109
+ return channel;
110
+ }
111
+ unsubscribe(topic) {
112
+ this.ensureLeaveChannel(topic);
113
+ }
114
+ };
115
+ };
116
+
117
+ //#endregion
118
+ export { base_default as default };
@@ -0,0 +1,30 @@
1
+ import _default$1 from "../logger.mjs";
2
+ import { Channel, EventEmitterInstance, WsClientOptions } from "./base.mjs";
3
+
4
+ //#region src/client/browser.d.ts
5
+ declare const _default: {
6
+ new (endpoint: string, opts?: WsClientOptions): {
7
+ _logger: ReturnType<typeof _default$1>;
8
+ emitter: EventEmitterInstance;
9
+ on(event: string, handler: (data: unknown) => void, params?: object): void;
10
+ off(event: string, handler?: (data: unknown) => void): void;
11
+ disconnect(callback?: () => void, code?: number, reason?: string): void;
12
+ ensureJoinChannel(topic: string, params?: object): void;
13
+ ensureLeaveChannel(topic: string): void;
14
+ subscribe(topic: string, params?: object): Channel;
15
+ unsubscribe(topic: string): void;
16
+ channels: Channel[];
17
+ connect(): void;
18
+ isConnected(): boolean;
19
+ onOpen(cb: () => void): void;
20
+ onClose(cb: () => void): void;
21
+ onError(cb: (err: {
22
+ error: Error;
23
+ }) => void): void;
24
+ onMessage(cb: (message: unknown) => void): void;
25
+ channel(topic: string, params?: object | (() => object)): Channel;
26
+ remove(channel: Channel): void;
27
+ };
28
+ };
29
+ //#endregion
30
+ export { _default as default };
@@ -0,0 +1,9 @@
1
+ import base_default from "./base.mjs";
2
+ import EventEmitter from "eventemitter3";
3
+ import { Socket } from "phoenix";
4
+
5
+ //#region src/client/browser.ts
6
+ var browser_default = base_default(Socket, EventEmitter);
7
+
8
+ //#endregion
9
+ export { browser_default as default };
@@ -0,0 +1,30 @@
1
+ import _default$1 from "../logger.mjs";
2
+ import { Channel, EventEmitterInstance, WsClientOptions } from "./base.mjs";
3
+
4
+ //#region src/client/index.d.ts
5
+ declare const _default: {
6
+ new (endpoint: string, opts?: WsClientOptions): {
7
+ _logger: ReturnType<typeof _default$1>;
8
+ emitter: EventEmitterInstance;
9
+ on(event: string, handler: (data: unknown) => void, params?: object): void;
10
+ off(event: string, handler?: (data: unknown) => void): void;
11
+ disconnect(callback?: () => void, code?: number, reason?: string): void;
12
+ ensureJoinChannel(topic: string, params?: object): void;
13
+ ensureLeaveChannel(topic: string): void;
14
+ subscribe(topic: string, params?: object): Channel;
15
+ unsubscribe(topic: string): void;
16
+ channels: Channel[];
17
+ connect(): void;
18
+ isConnected(): boolean;
19
+ onOpen(cb: () => void): void;
20
+ onClose(cb: () => void): void;
21
+ onError(cb: (err: {
22
+ error: Error;
23
+ }) => void): void;
24
+ onMessage(cb: (message: unknown) => void): void;
25
+ channel(topic: string, params?: object | (() => object)): Channel;
26
+ remove(channel: Channel): void;
27
+ };
28
+ };
29
+ //#endregion
30
+ export { _default as default };
@@ -0,0 +1,10 @@
1
+ import base_default from "./base.mjs";
2
+ import { Socket } from "phoenix";
3
+ import EventEmitter from "node:events";
4
+ import WebSocket from "ws";
5
+
6
+ //#region src/client/index.ts
7
+ var client_default = base_default(Socket, EventEmitter, WebSocket);
8
+
9
+ //#endregion
10
+ export { client_default as default };
@@ -0,0 +1,3 @@
1
+ import _default from "./client/index.mjs";
2
+ import WsServer from "./server/index.mjs";
3
+ export { _default as WsClient, WsServer };
package/esm/index.mjs ADDED
@@ -0,0 +1,4 @@
1
+ import client_default from "./client/index.mjs";
2
+ import server_default from "./server/index.mjs";
3
+
4
+ export { client_default as WsClient, server_default as WsServer };
@@ -0,0 +1,13 @@
1
+ import debug from "debug";
2
+
3
+ //#region src/logger.d.ts
4
+ interface Logger {
5
+ debug: debug.Debugger | ((...args: unknown[]) => void);
6
+ warn?: debug.Debugger | ((...args: unknown[]) => void);
7
+ info: debug.Debugger | ((...args: unknown[]) => void);
8
+ trace?: (...args: unknown[]) => void;
9
+ error: (...args: unknown[]) => void;
10
+ }
11
+ declare const _default: (subModule: string, silent?: boolean) => Logger;
12
+ //#endregion
13
+ export { Logger, _default as default };
package/esm/logger.mjs ADDED
@@ -0,0 +1,16 @@
1
+ import debug from "debug";
2
+
3
+ //#region src/logger.ts
4
+ var logger_default = (subModule, silent = false) => {
5
+ const d = debug(["@arcblock/ws", subModule].join(":"));
6
+ return {
7
+ debug: d,
8
+ warn: d,
9
+ info: d,
10
+ trace: silent ? d : console.error,
11
+ error: silent ? d : console.error
12
+ };
13
+ };
14
+
15
+ //#endregion
16
+ export { logger_default as default };
@@ -0,0 +1,138 @@
1
+ import { Logger } from "../logger.mjs";
2
+ import EventEmitter from "node:events";
3
+ import WebSocket, { WebSocketServer } from "ws";
4
+ import http from "node:http";
5
+ import { Duplex } from "node:stream";
6
+
7
+ //#region src/server/index.d.ts
8
+ interface WsSocket extends WebSocket {
9
+ id: string;
10
+ channel: Record<string, {
11
+ authInfo?: unknown;
12
+ }>;
13
+ heartbeatAt: number;
14
+ authInfo?: unknown;
15
+ }
16
+ interface HookParams {
17
+ socket: WsSocket;
18
+ joinRef: string;
19
+ ref: string;
20
+ topic: string;
21
+ event: string;
22
+ payload: unknown;
23
+ }
24
+ interface Hooks {
25
+ authenticateJoinChannel: (params: any) => unknown;
26
+ preJoinChannel: (params: any) => void | Promise<void>;
27
+ postJoinChannel: (params: any) => void | Promise<void>;
28
+ preLeaveChannel: (params: any) => void | Promise<void>;
29
+ postLeaveChannel: (params: any) => void | Promise<void>;
30
+ postBroadcast: (opts: BroadcastResult) => void | Promise<void>;
31
+ postSend: (opts: SendOptions) => void | Promise<void>;
32
+ receiveMessage: (params: any) => void | Promise<void>;
33
+ }
34
+ interface WsServerOptions {
35
+ pathname?: string;
36
+ authenticate?: (req: http.IncomingMessage, cb: (err: Error | null, authInfo?: unknown) => void) => void;
37
+ hooks?: Partial<Hooks>;
38
+ logger?: Logger;
39
+ silent?: boolean;
40
+ skipLogOnHookError?: boolean;
41
+ broadcastEventName?: string;
42
+ heartbeatTimeout?: number;
43
+ }
44
+ interface BroadcastOptions {
45
+ enableLog?: boolean;
46
+ socketFilters?: Record<string, unknown>;
47
+ noCluster?: boolean;
48
+ }
49
+ interface BroadcastResult {
50
+ count: number;
51
+ topic: string;
52
+ event: string;
53
+ data: unknown;
54
+ options: BroadcastOptions;
55
+ }
56
+ interface SendOptions {
57
+ topic: string;
58
+ event: string;
59
+ data: unknown;
60
+ options: {
61
+ enableLog?: boolean;
62
+ };
63
+ }
64
+ /**
65
+ * Create a websocket server
66
+ *
67
+ * @param {Object} opts
68
+ * @param {String} opts.pathname - which path to mount the socket server
69
+ * @param {Object} opts.authenticate - authentication function to be called on connection
70
+ * @param {Object} opts.hooks - hooks to be called on events
71
+ * @param {Object} opts.logger - logger used to log messages
72
+ * @param {Object} opts.broadcastEventName - used in cluster mode, default is '@arcblock/ws:broadcast'
73
+ * @param {Object} opts.heartbeatTimeout - maximum non-response time of a connection socket
74
+ * @class WsServer
75
+ * @extends {EventEmitter}
76
+ */
77
+ declare class WsServer extends EventEmitter {
78
+ pathname?: string;
79
+ authenticate: WsServerOptions['authenticate'];
80
+ hooks: Hooks;
81
+ logger: Logger;
82
+ skipLogOnHookError: boolean;
83
+ heartbeatTimeout: number;
84
+ wss: WebSocketServer;
85
+ topics: Record<string, Set<WsSocket>>;
86
+ broadcastEventName: string;
87
+ constructor(opts?: WsServerOptions);
88
+ attach(server: http.Server): this;
89
+ onConnect(request: http.IncomingMessage, socket: Duplex, head: Buffer): void;
90
+ /**
91
+ * Broadcast message to all subscribers of a topic, can be used as
92
+ * - broadcast(event, data) ==> broadcast(event, event, data)
93
+ * - broadcast(topic, event, data)
94
+ * - broadcast(topic, event, data, options)
95
+ */
96
+ broadcast(...args: unknown[]): Promise<void>;
97
+ _doBroadCast({
98
+ topic,
99
+ event,
100
+ data,
101
+ enableLog,
102
+ replyId,
103
+ socketFilters
104
+ }?: DoBroadcastParams): {
105
+ count: number;
106
+ error?: Error;
107
+ };
108
+ /**
109
+ * Send message to 1 subscriber of a topic, can be used as
110
+ * - send(socket, event, data)
111
+ * - send(socket, topic, event, data)
112
+ * - send(socket, topic, event, data, options)
113
+ */
114
+ send(...args: unknown[]): Promise<void>;
115
+ /**
116
+ * private
117
+ */
118
+ onWssConnection(socket: WebSocket): Promise<void>;
119
+ /**
120
+ * private
121
+ */
122
+ onWssClose(): void;
123
+ /**
124
+ * private
125
+ */
126
+ onWssError(error: Error): void;
127
+ _leaveChannel(socket: WsSocket, topic: string): void;
128
+ }
129
+ interface DoBroadcastParams {
130
+ topic: string;
131
+ event: string;
132
+ data: unknown;
133
+ enableLog?: boolean;
134
+ replyId?: string;
135
+ socketFilters?: Record<string, unknown>;
136
+ }
137
+ //#endregion
138
+ export { HookParams, Hooks, WsSocket, WsServer as default };