@arcblock/event-hub 1.28.8 → 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,43 @@
1
+ import { EventEmitter } from "node:events";
2
+ import { fromSecretKey } from "@ocap/wallet";
3
+ import axon from "axon";
4
+
5
+ //#region src/client.d.ts
6
+ interface ClientOptions {
7
+ port?: number;
8
+ hostname?: string;
9
+ autoConnect?: boolean;
10
+ wallet?: ReturnType<typeof fromSecretKey>;
11
+ did?: string;
12
+ sk?: string;
13
+ }
14
+ declare class Socket extends axon.SubEmitterSocket {
15
+ _authenticated: boolean;
16
+ _pendingMessages: [string, unknown][];
17
+ _wallet: ReturnType<typeof fromSecretKey>;
18
+ send: (event: string, data: unknown) => void;
19
+ constructor(opts: ClientOptions);
20
+ }
21
+ declare class Client extends EventEmitter {
22
+ opts: ClientOptions & {
23
+ wallet: ReturnType<typeof fromSecretKey>;
24
+ did: string;
25
+ };
26
+ _client: Socket;
27
+ _wallet: ReturnType<typeof fromSecretKey>;
28
+ constructor(opts?: ClientOptions);
29
+ connect(): void;
30
+ close(): void;
31
+ broadcast(event: string, data: unknown): void;
32
+ on(name: string, fn: (...args: unknown[]) => void): this;
33
+ off(name: string, fn?: (...args: unknown[]) => void): this;
34
+ /**
35
+ * Get the wallet instance
36
+ * Business can override wallet.signJWT() for remote signing
37
+ * @returns {WalletObject}
38
+ */
39
+ getWallet(): ReturnType<typeof fromSecretKey>;
40
+ _bindEvent(): void;
41
+ }
42
+ //#endregion
43
+ export { Client as default };
package/esm/client.mjs ADDED
@@ -0,0 +1,134 @@
1
+ import { EVENT_AUTH, EVENT_AUTH_FAIL, EVENT_AUTH_SUCCESS, RESERVED_EVENT_PREFIX } from "./constant.mjs";
2
+ import { EventEmitter } from "node:events";
3
+ import { DidType, isEthereumType, toTypeInfo } from "@arcblock/did";
4
+ import { WalletType, fromSecretKey } from "@ocap/wallet";
5
+ import axon from "axon";
6
+ import queue from "axon/lib/plugins/queue.js";
7
+ import roundrobin from "axon/lib/plugins/round-robin.js";
8
+
9
+ //#region src/client.ts
10
+ const checkEvent = (event) => {
11
+ if (event.startsWith(RESERVED_EVENT_PREFIX)) throw new Error(`event cannot start with ${RESERVED_EVENT_PREFIX}`);
12
+ };
13
+ const getWallet = (appSk, type) => {
14
+ let t = type;
15
+ let sk = appSk;
16
+ if (isEthereumType(DidType(type))) {
17
+ sk = appSk.slice(0, 66);
18
+ t = WalletType(type);
19
+ }
20
+ return fromSecretKey(sk, t);
21
+ };
22
+ const defaultOpts = {
23
+ port: void 0,
24
+ hostname: "0.0.0.0",
25
+ autoConnect: false,
26
+ wallet: void 0,
27
+ did: void 0,
28
+ sk: void 0
29
+ };
30
+ var Socket = class extends axon.SubEmitterSocket {
31
+ constructor(opts) {
32
+ super();
33
+ const wallet = opts.wallet || getWallet(opts.sk, toTypeInfo(opts.did));
34
+ this._authenticated = false;
35
+ this._pendingMessages = [];
36
+ this._wallet = wallet;
37
+ this.sock.use((sock) => {
38
+ sock.on("connect", async () => {
39
+ this._authenticated = false;
40
+ const token = await wallet.signJWT();
41
+ sock.send(EVENT_AUTH, {
42
+ pk: wallet.publicKey,
43
+ token
44
+ });
45
+ });
46
+ sock.on("close", () => {
47
+ this._authenticated = false;
48
+ this._pendingMessages = [];
49
+ });
50
+ });
51
+ this.on(EVENT_AUTH_SUCCESS, () => {
52
+ this._authenticated = true;
53
+ const pending = this._pendingMessages.slice();
54
+ this._pendingMessages = [];
55
+ pending.forEach(([event, data]) => this.sock.send(event, data));
56
+ });
57
+ this.on(EVENT_AUTH_FAIL, ({ msg } = {}) => {
58
+ this.emit("error", { msg });
59
+ this._authenticated = false;
60
+ this._pendingMessages = [];
61
+ this.sock.socks.forEach((s) => s.close());
62
+ });
63
+ this.sock.use(queue());
64
+ this.sock.use(roundrobin({ fallback: this.sock.enqueue }));
65
+ const originalSend = this.sock.send.bind(this.sock);
66
+ this.send = (event, data) => {
67
+ const hasConnection = this.sock.socks && this.sock.socks.length > 0;
68
+ if (this._authenticated && hasConnection) originalSend(event, data);
69
+ else this._pendingMessages.push([event, data]);
70
+ };
71
+ }
72
+ };
73
+ var Client = class extends EventEmitter {
74
+ constructor(opts = {}) {
75
+ super();
76
+ if (!opts.port) throw new Error("port should not be empty");
77
+ if (!opts.wallet) {
78
+ if (!opts.did) throw new Error("did should not be empty when wallet is not provided");
79
+ if (!opts.sk) throw new Error("Either wallet or sk should be provided");
80
+ }
81
+ const wallet = opts.wallet || getWallet(opts.sk, toTypeInfo(opts.did));
82
+ const did = opts.wallet ? opts.wallet.address : opts.did;
83
+ if (wallet.address !== did) throw new Error("did does not match the provided wallet/sk");
84
+ this.opts = Object.assign({}, defaultOpts, opts, {
85
+ wallet,
86
+ did
87
+ });
88
+ this._client = new Socket(this.opts);
89
+ this._wallet = wallet;
90
+ this._bindEvent();
91
+ if (this.opts.autoConnect) this.connect();
92
+ }
93
+ connect() {
94
+ const { port, hostname } = this.opts;
95
+ this._client.connect(port, hostname);
96
+ }
97
+ close() {
98
+ this._client._authenticated = false;
99
+ this._client._pendingMessages = [];
100
+ this._client.close();
101
+ }
102
+ broadcast(event, data) {
103
+ checkEvent(event);
104
+ this._client.send(event, data);
105
+ }
106
+ on(name, fn) {
107
+ checkEvent(name);
108
+ super.on(name, fn);
109
+ this._client.on(name, fn);
110
+ return this;
111
+ }
112
+ off(name, fn) {
113
+ checkEvent(name);
114
+ this._client.off(name);
115
+ if (fn) super.off(name, fn);
116
+ else super.removeAllListeners(name);
117
+ return this;
118
+ }
119
+ /**
120
+ * Get the wallet instance
121
+ * Business can override wallet.signJWT() for remote signing
122
+ * @returns {WalletObject}
123
+ */
124
+ getWallet() {
125
+ return this._wallet;
126
+ }
127
+ _bindEvent() {
128
+ this._client.on("error", this.emit.bind(this, "error"));
129
+ }
130
+ };
131
+ var client_default = Client;
132
+
133
+ //#endregion
134
+ export { client_default as default };
@@ -0,0 +1,7 @@
1
+ //#region src/constant.d.ts
2
+ declare const RESERVED_EVENT_PREFIX = "EVENT_HUB:";
3
+ declare const EVENT_AUTH = "EVENT_HUB:AUTH";
4
+ declare const EVENT_AUTH_SUCCESS = "EVENT_HUB:AUTH_SUCCESS";
5
+ declare const EVENT_AUTH_FAIL = "EVENT_HUB:AUTH_FAIL";
6
+ //#endregion
7
+ export { EVENT_AUTH, EVENT_AUTH_FAIL, EVENT_AUTH_SUCCESS, RESERVED_EVENT_PREFIX };
@@ -0,0 +1,8 @@
1
+ //#region src/constant.ts
2
+ const RESERVED_EVENT_PREFIX = "EVENT_HUB:";
3
+ const EVENT_AUTH = "EVENT_HUB:AUTH";
4
+ const EVENT_AUTH_SUCCESS = "EVENT_HUB:AUTH_SUCCESS";
5
+ const EVENT_AUTH_FAIL = "EVENT_HUB:AUTH_FAIL";
6
+
7
+ //#endregion
8
+ export { EVENT_AUTH, EVENT_AUTH_FAIL, EVENT_AUTH_SUCCESS, RESERVED_EVENT_PREFIX };
@@ -0,0 +1,7 @@
1
+ import Client from "./client.mjs";
2
+ import { Client as Client$1 } from "./single.mjs";
3
+
4
+ //#region src/index.d.ts
5
+ declare let defaultExport: Client | Client$1;
6
+ //#endregion
7
+ export { Client, Client$1 as ClientFallback, defaultExport as default };
package/esm/index.mjs ADDED
@@ -0,0 +1,28 @@
1
+ import client_default from "./client.mjs";
2
+ import { Client } from "./single.mjs";
3
+
4
+ //#region src/index.ts
5
+ const port = Number(process.env.ABT_NODE_EVENT_PORT);
6
+ const hostname = process.env.ABT_NODE_EVENT_HOSTNAME || "127.0.0.1";
7
+ let did;
8
+ let sk;
9
+ if (process.env.BLOCKLET_APP_SK && process.env.BLOCKLET_APP_ID) {
10
+ sk = process.env.BLOCKLET_APP_SK;
11
+ did = process.env.BLOCKLET_APP_ID;
12
+ } else if (process.env.ABT_NODE_SK && process.env.ABT_NODE_DID) {
13
+ sk = process.env.ABT_NODE_SK;
14
+ did = process.env.ABT_NODE_DID;
15
+ }
16
+ let defaultExport;
17
+ if (port && did && sk) defaultExport = new client_default({
18
+ port,
19
+ hostname,
20
+ did,
21
+ sk,
22
+ autoConnect: true
23
+ });
24
+ else defaultExport = new Client();
25
+ var src_default = defaultExport;
26
+
27
+ //#endregion
28
+ export { client_default as Client, Client as ClientFallback, src_default as default };
package/esm/rpc.d.mts ADDED
@@ -0,0 +1,51 @@
1
+ import axon from "axon";
2
+
3
+ //#region src/rpc.d.ts
4
+ interface InflightEntry {
5
+ resolve: (value: unknown) => void;
6
+ reject: (reason: Error) => void;
7
+ to: ReturnType<typeof setTimeout>;
8
+ errorPrefix?: string;
9
+ }
10
+ interface RpcOptions {
11
+ timeoutMs?: number;
12
+ respEvent?: string;
13
+ errorPrefix?: string;
14
+ }
15
+ interface SocketLike {
16
+ writable: boolean;
17
+ write(buf: Buffer): void;
18
+ }
19
+ declare class Client extends axon.Socket {
20
+ socks: SocketLike[];
21
+ port: number;
22
+ host: string;
23
+ online: boolean;
24
+ connectPromise: Promise<this> | null;
25
+ inflight: Map<string, InflightEntry>;
26
+ /**
27
+ * @param {number} port
28
+ * @param {string} host
29
+ */
30
+ constructor(port: number, host?: string);
31
+ onmessage(): (buf: Buffer) => void;
32
+ sendEvent(event: string, data: unknown): void;
33
+ ensureOnline(): Promise<this>;
34
+ /**
35
+ * 通用 RPC:发送 event,等待响应(默认只按 reqId 匹配)
36
+ * @param {string} event 例如 'pm2/start'
37
+ * @param {object} payload 发送为 { reqId, payload }
38
+ * @param {object} [opts]
39
+ * @param {number} [opts.timeoutMs=120000]
40
+ * @param {string} [opts.respEvent] // 可选:仅用于调试;匹配靠 reqId,不强依赖此项
41
+ * @param {string} [opts.errorPrefix] // 统一错误前缀
42
+ * @returns {Promise<any>}
43
+ */
44
+ rpc(event: string, payload?: unknown, {
45
+ timeoutMs,
46
+ respEvent,
47
+ errorPrefix
48
+ }?: RpcOptions): Promise<unknown>;
49
+ }
50
+ //#endregion
51
+ export { Client as default };
package/esm/rpc.mjs ADDED
@@ -0,0 +1,106 @@
1
+ import axon from "axon";
2
+ import { randomUUID } from "node:crypto";
3
+ import Message from "amp-message";
4
+
5
+ //#region src/rpc.ts
6
+ var Client = class extends axon.Socket {
7
+ /**
8
+ * @param {number} port
9
+ * @param {string} host
10
+ */
11
+ constructor(port, host = "127.0.0.1") {
12
+ super();
13
+ this.port = port;
14
+ this.host = host;
15
+ this.online = false;
16
+ this.connectPromise = null;
17
+ this.inflight = /* @__PURE__ */ new Map();
18
+ this.on("connect", () => {
19
+ this.online = true;
20
+ });
21
+ this.on("reconnect attempt", () => {
22
+ this.online = false;
23
+ });
24
+ this.on("disconnect", () => {
25
+ this.online = false;
26
+ });
27
+ this.on("error", () => {});
28
+ }
29
+ onmessage() {
30
+ return (buf) => {
31
+ try {
32
+ const [event, data] = new Message(buf).args;
33
+ if (data && typeof data === "object" && data.reqId) {
34
+ const entry = this.inflight.get(data.reqId);
35
+ if (entry) {
36
+ clearTimeout(entry.to);
37
+ this.inflight.delete(data.reqId);
38
+ if (data.ok === false) entry.reject(new Error(entry.errorPrefix ? `${entry.errorPrefix}: ${data.error}` : data.error || "request failed"));
39
+ else entry.resolve(data.data);
40
+ return;
41
+ }
42
+ }
43
+ this.emit(event, data);
44
+ } catch (e) {
45
+ console.error("[axon] decode error", e);
46
+ }
47
+ };
48
+ }
49
+ sendEvent(event, data) {
50
+ const buf = this.pack([event, data]);
51
+ const s = this.socks[0];
52
+ if (s?.writable) s.write(buf);
53
+ else throw new Error("axon socket not writable/connected");
54
+ }
55
+ async ensureOnline() {
56
+ if (!this.port || !this.host) throw new Error("PORT and HOST must be set via constructor: new Client(port, host)");
57
+ if (!this.connectPromise) this.connectPromise = new Promise((resolve, reject) => {
58
+ this.connect(this.port, this.host, (err) => err ? reject(err) : resolve(this));
59
+ });
60
+ await this.connectPromise;
61
+ if (this.online) return this;
62
+ await new Promise((r) => this.once("connect", r));
63
+ return this;
64
+ }
65
+ /**
66
+ * 通用 RPC:发送 event,等待响应(默认只按 reqId 匹配)
67
+ * @param {string} event 例如 'pm2/start'
68
+ * @param {object} payload 发送为 { reqId, payload }
69
+ * @param {object} [opts]
70
+ * @param {number} [opts.timeoutMs=120000]
71
+ * @param {string} [opts.respEvent] // 可选:仅用于调试;匹配靠 reqId,不强依赖此项
72
+ * @param {string} [opts.errorPrefix] // 统一错误前缀
73
+ * @returns {Promise<any>}
74
+ */
75
+ async rpc(event, payload = {}, { timeoutMs = 12e4, respEvent, errorPrefix } = {}) {
76
+ await this.ensureOnline();
77
+ const reqId = randomUUID();
78
+ return new Promise((resolve, reject) => {
79
+ const to = setTimeout(() => {
80
+ this.inflight.delete(reqId);
81
+ reject(/* @__PURE__ */ new Error(`${errorPrefix || "request"} timeout`));
82
+ }, timeoutMs);
83
+ this.inflight.set(reqId, {
84
+ resolve,
85
+ reject,
86
+ to,
87
+ errorPrefix
88
+ });
89
+ this.sendEvent(event, {
90
+ reqId,
91
+ payload
92
+ });
93
+ if (respEvent) {
94
+ const once = (data) => {
95
+ if (!data || data.reqId !== reqId) return;
96
+ this.off(respEvent, once);
97
+ };
98
+ this.on(respEvent, once);
99
+ }
100
+ });
101
+ }
102
+ };
103
+ var rpc_default = Client;
104
+
105
+ //#endregion
106
+ export { rpc_default as default };
@@ -0,0 +1,6 @@
1
+ import Server from "./server.mjs";
2
+
3
+ //#region src/server-abtnode.d.ts
4
+ declare const server: Server;
5
+ //#endregion
6
+ export { server as default };
@@ -0,0 +1,11 @@
1
+ import server_default from "./server.mjs";
2
+
3
+ //#region src/server-abtnode.ts
4
+ const port = Number(process.env.ABT_NODE_EVENT_PORT);
5
+ const hostname = Number(process.env.ABT_NODE_EVENT_HOSTNAME) || "127.0.0.1";
6
+ const server = new server_default();
7
+ server.bind(port, hostname);
8
+ var server_abtnode_default = server;
9
+
10
+ //#endregion
11
+ export { server_abtnode_default as default };
@@ -0,0 +1,55 @@
1
+ import axon from "axon";
2
+
3
+ //#region src/server.d.ts
4
+ interface JwtLike {
5
+ verify(token: string, pk: string): Promise<boolean>;
6
+ decode(token: string): {
7
+ iss: string;
8
+ };
9
+ }
10
+ interface ServerOptions {
11
+ jwt?: JwtLike;
12
+ }
13
+ interface SocketWithChannel {
14
+ channel?: string;
15
+ writable: boolean;
16
+ write(buf: Buffer): void;
17
+ _peername?: {
18
+ family: string;
19
+ address: string;
20
+ port: number;
21
+ };
22
+ }
23
+ interface RouteHandler {
24
+ fn: (payload: unknown, ctx: {
25
+ sock: SocketWithChannel;
26
+ channel?: string;
27
+ event: string;
28
+ server: Server;
29
+ }) => unknown | Promise<unknown>;
30
+ authRequired: boolean;
31
+ }
32
+ declare class Server extends axon.Socket {
33
+ jwt: JwtLike;
34
+ handlers: Map<string, RouteHandler>;
35
+ socks: SocketWithChannel[];
36
+ constructor(opts?: ServerOptions);
37
+ onmessage(sock: SocketWithChannel): (buf: Buffer) => void;
38
+ send(event: string, data: unknown, channel: string): this;
39
+ /**
40
+ * 注册路由
41
+ * @param {string} event
42
+ * @param {(payload:any, ctx:{sock:any, channel?:string, event:string, server:Server})=>any|Promise<any>} handler
43
+ * @param {{authRequired?: boolean}} [opts] - 默认 true;设为 false 则该事件免鉴权
44
+ */
45
+ register(event: string, handler: (payload: unknown, ctx: {
46
+ sock: SocketWithChannel;
47
+ channel?: string;
48
+ event: string;
49
+ server: Server;
50
+ }) => unknown | Promise<unknown>, opts?: {
51
+ authRequired?: boolean;
52
+ }): this;
53
+ }
54
+ //#endregion
55
+ export { Server as default };
package/esm/server.mjs ADDED
@@ -0,0 +1,142 @@
1
+ import { EVENT_AUTH, EVENT_AUTH_FAIL, EVENT_AUTH_SUCCESS } from "./constant.mjs";
2
+ import axon from "axon";
3
+ import Message from "amp-message";
4
+ import * as JWT from "@arcblock/jwt";
5
+
6
+ //#region src/server.ts
7
+ const getDid = (jwt) => jwt.iss.replace(/^did:abt:/, "");
8
+ function normalizeReq(input) {
9
+ if (input && typeof input === "object" && ("payload" in input || "reqId" in input)) {
10
+ const { reqId, payload } = input;
11
+ return {
12
+ reqId,
13
+ payload
14
+ };
15
+ }
16
+ return {
17
+ reqId: void 0,
18
+ payload: input
19
+ };
20
+ }
21
+ function normalizeRes(result) {
22
+ if (result && typeof result === "object" && ("ok" in result || "data" in result || "error" in result)) return result;
23
+ return {
24
+ ok: true,
25
+ data: result
26
+ };
27
+ }
28
+ var Server = class extends axon.Socket {
29
+ constructor(opts = {}) {
30
+ super();
31
+ this.jwt = opts?.jwt || JWT;
32
+ this.handlers = /* @__PURE__ */ new Map();
33
+ this.on("message", async (event, data, sock) => {
34
+ const route = this.handlers.get(event);
35
+ if (route) {
36
+ const { fn, authRequired } = route;
37
+ if (authRequired && !sock.channel) {
38
+ console.error(`unauthenticated socket blocked for event "${event}"`);
39
+ return;
40
+ }
41
+ const { reqId, payload } = normalizeReq(data);
42
+ try {
43
+ const res = normalizeRes(await fn(payload, {
44
+ sock,
45
+ channel: sock.channel,
46
+ event,
47
+ server: this
48
+ }));
49
+ const replyEvent = `${event}:res`;
50
+ if (sock.channel) this.send(replyEvent, {
51
+ reqId,
52
+ ...res
53
+ }, sock.channel);
54
+ else {
55
+ const buf = this.pack([replyEvent, {
56
+ reqId,
57
+ ...res
58
+ }]);
59
+ if (sock.writable) sock.write(buf);
60
+ }
61
+ } catch (err) {
62
+ const replyEvent = `${event}:res`;
63
+ const payloadErr = {
64
+ reqId,
65
+ ok: false,
66
+ error: err?.message || String(err)
67
+ };
68
+ if (sock.channel) this.send(replyEvent, payloadErr, sock.channel);
69
+ else {
70
+ const buf = this.pack([replyEvent, payloadErr]);
71
+ if (sock.writable) sock.write(buf);
72
+ }
73
+ }
74
+ return;
75
+ }
76
+ if (!sock.channel) {
77
+ console.error("skip message of unauthenticated socket");
78
+ return;
79
+ }
80
+ this.send(event, data, sock.channel);
81
+ });
82
+ this.on("connect", (socket) => {
83
+ console.log("event-hub client connected", socket._peername);
84
+ });
85
+ this.on("reconnect attempt", (socket) => {
86
+ console.log("event-hub client reconnect", socket._peername);
87
+ });
88
+ this.on("disconnect", (socket) => {
89
+ console.log("event-hub client disconnected", socket._peername);
90
+ });
91
+ this.on("drop", (args) => {
92
+ console.log("event-hub server drop message", args);
93
+ });
94
+ this.on("error", (err) => {
95
+ console.log("event-hub server error", err);
96
+ });
97
+ }
98
+ onmessage(sock) {
99
+ return (buf) => {
100
+ const [event, data] = new Message(buf).args;
101
+ if (event === EVENT_AUTH) {
102
+ const { pk, token } = data;
103
+ this.jwt.verify(token, pk).then((valid) => {
104
+ if (!valid) throw new Error("token verify failed");
105
+ sock.channel = getDid(this.jwt.decode(token));
106
+ const successBuf = this.pack([EVENT_AUTH_SUCCESS, {}]);
107
+ sock.write(successBuf);
108
+ }).catch((err) => {
109
+ console.error(err);
110
+ const resBuf = this.pack([EVENT_AUTH_FAIL, { msg: err.message }]);
111
+ sock.write(resBuf);
112
+ });
113
+ return;
114
+ }
115
+ this.emit("message", event, data, sock);
116
+ };
117
+ }
118
+ send(event, data, channel) {
119
+ const { socks } = this;
120
+ const buf = this.pack([event, data]);
121
+ for (const sock of socks) if (sock.channel === channel && sock.writable) sock.write(buf);
122
+ return this;
123
+ }
124
+ /**
125
+ * 注册路由
126
+ * @param {string} event
127
+ * @param {(payload:any, ctx:{sock:any, channel?:string, event:string, server:Server})=>any|Promise<any>} handler
128
+ * @param {{authRequired?: boolean}} [opts] - 默认 true;设为 false 则该事件免鉴权
129
+ */
130
+ register(event, handler, opts = {}) {
131
+ const authRequired = opts.authRequired !== false;
132
+ this.handlers.set(event, {
133
+ fn: handler,
134
+ authRequired
135
+ });
136
+ return this;
137
+ }
138
+ };
139
+ var server_default = Server;
140
+
141
+ //#endregion
142
+ export { server_default as default };
@@ -0,0 +1,10 @@
1
+ import { EventEmitter } from "node:events";
2
+
3
+ //#region src/single.d.ts
4
+ declare class Client extends EventEmitter {
5
+ broadcast(...args: Parameters<EventEmitter['emit']>): boolean;
6
+ off(event: string | symbol): this;
7
+ }
8
+ declare const _default: Client;
9
+ //#endregion
10
+ export { Client, _default as default };
package/esm/single.mjs ADDED
@@ -0,0 +1,16 @@
1
+ import { EventEmitter } from "node:events";
2
+
3
+ //#region src/single.ts
4
+ var Client = class extends EventEmitter {
5
+ broadcast(...args) {
6
+ return this.emit(...args);
7
+ }
8
+ off(event) {
9
+ this.removeAllListeners(event);
10
+ return this;
11
+ }
12
+ };
13
+ var single_default = new Client();
14
+
15
+ //#endregion
16
+ export { Client, single_default as default };
@@ -0,0 +1,29 @@
1
+ //#region rolldown:runtime
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") {
10
+ for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
11
+ key = keys[i];
12
+ if (!__hasOwnProp.call(to, key) && key !== except) {
13
+ __defProp(to, key, {
14
+ get: ((k) => from[k]).bind(null, key),
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ });
17
+ }
18
+ }
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+
27
+ //#endregion
28
+
29
+ exports.__toESM = __toESM;