@zap-socket/server 0.0.6 → 0.0.8
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/server.d.ts +9 -4
- package/dist/server.js +90 -80
- package/package.json +2 -2
package/dist/server.d.ts
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
import { WebSocketServer, WebSocket } from "ws";
|
2
|
-
import type { EventMap, ZapServerEvent } from "@zap-socket/types";
|
2
|
+
import type { EventMap, ZapEvent, ZapServerEvent } from "@zap-socket/types";
|
3
3
|
interface ZapServerConstructorT {
|
4
4
|
port: number;
|
5
5
|
events?: EventMap;
|
6
6
|
}
|
7
7
|
export declare class ZapServer<T extends EventMap> {
|
8
8
|
wss: WebSocketServer;
|
9
|
+
onconnect: (handler: (ctx: {
|
10
|
+
id: string;
|
11
|
+
ws: WebSocket;
|
12
|
+
}) => void) => void;
|
13
|
+
private onconnectHandler;
|
9
14
|
private wsToId;
|
10
15
|
private idToWs;
|
11
16
|
private _events;
|
@@ -16,9 +21,9 @@ export declare class ZapServer<T extends EventMap> {
|
|
16
21
|
broadcastRaw(data: any): void;
|
17
22
|
broadcast(event: keyof T, data: any): void;
|
18
23
|
selectiveBroascast(event: string, data: any, connections: string[]): void;
|
19
|
-
get
|
20
|
-
send: (clientId: string, data?: (T[K] extends ZapServerEvent<any> ? T[K]["data"] : never)) => void;
|
21
|
-
broadcast: (data?: (T[K] extends ZapServerEvent<any> ? T[K]["data"] : never)) => void;
|
24
|
+
get events(): { [K in keyof T as T[K] extends ZapServerEvent<any> | ZapEvent<any, any> ? K : never]: {
|
25
|
+
send: (clientId: string, data?: (T[K] extends ZapServerEvent<any> ? T[K]["data"] : T[K] extends ZapEvent<any, any> ? ReturnType<T[K]["process"]> : never)) => void;
|
26
|
+
broadcast: (data?: (T[K] extends ZapServerEvent<any> ? T[K]["data"] : T[K] extends ZapEvent<any, any> ? ReturnType<T[K]["process"]> : never)) => void;
|
22
27
|
}; };
|
23
28
|
get clients(): Set<string>;
|
24
29
|
get socketMap(): Map<string, WebSocket>;
|
package/dist/server.js
CHANGED
@@ -5,6 +5,8 @@ const isClientEvent = (event) => {
|
|
5
5
|
};
|
6
6
|
export class ZapServer {
|
7
7
|
wss;
|
8
|
+
onconnect;
|
9
|
+
onconnectHandler;
|
8
10
|
wsToId;
|
9
11
|
idToWs;
|
10
12
|
_events = {};
|
@@ -13,78 +15,88 @@ export class ZapServer {
|
|
13
15
|
this.wsToId = new Map();
|
14
16
|
this.idToWs = new Map();
|
15
17
|
this._events = events;
|
18
|
+
this.onconnectHandler = () => { };
|
19
|
+
this.onconnect = (handler) => {
|
20
|
+
this.onconnectHandler = handler;
|
21
|
+
};
|
16
22
|
this.wss.on("listening", () => {
|
17
23
|
if (callback)
|
18
24
|
callback();
|
19
25
|
});
|
20
26
|
this.wss.on("connection", (ws, req) => {
|
21
27
|
ws.on("message", (message) => {
|
22
|
-
if (!this.wsToId.get(ws)) {
|
28
|
+
if (!this.wsToId.get(ws) && message.toString() === "OPEN") {
|
23
29
|
const id = generateId();
|
24
30
|
this.wsToId.set(ws, id);
|
25
31
|
this.idToWs.set(id, ws);
|
26
32
|
ws.send("ID " + id);
|
27
|
-
|
33
|
+
this.onconnectHandler({
|
34
|
+
id,
|
35
|
+
ws
|
36
|
+
});
|
28
37
|
return;
|
29
38
|
}
|
30
39
|
const clientId = this.wsToId.get(ws);
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
ws.send(serialized);
|
68
|
-
}
|
69
|
-
else if (streamId) {
|
70
|
-
const consumeStream = async () => {
|
71
|
-
const result = process(data, { server: this, id: this.wsToId.get(ws), buffer: ctx });
|
72
|
-
for await (const x of result) {
|
73
|
-
const packet = {
|
74
|
-
streamId,
|
75
|
-
fragment: x
|
76
|
-
};
|
77
|
-
this.sendMessageRaw(clientId, packet);
|
78
|
-
}
|
79
|
-
this.sendMessageRaw(clientId, {
|
80
|
-
streamId,
|
81
|
-
done: true
|
82
|
-
});
|
83
|
-
};
|
84
|
-
consumeStream();
|
40
|
+
const parsedMessage = deserialize(message.toString());
|
41
|
+
if (!parsedMessage)
|
42
|
+
return;
|
43
|
+
const { event, stream, data, requestId, streamId, batch } = parsedMessage;
|
44
|
+
const key = event || stream;
|
45
|
+
const eventObj = this._events[key];
|
46
|
+
if (!eventObj || !isClientEvent(eventObj))
|
47
|
+
return;
|
48
|
+
const { process, middleware } = eventObj;
|
49
|
+
// Setup middleware context
|
50
|
+
const ctx = {};
|
51
|
+
if (middleware) {
|
52
|
+
for (const m of middleware) {
|
53
|
+
const metadata = {
|
54
|
+
id: clientId,
|
55
|
+
ip: req.socket.remoteAddress,
|
56
|
+
timestamp: Date.now(),
|
57
|
+
size: message.toString().length,
|
58
|
+
};
|
59
|
+
const msg = {
|
60
|
+
event: key,
|
61
|
+
data: parsedMessage,
|
62
|
+
metadata,
|
63
|
+
};
|
64
|
+
if (!m(ctx, msg))
|
65
|
+
return;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
// All middleware passed
|
69
|
+
const context = { server: this, id: this.wsToId.get(ws), buffer: ctx };
|
70
|
+
if (requestId) { // req-res premitive
|
71
|
+
let result;
|
72
|
+
if (batch) {
|
73
|
+
if (!data) {
|
74
|
+
ws.send("ACK " + requestId);
|
75
|
+
return;
|
85
76
|
}
|
86
|
-
|
77
|
+
result = data.map((part) => process(part, context));
|
87
78
|
}
|
79
|
+
else {
|
80
|
+
result = process(data, context);
|
81
|
+
}
|
82
|
+
if (result === undefined) { // just ACK the request process returns nothing
|
83
|
+
ws.send("ACK " + requestId);
|
84
|
+
return;
|
85
|
+
}
|
86
|
+
const serialized = serialize({ requestId, event: key, data: result });
|
87
|
+
if (!serialized)
|
88
|
+
return;
|
89
|
+
ws.send(serialized);
|
90
|
+
}
|
91
|
+
else if (streamId) { // stream premitive
|
92
|
+
const consumeStream = async () => {
|
93
|
+
const result = process(data, context);
|
94
|
+
for await (const fragment of result) {
|
95
|
+
this.sendMessageRaw(clientId, { streamId, fragment });
|
96
|
+
}
|
97
|
+
this.sendMessageRaw(clientId, { streamId, done: true });
|
98
|
+
};
|
99
|
+
consumeStream();
|
88
100
|
}
|
89
101
|
});
|
90
102
|
ws.on("close", () => {
|
@@ -167,30 +179,28 @@ export class ZapServer {
|
|
167
179
|
ws.send(serializedPacket);
|
168
180
|
});
|
169
181
|
}
|
170
|
-
get
|
182
|
+
get events() {
|
171
183
|
return Object.fromEntries(Object.keys(this._events).map((eventName) => {
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
return null;
|
193
|
-
}).filter(entry => entry !== null));
|
184
|
+
return [
|
185
|
+
eventName,
|
186
|
+
{
|
187
|
+
send: (clientId, data) => {
|
188
|
+
const packet = {
|
189
|
+
event: eventName,
|
190
|
+
data
|
191
|
+
};
|
192
|
+
this.sendMessageRaw(clientId, packet);
|
193
|
+
},
|
194
|
+
broadcast: (data) => {
|
195
|
+
const packet = {
|
196
|
+
event: eventName,
|
197
|
+
data
|
198
|
+
};
|
199
|
+
this.broadcastRaw(packet);
|
200
|
+
}
|
201
|
+
}
|
202
|
+
];
|
203
|
+
}));
|
194
204
|
}
|
195
205
|
get clients() {
|
196
206
|
return new Set(this.idToWs.keys());
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@zap-socket/server",
|
3
|
-
"version": "0.0.
|
3
|
+
"version": "0.0.8",
|
4
4
|
"description": "A fully typesafe tRPC-inspired WebSocket library with Zod validation, req-res model, and native subscriptions.",
|
5
5
|
"main": "dist/index.js",
|
6
6
|
"types": "dist/index.d.ts",
|
@@ -23,7 +23,7 @@
|
|
23
23
|
"vitest": "^3.0.9"
|
24
24
|
},
|
25
25
|
"dependencies": {
|
26
|
-
"@zap-socket/types": "^0.0.
|
26
|
+
"@zap-socket/types": "^0.0.4",
|
27
27
|
"zod": "^3.24.2"
|
28
28
|
}
|
29
29
|
}
|