@zap-socket/server 0.0.2 → 0.0.5

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/events.d.ts CHANGED
@@ -1,16 +1,13 @@
1
1
  import { z } from "zod";
2
- export type EventInput = z.ZodTypeAny | undefined;
3
- export type ZapEvent<T extends EventInput, R = any> = T extends z.ZodTypeAny ? {
4
- input: T;
5
- process: (input: z.infer<T>) => R;
6
- } : {
7
- input: z.ZodVoid;
8
- process: () => R;
9
- };
10
- export type EventMap = Record<string, ZapEvent<any, any>>;
2
+ import type { EventInput, Context, ZapEvent, ZapServerEvent, MiddlewareType } from "@zap-socket/types";
11
3
  export declare const zapEvent: <T extends EventInput, R>(eventObj: T extends z.ZodTypeAny ? {
12
4
  input: T;
13
- process: (input: z.infer<T>) => R;
5
+ middleware?: MiddlewareType[];
6
+ process: (input: z.infer<T>, ctx: Context) => R;
14
7
  } : {
15
- process: () => R;
8
+ middleware?: MiddlewareType[];
9
+ process: (ctx: Context) => R;
16
10
  }) => ZapEvent<T, R>;
11
+ export declare const zapServerEvent: <T extends z.ZodTypeAny>(eventObj: {
12
+ data: T;
13
+ }) => ZapServerEvent<T>;
package/dist/events.js CHANGED
@@ -8,3 +8,8 @@ export const zapEvent = (eventObj) => {
8
8
  process: eventObj.process
9
9
  };
10
10
  };
11
+ export const zapServerEvent = (eventObj) => {
12
+ return {
13
+ data: eventObj.data
14
+ };
15
+ };
package/dist/server.d.ts CHANGED
@@ -1,17 +1,19 @@
1
- import type { EventMap } from "./events";
1
+ import type { EventMap, ZapServerEvent } from "@zap-socket/types";
2
2
  interface ZapServerConstructorT {
3
3
  port: number;
4
+ events?: EventMap;
4
5
  }
5
- export declare class ZapServer {
6
+ export declare class ZapServer<T extends EventMap> {
6
7
  private wss;
7
8
  private wsToId;
8
9
  private idToWs;
9
- private events;
10
- constructor({ port }: ZapServerConstructorT);
10
+ private _events;
11
+ constructor({ port, events }: ZapServerConstructorT, callback?: () => void);
11
12
  private removeClient;
12
- attachEvents<T extends EventMap>(events: T): void;
13
+ sendMessageRaw(clientId: string, data: any): void;
14
+ get event(): { [K in keyof T as T[K] extends ZapServerEvent<any> ? K : never]: {
15
+ send: (clientId: string, data?: (T[K] extends ZapServerEvent<any> ? T[K]["data"] : never)) => void;
16
+ }; };
13
17
  }
14
- export declare const createZapServer: ({ port }: {
15
- port: number;
16
- }) => ZapServer;
18
+ export declare const createZapServer: <T extends EventMap>({ port, events }: ZapServerConstructorT, callback?: () => void) => ZapServer<T>;
17
19
  export {};
package/dist/server.js CHANGED
@@ -1,18 +1,24 @@
1
1
  import { WebSocketServer } from "ws";
2
2
  import { serialize, deserialize, generateId } from "./utils";
3
+ const isZapEvent = (event) => {
4
+ return "process" in event;
5
+ };
3
6
  export class ZapServer {
4
7
  wss;
5
8
  wsToId;
6
9
  idToWs;
7
- events = {};
8
- constructor({ port }) {
10
+ _events = {};
11
+ constructor({ port, events = {} }, callback) {
9
12
  this.wss = new WebSocketServer({ port });
10
13
  this.wsToId = new Map();
11
14
  this.idToWs = new Map();
12
- this.wss.on("connection", (ws) => {
15
+ this._events = events;
16
+ this.wss.on("listening", () => {
17
+ if (callback)
18
+ callback();
19
+ });
20
+ this.wss.on("connection", (ws, req) => {
13
21
  ws.on("message", (message) => {
14
- const parsedMessage = deserialize(message.toString());
15
- console.log("got message: ", parsedMessage);
16
22
  if (!this.wsToId.get(ws)) {
17
23
  const id = generateId();
18
24
  this.wsToId.set(ws, id);
@@ -21,18 +27,44 @@ export class ZapServer {
21
27
  console.log(`client ${id} connected.`);
22
28
  return;
23
29
  }
24
- for (const [event, { process }] of Object.entries(this.events)) {
30
+ const clientId = this.wsToId.get(ws);
31
+ for (const [event, eventObj] of Object.entries(this._events)) {
32
+ if (!isZapEvent(eventObj))
33
+ continue; // skip server events
34
+ const { process, middleware } = eventObj;
25
35
  const parsedMessage = deserialize(message.toString());
26
36
  if (parsedMessage &&
27
37
  parsedMessage["event"] === event) {
28
38
  const { data, requestId } = parsedMessage;
29
- const result = process(data);
39
+ // Do middleware checks
40
+ const ctx = {};
41
+ if (middleware) {
42
+ middleware.forEach((m) => {
43
+ const metadata = {
44
+ id: clientId,
45
+ ip: req.socket.remoteAddress,
46
+ timestamp: Date.now(),
47
+ size: message.toString().length
48
+ };
49
+ const msg = {
50
+ event,
51
+ data: parsedMessage,
52
+ metadata
53
+ };
54
+ if (!m(ctx, msg)) {
55
+ return;
56
+ }
57
+ });
58
+ }
59
+ // By this point all the middlewares allow to pass through
60
+ const result = process(data, { server: this, id: this.wsToId.get(ws), buffer: ctx });
30
61
  const serialized = serialize({ requestId, event, data: result });
31
62
  // TODO: throw some nice error: only return stuff that is serializable
32
63
  // i.e. primary data types and objects
33
64
  if (!serialized)
34
65
  return;
35
66
  ws.send(serialized);
67
+ return; // finally return to avoid looping through rest of events unneccessarily
36
68
  }
37
69
  }
38
70
  });
@@ -51,10 +83,37 @@ export class ZapServer {
51
83
  this.idToWs.delete(clientId);
52
84
  }
53
85
  }
54
- attachEvents(events) {
55
- this.events = events;
86
+ sendMessageRaw(clientId, data) {
87
+ const ws = this.idToWs.get(clientId);
88
+ // TODO: throw a nice error
89
+ if (!ws)
90
+ return;
91
+ const serializedData = serialize(data);
92
+ // TODO: throw a nice error
93
+ if (!serializedData)
94
+ return;
95
+ ws.send(serializedData);
96
+ }
97
+ get event() {
98
+ return Object.fromEntries(Object.keys(this._events).map((eventName) => {
99
+ // HACK: use a better method to determine the type of event.
100
+ if ("data" in this._events[eventName]) {
101
+ // event is server event
102
+ return [eventName, {
103
+ send: (clientId, data) => {
104
+ const packet = {
105
+ event: eventName,
106
+ data
107
+ };
108
+ this.sendMessageRaw(clientId, packet);
109
+ }
110
+ }];
111
+ }
112
+ return null;
113
+ }).filter(entry => entry !== null));
56
114
  }
57
115
  }
58
- export const createZapServer = ({ port }) => {
59
- return new ZapServer({ port });
116
+ export const createZapServer = ({ port, events }, callback) => {
117
+ const server = new ZapServer({ port, events }, callback);
118
+ return server;
60
119
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zap-socket/server",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
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,6 +23,7 @@
23
23
  "vitest": "^3.0.9"
24
24
  },
25
25
  "dependencies": {
26
+ "@zap-socket/types": "^0.0.2",
26
27
  "zod": "^3.24.2"
27
28
  }
28
29
  }