@hazeljs/websocket 0.2.0-beta.1

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 (45) hide show
  1. package/README.md +530 -0
  2. package/dist/decorators/realtime.decorator.d.ts +113 -0
  3. package/dist/decorators/realtime.decorator.d.ts.map +1 -0
  4. package/dist/decorators/realtime.decorator.js +202 -0
  5. package/dist/index.d.ts +10 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +32 -0
  8. package/dist/room/room.manager.d.ts +81 -0
  9. package/dist/room/room.manager.d.ts.map +1 -0
  10. package/dist/room/room.manager.js +209 -0
  11. package/dist/src/decorators/realtime.decorator.d.ts +113 -0
  12. package/dist/src/decorators/realtime.decorator.d.ts.map +1 -0
  13. package/dist/src/decorators/realtime.decorator.js +202 -0
  14. package/dist/src/index.d.ts +10 -0
  15. package/dist/src/index.d.ts.map +1 -0
  16. package/dist/src/index.js +32 -0
  17. package/dist/src/room/room.manager.d.ts +81 -0
  18. package/dist/src/room/room.manager.d.ts.map +1 -0
  19. package/dist/src/room/room.manager.js +209 -0
  20. package/dist/src/sse/sse.handler.d.ts +61 -0
  21. package/dist/src/sse/sse.handler.d.ts.map +1 -0
  22. package/dist/src/sse/sse.handler.js +209 -0
  23. package/dist/src/websocket.gateway.d.ts +94 -0
  24. package/dist/src/websocket.gateway.d.ts.map +1 -0
  25. package/dist/src/websocket.gateway.js +309 -0
  26. package/dist/src/websocket.module.d.ts +57 -0
  27. package/dist/src/websocket.module.d.ts.map +1 -0
  28. package/dist/src/websocket.module.js +88 -0
  29. package/dist/src/websocket.types.d.ts +258 -0
  30. package/dist/src/websocket.types.d.ts.map +1 -0
  31. package/dist/src/websocket.types.js +2 -0
  32. package/dist/sse/sse.handler.d.ts +61 -0
  33. package/dist/sse/sse.handler.d.ts.map +1 -0
  34. package/dist/sse/sse.handler.js +209 -0
  35. package/dist/tsconfig.tsbuildinfo +1 -0
  36. package/dist/websocket.gateway.d.ts +79 -0
  37. package/dist/websocket.gateway.d.ts.map +1 -0
  38. package/dist/websocket.gateway.js +214 -0
  39. package/dist/websocket.module.d.ts +57 -0
  40. package/dist/websocket.module.d.ts.map +1 -0
  41. package/dist/websocket.module.js +88 -0
  42. package/dist/websocket.types.d.ts +258 -0
  43. package/dist/websocket.types.d.ts.map +1 -0
  44. package/dist/websocket.types.js +2 -0
  45. package/package.json +48 -0
package/README.md ADDED
@@ -0,0 +1,530 @@
1
+ # @hazeljs/websocket
2
+
3
+ **WebSocket and Server-Sent Events Module for HazelJS**
4
+
5
+ Build real-time applications with WebSocket support, room management, and event-driven architecture.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/@hazeljs/websocket.svg)](https://www.npmjs.com/package/@hazeljs/websocket)
8
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
+
10
+ ## Features
11
+
12
+ - 🔌 **WebSocket Support** - Full-duplex real-time communication
13
+ - 🏠 **Room Management** - Group clients into rooms
14
+ - 📡 **Event-Driven** - Decorator-based event handling
15
+ - 🎨 **Decorator API** - `@WebSocketGateway`, `@OnMessage`, `@Subscribe`
16
+ - 🔐 **Authentication** - Integrate with auth guards
17
+ - 📊 **Broadcasting** - Send messages to multiple clients
18
+ - 🎯 **Namespaces** - Separate WebSocket endpoints
19
+ - 💾 **State Management** - Per-client state storage
20
+
21
+ ## Installation
22
+
23
+ ```bash
24
+ npm install @hazeljs/websocket
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Create WebSocket Gateway
30
+
31
+ ```typescript
32
+ import { Injectable } from '@hazeljs/core';
33
+ import {
34
+ WebSocketGateway,
35
+ OnConnect,
36
+ OnDisconnect,
37
+ OnMessage,
38
+ WebSocketClient,
39
+ Data,
40
+ } from '@hazeljs/websocket';
41
+
42
+ @Injectable()
43
+ @WebSocketGateway({ path: '/ws' })
44
+ export class ChatGateway {
45
+ @OnConnect()
46
+ handleConnection(client: WebSocketClient) {
47
+ console.log('Client connected:', client.id);
48
+ client.emit('welcome', { message: 'Welcome to the chat!' });
49
+ }
50
+
51
+ @OnDisconnect()
52
+ handleDisconnect(client: WebSocketClient) {
53
+ console.log('Client disconnected:', client.id);
54
+ }
55
+
56
+ @OnMessage('message')
57
+ handleMessage(client: WebSocketClient, @Data() data: { text: string }) {
58
+ console.log('Received message:', data.text);
59
+
60
+ // Broadcast to all clients
61
+ client.broadcast('message', {
62
+ from: client.id,
63
+ text: data.text,
64
+ timestamp: new Date(),
65
+ });
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### 2. Register Gateway
71
+
72
+ ```typescript
73
+ import { HazelModule } from '@hazeljs/core';
74
+ import { WebSocketModule } from '@hazeljs/websocket';
75
+ import { ChatGateway } from './chat.gateway';
76
+
77
+ @HazelModule({
78
+ imports: [WebSocketModule],
79
+ providers: [ChatGateway],
80
+ })
81
+ export class AppModule {}
82
+ ```
83
+
84
+ ### 3. Connect from Client
85
+
86
+ ```javascript
87
+ // Browser client
88
+ const ws = new WebSocket('ws://localhost:3000/ws');
89
+
90
+ ws.onopen = () => {
91
+ console.log('Connected');
92
+ ws.send(JSON.stringify({ event: 'message', data: { text: 'Hello!' } }));
93
+ };
94
+
95
+ ws.onmessage = (event) => {
96
+ const message = JSON.parse(event.data);
97
+ console.log('Received:', message);
98
+ };
99
+ ```
100
+
101
+ ## Decorators
102
+
103
+ ### @WebSocketGateway()
104
+
105
+ Define a WebSocket gateway:
106
+
107
+ ```typescript
108
+ @WebSocketGateway({
109
+ path: '/chat',
110
+ namespace: '/chat',
111
+ cors: {
112
+ origin: '*',
113
+ credentials: true,
114
+ },
115
+ })
116
+ export class ChatGateway {}
117
+ ```
118
+
119
+ ### @OnConnect()
120
+
121
+ Handle client connections:
122
+
123
+ ```typescript
124
+ @OnConnect()
125
+ handleConnection(client: WebSocketClient) {
126
+ console.log('New client:', client.id);
127
+
128
+ // Send welcome message
129
+ client.emit('welcome', { message: 'Hello!' });
130
+
131
+ // Store client data
132
+ client.data.username = 'Guest';
133
+ }
134
+ ```
135
+
136
+ ### @OnDisconnect()
137
+
138
+ Handle client disconnections:
139
+
140
+ ```typescript
141
+ @OnDisconnect()
142
+ handleDisconnect(client: WebSocketClient) {
143
+ console.log('Client left:', client.id);
144
+
145
+ // Notify others
146
+ client.broadcast('user-left', {
147
+ userId: client.id,
148
+ username: client.data.username,
149
+ });
150
+ }
151
+ ```
152
+
153
+ ### @OnMessage()
154
+
155
+ Handle specific messages:
156
+
157
+ ```typescript
158
+ @OnMessage('chat-message')
159
+ handleChatMessage(client: WebSocketClient, @Data() data: ChatMessage) {
160
+ console.log('Chat message from', client.id, ':', data.text);
161
+
162
+ // Broadcast to all
163
+ client.broadcast('chat-message', {
164
+ from: client.data.username,
165
+ text: data.text,
166
+ timestamp: new Date(),
167
+ });
168
+ }
169
+ ```
170
+
171
+ ### @Subscribe()
172
+
173
+ Subscribe to events:
174
+
175
+ ```typescript
176
+ @Subscribe('join-room')
177
+ handleJoinRoom(client: WebSocketClient, @Data() data: { room: string }) {
178
+ client.join(data.room);
179
+
180
+ // Notify room members
181
+ client.to(data.room).emit('user-joined', {
182
+ userId: client.id,
183
+ username: client.data.username,
184
+ });
185
+ }
186
+ ```
187
+
188
+ ## Room Management
189
+
190
+ ### Join Room
191
+
192
+ ```typescript
193
+ @Subscribe('join-room')
194
+ handleJoinRoom(client: WebSocketClient, @Data() data: { room: string }) {
195
+ client.join(data.room);
196
+ client.emit('joined', { room: data.room });
197
+ }
198
+ ```
199
+
200
+ ### Leave Room
201
+
202
+ ```typescript
203
+ @Subscribe('leave-room')
204
+ handleLeaveRoom(client: WebSocketClient, @Data() data: { room: string }) {
205
+ client.leave(data.room);
206
+ client.emit('left', { room: data.room });
207
+ }
208
+ ```
209
+
210
+ ### Send to Room
211
+
212
+ ```typescript
213
+ @Subscribe('room-message')
214
+ handleRoomMessage(
215
+ client: WebSocketClient,
216
+ @Data() data: { room: string; text: string }
217
+ ) {
218
+ // Send to all clients in room except sender
219
+ client.to(data.room).emit('room-message', {
220
+ from: client.id,
221
+ text: data.text,
222
+ });
223
+ }
224
+ ```
225
+
226
+ ### Broadcast to Room
227
+
228
+ ```typescript
229
+ @Subscribe('room-announcement')
230
+ handleAnnouncement(
231
+ client: WebSocketClient,
232
+ @Data() data: { room: string; text: string }
233
+ ) {
234
+ // Send to all clients in room including sender
235
+ client.in(data.room).emit('announcement', {
236
+ text: data.text,
237
+ });
238
+ }
239
+ ```
240
+
241
+ ## Broadcasting
242
+
243
+ ### Broadcast to All
244
+
245
+ ```typescript
246
+ @OnMessage('global-message')
247
+ handleGlobalMessage(client: WebSocketClient, @Data() data: any) {
248
+ // Send to all connected clients except sender
249
+ client.broadcast('global-message', data);
250
+ }
251
+ ```
252
+
253
+ ### Emit to All
254
+
255
+ ```typescript
256
+ @OnMessage('system-message')
257
+ handleSystemMessage(client: WebSocketClient, @Data() data: any) {
258
+ // Send to all connected clients including sender
259
+ this.server.emit('system-message', data);
260
+ }
261
+ ```
262
+
263
+ ### Emit to Specific Client
264
+
265
+ ```typescript
266
+ @Subscribe('private-message')
267
+ handlePrivateMessage(
268
+ client: WebSocketClient,
269
+ @Data() data: { to: string; text: string }
270
+ ) {
271
+ const targetClient = this.server.getClient(data.to);
272
+
273
+ if (targetClient) {
274
+ targetClient.emit('private-message', {
275
+ from: client.id,
276
+ text: data.text,
277
+ });
278
+ }
279
+ }
280
+ ```
281
+
282
+ ## Authentication
283
+
284
+ ### With Guards
285
+
286
+ ```typescript
287
+ import { UseGuard } from '@hazeljs/core';
288
+ import { AuthGuard } from '@hazeljs/auth';
289
+
290
+ @WebSocketGateway({ path: '/secure' })
291
+ @UseGuard(AuthGuard)
292
+ export class SecureGateway {
293
+ @OnConnect()
294
+ handleConnection(client: WebSocketClient) {
295
+ // Only authenticated clients reach here
296
+ console.log('Authenticated user:', client.data.user);
297
+ }
298
+ }
299
+ ```
300
+
301
+ ### Custom Authentication
302
+
303
+ ```typescript
304
+ @WebSocketGateway({ path: '/chat' })
305
+ export class ChatGateway {
306
+ @OnConnect()
307
+ async handleConnection(client: WebSocketClient) {
308
+ const token = client.handshake.query.token;
309
+
310
+ try {
311
+ const user = await this.authService.verifyToken(token);
312
+ client.data.user = user;
313
+ client.emit('authenticated', { user });
314
+ } catch (error) {
315
+ client.disconnect();
316
+ }
317
+ }
318
+ }
319
+ ```
320
+
321
+ ## Complete Example: Chat Application
322
+
323
+ ```typescript
324
+ import { Injectable } from '@hazeljs/core';
325
+ import {
326
+ WebSocketGateway,
327
+ OnConnect,
328
+ OnDisconnect,
329
+ Subscribe,
330
+ WebSocketClient,
331
+ Data,
332
+ WebSocketServer,
333
+ } from '@hazeljs/websocket';
334
+
335
+ interface ChatMessage {
336
+ text: string;
337
+ room?: string;
338
+ }
339
+
340
+ interface JoinRoomData {
341
+ room: string;
342
+ username: string;
343
+ }
344
+
345
+ @Injectable()
346
+ @WebSocketGateway({ path: '/chat' })
347
+ export class ChatGateway {
348
+ @WebSocketServer()
349
+ server: WebSocketServer;
350
+
351
+ @OnConnect()
352
+ handleConnection(client: WebSocketClient) {
353
+ console.log(`Client connected: ${client.id}`);
354
+
355
+ client.emit('connected', {
356
+ clientId: client.id,
357
+ message: 'Welcome to the chat!',
358
+ });
359
+ }
360
+
361
+ @OnDisconnect()
362
+ handleDisconnect(client: WebSocketClient) {
363
+ console.log(`Client disconnected: ${client.id}`);
364
+
365
+ // Notify rooms
366
+ const rooms = client.rooms;
367
+ rooms.forEach(room => {
368
+ client.to(room).emit('user-left', {
369
+ userId: client.id,
370
+ username: client.data.username,
371
+ });
372
+ });
373
+ }
374
+
375
+ @Subscribe('join-room')
376
+ handleJoinRoom(client: WebSocketClient, @Data() data: JoinRoomData) {
377
+ client.join(data.room);
378
+ client.data.username = data.username;
379
+
380
+ // Notify room members
381
+ client.to(data.room).emit('user-joined', {
382
+ userId: client.id,
383
+ username: data.username,
384
+ room: data.room,
385
+ });
386
+
387
+ // Confirm to sender
388
+ client.emit('joined-room', {
389
+ room: data.room,
390
+ members: this.getRoomMembers(data.room),
391
+ });
392
+ }
393
+
394
+ @Subscribe('leave-room')
395
+ handleLeaveRoom(client: WebSocketClient, @Data() data: { room: string }) {
396
+ client.leave(data.room);
397
+
398
+ // Notify room
399
+ client.to(data.room).emit('user-left', {
400
+ userId: client.id,
401
+ username: client.data.username,
402
+ });
403
+ }
404
+
405
+ @Subscribe('chat-message')
406
+ handleMessage(client: WebSocketClient, @Data() data: ChatMessage) {
407
+ const message = {
408
+ from: client.id,
409
+ username: client.data.username,
410
+ text: data.text,
411
+ timestamp: new Date(),
412
+ };
413
+
414
+ if (data.room) {
415
+ // Send to specific room
416
+ client.to(data.room).emit('chat-message', message);
417
+ } else {
418
+ // Broadcast to all
419
+ client.broadcast('chat-message', message);
420
+ }
421
+ }
422
+
423
+ @Subscribe('typing')
424
+ handleTyping(client: WebSocketClient, @Data() data: { room?: string }) {
425
+ const typingData = {
426
+ userId: client.id,
427
+ username: client.data.username,
428
+ };
429
+
430
+ if (data.room) {
431
+ client.to(data.room).emit('typing', typingData);
432
+ } else {
433
+ client.broadcast('typing', typingData);
434
+ }
435
+ }
436
+
437
+ private getRoomMembers(room: string): any[] {
438
+ const clients = this.server.getClientsInRoom(room);
439
+ return clients.map(c => ({
440
+ id: c.id,
441
+ username: c.data.username,
442
+ }));
443
+ }
444
+ }
445
+ ```
446
+
447
+ ## Client State
448
+
449
+ Store per-client data:
450
+
451
+ ```typescript
452
+ @OnConnect()
453
+ handleConnection(client: WebSocketClient) {
454
+ // Store custom data
455
+ client.data.username = 'Guest';
456
+ client.data.score = 0;
457
+ client.data.joinedAt = new Date();
458
+ }
459
+
460
+ @Subscribe('update-profile')
461
+ handleUpdateProfile(client: WebSocketClient, @Data() data: any) {
462
+ client.data.username = data.username;
463
+ client.data.avatar = data.avatar;
464
+ }
465
+ ```
466
+
467
+ ## Server-Sent Events (SSE)
468
+
469
+ ```typescript
470
+ import { Controller, Get, Res } from '@hazeljs/core';
471
+ import { Response } from 'express';
472
+
473
+ @Controller('/events')
474
+ export class EventsController {
475
+ @Get('/stream')
476
+ streamEvents(@Res() res: Response) {
477
+ res.setHeader('Content-Type', 'text/event-stream');
478
+ res.setHeader('Cache-Control', 'no-cache');
479
+ res.setHeader('Connection', 'keep-alive');
480
+
481
+ // Send event every second
482
+ const interval = setInterval(() => {
483
+ res.write(`data: ${JSON.stringify({ time: new Date() })}\n\n`);
484
+ }, 1000);
485
+
486
+ // Cleanup on close
487
+ res.on('close', () => {
488
+ clearInterval(interval);
489
+ res.end();
490
+ });
491
+ }
492
+ }
493
+ ```
494
+
495
+ ## Best Practices
496
+
497
+ 1. **Handle Disconnections** - Always implement `@OnDisconnect()`
498
+ 2. **Validate Messages** - Validate incoming data
499
+ 3. **Use Rooms** - Group related clients
500
+ 4. **Authentication** - Verify clients on connection
501
+ 5. **Error Handling** - Catch and handle errors gracefully
502
+ 6. **Rate Limiting** - Prevent message flooding
503
+ 7. **Heartbeat** - Implement ping/pong for connection health
504
+ 8. **Clean Up** - Remove client data on disconnect
505
+
506
+ ## Examples
507
+
508
+ See the [examples](../../example/src/websocket) directory for complete working examples.
509
+
510
+ ## Testing
511
+
512
+ ```bash
513
+ npm test
514
+ ```
515
+
516
+ ## Contributing
517
+
518
+ Contributions are welcome! Please read our [Contributing Guide](../../CONTRIBUTING.md) for details.
519
+
520
+ ## License
521
+
522
+ MIT © [HazelJS](https://hazeljs.com)
523
+
524
+ ## Links
525
+
526
+ - [Documentation](https://hazeljs.com/docs/packages/websocket)
527
+ - [WebSocket API](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket)
528
+ - [GitHub](https://github.com/hazel-js/hazeljs)
529
+ - [Issues](https://github.com/hazeljs/hazel-js/issues)
530
+ - [Discord](https://discord.gg/hazeljs)
@@ -0,0 +1,113 @@
1
+ import 'reflect-metadata';
2
+ import { WebSocketGatewayOptions } from '../websocket.types';
3
+ /**
4
+ * Realtime decorator for WebSocket gateways
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * @Realtime('/notifications')
9
+ * export class NotificationGateway {
10
+ * // Gateway methods
11
+ * }
12
+ * ```
13
+ */
14
+ export declare function Realtime(pathOrOptions?: string | WebSocketGatewayOptions): ClassDecorator;
15
+ /**
16
+ * Get realtime metadata from a class
17
+ */
18
+ export declare function getRealtimeMetadata(target: object | (new (...args: unknown[]) => object)): WebSocketGatewayOptions | undefined;
19
+ /**
20
+ * Check if a class is a realtime gateway
21
+ */
22
+ export declare function isRealtimeGateway(target: object | (new (...args: unknown[]) => object)): boolean;
23
+ /**
24
+ * Subscribe decorator for event handlers
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * @Subscribe('user-{userId}')
29
+ * onUserEvent(@Param('userId') userId: string, @Data() data: any) {
30
+ * // Handle event
31
+ * }
32
+ * ```
33
+ */
34
+ export declare function Subscribe(event: string): MethodDecorator;
35
+ /**
36
+ * Get subscribe metadata from a method
37
+ */
38
+ export declare function getSubscribeMetadata(target: object, propertyKey: string | symbol): string | undefined;
39
+ /**
40
+ * OnConnect decorator for connection handlers
41
+ *
42
+ * @example
43
+ * ```typescript
44
+ * @OnConnect()
45
+ * handleConnection(@Client() client: WebSocketClient) {
46
+ * console.log('Client connected:', client.id);
47
+ * }
48
+ * ```
49
+ */
50
+ export declare function OnConnect(): MethodDecorator;
51
+ /**
52
+ * Get OnConnect metadata
53
+ */
54
+ export declare function getOnConnectMetadata(target: object, propertyKey: string | symbol): boolean;
55
+ /**
56
+ * OnDisconnect decorator for disconnection handlers
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * @OnDisconnect()
61
+ * handleDisconnect(@Client() client: WebSocketClient) {
62
+ * console.log('Client disconnected:', client.id);
63
+ * }
64
+ * ```
65
+ */
66
+ export declare function OnDisconnect(): MethodDecorator;
67
+ /**
68
+ * Get OnDisconnect metadata
69
+ */
70
+ export declare function getOnDisconnectMetadata(target: object, propertyKey: string | symbol): boolean;
71
+ /**
72
+ * OnMessage decorator for message handlers
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * @OnMessage('chat')
77
+ * handleMessage(@Client() client: WebSocketClient, @Data() data: any) {
78
+ * // Handle message
79
+ * }
80
+ * ```
81
+ */
82
+ export declare function OnMessage(event: string): MethodDecorator;
83
+ /**
84
+ * Get OnMessage metadata
85
+ */
86
+ export declare function getOnMessageMetadata(target: object, propertyKey: string | symbol): string | undefined;
87
+ /**
88
+ * Client parameter decorator
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * handleConnection(@Client() client: WebSocketClient) {
93
+ * // client is injected
94
+ * }
95
+ * ```
96
+ */
97
+ export declare function Client(): ParameterDecorator;
98
+ /**
99
+ * Data parameter decorator
100
+ *
101
+ * @example
102
+ * ```typescript
103
+ * handleMessage(@Data() data: any) {
104
+ * // data is injected
105
+ * }
106
+ * ```
107
+ */
108
+ export declare function Data(): ParameterDecorator;
109
+ /**
110
+ * Get parameter metadata
111
+ */
112
+ export declare function getParameterMetadata(target: object, propertyKey: string | symbol): string[];
113
+ //# sourceMappingURL=realtime.decorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"realtime.decorator.d.ts","sourceRoot":"","sources":["../../src/decorators/realtime.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,CAAC;AAC1B,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAC;AAS7D;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,uBAAuB,GAAG,cAAc,CAmBzF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,MAAM,CAAC,GACpD,uBAAuB,GAAG,SAAS,CAErC;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,KAAK,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,MAAM,CAAC,GAAG,OAAO,CAEhG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAQxD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,MAAM,GAC3B,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,IAAI,eAAe,CAQ3C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAE1F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,IAAI,eAAe,CAQ9C;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAE7F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAQxD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,GAAG,MAAM,GAC3B,MAAM,GAAG,SAAS,CAEpB;AAED;;;;;;;;;GASG;AACH,wBAAgB,MAAM,IAAI,kBAAkB,CAM3C;AAED;;;;;;;;;GASG;AACH,wBAAgB,IAAI,IAAI,kBAAkB,CAMzC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,CAE3F"}