@arcblock/ws 1.28.9 → 1.29.1

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,138 @@
1
+ import { Logger } from "../logger.cjs";
2
+ import EventEmitter from "node:events";
3
+ import http from "node:http";
4
+ import { Duplex } from "node:stream";
5
+ import WebSocket, { WebSocketServer } from "ws";
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcblock/ws",
3
- "version": "1.28.9",
3
+ "version": "1.29.1",
4
4
  "description": "OCAP Chain websocket server and client",
5
5
  "keywords": [
6
6
  "websocket"
@@ -8,14 +8,31 @@
8
8
  "author": "arcblock <engineer@arcblock.io>",
9
9
  "homepage": "https://github.com/ArcBlock/blockchain#readme",
10
10
  "license": "Apache-2.0",
11
- "main": "./lib/index.js",
12
- "browser": "./lib/browser.js",
13
- "directories": {
14
- "lib": "lib",
15
- "test": "__tests__"
11
+ "type": "module",
12
+ "main": "./lib/index.cjs",
13
+ "module": "./esm/index.mjs",
14
+ "types": "./esm/index.d.mts",
15
+ "browser": "./esm/browser.mjs",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./esm/index.d.mts",
19
+ "import": "./esm/index.mjs",
20
+ "default": "./lib/index.cjs"
21
+ },
22
+ "./lib/*.js": {
23
+ "types": "./esm/*.d.mts",
24
+ "import": "./esm/*.mjs",
25
+ "default": "./lib/*.cjs"
26
+ },
27
+ "./lib/*": {
28
+ "types": "./esm/*.d.mts",
29
+ "import": "./esm/*.mjs",
30
+ "default": "./lib/*.cjs"
31
+ }
16
32
  },
17
33
  "files": [
18
- "lib"
34
+ "lib",
35
+ "esm"
19
36
  ],
20
37
  "publishConfig": {
21
38
  "access": "public"
@@ -25,6 +42,8 @@
25
42
  "url": "git+https://github.com/ArcBlock/blockchain.git"
26
43
  },
27
44
  "scripts": {
45
+ "build": "tsdown",
46
+ "prebuild": "rm -rf lib esm",
28
47
  "lint": "biome check",
29
48
  "lint:fix": "biome check --write",
30
49
  "test": "bun test",
@@ -34,14 +53,17 @@
34
53
  "url": "https://github.com/ArcBlock/blockchain/issues"
35
54
  },
36
55
  "dependencies": {
37
- "@arcblock/event-hub": "1.28.9",
38
- "debug": "^4.3.6",
56
+ "@arcblock/event-hub": "1.29.1",
57
+ "debug": "^4.4.3",
39
58
  "eventemitter3": "^4.0.7",
40
- "lodash": "^4.17.21",
59
+ "lodash": "^4.17.23",
41
60
  "phoenix": "1.7.2",
42
61
  "ws": "^8.18.0"
43
62
  },
44
63
  "devDependencies": {
64
+ "@types/debug": "^4.1.12",
65
+ "@types/lodash": "^4.17.15",
66
+ "@types/ws": "^8.5.13",
45
67
  "get-port": "^5.1.1"
46
68
  }
47
69
  }
package/lib/browser.js DELETED
@@ -1,5 +0,0 @@
1
- const WsClient = require('./client/browser');
2
-
3
- module.exports = {
4
- WsClient,
5
- };
@@ -1,134 +0,0 @@
1
- const createLogger = require('../logger');
2
-
3
- module.exports = (Socket, EventEmitter, transport) => {
4
- return class WsClient extends Socket {
5
- constructor(endpoint, opts = {}) {
6
- super(endpoint, { transport, ...opts });
7
-
8
- this._logger = createLogger('client', opts.silent);
9
- this.emitter = new EventEmitter();
10
-
11
- this.onOpen(() => {
12
- this._logger.debug('socket open', endpoint);
13
- });
14
- this.onClose(() => {
15
- this._logger.debug('socket close', endpoint);
16
- });
17
- this.onError((err) => {
18
- this._logger.error('socket error', err.error);
19
- });
20
- this.onMessage((message) => {
21
- this._logger.debug('socket message', message);
22
- });
23
- }
24
-
25
- on(event, handler, params = {}) {
26
- this.ensureJoinChannel(event, params);
27
- this.emitter.on(event, handler);
28
- }
29
-
30
- off(event, handler) {
31
- if (handler) {
32
- this.emitter.off(event, handler);
33
- } else {
34
- this.emitter.removeAllListeners(event);
35
- }
36
-
37
- this.ensureLeaveChannel(event);
38
- }
39
-
40
- disconnect(callback, code, reason) {
41
- this.emitter.eventNames().forEach((event) => {
42
- this.emitter.removeAllListeners(event);
43
- });
44
- super.disconnect(callback, code, reason);
45
- }
46
-
47
- /**
48
- * private
49
- */
50
- ensureJoinChannel(topic, params = {}) {
51
- const count = this.emitter.listenerCount(topic);
52
- if (count > 0) {
53
- return;
54
- }
55
-
56
- const channel = this.channel(topic, params);
57
- channel
58
- .join()
59
- .receive('ok', (message) => {
60
- this._logger.debug('join success', { topic, message });
61
- })
62
- .receive('error', (error) => {
63
- this._logger.error('join error', { topic, error });
64
- })
65
- .receive('timeout', () => {
66
- this._logger.debug('join timeout', { topic });
67
- });
68
- channel.on(topic, ({ status, response: data }) => {
69
- if (status === 'ok') {
70
- this.emitter.emit(topic, data);
71
- } else {
72
- this._logger.debug('response error', { topic, status, data });
73
- }
74
- });
75
- }
76
-
77
- /**
78
- * private
79
- */
80
- ensureLeaveChannel(topic) {
81
- const count = this.emitter.listenerCount(topic);
82
- if (count > 0) {
83
- return;
84
- }
85
-
86
- const channel = this.channels.find((c) => c.topic === topic);
87
- if (!channel) {
88
- return;
89
- }
90
-
91
- this.remove(channel);
92
- channel
93
- .leave()
94
- .receive('ok', (message) => {
95
- this._logger.debug('leave success', { topic, message });
96
- })
97
- .receive('error', (err) => {
98
- this._logger.error('leave error', { topic, err });
99
- })
100
- .receive('timeout', () => {
101
- this._logger.debug('leave timeout', { topic });
102
- });
103
- channel.off(topic);
104
- }
105
-
106
- // More flexible subscribe
107
- // Allow user to join a channel and listen to any POI events
108
- subscribe(topic, params = {}) {
109
- let channel = this.channels.find((c) => c.topic === topic);
110
- if (channel) {
111
- return channel;
112
- }
113
-
114
- channel = this.channel(topic, params);
115
- channel
116
- .join()
117
- .receive('ok', (message) => {
118
- this._logger.debug('join success', { topic, message });
119
- })
120
- .receive('error', (error) => {
121
- this._logger.error('join error', { topic, error });
122
- })
123
- .receive('timeout', () => {
124
- this._logger.debug('join timeout', { topic });
125
- });
126
-
127
- return channel;
128
- }
129
-
130
- unsubscribe(topic) {
131
- this.ensureLeaveChannel(topic);
132
- }
133
- };
134
- };
@@ -1,6 +0,0 @@
1
- const EventEmitter = require('eventemitter3');
2
- const { Socket } = require('phoenix');
3
-
4
- const createClient = require('./base');
5
-
6
- module.exports = createClient(Socket, EventEmitter);
@@ -1,7 +0,0 @@
1
- const EventEmitter = require('node:events');
2
- const { Socket } = require('phoenix');
3
- const WebSocket = require('ws');
4
-
5
- const createClient = require('./base');
6
-
7
- module.exports = createClient(Socket, EventEmitter, WebSocket);
package/lib/index.js DELETED
@@ -1,7 +0,0 @@
1
- const WsServer = require('./server');
2
- const WsClient = require('./client');
3
-
4
- module.exports = {
5
- WsServer,
6
- WsClient,
7
- };
package/lib/logger.js DELETED
@@ -1,12 +0,0 @@
1
- const debug = require('debug');
2
-
3
- module.exports = (subModule, silent = false) => {
4
- const d = debug(['@arcblock/ws', subModule].join(':'));
5
- return {
6
- debug: d,
7
- warn: d,
8
- info: d,
9
- trace: silent ? d : console.error,
10
- error: silent ? d : console.error,
11
- };
12
- };