@morojs/moro 1.3.0 → 1.4.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.
Files changed (70) hide show
  1. package/README.md +61 -7
  2. package/dist/core/config/types.d.ts +147 -0
  3. package/dist/core/config/types.js +124 -0
  4. package/dist/core/config/types.js.map +1 -0
  5. package/dist/core/config/typescript-loader.d.ts +6 -0
  6. package/dist/core/config/typescript-loader.js +268 -0
  7. package/dist/core/config/typescript-loader.js.map +1 -0
  8. package/dist/core/config/validation.d.ts +18 -0
  9. package/dist/core/config/validation.js +134 -0
  10. package/dist/core/config/validation.js.map +1 -0
  11. package/dist/core/docs/openapi-generator.js +6 -6
  12. package/dist/core/docs/openapi-generator.js.map +1 -1
  13. package/dist/core/docs/schema-to-openapi.d.ts +7 -0
  14. package/dist/core/docs/schema-to-openapi.js +124 -0
  15. package/dist/core/docs/schema-to-openapi.js.map +1 -0
  16. package/dist/core/docs/zod-to-openapi.d.ts +2 -0
  17. package/dist/core/docs/zod-to-openapi.js.map +1 -1
  18. package/dist/core/framework.d.ts +29 -6
  19. package/dist/core/framework.js +117 -18
  20. package/dist/core/framework.js.map +1 -1
  21. package/dist/core/networking/adapters/index.d.ts +3 -0
  22. package/dist/core/networking/adapters/index.js +10 -0
  23. package/dist/core/networking/adapters/index.js.map +1 -0
  24. package/dist/core/networking/adapters/socketio-adapter.d.ts +16 -0
  25. package/dist/core/networking/adapters/socketio-adapter.js +244 -0
  26. package/dist/core/networking/adapters/socketio-adapter.js.map +1 -0
  27. package/dist/core/networking/adapters/ws-adapter.d.ts +54 -0
  28. package/dist/core/networking/adapters/ws-adapter.js +383 -0
  29. package/dist/core/networking/adapters/ws-adapter.js.map +1 -0
  30. package/dist/core/networking/websocket-adapter.d.ts +171 -0
  31. package/dist/core/networking/websocket-adapter.js +5 -0
  32. package/dist/core/networking/websocket-adapter.js.map +1 -0
  33. package/dist/core/networking/websocket-manager.d.ts +53 -17
  34. package/dist/core/networking/websocket-manager.js +166 -108
  35. package/dist/core/networking/websocket-manager.js.map +1 -1
  36. package/dist/core/routing/index.d.ts +13 -13
  37. package/dist/core/routing/index.js.map +1 -1
  38. package/dist/core/validation/adapters.d.ts +51 -0
  39. package/dist/core/validation/adapters.js +135 -0
  40. package/dist/core/validation/adapters.js.map +1 -0
  41. package/dist/core/validation/index.d.ts +14 -11
  42. package/dist/core/validation/index.js +37 -26
  43. package/dist/core/validation/index.js.map +1 -1
  44. package/dist/core/validation/schema-interface.d.ts +36 -0
  45. package/dist/core/validation/schema-interface.js +68 -0
  46. package/dist/core/validation/schema-interface.js.map +1 -0
  47. package/dist/index.d.ts +6 -1
  48. package/dist/index.js +14 -3
  49. package/dist/index.js.map +1 -1
  50. package/dist/moro.js +8 -2
  51. package/dist/moro.js.map +1 -1
  52. package/package.json +31 -7
  53. package/src/core/config/types.ts +277 -0
  54. package/src/core/config/typescript-loader.ts +571 -0
  55. package/src/core/config/validation.ts +145 -0
  56. package/src/core/docs/openapi-generator.ts +7 -6
  57. package/src/core/docs/schema-to-openapi.ts +148 -0
  58. package/src/core/docs/zod-to-openapi.ts +2 -0
  59. package/src/core/framework.ts +121 -28
  60. package/src/core/networking/adapters/index.ts +16 -0
  61. package/src/core/networking/adapters/socketio-adapter.ts +252 -0
  62. package/src/core/networking/adapters/ws-adapter.ts +425 -0
  63. package/src/core/networking/websocket-adapter.ts +217 -0
  64. package/src/core/networking/websocket-manager.ts +185 -127
  65. package/src/core/routing/index.ts +13 -13
  66. package/src/core/validation/adapters.ts +147 -0
  67. package/src/core/validation/index.ts +60 -38
  68. package/src/core/validation/schema-interface.ts +100 -0
  69. package/src/index.ts +25 -2
  70. package/src/moro.ts +11 -2
@@ -0,0 +1,244 @@
1
+ "use strict";
2
+ // Socket.IO WebSocket Adapter for Moro Framework
3
+ // Implements the WebSocket adapter interface using Socket.IO
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.SocketIOAdapter = void 0;
39
+ /**
40
+ * Socket.IO adapter implementation
41
+ */
42
+ class SocketIOAdapter {
43
+ async initialize(httpServer, options = {}) {
44
+ try {
45
+ // Dynamic import to avoid requiring socket.io as a hard dependency
46
+ const { Server } = await Promise.resolve().then(() => __importStar(require('socket.io')));
47
+ this.io = new Server(httpServer, {
48
+ cors: options.cors || { origin: '*' },
49
+ path: options.path || '/socket.io/',
50
+ compression: options.compression !== false,
51
+ maxHttpBufferSize: options.maxPayloadLength,
52
+ ...options,
53
+ });
54
+ // Apply custom ID generator if set
55
+ if (this.customIdGenerator) {
56
+ this.io.engine.generateId = this.customIdGenerator;
57
+ }
58
+ // Setup compression if enabled
59
+ if (options.compression) {
60
+ this.setCompression(true);
61
+ }
62
+ }
63
+ catch (error) {
64
+ throw new Error('Socket.IO not found. Install it with: npm install socket.io\n' +
65
+ 'Or use a different WebSocket adapter.');
66
+ }
67
+ }
68
+ createNamespace(namespace) {
69
+ if (!this.io) {
70
+ throw new Error('Socket.IO adapter not initialized');
71
+ }
72
+ const ns = this.io.of(namespace);
73
+ return new SocketIONamespaceWrapper(ns);
74
+ }
75
+ getDefaultNamespace() {
76
+ return this.createNamespace('/');
77
+ }
78
+ async close() {
79
+ if (this.io) {
80
+ return new Promise(resolve => {
81
+ this.io.close(() => resolve());
82
+ });
83
+ }
84
+ }
85
+ setCompression(enabled, options = {}) {
86
+ if (this.io && enabled) {
87
+ this.io.engine.compression = true;
88
+ this.io.engine.perMessageDeflate = {
89
+ threshold: 1024,
90
+ concurrencyLimit: 10,
91
+ memLevel: 8,
92
+ ...options,
93
+ };
94
+ }
95
+ }
96
+ setCustomIdGenerator(generator) {
97
+ this.customIdGenerator = generator;
98
+ if (this.io) {
99
+ this.io.engine.generateId = generator;
100
+ }
101
+ }
102
+ getAdapterName() {
103
+ return 'socket.io';
104
+ }
105
+ getConnectionCount() {
106
+ if (!this.io)
107
+ return 0;
108
+ return this.io.engine.clientsCount || 0;
109
+ }
110
+ }
111
+ exports.SocketIOAdapter = SocketIOAdapter;
112
+ /**
113
+ * Socket.IO namespace wrapper
114
+ */
115
+ class SocketIONamespaceWrapper {
116
+ constructor(namespace) {
117
+ this.namespace = namespace;
118
+ }
119
+ on(event, handler) {
120
+ this.namespace.on(event, (socket) => {
121
+ handler(new SocketIOConnectionWrapper(socket));
122
+ });
123
+ }
124
+ emit(event, data) {
125
+ this.namespace.emit(event, data);
126
+ }
127
+ to(room) {
128
+ const target = Array.isArray(room)
129
+ ? room.reduce((acc, r) => acc.to(r), this.namespace)
130
+ : this.namespace.to(room);
131
+ return new SocketIOEmitterWrapper(target);
132
+ }
133
+ except(room) {
134
+ const target = Array.isArray(room)
135
+ ? room.reduce((acc, r) => acc.except(r), this.namespace)
136
+ : this.namespace.except(room);
137
+ return new SocketIOEmitterWrapper(target);
138
+ }
139
+ getSockets() {
140
+ const sockets = this.namespace.sockets;
141
+ return Array.from(sockets.values()).map((socket) => new SocketIOConnectionWrapper(socket));
142
+ }
143
+ getConnectionCount() {
144
+ return this.namespace.sockets.size;
145
+ }
146
+ use(middleware) {
147
+ this.namespace.use((socket, next) => {
148
+ middleware(new SocketIOConnectionWrapper(socket), next);
149
+ });
150
+ }
151
+ }
152
+ /**
153
+ * Socket.IO connection wrapper
154
+ */
155
+ class SocketIOConnectionWrapper {
156
+ constructor(socket) {
157
+ this.socket = socket;
158
+ this.data = {};
159
+ // Map socket.data to our data property
160
+ this.data = socket.data || {};
161
+ }
162
+ get id() {
163
+ return this.socket.id;
164
+ }
165
+ get ip() {
166
+ return this.socket.handshake?.address;
167
+ }
168
+ get headers() {
169
+ return this.socket.handshake?.headers;
170
+ }
171
+ get connected() {
172
+ return this.socket.connected;
173
+ }
174
+ get broadcast() {
175
+ return new SocketIOEmitterWrapper(this.socket.broadcast);
176
+ }
177
+ on(event, handler) {
178
+ this.socket.on(event, handler);
179
+ }
180
+ onAny(handler) {
181
+ this.socket.onAny(handler);
182
+ }
183
+ emit(event, data) {
184
+ this.socket.emit(event, data);
185
+ }
186
+ compressedEmit(event, data) {
187
+ this.socket.compress(true).emit(event, data);
188
+ }
189
+ join(room) {
190
+ if (Array.isArray(room)) {
191
+ room.forEach(r => this.socket.join(r));
192
+ }
193
+ else {
194
+ this.socket.join(room);
195
+ }
196
+ }
197
+ leave(room) {
198
+ if (Array.isArray(room)) {
199
+ room.forEach(r => this.socket.leave(r));
200
+ }
201
+ else {
202
+ this.socket.leave(room);
203
+ }
204
+ }
205
+ to(room) {
206
+ const target = Array.isArray(room)
207
+ ? room.reduce((acc, r) => acc.to(r), this.socket)
208
+ : this.socket.to(room);
209
+ return new SocketIOEmitterWrapper(target);
210
+ }
211
+ getRooms() {
212
+ return new Set(this.socket.rooms);
213
+ }
214
+ disconnect(close) {
215
+ this.socket.disconnect(close);
216
+ }
217
+ }
218
+ /**
219
+ * Socket.IO emitter wrapper
220
+ */
221
+ class SocketIOEmitterWrapper {
222
+ constructor(emitter) {
223
+ this.emitter = emitter;
224
+ }
225
+ emit(event, data) {
226
+ this.emitter.emit(event, data);
227
+ }
228
+ to(room) {
229
+ const target = Array.isArray(room)
230
+ ? room.reduce((acc, r) => acc.to(r), this.emitter)
231
+ : this.emitter.to(room);
232
+ return new SocketIOEmitterWrapper(target);
233
+ }
234
+ except(room) {
235
+ const target = Array.isArray(room)
236
+ ? room.reduce((acc, r) => acc.except(r), this.emitter)
237
+ : this.emitter.except(room);
238
+ return new SocketIOEmitterWrapper(target);
239
+ }
240
+ compress(compress) {
241
+ return new SocketIOEmitterWrapper(this.emitter.compress(compress));
242
+ }
243
+ }
244
+ //# sourceMappingURL=socketio-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"socketio-adapter.js","sourceRoot":"","sources":["../../../../src/core/networking/adapters/socketio-adapter.ts"],"names":[],"mappings":";AAAA,iDAAiD;AACjD,6DAA6D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAW7D;;GAEG;AACH,MAAa,eAAe;IAI1B,KAAK,CAAC,UAAU,CAAC,UAAe,EAAE,UAAmC,EAAE;QACrE,IAAI,CAAC;YACH,mEAAmE;YACnE,MAAM,EAAE,MAAM,EAAE,GAAG,wDAAa,WAAW,GAAC,CAAC;YAE7C,IAAI,CAAC,EAAE,GAAG,IAAI,MAAM,CAAC,UAAU,EAAE;gBAC/B,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;gBACrC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,aAAa;gBACnC,WAAW,EAAE,OAAO,CAAC,WAAW,KAAK,KAAK;gBAC1C,iBAAiB,EAAE,OAAO,CAAC,gBAAgB;gBAC3C,GAAG,OAAO;aACX,CAAC,CAAC;YAEH,mCAAmC;YACnC,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC1B,IAAI,CAAC,EAAE,CAAC,MAAc,CAAC,UAAU,GAAG,IAAI,CAAC,iBAAiB,CAAC;YAC9D,CAAC;YAED,+BAA+B;YAC/B,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;gBACxB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,+DAA+D;gBAC7D,uCAAuC,CAC1C,CAAC;QACJ,CAAC;IACH,CAAC;IAED,eAAe,CAAC,SAAiB;QAC/B,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;QACvD,CAAC;QAED,MAAM,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC;QACjC,OAAO,IAAI,wBAAwB,CAAC,EAAE,CAAC,CAAC;IAC1C,CAAC;IAED,mBAAmB;QACjB,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACZ,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC3B,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;YACjC,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,cAAc,CAAC,OAAgB,EAAE,UAAe,EAAE;QAChD,IAAI,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,CAAC;YACtB,IAAI,CAAC,EAAE,CAAC,MAAc,CAAC,WAAW,GAAG,IAAI,CAAC;YAC1C,IAAI,CAAC,EAAE,CAAC,MAAc,CAAC,iBAAiB,GAAG;gBAC1C,SAAS,EAAE,IAAI;gBACf,gBAAgB,EAAE,EAAE;gBACpB,QAAQ,EAAE,CAAC;gBACX,GAAG,OAAO;aACX,CAAC;QACJ,CAAC;IACH,CAAC;IAED,oBAAoB,CAAC,SAAuB;QAC1C,IAAI,CAAC,iBAAiB,GAAG,SAAS,CAAC;QACnC,IAAI,IAAI,CAAC,EAAE,EAAE,CAAC;YACX,IAAI,CAAC,EAAE,CAAC,MAAc,CAAC,UAAU,GAAG,SAAS,CAAC;QACjD,CAAC;IACH,CAAC;IAED,cAAc;QACZ,OAAO,WAAW,CAAC;IACrB,CAAC;IAED,kBAAkB;QAChB,IAAI,CAAC,IAAI,CAAC,EAAE;YAAE,OAAO,CAAC,CAAC;QACvB,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,IAAI,CAAC,CAAC;IAC1C,CAAC;CACF;AAlFD,0CAkFC;AAED;;GAEG;AACH,MAAM,wBAAwB;IAC5B,YAAoB,SAAc;QAAd,cAAS,GAAT,SAAS,CAAK;IAAG,CAAC;IAEtC,EAAE,CAAC,KAAmB,EAAE,OAA8C;QACpE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,MAAW,EAAE,EAAE;YACvC,OAAO,CAAC,IAAI,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,IAAS;QAC3B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,EAAE,CAAC,IAAuB;QACxB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAChC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;YACpD,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAC5B,OAAO,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,CAAC,IAAuB;QAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAChC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC;YACxD,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,UAAU;QACR,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;QACvC,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAW,EAAE,EAAE,CAAC,IAAI,yBAAyB,CAAC,MAAM,CAAC,CAAC,CAAC;IAClG,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;IACrC,CAAC;IAED,GAAG,CAAC,UAA+B;QACjC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,MAAW,EAAE,IAAS,EAAE,EAAE;YAC5C,UAAU,CAAC,IAAI,yBAAyB,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAED;;GAEG;AACH,MAAM,yBAAyB;IAG7B,YAAoB,MAAW;QAAX,WAAM,GAAN,MAAM,CAAK;QAFxB,SAAI,GAAwB,EAAE,CAAC;QAGpC,uCAAuC;QACvC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;IAChC,CAAC;IAED,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACxB,CAAC;IAED,IAAI,EAAE;QACJ,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC;IACxC,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC;IACxC,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;IAC/B,CAAC;IAED,IAAI,SAAS;QACX,OAAO,IAAI,sBAAsB,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAC3D,CAAC;IAED,EAAE,CAAC,KAAa,EAAE,OAAiE;QACjF,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,OAAgD;QACpD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,IAAS;QAC3B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,cAAc,CAAC,KAAa,EAAE,IAAS;QACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,IAAI,CAAC,IAAuB;QAC1B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAuB;QAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,EAAE,CAAC,IAAuB;QACxB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAChC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC;YACjD,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QACzB,OAAO,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,QAAQ;QACN,OAAO,IAAI,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,UAAU,CAAC,KAAe;QACxB,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,sBAAsB;IAC1B,YAAoB,OAAY;QAAZ,YAAO,GAAP,OAAO,CAAK;IAAG,CAAC;IAEpC,IAAI,CAAC,KAAa,EAAE,IAAS;QAC3B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,EAAE,CAAC,IAAuB;QACxB,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAChC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;YAClD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QAC1B,OAAO,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,CAAC,IAAuB;QAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;YAChC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC;YACtD,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC9B,OAAO,IAAI,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC5C,CAAC;IAED,QAAQ,CAAC,QAAiB;QACxB,OAAO,IAAI,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrE,CAAC;CACF"}
@@ -0,0 +1,54 @@
1
+ import { WebSocketAdapter, WebSocketAdapterOptions, WebSocketNamespace, WebSocketConnection, WebSocketEmitter } from '../websocket-adapter';
2
+ /**
3
+ * Native WebSocket adapter using the 'ws' library
4
+ * Provides a lightweight, standards-compliant WebSocket implementation
5
+ */
6
+ export declare class WSAdapter implements WebSocketAdapter {
7
+ private wss;
8
+ private namespaces;
9
+ private connections;
10
+ private customIdGenerator?;
11
+ private connectionCounter;
12
+ initialize(httpServer: any, options?: WebSocketAdapterOptions): Promise<void>;
13
+ private handleConnection;
14
+ createNamespace(namespace: string): WebSocketNamespace;
15
+ getDefaultNamespace(): WebSocketNamespace;
16
+ close(): Promise<void>;
17
+ setCompression(enabled: boolean, _options?: any): void;
18
+ setCustomIdGenerator(generator: () => string): void;
19
+ getAdapterName(): string;
20
+ getConnectionCount(): number;
21
+ generateId(): string;
22
+ addConnection(id: string, connection: WSConnectionWrapper): void;
23
+ removeConnection(id: string): void;
24
+ getAllConnections(): Map<string, WSConnectionWrapper>;
25
+ }
26
+ /**
27
+ * WebSocket connection wrapper
28
+ */
29
+ declare class WSConnectionWrapper implements WebSocketConnection {
30
+ readonly id: string;
31
+ readonly ws: any;
32
+ private request;
33
+ data: Record<string, any>;
34
+ private eventHandlers;
35
+ private anyHandlers;
36
+ private rooms;
37
+ private _connected;
38
+ constructor(id: string, ws: any, request: any);
39
+ get ip(): string | undefined;
40
+ get headers(): Record<string, string> | undefined;
41
+ get connected(): boolean;
42
+ get broadcast(): WebSocketEmitter;
43
+ on(event: string, handler: (data: any, callback?: (response?: any) => void) => void): void;
44
+ onAny(handler: (event: string, ...args: any[]) => void): void;
45
+ emit(event: string, data?: any): void;
46
+ compressedEmit(event: string, data: any): void;
47
+ join(room: string | string[]): void;
48
+ leave(room: string | string[]): void;
49
+ to(room: string | string[]): WebSocketEmitter;
50
+ getRooms(): Set<string>;
51
+ disconnect(close?: boolean): void;
52
+ private handleMessage;
53
+ }
54
+ export {};
@@ -0,0 +1,383 @@
1
+ "use strict";
2
+ // Native WebSocket Adapter for Moro Framework
3
+ // Implements the WebSocket adapter interface using the 'ws' library
4
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
5
+ if (k2 === undefined) k2 = k;
6
+ var desc = Object.getOwnPropertyDescriptor(m, k);
7
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
8
+ desc = { enumerable: true, get: function() { return m[k]; } };
9
+ }
10
+ Object.defineProperty(o, k2, desc);
11
+ }) : (function(o, m, k, k2) {
12
+ if (k2 === undefined) k2 = k;
13
+ o[k2] = m[k];
14
+ }));
15
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
16
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
17
+ }) : function(o, v) {
18
+ o["default"] = v;
19
+ });
20
+ var __importStar = (this && this.__importStar) || (function () {
21
+ var ownKeys = function(o) {
22
+ ownKeys = Object.getOwnPropertyNames || function (o) {
23
+ var ar = [];
24
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
25
+ return ar;
26
+ };
27
+ return ownKeys(o);
28
+ };
29
+ return function (mod) {
30
+ if (mod && mod.__esModule) return mod;
31
+ var result = {};
32
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
33
+ __setModuleDefault(result, mod);
34
+ return result;
35
+ };
36
+ })();
37
+ Object.defineProperty(exports, "__esModule", { value: true });
38
+ exports.WSAdapter = void 0;
39
+ /**
40
+ * Native WebSocket adapter using the 'ws' library
41
+ * Provides a lightweight, standards-compliant WebSocket implementation
42
+ */
43
+ class WSAdapter {
44
+ constructor() {
45
+ this.namespaces = new Map();
46
+ this.connections = new Map();
47
+ this.connectionCounter = 0;
48
+ }
49
+ async initialize(httpServer, options = {}) {
50
+ try {
51
+ // Dynamic import to avoid requiring ws as a hard dependency
52
+ const { WebSocketServer } = await Promise.resolve().then(() => __importStar(require('ws')));
53
+ this.wss = new WebSocketServer({
54
+ server: httpServer,
55
+ path: options.path || '/ws',
56
+ maxPayload: options.maxPayloadLength || 100 * 1024 * 1024, // 100MB default
57
+ // Note: ws doesn't have built-in compression like socket.io
58
+ // but browsers handle compression at the transport level
59
+ });
60
+ // Setup connection handling
61
+ this.wss.on('connection', (ws, request) => {
62
+ this.handleConnection(ws, request);
63
+ });
64
+ // Setup default namespace
65
+ this.createNamespace('/');
66
+ }
67
+ catch (error) {
68
+ throw new Error('ws library not found. Install it with: npm install ws @types/ws\n' +
69
+ 'Or use a different WebSocket adapter.');
70
+ }
71
+ }
72
+ handleConnection(ws, request) {
73
+ const id = this.generateId();
74
+ const connection = new WSConnectionWrapper(id, ws, request);
75
+ this.connections.set(id, connection);
76
+ // Parse namespace from URL path or default to '/'
77
+ const url = new URL(request.url || '/', `http://${request.headers.host}`);
78
+ const namespacePath = url.pathname === '/ws' ? '/' : url.pathname.replace('/ws', '') || '/';
79
+ const namespace = this.namespaces.get(namespacePath);
80
+ if (namespace) {
81
+ namespace.handleConnection(connection);
82
+ }
83
+ // Clean up on disconnect
84
+ ws.on('close', () => {
85
+ this.connections.delete(id);
86
+ });
87
+ }
88
+ createNamespace(namespace) {
89
+ if (!this.namespaces.has(namespace)) {
90
+ const ns = new WSNamespaceWrapper(namespace, this);
91
+ this.namespaces.set(namespace, ns);
92
+ }
93
+ return this.namespaces.get(namespace);
94
+ }
95
+ getDefaultNamespace() {
96
+ return this.createNamespace('/');
97
+ }
98
+ async close() {
99
+ if (this.wss) {
100
+ return new Promise(resolve => {
101
+ this.wss.close(() => {
102
+ this.connections.clear();
103
+ this.namespaces.clear();
104
+ resolve();
105
+ });
106
+ });
107
+ }
108
+ }
109
+ setCompression(enabled, _options = {}) {
110
+ // ws library handles compression at the browser level
111
+ // This is a no-op but kept for interface compatibility
112
+ if (enabled) {
113
+ console.warn('Compression is handled automatically by the ws library and browsers');
114
+ }
115
+ }
116
+ setCustomIdGenerator(generator) {
117
+ this.customIdGenerator = generator;
118
+ }
119
+ getAdapterName() {
120
+ return 'ws';
121
+ }
122
+ getConnectionCount() {
123
+ return this.connections.size;
124
+ }
125
+ generateId() {
126
+ if (this.customIdGenerator) {
127
+ return this.customIdGenerator();
128
+ }
129
+ return `ws_${++this.connectionCounter}_${Date.now()}`;
130
+ }
131
+ addConnection(id, connection) {
132
+ this.connections.set(id, connection);
133
+ }
134
+ removeConnection(id) {
135
+ this.connections.delete(id);
136
+ }
137
+ getAllConnections() {
138
+ return this.connections;
139
+ }
140
+ }
141
+ exports.WSAdapter = WSAdapter;
142
+ /**
143
+ * WebSocket namespace wrapper
144
+ */
145
+ class WSNamespaceWrapper {
146
+ constructor(namespacePath, adapter) {
147
+ this.namespacePath = namespacePath;
148
+ this.adapter = adapter;
149
+ this.connectionHandlers = [];
150
+ this.middlewares = [];
151
+ this.connections = new Map();
152
+ }
153
+ handleConnection(connection) {
154
+ this.connections.set(connection.id, connection);
155
+ // Run middlewares
156
+ this.runMiddlewares(connection, () => {
157
+ // Notify connection handlers
158
+ this.connectionHandlers.forEach(handler => handler(connection));
159
+ });
160
+ // Clean up on disconnect
161
+ connection.on('close', () => {
162
+ this.connections.delete(connection.id);
163
+ });
164
+ }
165
+ runMiddlewares(connection, callback) {
166
+ let index = 0;
167
+ const next = (err) => {
168
+ if (err || index >= this.middlewares.length) {
169
+ if (!err)
170
+ callback();
171
+ return;
172
+ }
173
+ const middleware = this.middlewares[index++];
174
+ middleware(connection, next);
175
+ };
176
+ next();
177
+ }
178
+ on(event, handler) {
179
+ this.connectionHandlers.push(handler);
180
+ }
181
+ emit(event, data) {
182
+ const message = JSON.stringify({ event, data });
183
+ for (const connection of this.connections.values()) {
184
+ if (connection.connected) {
185
+ connection.ws.send(message);
186
+ }
187
+ }
188
+ }
189
+ to(room) {
190
+ return new WSEmitterWrapper(this.connections, room);
191
+ }
192
+ except(room) {
193
+ return new WSEmitterWrapper(this.connections, undefined, room);
194
+ }
195
+ getSockets() {
196
+ return Array.from(this.connections.values());
197
+ }
198
+ getConnectionCount() {
199
+ return this.connections.size;
200
+ }
201
+ use(middleware) {
202
+ this.middlewares.push(middleware);
203
+ }
204
+ }
205
+ /**
206
+ * WebSocket connection wrapper
207
+ */
208
+ class WSConnectionWrapper {
209
+ constructor(id, ws, request) {
210
+ this.id = id;
211
+ this.ws = ws;
212
+ this.request = request;
213
+ this.data = {};
214
+ this.eventHandlers = new Map();
215
+ this.anyHandlers = [];
216
+ this.rooms = new Set();
217
+ this._connected = true;
218
+ // Setup message handling
219
+ this.ws.on('message', (data) => {
220
+ this.handleMessage(data);
221
+ });
222
+ this.ws.on('close', () => {
223
+ this._connected = false;
224
+ this.emit('close');
225
+ });
226
+ this.ws.on('error', (error) => {
227
+ this.emit('error', error);
228
+ });
229
+ }
230
+ get ip() {
231
+ return (this.request.socket?.remoteAddress || this.request.headers['x-forwarded-for']?.split(',')[0]);
232
+ }
233
+ get headers() {
234
+ return this.request.headers;
235
+ }
236
+ get connected() {
237
+ return this._connected && this.ws.readyState === 1; // WebSocket.OPEN
238
+ }
239
+ get broadcast() {
240
+ // Get all connections except this one
241
+ const allConnections = new Map();
242
+ // This would need access to adapter's connections
243
+ return new WSEmitterWrapper(allConnections, undefined, undefined, this.id);
244
+ }
245
+ on(event, handler) {
246
+ if (event === 'close' || event === 'error') {
247
+ // Special internal events
248
+ if (!this.eventHandlers.has(event)) {
249
+ this.eventHandlers.set(event, []);
250
+ }
251
+ this.eventHandlers.get(event).push(handler);
252
+ return;
253
+ }
254
+ if (!this.eventHandlers.has(event)) {
255
+ this.eventHandlers.set(event, []);
256
+ }
257
+ this.eventHandlers.get(event).push(handler);
258
+ }
259
+ onAny(handler) {
260
+ this.anyHandlers.push(handler);
261
+ }
262
+ emit(event, data) {
263
+ if (event === 'close' || event === 'error') {
264
+ // Internal events
265
+ const handlers = this.eventHandlers.get(event);
266
+ if (handlers) {
267
+ handlers.forEach(handler => handler(data));
268
+ }
269
+ return;
270
+ }
271
+ if (this.connected) {
272
+ const message = JSON.stringify({ event, data });
273
+ this.ws.send(message);
274
+ }
275
+ }
276
+ compressedEmit(event, data) {
277
+ // ws library handles compression automatically
278
+ this.emit(event, data);
279
+ }
280
+ join(room) {
281
+ if (Array.isArray(room)) {
282
+ room.forEach(r => this.rooms.add(r));
283
+ }
284
+ else {
285
+ this.rooms.add(room);
286
+ }
287
+ }
288
+ leave(room) {
289
+ if (Array.isArray(room)) {
290
+ room.forEach(r => this.rooms.delete(r));
291
+ }
292
+ else {
293
+ this.rooms.delete(room);
294
+ }
295
+ }
296
+ to(room) {
297
+ const connections = new Map([[this.id, this]]);
298
+ return new WSEmitterWrapper(connections, room);
299
+ }
300
+ getRooms() {
301
+ return new Set(this.rooms);
302
+ }
303
+ disconnect(close) {
304
+ if (close !== false && this.ws.readyState === 1) {
305
+ this.ws.close();
306
+ }
307
+ this._connected = false;
308
+ }
309
+ handleMessage(data) {
310
+ try {
311
+ const text = data.toString();
312
+ const parsed = JSON.parse(text);
313
+ const { event, data: messageData, callback: callbackId } = parsed;
314
+ // Create callback function if callback ID is provided
315
+ const callback = callbackId
316
+ ? (response) => {
317
+ this.emit('callback', { id: callbackId, data: response });
318
+ }
319
+ : undefined;
320
+ // Call any handlers
321
+ this.anyHandlers.forEach(handler => handler(event, messageData));
322
+ // Call specific event handlers
323
+ const handlers = this.eventHandlers.get(event);
324
+ if (handlers) {
325
+ handlers.forEach(handler => handler(messageData, callback));
326
+ }
327
+ }
328
+ catch (error) {
329
+ // Invalid message format - ignore
330
+ }
331
+ }
332
+ }
333
+ /**
334
+ * WebSocket emitter wrapper
335
+ */
336
+ class WSEmitterWrapper {
337
+ constructor(connections, targetRooms, excludeRooms, excludeId) {
338
+ this.connections = connections;
339
+ this.targetRooms = targetRooms;
340
+ this.excludeRooms = excludeRooms;
341
+ this.excludeId = excludeId;
342
+ }
343
+ emit(event, data) {
344
+ const message = JSON.stringify({ event, data });
345
+ for (const connection of this.connections.values()) {
346
+ if (this.excludeId && connection.id === this.excludeId) {
347
+ continue;
348
+ }
349
+ if (this.shouldIncludeConnection(connection) && connection.connected) {
350
+ connection.ws.send(message);
351
+ }
352
+ }
353
+ }
354
+ to(room) {
355
+ return new WSEmitterWrapper(this.connections, room, this.excludeRooms, this.excludeId);
356
+ }
357
+ except(room) {
358
+ return new WSEmitterWrapper(this.connections, this.targetRooms, room, this.excludeId);
359
+ }
360
+ compress(_compress) {
361
+ // ws library handles compression automatically
362
+ return this;
363
+ }
364
+ shouldIncludeConnection(connection) {
365
+ const rooms = connection.getRooms();
366
+ // Check target rooms
367
+ if (this.targetRooms) {
368
+ const targets = Array.isArray(this.targetRooms) ? this.targetRooms : [this.targetRooms];
369
+ if (!targets.some(room => rooms.has(room))) {
370
+ return false;
371
+ }
372
+ }
373
+ // Check exclude rooms
374
+ if (this.excludeRooms) {
375
+ const excludes = Array.isArray(this.excludeRooms) ? this.excludeRooms : [this.excludeRooms];
376
+ if (excludes.some(room => rooms.has(room))) {
377
+ return false;
378
+ }
379
+ }
380
+ return true;
381
+ }
382
+ }
383
+ //# sourceMappingURL=ws-adapter.js.map