@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,67 @@
|
|
|
1
|
+
import type { ICoreService } from '../../ioc';
|
|
2
|
+
/**
|
|
3
|
+
* @description Event Emitter - Public API for event-driven architecture
|
|
4
|
+
*
|
|
5
|
+
* Architecture:
|
|
6
|
+
* - EventEmitter (public API) → EventDispatchService (internal logic)
|
|
7
|
+
* - Similar pattern to: AsenaWebSocketService → AsenaWebSocketServer
|
|
8
|
+
*
|
|
9
|
+
* Usage:
|
|
10
|
+
* ```typescript
|
|
11
|
+
* // In your code
|
|
12
|
+
* @Inject(emitter())
|
|
13
|
+
* private emitter!: EventEmitter;
|
|
14
|
+
*
|
|
15
|
+
* // Emit events
|
|
16
|
+
* this.emitter.emit('user.created', { id: 123, name: 'John' });
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* Event handlers are registered via decorators:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* @EventService({ prefix: 'user' })
|
|
22
|
+
* export class UserEventService {
|
|
23
|
+
* @On('created')
|
|
24
|
+
* handleUserCreated(eventName: string, data: any) {
|
|
25
|
+
* // Handle event
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* Fire-and-Forget Pattern:
|
|
31
|
+
* - emit() returns immediately (doesn't wait for handlers)
|
|
32
|
+
* - Async handlers are executed without blocking
|
|
33
|
+
* - Handler errors are isolated and logged
|
|
34
|
+
*
|
|
35
|
+
* @see EventDispatchService for internal implementation details
|
|
36
|
+
*/
|
|
37
|
+
export declare class EventEmitter implements ICoreService {
|
|
38
|
+
readonly serviceName = "EventEmitter";
|
|
39
|
+
private dispatcher;
|
|
40
|
+
/**
|
|
41
|
+
* Emit an event to all registered handlers
|
|
42
|
+
*
|
|
43
|
+
* Fire-and-forget pattern (Spring style):
|
|
44
|
+
* - Returns immediately without waiting for handlers
|
|
45
|
+
* - Async handlers execute in background
|
|
46
|
+
* - Handler errors are caught and logged
|
|
47
|
+
*
|
|
48
|
+
* @param eventName - Event name to emit (e.g., 'user.created', 'download.complete')
|
|
49
|
+
* @param data - Optional data to pass to handlers
|
|
50
|
+
* @returns true if any handler was called, false if no handlers matched
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Emit event with data
|
|
54
|
+
* const success = this.emitter.emit('user.created', { id: 123, name: 'John' });
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* // Emit event without data
|
|
58
|
+
* this.emitter.emit('app.started');
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // Check if event was handled
|
|
62
|
+
* if (!this.emitter.emit('user.created', data)) {
|
|
63
|
+
* console.warn('No handlers registered for user.created event');
|
|
64
|
+
* }
|
|
65
|
+
*/
|
|
66
|
+
emit(eventName: string, data?: any): boolean;
|
|
67
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
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 { Inject } from '../../ioc/component';
|
|
12
|
+
/**
|
|
13
|
+
* @description Event Emitter - Public API for event-driven architecture
|
|
14
|
+
*
|
|
15
|
+
* Architecture:
|
|
16
|
+
* - EventEmitter (public API) → EventDispatchService (internal logic)
|
|
17
|
+
* - Similar pattern to: AsenaWebSocketService → AsenaWebSocketServer
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```typescript
|
|
21
|
+
* // In your code
|
|
22
|
+
* @Inject(emitter())
|
|
23
|
+
* private emitter!: EventEmitter;
|
|
24
|
+
*
|
|
25
|
+
* // Emit events
|
|
26
|
+
* this.emitter.emit('user.created', { id: 123, name: 'John' });
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* Event handlers are registered via decorators:
|
|
30
|
+
* ```typescript
|
|
31
|
+
* @EventService({ prefix: 'user' })
|
|
32
|
+
* export class UserEventService {
|
|
33
|
+
* @On('created')
|
|
34
|
+
* handleUserCreated(eventName: string, data: any) {
|
|
35
|
+
* // Handle event
|
|
36
|
+
* }
|
|
37
|
+
* }
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* Fire-and-Forget Pattern:
|
|
41
|
+
* - emit() returns immediately (doesn't wait for handlers)
|
|
42
|
+
* - Async handlers are executed without blocking
|
|
43
|
+
* - Handler errors are isolated and logged
|
|
44
|
+
*
|
|
45
|
+
* @see EventDispatchService for internal implementation details
|
|
46
|
+
*/
|
|
47
|
+
let EventEmitter = class EventEmitter {
|
|
48
|
+
serviceName = 'EventEmitter';
|
|
49
|
+
dispatcher;
|
|
50
|
+
/**
|
|
51
|
+
* Emit an event to all registered handlers
|
|
52
|
+
*
|
|
53
|
+
* Fire-and-forget pattern (Spring style):
|
|
54
|
+
* - Returns immediately without waiting for handlers
|
|
55
|
+
* - Async handlers execute in background
|
|
56
|
+
* - Handler errors are caught and logged
|
|
57
|
+
*
|
|
58
|
+
* @param eventName - Event name to emit (e.g., 'user.created', 'download.complete')
|
|
59
|
+
* @param data - Optional data to pass to handlers
|
|
60
|
+
* @returns true if any handler was called, false if no handlers matched
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Emit event with data
|
|
64
|
+
* const success = this.emitter.emit('user.created', { id: 123, name: 'John' });
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // Emit event without data
|
|
68
|
+
* this.emitter.emit('app.started');
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* // Check if event was handled
|
|
72
|
+
* if (!this.emitter.emit('user.created', data)) {
|
|
73
|
+
* console.warn('No handlers registered for user.created event');
|
|
74
|
+
* }
|
|
75
|
+
*/
|
|
76
|
+
emit(eventName, data) {
|
|
77
|
+
return this.dispatcher.dispatch(eventName, data);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
__decorate([
|
|
81
|
+
Inject(ICoreServiceNames.EVENT_DISPATCH_SERVICE),
|
|
82
|
+
__metadata("design:type", Function)
|
|
83
|
+
], EventEmitter.prototype, "dispatcher", void 0);
|
|
84
|
+
EventEmitter = __decorate([
|
|
85
|
+
CoreService(ICoreServiceNames.EVENT_EMITTER)
|
|
86
|
+
], EventEmitter);
|
|
87
|
+
export { EventEmitter };
|
|
88
|
+
//# sourceMappingURL=EventEmitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventEmitter.js","sourceRoot":"","sources":["../../../../lib/server/event/EventEmitter.ts"],"names":[],"mappings":";;;;;;;;;AACA,OAAO,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAG7C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAEI,IAAM,YAAY,GAAlB,MAAM,YAAY;IACP,WAAW,GAAG,cAAc,CAAC;IAGrC,UAAU,CAAwB;IAE1C;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACI,IAAI,CAAC,SAAiB,EAAE,IAAU;QACvC,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;CACF,CAAA;AA/BS;IADP,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,CAAC;;gDACP;AAJ/B,YAAY;IADxB,WAAW,CAAC,iBAAiB,CAAC,aAAa,CAAC;GAChC,YAAY,CAmCxB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EventService.js","sourceRoot":"","sources":["../../../../lib/server/event/EventService.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,OAAO,iBAAiB;CAAG"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { OnParams } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* @description On decorator - Marks a method as an event handler
|
|
4
|
+
*
|
|
5
|
+
* Methods decorated with @On will be automatically registered when
|
|
6
|
+
* the event system boots up (via PrepareEventService).
|
|
7
|
+
*
|
|
8
|
+
* @param params - Event pattern or configuration object
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* @EventService({ prefix: 'user' })
|
|
12
|
+
* export class UserEventService {
|
|
13
|
+
* @On('created') // Handles 'user.created'
|
|
14
|
+
* handleCreated(eventName: string, data: any) {
|
|
15
|
+
* console.log('User created:', data);
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* @On('*.updated') // Handles 'user.*.updated'
|
|
19
|
+
* handleUpdated(eventName: string, data: any) { }
|
|
20
|
+
*
|
|
21
|
+
* @On({ event: 'deleted', skip: true }) // Temporarily disabled
|
|
22
|
+
* handleDeleted(eventName: string, data: any) { }
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Without prefix (absolute pattern)
|
|
27
|
+
* @EventService()
|
|
28
|
+
* export class GlobalEventService {
|
|
29
|
+
* @On('*') // Handles ALL events
|
|
30
|
+
* handleAll(eventName: string, data: any) {
|
|
31
|
+
* console.log('Event:', eventName);
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* @On('*.error') // Handles all error events
|
|
35
|
+
* handleErrors(eventName: string, data: any) { }
|
|
36
|
+
* }
|
|
37
|
+
*/
|
|
38
|
+
export declare function On(params: OnParams | string): MethodDecorator;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ComponentConstants } from '../../../ioc';
|
|
2
|
+
import { defineTypedMetadata, getOwnTypedMetadata } from '../../../utils';
|
|
3
|
+
/**
|
|
4
|
+
* @description On decorator - Marks a method as an event handler
|
|
5
|
+
*
|
|
6
|
+
* Methods decorated with @On will be automatically registered when
|
|
7
|
+
* the event system boots up (via PrepareEventService).
|
|
8
|
+
*
|
|
9
|
+
* @param params - Event pattern or configuration object
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* @EventService({ prefix: 'user' })
|
|
13
|
+
* export class UserEventService {
|
|
14
|
+
* @On('created') // Handles 'user.created'
|
|
15
|
+
* handleCreated(eventName: string, data: any) {
|
|
16
|
+
* console.log('User created:', data);
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* @On('*.updated') // Handles 'user.*.updated'
|
|
20
|
+
* handleUpdated(eventName: string, data: any) { }
|
|
21
|
+
*
|
|
22
|
+
* @On({ event: 'deleted', skip: true }) // Temporarily disabled
|
|
23
|
+
* handleDeleted(eventName: string, data: any) { }
|
|
24
|
+
* }
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* // Without prefix (absolute pattern)
|
|
28
|
+
* @EventService()
|
|
29
|
+
* export class GlobalEventService {
|
|
30
|
+
* @On('*') // Handles ALL events
|
|
31
|
+
* handleAll(eventName: string, data: any) {
|
|
32
|
+
* console.log('Event:', eventName);
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* @On('*.error') // Handles all error events
|
|
36
|
+
* handleErrors(eventName: string, data: any) { }
|
|
37
|
+
* }
|
|
38
|
+
*/
|
|
39
|
+
export function On(params) {
|
|
40
|
+
// Normalize params - support both object and string
|
|
41
|
+
const _params = typeof params === 'string' ? { event: params, skip: false } : params;
|
|
42
|
+
return function (target, propertyKey, descriptor) {
|
|
43
|
+
// Get existing handlers metadata (other @On methods)
|
|
44
|
+
const handlers = getOwnTypedMetadata(ComponentConstants.EventHandlersKey, target.constructor) || {};
|
|
45
|
+
// Add this handler's metadata
|
|
46
|
+
handlers[propertyKey.toString()] = {
|
|
47
|
+
pattern: _params.event,
|
|
48
|
+
methodName: propertyKey.toString(),
|
|
49
|
+
skip: _params.skip || false,
|
|
50
|
+
};
|
|
51
|
+
// Store updated metadata
|
|
52
|
+
defineTypedMetadata(ComponentConstants.EventHandlersKey, handlers, target.constructor);
|
|
53
|
+
return descriptor;
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=On.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"On.js","sourceRoot":"","sources":["../../../../../lib/server/event/decorators/On.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAG1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,UAAU,EAAE,CAAC,MAAyB;IAC1C,oDAAoD;IACpD,MAAM,OAAO,GAAG,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IAErF,OAAO,UAAU,MAAc,EAAE,WAA4B,EAAE,UAA8B;QAC3F,qDAAqD;QACrD,MAAM,QAAQ,GACZ,mBAAmB,CACjB,kBAAkB,CAAC,gBAAgB,EACnC,MAAM,CAAC,WAAW,CACnB,IAAI,EAAE,CAAC;QAEV,8BAA8B;QAC9B,QAAQ,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,GAAG;YACjC,OAAO,EAAE,OAAO,CAAC,KAAK;YACtB,UAAU,EAAE,WAAW,CAAC,QAAQ,EAAE;YAClC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,KAAK;SAC5B,CAAC;QAEF,yBAAyB;QACzB,mBAAmB,CAAC,kBAAkB,CAAC,gBAAgB,EAAE,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;QAEvF,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './On';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../lib/server/event/decorators/index.ts"],"names":[],"mappings":"AAAA,cAAc,MAAM,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Utility for injecting EventEmitter
|
|
3
|
+
*
|
|
4
|
+
* Returns the EventEmitter service key for use with @Inject decorator.
|
|
5
|
+
*
|
|
6
|
+
* @returns The EventEmitter service key
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```typescript
|
|
10
|
+
* @Service()
|
|
11
|
+
* export class UserService {
|
|
12
|
+
* @Inject(emitter())
|
|
13
|
+
* private emitter!: EventEmitter;
|
|
14
|
+
*
|
|
15
|
+
* createUser(name: string) {
|
|
16
|
+
* this.emitter.emit('user.created', { name });
|
|
17
|
+
* }
|
|
18
|
+
* }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function emitter(): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ICoreServiceNames } from '../../ioc';
|
|
2
|
+
/**
|
|
3
|
+
* @description Utility for injecting EventEmitter
|
|
4
|
+
*
|
|
5
|
+
* Returns the EventEmitter service key for use with @Inject decorator.
|
|
6
|
+
*
|
|
7
|
+
* @returns The EventEmitter service key
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* @Service()
|
|
12
|
+
* export class UserService {
|
|
13
|
+
* @Inject(emitter())
|
|
14
|
+
* private emitter!: EventEmitter;
|
|
15
|
+
*
|
|
16
|
+
* createUser(name: string) {
|
|
17
|
+
* this.emitter.emit('user.created', { name });
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
export function emitter() {
|
|
23
|
+
return ICoreServiceNames.EVENT_EMITTER;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=emitter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"emitter.js","sourceRoot":"","sources":["../../../../lib/server/event/emitter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAE9C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,OAAO;IACrB,OAAO,iBAAiB,CAAC,aAAa,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Zero-dependency event pattern matcher for Asena event system
|
|
3
|
+
* Supports dot-notation wildcard patterns for event matching
|
|
4
|
+
*
|
|
5
|
+
* Pattern examples:
|
|
6
|
+
* - `*` matches all events
|
|
7
|
+
* - `download.*` matches `download.start`, `download.complete`, etc.
|
|
8
|
+
* - `*.complete` matches any event ending with `.complete`
|
|
9
|
+
* - `user.*.created` matches `user.admin.created`, `user.guest.created`, etc.
|
|
10
|
+
*
|
|
11
|
+
* Algorithm: Iterative backtracking with explicit stack
|
|
12
|
+
* Time Complexity: O(n * m) where n = event segments, m = pattern segments
|
|
13
|
+
* Space Complexity: O(n + m) for the stack
|
|
14
|
+
*
|
|
15
|
+
* @param eventName - The event name to test (e.g., 'download.complete')
|
|
16
|
+
* @param pattern - The pattern to match against (e.g., 'download.*', '*.complete')
|
|
17
|
+
* @returns true if the event name matches the pattern
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* matchesEventPattern('download.complete', 'download.*') // => true
|
|
21
|
+
* matchesEventPattern('user.admin.created', 'user.*.created') // => true
|
|
22
|
+
* matchesEventPattern('upload.start', 'download.*') // => false
|
|
23
|
+
*/
|
|
24
|
+
export declare function matchesEventPattern(eventName: string, pattern: string): boolean;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description Zero-dependency event pattern matcher for Asena event system
|
|
3
|
+
* Supports dot-notation wildcard patterns for event matching
|
|
4
|
+
*
|
|
5
|
+
* Pattern examples:
|
|
6
|
+
* - `*` matches all events
|
|
7
|
+
* - `download.*` matches `download.start`, `download.complete`, etc.
|
|
8
|
+
* - `*.complete` matches any event ending with `.complete`
|
|
9
|
+
* - `user.*.created` matches `user.admin.created`, `user.guest.created`, etc.
|
|
10
|
+
*
|
|
11
|
+
* Algorithm: Iterative backtracking with explicit stack
|
|
12
|
+
* Time Complexity: O(n * m) where n = event segments, m = pattern segments
|
|
13
|
+
* Space Complexity: O(n + m) for the stack
|
|
14
|
+
*
|
|
15
|
+
* @param eventName - The event name to test (e.g., 'download.complete')
|
|
16
|
+
* @param pattern - The pattern to match against (e.g., 'download.*', '*.complete')
|
|
17
|
+
* @returns true if the event name matches the pattern
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* matchesEventPattern('download.complete', 'download.*') // => true
|
|
21
|
+
* matchesEventPattern('user.admin.created', 'user.*.created') // => true
|
|
22
|
+
* matchesEventPattern('upload.start', 'download.*') // => false
|
|
23
|
+
*/
|
|
24
|
+
export function matchesEventPattern(eventName, pattern) {
|
|
25
|
+
// Exact match (fast path)
|
|
26
|
+
if (eventName === pattern) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
// Universal wildcard matches all events
|
|
30
|
+
if (pattern === '*') {
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
// No wildcard in pattern means exact match only (already checked above)
|
|
34
|
+
if (!pattern.includes('*')) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
// Split both event and pattern by dots
|
|
38
|
+
const eventSegments = eventName.split('.');
|
|
39
|
+
const patternSegments = pattern.split('.');
|
|
40
|
+
// Use iterative backtracking algorithm to avoid recursion
|
|
41
|
+
return matchSegmentsIterative(eventSegments, patternSegments);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* @description Iteratively matches event segments against pattern segments using backtracking
|
|
45
|
+
* Uses explicit stack to avoid recursion and prevent stack overflow
|
|
46
|
+
*
|
|
47
|
+
* Algorithm explanation:
|
|
48
|
+
* 1. Maintain a stack of (eventIndex, patternIndex) states to explore
|
|
49
|
+
* 2. For each state, try to match current segments
|
|
50
|
+
* 3. On wildcard, push multiple potential states (greedy matching)
|
|
51
|
+
* 4. On exact match, advance both indices
|
|
52
|
+
* 5. If we reach end of both arrays, success
|
|
53
|
+
*
|
|
54
|
+
* @param eventSegments - Array of event name segments
|
|
55
|
+
* @param patternSegments - Array of pattern segments
|
|
56
|
+
* @returns true if segments match
|
|
57
|
+
*/
|
|
58
|
+
function matchSegmentsIterative(eventSegments, patternSegments) {
|
|
59
|
+
// Stack for backtracking - holds states to explore
|
|
60
|
+
const stack = [{ eventIndex: 0, patternIndex: 0 }];
|
|
61
|
+
// Explored states to avoid infinite loops (eventIndex + patternIndex as key)
|
|
62
|
+
const explored = new Set();
|
|
63
|
+
while (stack.length > 0) {
|
|
64
|
+
const state = stack.pop();
|
|
65
|
+
const { eventIndex, patternIndex } = state;
|
|
66
|
+
// Create unique key for this state to avoid re-exploring
|
|
67
|
+
const stateKey = `${eventIndex}:${patternIndex}`;
|
|
68
|
+
if (explored.has(stateKey)) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
explored.add(stateKey);
|
|
72
|
+
// Success: consumed both arrays completely
|
|
73
|
+
if (eventIndex === eventSegments.length && patternIndex === patternSegments.length) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
// Failure: pattern exhausted but event has more segments
|
|
77
|
+
if (patternIndex === patternSegments.length) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
// Failure: event exhausted but pattern has more segments
|
|
81
|
+
// (Wildcards require at least one segment to match)
|
|
82
|
+
if (eventIndex === eventSegments.length) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const currentPattern = patternSegments[patternIndex];
|
|
86
|
+
// Case 1: Current pattern is wildcard
|
|
87
|
+
if (currentPattern === '*') {
|
|
88
|
+
// If this is the last pattern segment, wildcard must match all remaining event segments
|
|
89
|
+
if (patternIndex === patternSegments.length - 1) {
|
|
90
|
+
// Must have at least one event segment remaining
|
|
91
|
+
if (eventIndex < eventSegments.length) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
// Try matching wildcard with 1, 2, 3... event segments (greedy backtracking)
|
|
97
|
+
// Push states in reverse order so we try shortest match first (better performance)
|
|
98
|
+
for (let i = eventSegments.length - 1; i >= eventIndex; i--) {
|
|
99
|
+
stack.push({ eventIndex: i + 1, patternIndex: patternIndex + 1 });
|
|
100
|
+
}
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
// Case 2: Current pattern is not wildcard - must match exactly
|
|
104
|
+
if (eventSegments[eventIndex] === currentPattern) {
|
|
105
|
+
stack.push({ eventIndex: eventIndex + 1, patternIndex: patternIndex + 1 });
|
|
106
|
+
}
|
|
107
|
+
// No match, this path fails (don't push any new state)
|
|
108
|
+
}
|
|
109
|
+
// No path led to success
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=eventPatternMatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventPatternMatcher.js","sourceRoot":"","sources":["../../../../lib/server/event/eventPatternMatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { EventEmitter } from './EventEmitter';
|
|
2
|
+
export { EventDispatchService } from './EventDispatchService';
|
|
3
|
+
export { matchesEventPattern } from './eventPatternMatcher';
|
|
4
|
+
export { emitter } from './emitter';
|
|
5
|
+
export * from './types';
|
|
6
|
+
export * from './decorators';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Core event system
|
|
2
|
+
export { EventEmitter } from './EventEmitter';
|
|
3
|
+
export { EventDispatchService } from './EventDispatchService';
|
|
4
|
+
// Pattern matcher (utility)
|
|
5
|
+
export { matchesEventPattern } from './eventPatternMatcher';
|
|
6
|
+
// Injection utility
|
|
7
|
+
export { emitter } from './emitter';
|
|
8
|
+
// Types
|
|
9
|
+
export * from './types';
|
|
10
|
+
// Decorators
|
|
11
|
+
export * from './decorators';
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../lib/server/event/index.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAE9D,4BAA4B;AAC5B,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,oBAAoB;AACpB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,QAAQ;AACR,cAAc,SAAS,CAAC;AAExB,aAAa;AACb,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { ComponentParams } from '../../ioc';
|
|
2
|
+
/**
|
|
3
|
+
* @description Parameters for @EventService decorator
|
|
4
|
+
* Defines event service configuration including prefix for pattern matching
|
|
5
|
+
*/
|
|
6
|
+
export interface EventServiceParams extends ComponentParams {
|
|
7
|
+
/**
|
|
8
|
+
* Prefix for event patterns (used in pattern matching)
|
|
9
|
+
* @example 'download' for events like 'download.start', 'download.complete'
|
|
10
|
+
*/
|
|
11
|
+
prefix?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* @description Parameters for @On method decorator
|
|
15
|
+
* Defines event handler configuration
|
|
16
|
+
*/
|
|
17
|
+
export interface OnParams {
|
|
18
|
+
/**
|
|
19
|
+
* Event pattern to listen for
|
|
20
|
+
* Supports wildcards: *, download.*, *.complete, user.*.created
|
|
21
|
+
* @example 'download.complete' or 'download.*'
|
|
22
|
+
*/
|
|
23
|
+
event: string;
|
|
24
|
+
/**
|
|
25
|
+
* Skip this handler (useful for temporarily disabling handlers)
|
|
26
|
+
* @default false
|
|
27
|
+
*/
|
|
28
|
+
skip?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* @description Metadata stored for each event handler method
|
|
32
|
+
* Used by PrepareEventService to register handlers
|
|
33
|
+
*/
|
|
34
|
+
export interface EventHandlerMetadata {
|
|
35
|
+
/**
|
|
36
|
+
* Event pattern to match
|
|
37
|
+
*/
|
|
38
|
+
pattern: string;
|
|
39
|
+
/**
|
|
40
|
+
* Method name to call when event is emitted
|
|
41
|
+
*/
|
|
42
|
+
methodName: string;
|
|
43
|
+
/**
|
|
44
|
+
* Whether this handler should be skipped
|
|
45
|
+
*/
|
|
46
|
+
skip: boolean;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* @description Event handler function signature
|
|
50
|
+
* Handlers receive event name and optional data
|
|
51
|
+
*/
|
|
52
|
+
export type EventHandler<T = any> = (eventName: string, data?: T) => void | Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* @description Event subscription internal structure
|
|
55
|
+
* Used by EventBus to store and manage subscriptions
|
|
56
|
+
*/
|
|
57
|
+
export interface EventSubscription {
|
|
58
|
+
/**
|
|
59
|
+
* Event pattern for matching
|
|
60
|
+
*/
|
|
61
|
+
pattern: string;
|
|
62
|
+
/**
|
|
63
|
+
* Handler function to execute
|
|
64
|
+
*/
|
|
65
|
+
handler: EventHandler;
|
|
66
|
+
/**
|
|
67
|
+
* Whether this is a one-time subscription (once)
|
|
68
|
+
*/
|
|
69
|
+
once?: boolean;
|
|
70
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../lib/server/event/types.ts"],"names":[],"mappings":""}
|
package/dist/lib/server/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../lib/server/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,sBAAsB,CAAC"}
|