@asenajs/asena 0.4.0 → 0.6.0-beta.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.
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/adapter/AsenaAdapter.js.map +1 -1
- package/dist/lib/adapter/AsenaWebsocketAdapter.js.map +1 -1
- package/dist/lib/ioc/CircularDependencyDetector.js.map +1 -1
- package/dist/lib/ioc/Container.d.ts +7 -0
- package/dist/lib/ioc/Container.js +25 -6
- package/dist/lib/ioc/Container.js.map +1 -1
- package/dist/lib/ioc/CoreContainer.d.ts +1 -1
- package/dist/lib/ioc/CoreContainer.js +12 -1
- package/dist/lib/ioc/CoreContainer.js.map +1 -1
- package/dist/lib/ioc/IocEngine.js +0 -2
- package/dist/lib/ioc/IocEngine.js.map +1 -1
- package/dist/lib/ioc/component/componentUtils.js.map +1 -1
- package/dist/lib/ioc/component/decorators/Inject.d.ts +24 -4
- package/dist/lib/ioc/component/decorators/Inject.js +44 -7
- package/dist/lib/ioc/component/decorators/Inject.js.map +1 -1
- package/dist/lib/ioc/constants/ComponentConstants.d.ts +2 -0
- package/dist/lib/ioc/constants/ComponentConstants.js +3 -0
- package/dist/lib/ioc/constants/ComponentConstants.js.map +1 -1
- package/dist/lib/ioc/types/ICoreServiceNamesType.d.ts +4 -0
- package/dist/lib/ioc/types/ICoreServiceNamesType.js +6 -0
- package/dist/lib/ioc/types/ICoreServiceNamesType.js.map +1 -1
- package/dist/lib/ioc/types/decorators/ComponentType.d.ts +2 -1
- package/dist/lib/ioc/types/decorators/ComponentType.js +1 -0
- package/dist/lib/ioc/types/decorators/ComponentType.js.map +1 -1
- package/dist/lib/server/AsenaServer.d.ts +1 -0
- package/dist/lib/server/AsenaServer.js +16 -10
- package/dist/lib/server/AsenaServer.js.map +1 -1
- package/dist/lib/server/AsenaServerFactory.js +8 -0
- package/dist/lib/server/AsenaServerFactory.js.map +1 -1
- package/dist/lib/server/decorators/components/Controller.js +1 -2
- package/dist/lib/server/decorators/components/Controller.js.map +1 -1
- package/dist/lib/server/decorators/components/EventService.d.ts +37 -0
- package/dist/lib/server/decorators/components/EventService.js +47 -0
- package/dist/lib/server/decorators/components/EventService.js.map +1 -0
- package/dist/lib/server/decorators/components/Middleware.js +1 -2
- package/dist/lib/server/decorators/components/Middleware.js.map +1 -1
- package/dist/lib/server/decorators/components/Schedule.js +1 -2
- package/dist/lib/server/decorators/components/Schedule.js.map +1 -1
- package/dist/lib/server/decorators/components/StaticServe.js +1 -1
- package/dist/lib/server/decorators/components/StaticServe.js.map +1 -1
- package/dist/lib/server/decorators/components/WebSocket.js +1 -2
- package/dist/lib/server/decorators/components/WebSocket.js.map +1 -1
- package/dist/lib/server/decorators/components/index.d.ts +1 -0
- package/dist/lib/server/decorators/components/index.js +1 -0
- package/dist/lib/server/decorators/components/index.js.map +1 -1
- package/dist/lib/server/decorators/index.d.ts +1 -0
- package/dist/lib/server/decorators/index.js +1 -0
- package/dist/lib/server/decorators/index.js.map +1 -1
- package/dist/lib/server/event/EventDispatchService.d.ts +104 -0
- package/dist/lib/server/event/EventDispatchService.js +203 -0
- package/dist/lib/server/event/EventDispatchService.js.map +1 -0
- package/dist/lib/server/event/EventEmitter.d.ts +67 -0
- package/dist/lib/server/event/EventEmitter.js +88 -0
- package/dist/lib/server/event/EventEmitter.js.map +1 -0
- package/dist/lib/server/event/EventService.d.ts +5 -0
- package/dist/lib/server/event/EventService.js +6 -0
- package/dist/lib/server/event/EventService.js.map +1 -0
- package/dist/lib/server/event/decorators/On.d.ts +38 -0
- package/dist/lib/server/event/decorators/On.js +56 -0
- package/dist/lib/server/event/decorators/On.js.map +1 -0
- package/dist/lib/server/event/decorators/index.d.ts +1 -0
- package/dist/lib/server/event/decorators/index.js +2 -0
- package/dist/lib/server/event/decorators/index.js.map +1 -0
- package/dist/lib/server/event/emitter.d.ts +21 -0
- package/dist/lib/server/event/emitter.js +25 -0
- package/dist/lib/server/event/emitter.js.map +1 -0
- package/dist/lib/server/event/eventPatternMatcher.d.ts +24 -0
- package/dist/lib/server/event/eventPatternMatcher.js +112 -0
- package/dist/lib/server/event/eventPatternMatcher.js.map +1 -0
- package/dist/lib/server/event/index.d.ts +6 -0
- package/dist/lib/server/event/index.js +12 -0
- package/dist/lib/server/event/index.js.map +1 -0
- package/dist/lib/server/event/types.d.ts +70 -0
- package/dist/lib/server/event/types.js +2 -0
- package/dist/lib/server/event/types.js.map +1 -0
- package/dist/lib/server/index.d.ts +0 -1
- package/dist/lib/server/index.js +0 -1
- package/dist/lib/server/index.js.map +1 -1
- package/dist/lib/server/messaging/Ulak.d.ts +224 -0
- package/dist/lib/server/messaging/Ulak.js +351 -0
- package/dist/lib/server/messaging/Ulak.js.map +1 -0
- package/dist/lib/server/messaging/index.d.ts +8 -0
- package/dist/lib/server/messaging/index.js +9 -0
- package/dist/lib/server/messaging/index.js.map +1 -0
- package/dist/lib/server/messaging/types.d.ts +73 -0
- package/dist/lib/server/messaging/types.js +35 -0
- package/dist/lib/server/messaging/types.js.map +1 -0
- package/dist/lib/server/src/services/PrepareConfigService.js.map +1 -1
- package/dist/lib/server/src/services/PrepareEventService.d.ts +40 -0
- package/dist/lib/server/src/services/PrepareEventService.js +103 -0
- package/dist/lib/server/src/services/PrepareEventService.js.map +1 -0
- package/dist/lib/server/src/services/PrepareMiddlewareService.js +1 -2
- package/dist/lib/server/src/services/PrepareMiddlewareService.js.map +1 -1
- package/dist/lib/server/src/services/PrepareStaticServeConfigService.js +3 -3
- package/dist/lib/server/src/services/PrepareStaticServeConfigService.js.map +1 -1
- package/dist/lib/server/src/services/PrepareValidatorService.js.map +1 -1
- package/dist/lib/server/src/services/PrepareWebsocketService.d.ts +4 -3
- package/dist/lib/server/src/services/PrepareWebsocketService.js +11 -4
- package/dist/lib/server/src/services/PrepareWebsocketService.js.map +1 -1
- package/dist/lib/server/web/decorators/http.base.d.ts +1 -1
- package/dist/lib/server/web/decorators/http.base.js +1 -1
- package/dist/lib/server/web/decorators/http.base.js.map +1 -1
- package/dist/lib/server/web/helper/middlewareHelper.d.ts +1 -1
- package/dist/lib/server/web/helper/middlewareHelper.js +1 -1
- package/dist/lib/server/web/helper/middlewareHelper.js.map +1 -1
- package/dist/lib/server/web/middleware/AsenaMiddlewareService.js.map +1 -1
- package/dist/lib/server/web/middleware/AsenaStaticServeService.d.ts +1 -1
- package/dist/lib/server/web/middleware/AsenaStaticServeService.js.map +1 -1
- package/dist/lib/server/web/websocket/AsenaSocket.d.ts +237 -4
- package/dist/lib/server/web/websocket/AsenaSocket.js +234 -32
- package/dist/lib/server/web/websocket/AsenaSocket.js.map +1 -1
- package/dist/lib/server/web/websocket/AsenaWebSocketServer.d.ts +3 -16
- package/dist/lib/server/web/websocket/AsenaWebSocketServer.js +3 -20
- package/dist/lib/server/web/websocket/AsenaWebSocketServer.js.map +1 -1
- package/dist/lib/server/web/websocket/AsenaWebSocketService.d.ts +0 -13
- package/dist/lib/server/web/websocket/AsenaWebSocketService.js +1 -21
- package/dist/lib/server/web/websocket/AsenaWebSocketService.js.map +1 -1
- package/dist/lib/utils/index.d.ts +2 -0
- package/dist/lib/utils/index.js +3 -0
- package/dist/lib/utils/index.js.map +1 -0
- package/dist/lib/utils/typedMetadata.js +0 -1
- package/dist/lib/utils/typedMetadata.js.map +1 -1
- package/package.json +32 -15
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import type { AsenaWebSocketService } from '../web/websocket';
|
|
2
|
+
import { type ICoreService, ICoreServiceNames } from '../../ioc';
|
|
3
|
+
import { type BulkOperation, type BulkResult } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* Central WebSocket message broker for Asena.js
|
|
6
|
+
*
|
|
7
|
+
* Ulak (Turkish: Messenger/Courier) provides a centralized way to send WebSocket messages
|
|
8
|
+
* without circular dependencies. Services can inject Ulak to send messages to any
|
|
9
|
+
* WebSocket namespace without directly injecting WebSocket services.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* @Service('UserService')
|
|
14
|
+
* class UserService {
|
|
15
|
+
* @Inject(ulak("/notifications"))
|
|
16
|
+
* private notifications: Ulak.NameSpace<"/notifications">;
|
|
17
|
+
*
|
|
18
|
+
* async createUser(data: any) {
|
|
19
|
+
* const user = await this.saveUser(data);
|
|
20
|
+
* await this.notifications.broadcast({ type: 'user_created', user });
|
|
21
|
+
* }
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class Ulak implements ICoreService {
|
|
26
|
+
readonly serviceName: string;
|
|
27
|
+
/**
|
|
28
|
+
* Logger instance injected from CoreContainer
|
|
29
|
+
*/
|
|
30
|
+
private logger;
|
|
31
|
+
/**
|
|
32
|
+
* Map of namespace path to WebSocket service instance
|
|
33
|
+
*/
|
|
34
|
+
private namespaces;
|
|
35
|
+
/**
|
|
36
|
+
* Initialize Ulak messaging system
|
|
37
|
+
* Called after dependency injection is complete
|
|
38
|
+
*/
|
|
39
|
+
init(): Promise<void>;
|
|
40
|
+
/**
|
|
41
|
+
* Register a WebSocket namespace
|
|
42
|
+
* Called automatically during WebSocket service initialization
|
|
43
|
+
*
|
|
44
|
+
* @param path - The namespace path (e.g., "/notifications")
|
|
45
|
+
* @param service - The WebSocket service instance
|
|
46
|
+
*/
|
|
47
|
+
registerNamespace(path: string, service: AsenaWebSocketService<any>): void;
|
|
48
|
+
/**
|
|
49
|
+
* Unregister a WebSocket namespace
|
|
50
|
+
* Useful for cleanup and preventing memory leaks
|
|
51
|
+
*
|
|
52
|
+
* @param path - The namespace path to unregister
|
|
53
|
+
*/
|
|
54
|
+
unregisterNamespace(path: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* Select a specific namespace for scoped operations
|
|
57
|
+
* Returns a scoped namespace interface for ergonomic API
|
|
58
|
+
*
|
|
59
|
+
* @param path - The namespace path
|
|
60
|
+
* @returns Scoped namespace instance
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* ```typescript
|
|
64
|
+
* const chat = ulak.namespace('/chat');
|
|
65
|
+
* await chat.broadcast({ message: 'Hello' }); // No need to repeat '/chat'
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
namespace<T extends string>(path: T): Ulak.NameSpace<T>;
|
|
69
|
+
/**
|
|
70
|
+
* Broadcast message to all clients in a namespace
|
|
71
|
+
*
|
|
72
|
+
* @param namespace - The target namespace
|
|
73
|
+
* @param data - The data to send
|
|
74
|
+
* @throws {UlakError} If namespace not found or broadcast fails
|
|
75
|
+
*/
|
|
76
|
+
broadcast(namespace: string, data: any): Promise<void>;
|
|
77
|
+
/**
|
|
78
|
+
* Send message to specific room in a namespace
|
|
79
|
+
*
|
|
80
|
+
* @param namespace - The target namespace
|
|
81
|
+
* @param room - The room name
|
|
82
|
+
* @param data - The data to send
|
|
83
|
+
* @throws {UlakError} If namespace not found or send fails
|
|
84
|
+
*/
|
|
85
|
+
to(namespace: string, room: string, data: any): Promise<void>;
|
|
86
|
+
/**
|
|
87
|
+
* Send message to specific socket by ID
|
|
88
|
+
*
|
|
89
|
+
* @param namespace - The target namespace
|
|
90
|
+
* @param socketId - The socket ID
|
|
91
|
+
* @param data - The data to send
|
|
92
|
+
* @throws {UlakError} If namespace not found, socket not found, or send fails
|
|
93
|
+
*/
|
|
94
|
+
toSocket(namespace: string, socketId: string, data: any): Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* Send to multiple rooms at once (parallel execution)
|
|
97
|
+
*
|
|
98
|
+
* @param namespace - The target namespace
|
|
99
|
+
* @param rooms - Array of room names
|
|
100
|
+
* @param data - The data to send
|
|
101
|
+
*/
|
|
102
|
+
toMany(namespace: string, rooms: string[], data: any): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Broadcast to all registered namespaces
|
|
105
|
+
*
|
|
106
|
+
* @param data - The data to send
|
|
107
|
+
*/
|
|
108
|
+
broadcastAll(data: any): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Send different messages to different targets (bulk operation)
|
|
111
|
+
*
|
|
112
|
+
* @param operations - Array of operations to perform
|
|
113
|
+
* @returns Result summary
|
|
114
|
+
*/
|
|
115
|
+
bulkSend(operations: BulkOperation[]): Promise<BulkResult>;
|
|
116
|
+
/**
|
|
117
|
+
* Get all active namespaces
|
|
118
|
+
*
|
|
119
|
+
* @returns Array of namespace paths
|
|
120
|
+
*/
|
|
121
|
+
getNamespaces(): string[];
|
|
122
|
+
/**
|
|
123
|
+
* Check if namespace exists
|
|
124
|
+
*
|
|
125
|
+
* @param namespace - The namespace to check
|
|
126
|
+
* @returns True if namespace is registered
|
|
127
|
+
*/
|
|
128
|
+
hasNamespace(namespace: string): boolean;
|
|
129
|
+
/**
|
|
130
|
+
* Get socket count for a namespace
|
|
131
|
+
*
|
|
132
|
+
* @param namespace - The namespace to query
|
|
133
|
+
* @returns Number of active sockets
|
|
134
|
+
*/
|
|
135
|
+
getSocketCount(namespace: string): number;
|
|
136
|
+
/**
|
|
137
|
+
* Dispose of all resources and stop background tasks
|
|
138
|
+
* Should be called during application shutdown
|
|
139
|
+
*/
|
|
140
|
+
dispose(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Get namespace service or throw error
|
|
143
|
+
*
|
|
144
|
+
* @param namespace - The namespace to retrieve
|
|
145
|
+
* @returns The WebSocket service
|
|
146
|
+
* @throws {UlakError} If namespace not found
|
|
147
|
+
*/
|
|
148
|
+
private getNamespaceService;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Scoped namespace interface
|
|
152
|
+
* Provides ergonomic API without repeating namespace path
|
|
153
|
+
*/
|
|
154
|
+
export declare namespace Ulak {
|
|
155
|
+
interface NameSpace<T extends string = string> {
|
|
156
|
+
/**
|
|
157
|
+
* The namespace path
|
|
158
|
+
*/
|
|
159
|
+
readonly path: T;
|
|
160
|
+
/**
|
|
161
|
+
* Broadcast to all clients in this namespace
|
|
162
|
+
*
|
|
163
|
+
* @param data - The data to send
|
|
164
|
+
*/
|
|
165
|
+
broadcast(data: any): Promise<void>;
|
|
166
|
+
/**
|
|
167
|
+
* Send to specific room in this namespace
|
|
168
|
+
*
|
|
169
|
+
* @param room - The room name
|
|
170
|
+
* @param data - The data to send
|
|
171
|
+
*/
|
|
172
|
+
to(room: string, data: any): Promise<void>;
|
|
173
|
+
/**
|
|
174
|
+
* Send to specific socket by ID in this namespace
|
|
175
|
+
*
|
|
176
|
+
* @param socketId - The socket ID
|
|
177
|
+
* @param data - The data to send
|
|
178
|
+
*/
|
|
179
|
+
toSocket(socketId: string, data: any): Promise<void>;
|
|
180
|
+
/**
|
|
181
|
+
* Send to multiple rooms at once
|
|
182
|
+
*
|
|
183
|
+
* @param rooms - Array of room names
|
|
184
|
+
* @param data - The data to send
|
|
185
|
+
*/
|
|
186
|
+
toMany(rooms: string[], data: any): Promise<void>;
|
|
187
|
+
/**
|
|
188
|
+
* Get socket count for this namespace
|
|
189
|
+
*
|
|
190
|
+
* @returns Number of active sockets
|
|
191
|
+
*/
|
|
192
|
+
getSocketCount(): number;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Helper function for injecting scoped Ulak namespace
|
|
197
|
+
*
|
|
198
|
+
* This function returns a tuple that can be used with the @Inject decorator
|
|
199
|
+
* to inject a scoped namespace from Ulak. This provides an ergonomic API
|
|
200
|
+
* where you don't need to repeat the namespace path in every method call.
|
|
201
|
+
*
|
|
202
|
+
* @param namespace - The WebSocket namespace path (e.g., "/chat", "/notifications")
|
|
203
|
+
* @returns A tuple of [serviceName, expression] for @Inject decorator
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```typescript
|
|
207
|
+
* @Service('ChatService')
|
|
208
|
+
* export class ChatService {
|
|
209
|
+
* // Inject scoped namespace
|
|
210
|
+
* @Inject(ulak("/chat"))
|
|
211
|
+
* private chat: Ulak.NameSpace<"/chat">;
|
|
212
|
+
*
|
|
213
|
+
* async sendMessage(roomId: string, message: string) {
|
|
214
|
+
* // Clean API - no need to repeat '/chat'
|
|
215
|
+
* await this.chat.to(roomId, { message });
|
|
216
|
+
* }
|
|
217
|
+
*
|
|
218
|
+
* async broadcastAnnouncement(text: string) {
|
|
219
|
+
* await this.chat.broadcast({ type: 'announcement', text });
|
|
220
|
+
* }
|
|
221
|
+
* }
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
export declare function ulak<T extends string>(namespace: T): readonly [ICoreServiceNames.__ULAK__, (ulak: Ulak) => Ulak.NameSpace<T>];
|
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
|
+
};
|
|
10
|
+
import { CoreService, ICoreServiceNames } from '../../ioc';
|
|
11
|
+
import { UlakError, UlakErrorCode } from './types';
|
|
12
|
+
import { Inject } from '../../ioc/component';
|
|
13
|
+
import { blue } from '../../logger';
|
|
14
|
+
/**
|
|
15
|
+
* Central WebSocket message broker for Asena.js
|
|
16
|
+
*
|
|
17
|
+
* Ulak (Turkish: Messenger/Courier) provides a centralized way to send WebSocket messages
|
|
18
|
+
* without circular dependencies. Services can inject Ulak to send messages to any
|
|
19
|
+
* WebSocket namespace without directly injecting WebSocket services.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* @Service('UserService')
|
|
24
|
+
* class UserService {
|
|
25
|
+
* @Inject(ulak("/notifications"))
|
|
26
|
+
* private notifications: Ulak.NameSpace<"/notifications">;
|
|
27
|
+
*
|
|
28
|
+
* async createUser(data: any) {
|
|
29
|
+
* const user = await this.saveUser(data);
|
|
30
|
+
* await this.notifications.broadcast({ type: 'user_created', user });
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
let Ulak = class Ulak {
|
|
36
|
+
serviceName = 'Ulak';
|
|
37
|
+
/**
|
|
38
|
+
* Logger instance injected from CoreContainer
|
|
39
|
+
*/
|
|
40
|
+
logger;
|
|
41
|
+
/**
|
|
42
|
+
* Map of namespace path to WebSocket service instance
|
|
43
|
+
*/
|
|
44
|
+
namespaces = new Map();
|
|
45
|
+
/**
|
|
46
|
+
* Initialize Ulak messaging system
|
|
47
|
+
* Called after dependency injection is complete
|
|
48
|
+
*/
|
|
49
|
+
async init() {
|
|
50
|
+
this.logger.info(`${blue('[Ulak]')} Initializing WebSocket messaging system ready`);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Register a WebSocket namespace
|
|
54
|
+
* Called automatically during WebSocket service initialization
|
|
55
|
+
*
|
|
56
|
+
* @param path - The namespace path (e.g., "/notifications")
|
|
57
|
+
* @param service - The WebSocket service instance
|
|
58
|
+
*/
|
|
59
|
+
registerNamespace(path, service) {
|
|
60
|
+
if (this.namespaces.has(path)) {
|
|
61
|
+
this.logger.warn(`${blue('[Ulak]')} Namespace "${path}" already registered, skipping`);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
this.namespaces.set(path, service);
|
|
65
|
+
this.logger.info(`${blue('[Ulak]')} Namespace "${path}" registered`);
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Unregister a WebSocket namespace
|
|
69
|
+
* Useful for cleanup and preventing memory leaks
|
|
70
|
+
*
|
|
71
|
+
* @param path - The namespace path to unregister
|
|
72
|
+
*/
|
|
73
|
+
unregisterNamespace(path) {
|
|
74
|
+
if (!this.namespaces.has(path)) {
|
|
75
|
+
this.logger.warn(`${blue('[Ulak]')} Cannot unregister namespace "${path}" - not found`);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
this.namespaces.delete(path);
|
|
79
|
+
this.logger.info(`${blue('[Ulak]')} Namespace "${path}" unregistered`);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Select a specific namespace for scoped operations
|
|
83
|
+
* Returns a scoped namespace interface for ergonomic API
|
|
84
|
+
*
|
|
85
|
+
* @param path - The namespace path
|
|
86
|
+
* @returns Scoped namespace instance
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* ```typescript
|
|
90
|
+
* const chat = ulak.namespace('/chat');
|
|
91
|
+
* await chat.broadcast({ message: 'Hello' }); // No need to repeat '/chat'
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
namespace(path) {
|
|
95
|
+
return new UlakNameSpace(path, this);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Broadcast message to all clients in a namespace
|
|
99
|
+
*
|
|
100
|
+
* @param namespace - The target namespace
|
|
101
|
+
* @param data - The data to send
|
|
102
|
+
* @throws {UlakError} If namespace not found or broadcast fails
|
|
103
|
+
*/
|
|
104
|
+
async broadcast(namespace, data) {
|
|
105
|
+
try {
|
|
106
|
+
const service = this.getNamespaceService(namespace);
|
|
107
|
+
// Use service's in() method to broadcast to all clients
|
|
108
|
+
service.in(data);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
this.logger.error(`${blue('[Ulak]')} Broadcast failed for namespace "${namespace}"`, error);
|
|
112
|
+
// If already a UlakError (e.g., NAMESPACE_NOT_FOUND), rethrow as-is
|
|
113
|
+
if (error instanceof UlakError) {
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
throw new UlakError(`Failed to broadcast to namespace: ${namespace}`, UlakErrorCode.BROADCAST_FAILED, namespace, error);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Send message to specific room in a namespace
|
|
121
|
+
*
|
|
122
|
+
* @param namespace - The target namespace
|
|
123
|
+
* @param room - The room name
|
|
124
|
+
* @param data - The data to send
|
|
125
|
+
* @throws {UlakError} If namespace not found or send fails
|
|
126
|
+
*/
|
|
127
|
+
async to(namespace, room, data) {
|
|
128
|
+
try {
|
|
129
|
+
const service = this.getNamespaceService(namespace);
|
|
130
|
+
// Use service's to() method to send to specific room
|
|
131
|
+
service.to(room, data);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
this.logger.error(`${blue('[Ulak]')} Send to room "${room}" failed in namespace "${namespace}"`, error);
|
|
135
|
+
// If already a UlakError (e.g., NAMESPACE_NOT_FOUND), rethrow as-is
|
|
136
|
+
if (error instanceof UlakError) {
|
|
137
|
+
throw error;
|
|
138
|
+
}
|
|
139
|
+
throw new UlakError(`Failed to send to room "${room}" in namespace: ${namespace}`, UlakErrorCode.SEND_FAILED, namespace, error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Send message to specific socket by ID
|
|
144
|
+
*
|
|
145
|
+
* @param namespace - The target namespace
|
|
146
|
+
* @param socketId - The socket ID
|
|
147
|
+
* @param data - The data to send
|
|
148
|
+
* @throws {UlakError} If namespace not found, socket not found, or send fails
|
|
149
|
+
*/
|
|
150
|
+
async toSocket(namespace, socketId, data) {
|
|
151
|
+
try {
|
|
152
|
+
const service = this.getNamespaceService(namespace);
|
|
153
|
+
// Get socket from service's socket map
|
|
154
|
+
const socket = service.sockets.get(socketId);
|
|
155
|
+
if (!socket) {
|
|
156
|
+
throw new UlakError(`Socket "${socketId}" not found in namespace "${namespace}"`, UlakErrorCode.SOCKET_NOT_FOUND, namespace);
|
|
157
|
+
}
|
|
158
|
+
// Send data to socket
|
|
159
|
+
socket.send(typeof data === 'string' ? data : JSON.stringify(data));
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
this.logger.error(`${blue('[Ulak]')} Send to socket "${socketId}" failed in namespace "${namespace}"`, error);
|
|
163
|
+
if (error instanceof UlakError) {
|
|
164
|
+
throw error;
|
|
165
|
+
}
|
|
166
|
+
throw new UlakError(`Failed to send to socket "${socketId}" in namespace: ${namespace}`, UlakErrorCode.SEND_FAILED, namespace, error);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Send to multiple rooms at once (parallel execution)
|
|
171
|
+
*
|
|
172
|
+
* @param namespace - The target namespace
|
|
173
|
+
* @param rooms - Array of room names
|
|
174
|
+
* @param data - The data to send
|
|
175
|
+
*/
|
|
176
|
+
async toMany(namespace, rooms, data) {
|
|
177
|
+
const results = await Promise.allSettled(rooms.map((room) => this.to(namespace, room, data)));
|
|
178
|
+
// Track failures
|
|
179
|
+
const failures = results.filter((r) => r.status === 'rejected');
|
|
180
|
+
if (failures.length > 0) {
|
|
181
|
+
this.logger.warn(`${blue('[Ulak]')} Batch send failed for ${failures.length}/${rooms.length} rooms in "${namespace}"`);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Broadcast to all registered namespaces
|
|
186
|
+
*
|
|
187
|
+
* @param data - The data to send
|
|
188
|
+
*/
|
|
189
|
+
async broadcastAll(data) {
|
|
190
|
+
const namespaces = Array.from(this.namespaces.keys());
|
|
191
|
+
const results = await Promise.allSettled(namespaces.map((ns) => this.broadcast(ns, data)));
|
|
192
|
+
const succeeded = results.filter((r) => r.status === 'fulfilled').length;
|
|
193
|
+
const failed = results.filter((r) => r.status === 'rejected').length;
|
|
194
|
+
this.logger.info(`${blue('[Ulak]')} Broadcast to all: ${succeeded} succeeded, ${failed} failed`);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Send different messages to different targets (bulk operation)
|
|
198
|
+
*
|
|
199
|
+
* @param operations - Array of operations to perform
|
|
200
|
+
* @returns Result summary
|
|
201
|
+
*/
|
|
202
|
+
async bulkSend(operations) {
|
|
203
|
+
const results = await Promise.allSettled(operations.map((op) => {
|
|
204
|
+
switch (op.type) {
|
|
205
|
+
case 'broadcast':
|
|
206
|
+
return this.broadcast(op.namespace, op.data);
|
|
207
|
+
case 'room':
|
|
208
|
+
if (!op.room) {
|
|
209
|
+
return Promise.reject(new Error('Room name required for room operation'));
|
|
210
|
+
}
|
|
211
|
+
return this.to(op.namespace, op.room, op.data);
|
|
212
|
+
case 'socket':
|
|
213
|
+
if (!op.socketId) {
|
|
214
|
+
return Promise.reject(new Error('Socket ID required for socket operation'));
|
|
215
|
+
}
|
|
216
|
+
return this.toSocket(op.namespace, op.socketId, op.data);
|
|
217
|
+
default:
|
|
218
|
+
return Promise.reject(new Error(`Invalid operation type: ${op.type}`));
|
|
219
|
+
}
|
|
220
|
+
}));
|
|
221
|
+
const succeeded = results.filter((r) => r.status === 'fulfilled').length;
|
|
222
|
+
const failed = results.filter((r) => r.status === 'rejected').length;
|
|
223
|
+
this.logger.info(`${blue('[Ulak]')} Bulk send: ${succeeded}/${operations.length} succeeded, ${failed} failed`);
|
|
224
|
+
return {
|
|
225
|
+
total: operations.length,
|
|
226
|
+
succeeded,
|
|
227
|
+
failed,
|
|
228
|
+
results,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Get all active namespaces
|
|
233
|
+
*
|
|
234
|
+
* @returns Array of namespace paths
|
|
235
|
+
*/
|
|
236
|
+
getNamespaces() {
|
|
237
|
+
return Array.from(this.namespaces.keys());
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Check if namespace exists
|
|
241
|
+
*
|
|
242
|
+
* @param namespace - The namespace to check
|
|
243
|
+
* @returns True if namespace is registered
|
|
244
|
+
*/
|
|
245
|
+
hasNamespace(namespace) {
|
|
246
|
+
return this.namespaces.has(namespace);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Get socket count for a namespace
|
|
250
|
+
*
|
|
251
|
+
* @param namespace - The namespace to query
|
|
252
|
+
* @returns Number of active sockets
|
|
253
|
+
*/
|
|
254
|
+
getSocketCount(namespace) {
|
|
255
|
+
const service = this.namespaces.get(namespace);
|
|
256
|
+
return service ? service.sockets.size : 0;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Dispose of all resources and stop background tasks
|
|
260
|
+
* Should be called during application shutdown
|
|
261
|
+
*/
|
|
262
|
+
dispose() {
|
|
263
|
+
// Unregister all namespaces
|
|
264
|
+
const namespaces = Array.from(this.namespaces.keys());
|
|
265
|
+
for (const namespace of namespaces) {
|
|
266
|
+
this.unregisterNamespace(namespace);
|
|
267
|
+
}
|
|
268
|
+
this.logger.info(`${blue('[Ulak]')} Disposed`);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Get namespace service or throw error
|
|
272
|
+
*
|
|
273
|
+
* @param namespace - The namespace to retrieve
|
|
274
|
+
* @returns The WebSocket service
|
|
275
|
+
* @throws {UlakError} If namespace not found
|
|
276
|
+
*/
|
|
277
|
+
getNamespaceService(namespace) {
|
|
278
|
+
const service = this.namespaces.get(namespace);
|
|
279
|
+
if (!service) {
|
|
280
|
+
throw new UlakError(`Namespace "${namespace}" not found in Ulak`, UlakErrorCode.NAMESPACE_NOT_FOUND, namespace);
|
|
281
|
+
}
|
|
282
|
+
return service;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
__decorate([
|
|
286
|
+
Inject(ICoreServiceNames.SERVER_LOGGER),
|
|
287
|
+
__metadata("design:type", Object)
|
|
288
|
+
], Ulak.prototype, "logger", void 0);
|
|
289
|
+
Ulak = __decorate([
|
|
290
|
+
CoreService(ICoreServiceNames.__ULAK__)
|
|
291
|
+
], Ulak);
|
|
292
|
+
export { Ulak };
|
|
293
|
+
/**
|
|
294
|
+
* Internal implementation of scoped namespace
|
|
295
|
+
*/
|
|
296
|
+
class UlakNameSpace {
|
|
297
|
+
path;
|
|
298
|
+
ulak;
|
|
299
|
+
constructor(path, ulak) {
|
|
300
|
+
this.path = path;
|
|
301
|
+
this.ulak = ulak;
|
|
302
|
+
}
|
|
303
|
+
async broadcast(data) {
|
|
304
|
+
await this.ulak.broadcast(this.path, data);
|
|
305
|
+
}
|
|
306
|
+
async to(room, data) {
|
|
307
|
+
await this.ulak.to(this.path, room, data);
|
|
308
|
+
}
|
|
309
|
+
async toSocket(socketId, data) {
|
|
310
|
+
await this.ulak.toSocket(this.path, socketId, data);
|
|
311
|
+
}
|
|
312
|
+
async toMany(rooms, data) {
|
|
313
|
+
await this.ulak.toMany(this.path, rooms, data);
|
|
314
|
+
}
|
|
315
|
+
getSocketCount() {
|
|
316
|
+
return this.ulak.getSocketCount(this.path);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Helper function for injecting scoped Ulak namespace
|
|
321
|
+
*
|
|
322
|
+
* This function returns a tuple that can be used with the @Inject decorator
|
|
323
|
+
* to inject a scoped namespace from Ulak. This provides an ergonomic API
|
|
324
|
+
* where you don't need to repeat the namespace path in every method call.
|
|
325
|
+
*
|
|
326
|
+
* @param namespace - The WebSocket namespace path (e.g., "/chat", "/notifications")
|
|
327
|
+
* @returns A tuple of [serviceName, expression] for @Inject decorator
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* ```typescript
|
|
331
|
+
* @Service('ChatService')
|
|
332
|
+
* export class ChatService {
|
|
333
|
+
* // Inject scoped namespace
|
|
334
|
+
* @Inject(ulak("/chat"))
|
|
335
|
+
* private chat: Ulak.NameSpace<"/chat">;
|
|
336
|
+
*
|
|
337
|
+
* async sendMessage(roomId: string, message: string) {
|
|
338
|
+
* // Clean API - no need to repeat '/chat'
|
|
339
|
+
* await this.chat.to(roomId, { message });
|
|
340
|
+
* }
|
|
341
|
+
*
|
|
342
|
+
* async broadcastAnnouncement(text: string) {
|
|
343
|
+
* await this.chat.broadcast({ type: 'announcement', text });
|
|
344
|
+
* }
|
|
345
|
+
* }
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
export function ulak(namespace) {
|
|
349
|
+
return [ICoreServiceNames.__ULAK__, (ulak) => ulak.namespace(namespace)];
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=Ulak.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Ulak.js","sourceRoot":"","sources":["../../../../lib/server/messaging/Ulak.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ulak WebSocket Messaging System
|
|
3
|
+
*
|
|
4
|
+
* Provides a centralized message broker for WebSocket communications
|
|
5
|
+
* without circular dependencies.
|
|
6
|
+
*/
|
|
7
|
+
export { Ulak, ulak } from './Ulak';
|
|
8
|
+
export { UlakError, UlakErrorCode, type BulkOperation, type BulkResult, type BulkOperationType } from './types';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ulak WebSocket Messaging System
|
|
3
|
+
*
|
|
4
|
+
* Provides a centralized message broker for WebSocket communications
|
|
5
|
+
* without circular dependencies.
|
|
6
|
+
*/
|
|
7
|
+
export { Ulak, ulak } from './Ulak';
|
|
8
|
+
export { UlakError, UlakErrorCode } from './types';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/server/messaging/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,aAAa,EAA+D,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error codes for Ulak messaging system
|
|
3
|
+
*/
|
|
4
|
+
export declare enum UlakErrorCode {
|
|
5
|
+
NAMESPACE_NOT_FOUND = "NAMESPACE_NOT_FOUND",
|
|
6
|
+
NAMESPACE_ALREADY_EXISTS = "NAMESPACE_ALREADY_EXISTS",
|
|
7
|
+
INVALID_NAMESPACE = "INVALID_NAMESPACE",
|
|
8
|
+
INVALID_MESSAGE = "INVALID_MESSAGE",
|
|
9
|
+
SEND_FAILED = "SEND_FAILED",
|
|
10
|
+
BROADCAST_FAILED = "BROADCAST_FAILED",
|
|
11
|
+
SOCKET_NOT_FOUND = "SOCKET_NOT_FOUND",
|
|
12
|
+
SERVICE_NOT_INITIALIZED = "SERVICE_NOT_INITIALIZED"
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Custom error class for Ulak messaging system
|
|
16
|
+
* Provides structured error information with error codes
|
|
17
|
+
*/
|
|
18
|
+
export declare class UlakError extends Error {
|
|
19
|
+
readonly code: UlakErrorCode;
|
|
20
|
+
readonly namespace?: string;
|
|
21
|
+
readonly cause?: Error;
|
|
22
|
+
constructor(message: string, code: UlakErrorCode, namespace?: string, cause?: Error);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Operation types for bulk message sending
|
|
26
|
+
*/
|
|
27
|
+
export type BulkOperationType = 'broadcast' | 'room' | 'socket';
|
|
28
|
+
/**
|
|
29
|
+
* A single operation in a bulk send
|
|
30
|
+
*/
|
|
31
|
+
export interface BulkOperation {
|
|
32
|
+
/**
|
|
33
|
+
* Type of operation
|
|
34
|
+
*/
|
|
35
|
+
type: BulkOperationType;
|
|
36
|
+
/**
|
|
37
|
+
* Target namespace
|
|
38
|
+
*/
|
|
39
|
+
namespace: string;
|
|
40
|
+
/**
|
|
41
|
+
* Room name (required for 'room' type)
|
|
42
|
+
*/
|
|
43
|
+
room?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Socket ID (required for 'socket' type)
|
|
46
|
+
*/
|
|
47
|
+
socketId?: string;
|
|
48
|
+
/**
|
|
49
|
+
* Data to send
|
|
50
|
+
*/
|
|
51
|
+
data: any;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Result of a bulk send operation
|
|
55
|
+
*/
|
|
56
|
+
export interface BulkResult {
|
|
57
|
+
/**
|
|
58
|
+
* Total number of operations attempted
|
|
59
|
+
*/
|
|
60
|
+
total: number;
|
|
61
|
+
/**
|
|
62
|
+
* Number of successful operations
|
|
63
|
+
*/
|
|
64
|
+
succeeded: number;
|
|
65
|
+
/**
|
|
66
|
+
* Number of failed operations
|
|
67
|
+
*/
|
|
68
|
+
failed: number;
|
|
69
|
+
/**
|
|
70
|
+
* Detailed results for each operation
|
|
71
|
+
*/
|
|
72
|
+
results: PromiseSettledResult<void>[];
|
|
73
|
+
}
|