@zap-socket/server 0.0.20 → 0.0.22
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/adapters/types.d.ts +18 -0
- package/dist/adapters/types.js +1 -0
- package/dist/adapters/uWebSocketAdapter.d.ts +0 -0
- package/dist/adapters/uWebSocketAdapter.js +1 -0
- package/dist/adapters/wsAdapter.d.ts +6 -0
- package/dist/adapters/wsAdapter.js +48 -0
- package/dist/server.d.ts +8 -6
- package/dist/server.js +27 -26
- package/package.json +1 -1
@@ -0,0 +1,18 @@
|
|
1
|
+
import { IncomingMessage } from "http";
|
2
|
+
export interface WebSocketAdapter {
|
3
|
+
send(data: string): void;
|
4
|
+
close(): void;
|
5
|
+
on(event: 'message', listener: (data: Buffer | string) => void): void;
|
6
|
+
on(event: 'close', listener: () => void): void;
|
7
|
+
on(event: 'error', listener: (err: Error) => void): void;
|
8
|
+
}
|
9
|
+
export interface WebSocketServerAdapter {
|
10
|
+
on(event: 'listening', listener: () => void): void;
|
11
|
+
on(event: 'connection', listener: (ws: WebSocketAdapter, req: IncomingMessage) => void): void;
|
12
|
+
close(): void;
|
13
|
+
}
|
14
|
+
export interface WebSocketBackend {
|
15
|
+
createServer(options: {
|
16
|
+
port: number;
|
17
|
+
}): WebSocketServerAdapter;
|
18
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
"use strict";
|
@@ -0,0 +1,48 @@
|
|
1
|
+
import { WebSocketServer } from "ws";
|
2
|
+
class WSAdapter {
|
3
|
+
ws;
|
4
|
+
constructor(ws) {
|
5
|
+
this.ws = ws;
|
6
|
+
}
|
7
|
+
send(data) {
|
8
|
+
this.ws.send(data);
|
9
|
+
}
|
10
|
+
close() {
|
11
|
+
this.ws.close();
|
12
|
+
}
|
13
|
+
on(event, listener) {
|
14
|
+
if (event === 'message') {
|
15
|
+
this.ws.on('message', (data) => {
|
16
|
+
listener(data.toString());
|
17
|
+
});
|
18
|
+
}
|
19
|
+
else {
|
20
|
+
this.ws.on(event, listener);
|
21
|
+
}
|
22
|
+
}
|
23
|
+
}
|
24
|
+
class WSServerAdapter {
|
25
|
+
wss;
|
26
|
+
constructor(wss) {
|
27
|
+
this.wss = wss;
|
28
|
+
}
|
29
|
+
on(event, listener) {
|
30
|
+
if (event === 'connection') {
|
31
|
+
this.wss.on('connection', (ws, req) => {
|
32
|
+
listener(new WSAdapter(ws), req);
|
33
|
+
});
|
34
|
+
}
|
35
|
+
else {
|
36
|
+
this.wss.on(event, listener);
|
37
|
+
}
|
38
|
+
}
|
39
|
+
close() {
|
40
|
+
this.wss.close();
|
41
|
+
}
|
42
|
+
}
|
43
|
+
export class WSBackend {
|
44
|
+
createServer(options) {
|
45
|
+
const wss = new WebSocketServer(options);
|
46
|
+
return new WSServerAdapter(wss);
|
47
|
+
}
|
48
|
+
}
|
package/dist/server.d.ts
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import { WebSocketServer, WebSocket } from "ws";
|
2
1
|
import type { EventMap, ZapEvent, ZapServerEvent } from "@zap-socket/types";
|
3
2
|
import { ZodType, z } from "zod";
|
3
|
+
import { WebSocketAdapter } from "./adapters/types.js";
|
4
4
|
type CorsOptions = {
|
5
5
|
origin: string[];
|
6
6
|
methods: string[];
|
@@ -11,16 +11,18 @@ type ZapServerConstructorT = {
|
|
11
11
|
port: number;
|
12
12
|
events?: EventMap;
|
13
13
|
cors?: CorsOptions;
|
14
|
+
backend?: 'ws' | 'uws';
|
14
15
|
options?: {
|
15
16
|
heartbeatPingFrequency: number;
|
16
17
|
};
|
17
18
|
};
|
18
19
|
type ExtractSendData<T, K extends keyof T> = T[K] extends ZapServerEvent<any> ? T[K]['data'] : T[K] extends ZapEvent<any, any> ? T[K]['emitType'] extends ZodType<any, any, any> ? z.infer<T[K]['emitType']> : ReturnType<T[K]['process']> extends undefined ? undefined : ReturnType<T[K]['process']> : never;
|
19
20
|
export declare class ZapServer<T extends EventMap> {
|
20
|
-
wss
|
21
|
+
private wss;
|
22
|
+
private backend;
|
21
23
|
onconnect: (handler: (ctx: {
|
22
24
|
id: string;
|
23
|
-
ws:
|
25
|
+
ws: WebSocketAdapter;
|
24
26
|
}) => void) => void;
|
25
27
|
private onconnectHandler;
|
26
28
|
private wsToId;
|
@@ -28,7 +30,7 @@ export declare class ZapServer<T extends EventMap> {
|
|
28
30
|
private persistantContext;
|
29
31
|
private _events;
|
30
32
|
private heartbeatMiss;
|
31
|
-
constructor({ port, events, options }: ZapServerConstructorT, callback?: () => void);
|
33
|
+
constructor({ port, events, backend, options }: ZapServerConstructorT, callback?: () => void);
|
32
34
|
private removeClient;
|
33
35
|
private heartbeat;
|
34
36
|
private handleMessage;
|
@@ -42,7 +44,7 @@ export declare class ZapServer<T extends EventMap> {
|
|
42
44
|
broadcast: (data?: ExtractSendData<T, K>) => void;
|
43
45
|
}; };
|
44
46
|
get clients(): string[];
|
45
|
-
get socketMap(): Map<string,
|
47
|
+
get socketMap(): Map<string, WebSocketAdapter>;
|
46
48
|
}
|
47
|
-
export declare const createZapServer: <T extends EventMap>({ port, events, cors, options }: ZapServerConstructorT, callback?: () => void) => ZapServer<T>;
|
49
|
+
export declare const createZapServer: <T extends EventMap>({ port, events, cors, backend, options }: ZapServerConstructorT, callback?: () => void) => ZapServer<T>;
|
48
50
|
export {};
|
package/dist/server.js
CHANGED
@@ -1,15 +1,11 @@
|
|
1
|
-
import { WebSocketServer } from "ws";
|
2
1
|
import { serialize, deserialize, generateId } from "./utils.js";
|
2
|
+
import { WSBackend } from "./adapters/wsAdapter.js";
|
3
3
|
const isClientEvent = (event) => {
|
4
|
-
return "process" in event;
|
4
|
+
return "process" in event;
|
5
5
|
};
|
6
|
-
// make the server class abstracted away
|
7
|
-
// or atleast the ws interactions
|
8
|
-
// so that we can change the backends
|
9
|
-
// with ease (ws & uWebSocket).
|
10
6
|
export class ZapServer {
|
11
|
-
// public server: http.Server;
|
12
7
|
wss;
|
8
|
+
backend;
|
13
9
|
onconnect;
|
14
10
|
onconnectHandler;
|
15
11
|
wsToId;
|
@@ -17,8 +13,18 @@ export class ZapServer {
|
|
17
13
|
persistantContext;
|
18
14
|
_events = {};
|
19
15
|
heartbeatMiss = new Map();
|
20
|
-
constructor({ port, events = {}, options }, callback) {
|
21
|
-
|
16
|
+
constructor({ port, events = {}, backend = 'ws', options }, callback) {
|
17
|
+
// Select backend
|
18
|
+
switch (backend) {
|
19
|
+
// case 'uws':
|
20
|
+
// this.backend = new UWSBackend();
|
21
|
+
// break;
|
22
|
+
case 'ws':
|
23
|
+
default:
|
24
|
+
this.backend = new WSBackend();
|
25
|
+
break;
|
26
|
+
}
|
27
|
+
this.wss = this.backend.createServer({ port });
|
22
28
|
this.wsToId = new Map();
|
23
29
|
this.idToWs = new Map();
|
24
30
|
this.persistantContext = new Map();
|
@@ -69,9 +75,10 @@ export class ZapServer {
|
|
69
75
|
this.broadcastRaw("heartbeat");
|
70
76
|
}
|
71
77
|
async handleMessage(ws, req, message) {
|
78
|
+
const messageStr = message.toString();
|
72
79
|
const id = this.wsToId.get(ws);
|
73
80
|
// setting up socket id
|
74
|
-
if (!id &&
|
81
|
+
if (!id && messageStr === "OPEN") {
|
75
82
|
const id = generateId();
|
76
83
|
this.wsToId.set(ws, id);
|
77
84
|
this.idToWs.set(id, ws);
|
@@ -82,11 +89,11 @@ export class ZapServer {
|
|
82
89
|
});
|
83
90
|
return;
|
84
91
|
}
|
85
|
-
else if (id &&
|
92
|
+
else if (id && messageStr === "heartbeat") {
|
86
93
|
this.heartbeatMiss.set(id, 0);
|
87
94
|
}
|
88
95
|
const clientId = this.wsToId.get(ws);
|
89
|
-
const parsedMessage = deserialize(
|
96
|
+
const parsedMessage = deserialize(messageStr);
|
90
97
|
if (!parsedMessage)
|
91
98
|
return;
|
92
99
|
const { event, stream, data, requestId, streamId, batch } = parsedMessage;
|
@@ -98,8 +105,8 @@ export class ZapServer {
|
|
98
105
|
const inputType = eventObj.input;
|
99
106
|
const { success, error } = inputType.safeParse(data);
|
100
107
|
if (!success && error) {
|
101
|
-
// check if the message is of req-res
|
102
108
|
if (requestId) {
|
109
|
+
// Handle validation error response
|
103
110
|
}
|
104
111
|
return;
|
105
112
|
}
|
@@ -116,7 +123,7 @@ export class ZapServer {
|
|
116
123
|
id: clientId,
|
117
124
|
ip: req.socket.remoteAddress,
|
118
125
|
timestamp: Date.now(),
|
119
|
-
size:
|
126
|
+
size: messageStr.length,
|
120
127
|
};
|
121
128
|
const msg = {
|
122
129
|
event: key,
|
@@ -131,7 +138,7 @@ export class ZapServer {
|
|
131
138
|
}
|
132
139
|
// All middleware passed
|
133
140
|
const context = { server: this, id: this.wsToId.get(ws), buffer: ctx };
|
134
|
-
if (requestId) { // req-res
|
141
|
+
if (requestId) { // req-res primitive
|
135
142
|
let result;
|
136
143
|
if (batch) {
|
137
144
|
result = data.map((part) => process(part, context));
|
@@ -151,7 +158,7 @@ export class ZapServer {
|
|
151
158
|
return;
|
152
159
|
ws.send(serialized);
|
153
160
|
}
|
154
|
-
else if (streamId) { // stream
|
161
|
+
else if (streamId) { // stream primitive
|
155
162
|
const consumeStream = async () => {
|
156
163
|
const result = process(data, context);
|
157
164
|
for await (const fragment of result) {
|
@@ -164,18 +171,15 @@ export class ZapServer {
|
|
164
171
|
}
|
165
172
|
sendMessageRaw(clientId, data) {
|
166
173
|
const ws = this.idToWs.get(clientId);
|
167
|
-
// TODO: throw a nice error
|
168
174
|
if (!ws)
|
169
175
|
return;
|
170
176
|
const serializedData = serialize(data);
|
171
|
-
// TODO: throw a nice error
|
172
177
|
if (!serializedData)
|
173
178
|
return;
|
174
179
|
ws.send(serializedData);
|
175
180
|
}
|
176
181
|
sendMessage(event, clientId, data) {
|
177
182
|
const ws = this.idToWs.get(clientId);
|
178
|
-
// TODO: throw a nice error
|
179
183
|
if (!ws)
|
180
184
|
return;
|
181
185
|
const packet = {
|
@@ -183,7 +187,6 @@ export class ZapServer {
|
|
183
187
|
data
|
184
188
|
};
|
185
189
|
const serializedPacket = serialize(packet);
|
186
|
-
// TODO: throw a nice error
|
187
190
|
if (!serializedPacket)
|
188
191
|
return;
|
189
192
|
ws.send(serializedPacket);
|
@@ -191,7 +194,6 @@ export class ZapServer {
|
|
191
194
|
broadcastRaw(data) {
|
192
195
|
const serializedData = serialize(data);
|
193
196
|
if (!serializedData) {
|
194
|
-
// TODO: throw a nice error
|
195
197
|
return;
|
196
198
|
}
|
197
199
|
this.idToWs.forEach((ws) => {
|
@@ -213,14 +215,13 @@ export class ZapServer {
|
|
213
215
|
selectiveBroascast(event, data, connections) {
|
214
216
|
const serialized = serialize(data);
|
215
217
|
if (!serialized) {
|
216
|
-
// TODO: throw a nice error
|
217
218
|
return;
|
218
219
|
}
|
219
220
|
const packet = {
|
220
221
|
event,
|
221
222
|
data
|
222
223
|
};
|
223
|
-
const serializedPacket = serialize(packet);
|
224
|
+
const serializedPacket = serialize(packet);
|
224
225
|
connections
|
225
226
|
.flatMap(x => this.idToWs.get(x) ?? [])
|
226
227
|
.forEach((ws) => {
|
@@ -251,13 +252,13 @@ export class ZapServer {
|
|
251
252
|
}));
|
252
253
|
}
|
253
254
|
get clients() {
|
254
|
-
return this.idToWs.keys()
|
255
|
+
return Array.from(this.idToWs.keys());
|
255
256
|
}
|
256
257
|
get socketMap() {
|
257
258
|
return this.idToWs;
|
258
259
|
}
|
259
260
|
}
|
260
|
-
export const createZapServer = ({ port, events, cors, options }, callback) => {
|
261
|
-
const server = new ZapServer({ port, events, cors, options }, callback);
|
261
|
+
export const createZapServer = ({ port, events, cors, backend = 'ws', options }, callback) => {
|
262
|
+
const server = new ZapServer({ port, events, cors, backend, options }, callback);
|
262
263
|
return server;
|
263
264
|
};
|
package/package.json
CHANGED