@awesome-lang-auth/node 1.10.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.
- package/LICENSE +21 -0
- package/README.detailed.md +4059 -0
- package/README.md +248 -0
- package/dist/abstract/base-auth-strategy.abstract.d.ts +7 -0
- package/dist/abstract/base-auth-strategy.abstract.d.ts.map +1 -0
- package/dist/abstract/base-auth-strategy.abstract.js +7 -0
- package/dist/abstract/base-auth-strategy.abstract.js.map +1 -0
- package/dist/abstract/base-oauth-strategy.abstract.d.ts +27 -0
- package/dist/abstract/base-oauth-strategy.abstract.d.ts.map +1 -0
- package/dist/abstract/base-oauth-strategy.abstract.js +11 -0
- package/dist/abstract/base-oauth-strategy.abstract.js.map +1 -0
- package/dist/adapters/express.d.ts +45 -0
- package/dist/adapters/express.d.ts.map +1 -0
- package/dist/adapters/express.js +49 -0
- package/dist/adapters/express.js.map +1 -0
- package/dist/adapters/fastify.d.ts +72 -0
- package/dist/adapters/fastify.d.ts.map +1 -0
- package/dist/adapters/fastify.js +63 -0
- package/dist/adapters/fastify.js.map +1 -0
- package/dist/auth-configurator.d.ts +65 -0
- package/dist/auth-configurator.d.ts.map +1 -0
- package/dist/auth-configurator.js +127 -0
- package/dist/auth-configurator.js.map +1 -0
- package/dist/events/auth-event-bus.d.ts +68 -0
- package/dist/events/auth-event-bus.d.ts.map +1 -0
- package/dist/events/auth-event-bus.js +60 -0
- package/dist/events/auth-event-bus.js.map +1 -0
- package/dist/events/auth-event-names.d.ts +34 -0
- package/dist/events/auth-event-names.d.ts.map +1 -0
- package/dist/events/auth-event-names.js +41 -0
- package/dist/events/auth-event-names.js.map +1 -0
- package/dist/http-types.d.ts +135 -0
- package/dist/http-types.d.ts.map +1 -0
- package/dist/http-types.js +18 -0
- package/dist/http-types.js.map +1 -0
- package/dist/index.d.ts +80 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +88 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/api-key-store.interface.d.ts +94 -0
- package/dist/interfaces/api-key-store.interface.d.ts.map +1 -0
- package/dist/interfaces/api-key-store.interface.js +3 -0
- package/dist/interfaces/api-key-store.interface.js.map +1 -0
- package/dist/interfaces/auth-strategy.interface.d.ts +6 -0
- package/dist/interfaces/auth-strategy.interface.d.ts.map +1 -0
- package/dist/interfaces/auth-strategy.interface.js +3 -0
- package/dist/interfaces/auth-strategy.interface.js.map +1 -0
- package/dist/interfaces/linked-accounts-store.interface.d.ts +74 -0
- package/dist/interfaces/linked-accounts-store.interface.d.ts.map +1 -0
- package/dist/interfaces/linked-accounts-store.interface.js +3 -0
- package/dist/interfaces/linked-accounts-store.interface.js.map +1 -0
- package/dist/interfaces/pending-link-store.interface.d.ts +77 -0
- package/dist/interfaces/pending-link-store.interface.d.ts.map +1 -0
- package/dist/interfaces/pending-link-store.interface.js +3 -0
- package/dist/interfaces/pending-link-store.interface.js.map +1 -0
- package/dist/interfaces/roles-permissions-store.interface.d.ts +129 -0
- package/dist/interfaces/roles-permissions-store.interface.d.ts.map +1 -0
- package/dist/interfaces/roles-permissions-store.interface.js +3 -0
- package/dist/interfaces/roles-permissions-store.interface.js.map +1 -0
- package/dist/interfaces/session-store.interface.d.ts +92 -0
- package/dist/interfaces/session-store.interface.d.ts.map +1 -0
- package/dist/interfaces/session-store.interface.js +3 -0
- package/dist/interfaces/session-store.interface.js.map +1 -0
- package/dist/interfaces/settings-store.interface.d.ts +91 -0
- package/dist/interfaces/settings-store.interface.d.ts.map +1 -0
- package/dist/interfaces/settings-store.interface.js +3 -0
- package/dist/interfaces/settings-store.interface.js.map +1 -0
- package/dist/interfaces/sse-distributor.interface.d.ts +25 -0
- package/dist/interfaces/sse-distributor.interface.d.ts.map +1 -0
- package/dist/interfaces/sse-distributor.interface.js +3 -0
- package/dist/interfaces/sse-distributor.interface.js.map +1 -0
- package/dist/interfaces/telemetry-store.interface.d.ts +72 -0
- package/dist/interfaces/telemetry-store.interface.d.ts.map +1 -0
- package/dist/interfaces/telemetry-store.interface.js +3 -0
- package/dist/interfaces/telemetry-store.interface.js.map +1 -0
- package/dist/interfaces/template-store.interface.d.ts +37 -0
- package/dist/interfaces/template-store.interface.d.ts.map +1 -0
- package/dist/interfaces/template-store.interface.js +3 -0
- package/dist/interfaces/template-store.interface.js.map +1 -0
- package/dist/interfaces/tenant-store.interface.d.ts +97 -0
- package/dist/interfaces/tenant-store.interface.d.ts.map +1 -0
- package/dist/interfaces/tenant-store.interface.js +3 -0
- package/dist/interfaces/tenant-store.interface.js.map +1 -0
- package/dist/interfaces/token-store.interface.d.ts +10 -0
- package/dist/interfaces/token-store.interface.d.ts.map +1 -0
- package/dist/interfaces/token-store.interface.js +3 -0
- package/dist/interfaces/token-store.interface.js.map +1 -0
- package/dist/interfaces/user-metadata-store.interface.d.ts +50 -0
- package/dist/interfaces/user-metadata-store.interface.d.ts.map +1 -0
- package/dist/interfaces/user-metadata-store.interface.js +3 -0
- package/dist/interfaces/user-metadata-store.interface.js.map +1 -0
- package/dist/interfaces/user-store.interface.d.ts +113 -0
- package/dist/interfaces/user-store.interface.d.ts.map +1 -0
- package/dist/interfaces/user-store.interface.js +3 -0
- package/dist/interfaces/user-store.interface.js.map +1 -0
- package/dist/interfaces/webhook-store.interface.d.ts +139 -0
- package/dist/interfaces/webhook-store.interface.d.ts.map +1 -0
- package/dist/interfaces/webhook-store.interface.js +3 -0
- package/dist/interfaces/webhook-store.interface.js.map +1 -0
- package/dist/middleware/api-key.middleware.d.ts +35 -0
- package/dist/middleware/api-key.middleware.d.ts.map +1 -0
- package/dist/middleware/api-key.middleware.js +45 -0
- package/dist/middleware/api-key.middleware.js.map +1 -0
- package/dist/middleware/auth.middleware.d.ts +13 -0
- package/dist/middleware/auth.middleware.d.ts.map +1 -0
- package/dist/middleware/auth.middleware.js +55 -0
- package/dist/middleware/auth.middleware.js.map +1 -0
- package/dist/middleware/jwks-auth.middleware.d.ts +18 -0
- package/dist/middleware/jwks-auth.middleware.d.ts.map +1 -0
- package/dist/middleware/jwks-auth.middleware.js +77 -0
- package/dist/middleware/jwks-auth.middleware.js.map +1 -0
- package/dist/models/api-key.model.d.ts +66 -0
- package/dist/models/api-key.model.d.ts.map +1 -0
- package/dist/models/api-key.model.js +3 -0
- package/dist/models/api-key.model.js.map +1 -0
- package/dist/models/auth-config.model.d.ts +387 -0
- package/dist/models/auth-config.model.d.ts.map +1 -0
- package/dist/models/auth-config.model.js +3 -0
- package/dist/models/auth-config.model.js.map +1 -0
- package/dist/models/errors.d.ts +7 -0
- package/dist/models/errors.d.ts.map +1 -0
- package/dist/models/errors.js +14 -0
- package/dist/models/errors.js.map +1 -0
- package/dist/models/session.model.d.ts +28 -0
- package/dist/models/session.model.d.ts.map +1 -0
- package/dist/models/session.model.js +3 -0
- package/dist/models/session.model.js.map +1 -0
- package/dist/models/tenant.model.d.ts +20 -0
- package/dist/models/tenant.model.d.ts.map +1 -0
- package/dist/models/tenant.model.js +3 -0
- package/dist/models/tenant.model.js.map +1 -0
- package/dist/models/token.model.d.ts +21 -0
- package/dist/models/token.model.d.ts.map +1 -0
- package/dist/models/token.model.js +3 -0
- package/dist/models/token.model.js.map +1 -0
- package/dist/models/user.model.d.ts +92 -0
- package/dist/models/user.model.d.ts.map +1 -0
- package/dist/models/user.model.js +3 -0
- package/dist/models/user.model.js.map +1 -0
- package/dist/router/admin.router.d.ts +188 -0
- package/dist/router/admin.router.d.ts.map +1 -0
- package/dist/router/admin.router.js +1507 -0
- package/dist/router/admin.router.js.map +1 -0
- package/dist/router/auth.router.d.ts +199 -0
- package/dist/router/auth.router.d.ts.map +1 -0
- package/dist/router/auth.router.js +1636 -0
- package/dist/router/auth.router.js.map +1 -0
- package/dist/router/openapi.d.ts +98 -0
- package/dist/router/openapi.d.ts.map +1 -0
- package/dist/router/openapi.js +1518 -0
- package/dist/router/openapi.js.map +1 -0
- package/dist/router/router-events.d.ts +38 -0
- package/dist/router/router-events.d.ts.map +1 -0
- package/dist/router/router-events.js +74 -0
- package/dist/router/router-events.js.map +1 -0
- package/dist/router/tools.router.d.ts +104 -0
- package/dist/router/tools.router.d.ts.map +1 -0
- package/dist/router/tools.router.js +227 -0
- package/dist/router/tools.router.js.map +1 -0
- package/dist/router/ui.router.d.ts +49 -0
- package/dist/router/ui.router.d.ts.map +1 -0
- package/dist/router/ui.router.js +272 -0
- package/dist/router/ui.router.js.map +1 -0
- package/dist/services/api-key.service.d.ts +53 -0
- package/dist/services/api-key.service.d.ts.map +1 -0
- package/dist/services/api-key.service.js +66 -0
- package/dist/services/api-key.service.js.map +1 -0
- package/dist/services/jwks.service.d.ts +73 -0
- package/dist/services/jwks.service.d.ts.map +1 -0
- package/dist/services/jwks.service.js +174 -0
- package/dist/services/jwks.service.js.map +1 -0
- package/dist/services/mailer.service.d.ts +30 -0
- package/dist/services/mailer.service.d.ts.map +1 -0
- package/dist/services/mailer.service.js +248 -0
- package/dist/services/mailer.service.js.map +1 -0
- package/dist/services/notification.service.d.ts +110 -0
- package/dist/services/notification.service.d.ts.map +1 -0
- package/dist/services/notification.service.js +79 -0
- package/dist/services/notification.service.js.map +1 -0
- package/dist/services/password.service.d.ts +5 -0
- package/dist/services/password.service.d.ts.map +1 -0
- package/dist/services/password.service.js +17 -0
- package/dist/services/password.service.js.map +1 -0
- package/dist/services/sms.service.d.ts +14 -0
- package/dist/services/sms.service.d.ts.map +1 -0
- package/dist/services/sms.service.js +51 -0
- package/dist/services/sms.service.js.map +1 -0
- package/dist/services/token.service.d.ts +62 -0
- package/dist/services/token.service.d.ts.map +1 -0
- package/dist/services/token.service.js +354 -0
- package/dist/services/token.service.js.map +1 -0
- package/dist/stores/memory-template.store.d.ts +12 -0
- package/dist/stores/memory-template.store.d.ts.map +1 -0
- package/dist/stores/memory-template.store.js +35 -0
- package/dist/stores/memory-template.store.js.map +1 -0
- package/dist/strategies/api-key/api-key.strategy.d.ts +72 -0
- package/dist/strategies/api-key/api-key.strategy.d.ts.map +1 -0
- package/dist/strategies/api-key/api-key.strategy.js +182 -0
- package/dist/strategies/api-key/api-key.strategy.js.map +1 -0
- package/dist/strategies/local/local.strategy.d.ts +19 -0
- package/dist/strategies/local/local.strategy.d.ts.map +1 -0
- package/dist/strategies/local/local.strategy.js +45 -0
- package/dist/strategies/local/local.strategy.js.map +1 -0
- package/dist/strategies/magic-link/magic-link.strategy.d.ts +8 -0
- package/dist/strategies/magic-link/magic-link.strategy.d.ts.map +1 -0
- package/dist/strategies/magic-link/magic-link.strategy.js +53 -0
- package/dist/strategies/magic-link/magic-link.strategy.js.map +1 -0
- package/dist/strategies/oauth/generic-oauth.strategy.d.ts +120 -0
- package/dist/strategies/oauth/generic-oauth.strategy.d.ts.map +1 -0
- package/dist/strategies/oauth/generic-oauth.strategy.js +88 -0
- package/dist/strategies/oauth/generic-oauth.strategy.js.map +1 -0
- package/dist/strategies/oauth/github.strategy.d.ts +31 -0
- package/dist/strategies/oauth/github.strategy.d.ts.map +1 -0
- package/dist/strategies/oauth/github.strategy.js +72 -0
- package/dist/strategies/oauth/github.strategy.js.map +1 -0
- package/dist/strategies/oauth/google.strategy.d.ts +31 -0
- package/dist/strategies/oauth/google.strategy.d.ts.map +1 -0
- package/dist/strategies/oauth/google.strategy.js +61 -0
- package/dist/strategies/oauth/google.strategy.js.map +1 -0
- package/dist/strategies/sms/sms.strategy.d.ts +7 -0
- package/dist/strategies/sms/sms.strategy.d.ts.map +1 -0
- package/dist/strategies/sms/sms.strategy.js +39 -0
- package/dist/strategies/sms/sms.strategy.js.map +1 -0
- package/dist/strategies/two-factor/totp.strategy.d.ts +12 -0
- package/dist/strategies/two-factor/totp.strategy.d.ts.map +1 -0
- package/dist/strategies/two-factor/totp.strategy.js +32 -0
- package/dist/strategies/two-factor/totp.strategy.js.map +1 -0
- package/dist/tools/auth-tools.d.ts +200 -0
- package/dist/tools/auth-tools.d.ts.map +1 -0
- package/dist/tools/auth-tools.js +232 -0
- package/dist/tools/auth-tools.js.map +1 -0
- package/dist/tools/sse-manager.d.ts +118 -0
- package/dist/tools/sse-manager.d.ts.map +1 -0
- package/dist/tools/sse-manager.js +163 -0
- package/dist/tools/sse-manager.js.map +1 -0
- package/dist/tools/sse-notify.decorator.d.ts +74 -0
- package/dist/tools/sse-notify.decorator.d.ts.map +1 -0
- package/dist/tools/sse-notify.decorator.js +78 -0
- package/dist/tools/sse-notify.decorator.js.map +1 -0
- package/dist/tools/webhook-action.d.ts +130 -0
- package/dist/tools/webhook-action.d.ts.map +1 -0
- package/dist/tools/webhook-action.js +144 -0
- package/dist/tools/webhook-action.js.map +1 -0
- package/dist/tools/webhook-sender.d.ts +31 -0
- package/dist/tools/webhook-sender.d.ts.map +1 -0
- package/dist/tools/webhook-sender.js +80 -0
- package/dist/tools/webhook-sender.js.map +1 -0
- package/dist/ui-assets/2fa.html +115 -0
- package/dist/ui-assets/account-conflict.html +108 -0
- package/dist/ui-assets/admin.css +263 -0
- package/dist/ui-assets/admin.js +1927 -0
- package/dist/ui-assets/auth.js +725 -0
- package/dist/ui-assets/base.css +219 -0
- package/dist/ui-assets/forgot-password.html +93 -0
- package/dist/ui-assets/link-verify.html +74 -0
- package/dist/ui-assets/login.html +135 -0
- package/dist/ui-assets/magic-link.html +112 -0
- package/dist/ui-assets/register.html +122 -0
- package/dist/ui-assets/reset-password.html +103 -0
- package/dist/ui-assets/ui-i18n-keys.json +78 -0
- package/dist/ui-assets/verify-email.html +66 -0
- package/package.json +89 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthTools = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
const sse_manager_1 = require("./sse-manager");
|
|
6
|
+
const webhook_sender_1 = require("./webhook-sender");
|
|
7
|
+
const sse_notify_decorator_1 = require("./sse-notify.decorator");
|
|
8
|
+
const notification_service_1 = require("../services/notification.service");
|
|
9
|
+
/**
|
|
10
|
+
* The main tools module.
|
|
11
|
+
*
|
|
12
|
+
* Provides a unified API for telemetry tracking, real-time SSE notifications,
|
|
13
|
+
* and outgoing webhooks. All capabilities are optional and have zero overhead
|
|
14
|
+
* when disabled.
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { AuthTools, AuthEventBus } from '@awesome-lang-auth/node';
|
|
18
|
+
*
|
|
19
|
+
* const bus = new AuthEventBus();
|
|
20
|
+
* const tools = new AuthTools(bus, {
|
|
21
|
+
* telemetryStore: myStore,
|
|
22
|
+
* webhookStore: myWebhookStore,
|
|
23
|
+
* sse: true,
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Track an event programmatically
|
|
27
|
+
* await tools.track('identity.auth.login.success', { user }, { userId: user.id });
|
|
28
|
+
*
|
|
29
|
+
* // Notify a topic over SSE
|
|
30
|
+
* await tools.notify('user:123', { message: 'Welcome!' });
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
class AuthTools {
|
|
34
|
+
constructor(eventBus, options = {}) {
|
|
35
|
+
this.eventBus = eventBus;
|
|
36
|
+
this.telemetryStore = options.telemetryStore;
|
|
37
|
+
this.webhookStore = options.webhookStore;
|
|
38
|
+
this.webhookSender = new webhook_sender_1.WebhookSender();
|
|
39
|
+
this.webhookVersion = options.webhookVersion ?? '1';
|
|
40
|
+
this.sseManager = options.sse ? new sse_manager_1.SseManager(options.sseOptions) : null;
|
|
41
|
+
this.sseDistributor = options.sseDistributor;
|
|
42
|
+
this.userStore = options.userStore;
|
|
43
|
+
if (options.sse && options.sseDistributor) {
|
|
44
|
+
process.stderr.write('[awesome-node-auth] WARN: AuthTools received both sse=true and sseDistributor; notify() will use the custom distributor.\n');
|
|
45
|
+
}
|
|
46
|
+
if (options.emailConfig || options.smsConfig) {
|
|
47
|
+
this.notificationService = new notification_service_1.NotificationService({
|
|
48
|
+
email: options.emailConfig,
|
|
49
|
+
sms: options.smsConfig,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (this.sseManager) {
|
|
53
|
+
sse_notify_decorator_1.SseNotifyRegistry.setManager(this.sseManager);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Track an event: persist it (optional), emit it on the event bus, broadcast
|
|
58
|
+
* it to SSE subscribers and fire matching outgoing webhooks.
|
|
59
|
+
*
|
|
60
|
+
* @param eventName Standardised event name (see `AuthEventNames`).
|
|
61
|
+
* @param data Arbitrary event data.
|
|
62
|
+
* @param options Metadata (userId, tenantId, …).
|
|
63
|
+
*/
|
|
64
|
+
async track(eventName, data, options = {}) {
|
|
65
|
+
const id = (0, crypto_1.randomUUID)();
|
|
66
|
+
const timestamp = new Date().toISOString();
|
|
67
|
+
const telemetryEvent = {
|
|
68
|
+
id,
|
|
69
|
+
event: eventName,
|
|
70
|
+
timestamp,
|
|
71
|
+
data,
|
|
72
|
+
userId: options.userId,
|
|
73
|
+
tenantId: options.tenantId,
|
|
74
|
+
sessionId: options.sessionId,
|
|
75
|
+
correlationId: options.correlationId,
|
|
76
|
+
ip: options.ip,
|
|
77
|
+
userAgent: options.userAgent,
|
|
78
|
+
};
|
|
79
|
+
// 1. Persist
|
|
80
|
+
if (this.telemetryStore) {
|
|
81
|
+
await this.telemetryStore.save(telemetryEvent).catch(() => { });
|
|
82
|
+
}
|
|
83
|
+
// 2. Emit on the event bus
|
|
84
|
+
const busPayload = {
|
|
85
|
+
data,
|
|
86
|
+
userId: options.userId,
|
|
87
|
+
tenantId: options.tenantId,
|
|
88
|
+
sessionId: options.sessionId,
|
|
89
|
+
correlationId: options.correlationId,
|
|
90
|
+
ip: options.ip,
|
|
91
|
+
userAgent: options.userAgent,
|
|
92
|
+
};
|
|
93
|
+
this.eventBus.publish(eventName, busPayload);
|
|
94
|
+
// 3. SSE broadcast (topic per tenant or global)
|
|
95
|
+
if (this.sseManager) {
|
|
96
|
+
const topics = this.resolveTopics(eventName, options);
|
|
97
|
+
const streamEvent = {
|
|
98
|
+
id,
|
|
99
|
+
timestamp,
|
|
100
|
+
type: eventName,
|
|
101
|
+
data: telemetryEvent,
|
|
102
|
+
userId: options.userId,
|
|
103
|
+
tenantId: options.tenantId,
|
|
104
|
+
};
|
|
105
|
+
for (const topic of topics) {
|
|
106
|
+
this.sseManager.broadcast(topic, streamEvent);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// 4. Outgoing webhooks
|
|
110
|
+
if (this.webhookStore) {
|
|
111
|
+
const configs = await this.webhookStore.findByEvent(eventName, options.tenantId).catch(() => []);
|
|
112
|
+
const webhookEvent = {
|
|
113
|
+
event: eventName,
|
|
114
|
+
version: this.webhookVersion,
|
|
115
|
+
timestamp,
|
|
116
|
+
data: data ?? null,
|
|
117
|
+
metadata: {
|
|
118
|
+
userId: options.userId,
|
|
119
|
+
tenantId: options.tenantId,
|
|
120
|
+
sessionId: options.sessionId,
|
|
121
|
+
correlationId: options.correlationId,
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
for (const config of configs) {
|
|
125
|
+
// Fire-and-forget; don't let webhook failures block the caller
|
|
126
|
+
this.webhookSender.send(config, webhookEvent).catch(() => { });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Send a notification to one or more delivery channels.
|
|
132
|
+
*
|
|
133
|
+
* By default (or when `channels` is `['sse']`) the behaviour is identical to
|
|
134
|
+
* the original synchronous broadcast. Pass additional channels to also
|
|
135
|
+
* deliver the notification via email and/or SMS.
|
|
136
|
+
*
|
|
137
|
+
* When `'email'` or `'sms'` is included the method becomes asynchronous and
|
|
138
|
+
* requires:
|
|
139
|
+
* - `userStore` — to look up the user's contact details by `options.userId`.
|
|
140
|
+
* - `emailConfig` / `smsConfig` — transport configuration in
|
|
141
|
+
* {@link AuthToolsOptions}.
|
|
142
|
+
*
|
|
143
|
+
* Channel failures are best-effort and do not reject the returned Promise.
|
|
144
|
+
*
|
|
145
|
+
* @param target Target SSE topic (e.g. `'user:123'`, `'tenant:acme'`).
|
|
146
|
+
* @param data Payload to deliver.
|
|
147
|
+
* @param options Channels, type, tenantId, userId, metadata, etc.
|
|
148
|
+
*
|
|
149
|
+
* @since 1.8.0 (async + multi-channel)
|
|
150
|
+
*/
|
|
151
|
+
async notify(target, data, options = {}) {
|
|
152
|
+
const channels = options.channels ?? ['sse'];
|
|
153
|
+
// ── 1. SSE ──────────────────────────────────────────────────────────────
|
|
154
|
+
if (channels.includes('sse')) {
|
|
155
|
+
const streamEvent = {
|
|
156
|
+
type: options.type ?? 'notification',
|
|
157
|
+
data,
|
|
158
|
+
tenantId: options.tenantId,
|
|
159
|
+
userId: options.userId,
|
|
160
|
+
metadata: options.metadata,
|
|
161
|
+
};
|
|
162
|
+
if (this.sseDistributor) {
|
|
163
|
+
// Publish a complete StreamEvent, as SseManager.broadcast() does:
|
|
164
|
+
// receivers (SseManager included) deduplicate on `id`.
|
|
165
|
+
const fullEvent = {
|
|
166
|
+
id: (0, crypto_1.randomUUID)(),
|
|
167
|
+
timestamp: new Date().toISOString(),
|
|
168
|
+
topic: target,
|
|
169
|
+
...streamEvent,
|
|
170
|
+
};
|
|
171
|
+
this.sseDistributor.publish(target, fullEvent).catch(() => { });
|
|
172
|
+
}
|
|
173
|
+
else if (this.sseManager) {
|
|
174
|
+
this.sseManager.broadcast(target, streamEvent);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
// ── 2. Email / SMS (only when userId is provided and userStore is set) ───
|
|
178
|
+
if ((channels.includes('email') || channels.includes('sms')) && options.userId && this.userStore) {
|
|
179
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
180
|
+
let user = null;
|
|
181
|
+
try {
|
|
182
|
+
user = await this.userStore.findById(options.userId);
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
user = null;
|
|
186
|
+
}
|
|
187
|
+
if (user) {
|
|
188
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
189
|
+
const u = user;
|
|
190
|
+
// ── 2a. Email ─────────────────────────────────────────────────────
|
|
191
|
+
if (channels.includes('email') && u.email && this.notificationService?.hasEmail) {
|
|
192
|
+
const subject = options.emailSubject ?? (options.type ? String(options.type) : 'Notification');
|
|
193
|
+
const body = typeof data === 'string' ? data : JSON.stringify(data, null, 2);
|
|
194
|
+
this.notificationService.sendEmail({
|
|
195
|
+
to: u.email,
|
|
196
|
+
subject,
|
|
197
|
+
html: `<p>${body.replace(/\n/g, '<br>')}</p>`,
|
|
198
|
+
text: body,
|
|
199
|
+
}).catch(() => { });
|
|
200
|
+
}
|
|
201
|
+
// ── 2b. SMS ───────────────────────────────────────────────────────
|
|
202
|
+
if (channels.includes('sms') && u.phoneNumber && this.notificationService?.hasSms) {
|
|
203
|
+
const message = options.smsMessage ?? (typeof data === 'string' ? data : JSON.stringify(data));
|
|
204
|
+
this.notificationService.sendSms({
|
|
205
|
+
to: u.phoneNumber,
|
|
206
|
+
message,
|
|
207
|
+
}).catch(() => { });
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// ---------------------------------------------------------------------------
|
|
213
|
+
// Helpers
|
|
214
|
+
// ---------------------------------------------------------------------------
|
|
215
|
+
/**
|
|
216
|
+
* Resolve the SSE topics an event should be broadcast to.
|
|
217
|
+
* Always includes `'global'`; additionally adds tenant and user topics when
|
|
218
|
+
* the corresponding IDs are present.
|
|
219
|
+
*/
|
|
220
|
+
resolveTopics(eventName, options) {
|
|
221
|
+
const topics = ['global'];
|
|
222
|
+
if (options.tenantId)
|
|
223
|
+
topics.push(`tenant:${options.tenantId}`);
|
|
224
|
+
if (options.userId)
|
|
225
|
+
topics.push(`user:${options.userId}`);
|
|
226
|
+
if (options.sessionId)
|
|
227
|
+
topics.push(`session:${options.sessionId}`);
|
|
228
|
+
return topics;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
exports.AuthTools = AuthTools;
|
|
232
|
+
//# sourceMappingURL=auth-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-tools.js","sourceRoot":"","sources":["../../src/tools/auth-tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { Response } from 'express';
|
|
2
|
+
import { ISseDistributor } from '../interfaces/sse-distributor.interface';
|
|
3
|
+
/**
|
|
4
|
+
* A single real-time SSE event delivered to subscribers.
|
|
5
|
+
*/
|
|
6
|
+
export interface StreamEvent<T = unknown> {
|
|
7
|
+
/** Unique event identifier (auto-generated if not provided). */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Event type / name. */
|
|
10
|
+
type: string;
|
|
11
|
+
/** ISO 8601 timestamp. */
|
|
12
|
+
timestamp: string;
|
|
13
|
+
/** Topic / channel this event was published to. */
|
|
14
|
+
topic: string;
|
|
15
|
+
/** Arbitrary event data. */
|
|
16
|
+
data: T;
|
|
17
|
+
/** User ID (optional). */
|
|
18
|
+
userId?: string;
|
|
19
|
+
/** Tenant ID (optional). */
|
|
20
|
+
tenantId?: string;
|
|
21
|
+
/** Optional extra metadata. */
|
|
22
|
+
metadata?: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Options for the {@link SseManager}.
|
|
26
|
+
*/
|
|
27
|
+
export interface SseManagerOptions {
|
|
28
|
+
/**
|
|
29
|
+
* Interval in milliseconds between heartbeat comments (`:heartbeat`).
|
|
30
|
+
* Set to `0` to disable heartbeats.
|
|
31
|
+
* @default 30000
|
|
32
|
+
*/
|
|
33
|
+
heartbeatIntervalMs?: number;
|
|
34
|
+
/**
|
|
35
|
+
* Optional distributor for cross-instance event synchronization.
|
|
36
|
+
* Required for horizontal scaling.
|
|
37
|
+
*/
|
|
38
|
+
distributor?: ISseDistributor;
|
|
39
|
+
/**
|
|
40
|
+
* When `true` (default), events with the same ID are deduplicated per connection.
|
|
41
|
+
* This prevents clients from receiving the same event multiple times when
|
|
42
|
+
* subscribed to multiple matching topics.
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
deduplicate?: boolean;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Manages Server-Sent Events connections.
|
|
49
|
+
*
|
|
50
|
+
* Tracks open HTTP streams and broadcasts `StreamEvent` objects to all
|
|
51
|
+
* subscribers matching a given topic. Topics follow the hierarchical
|
|
52
|
+
* channel scheme:
|
|
53
|
+
*
|
|
54
|
+
* ```
|
|
55
|
+
* global
|
|
56
|
+
* tenant:{tenantId}
|
|
57
|
+
* tenant:{tenantId}:role:{role}
|
|
58
|
+
* tenant:{tenantId}:group:{groupId}
|
|
59
|
+
* user:{userId}
|
|
60
|
+
* session:{sessionId}
|
|
61
|
+
* custom:{namespace}
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* The server controls which topics a connection is allowed to subscribe to —
|
|
65
|
+
* clients cannot self-declare channels.
|
|
66
|
+
*/
|
|
67
|
+
export declare class SseManager {
|
|
68
|
+
private connections;
|
|
69
|
+
private readonly distributor?;
|
|
70
|
+
/**
|
|
71
|
+
* Interval in milliseconds between heartbeat comments (`:heartbeat`).
|
|
72
|
+
* Set to `0` to disable heartbeats.
|
|
73
|
+
* @default 30000
|
|
74
|
+
*/
|
|
75
|
+
readonly heartbeatIntervalMs: number;
|
|
76
|
+
/**
|
|
77
|
+
* Whether to deduplicate events by ID per connection.
|
|
78
|
+
*/
|
|
79
|
+
readonly deduplicate: boolean;
|
|
80
|
+
constructor(options?: SseManagerOptions);
|
|
81
|
+
/**
|
|
82
|
+
* Attach an SSE response to a new connection and register its authorised
|
|
83
|
+
* topics.
|
|
84
|
+
*
|
|
85
|
+
* @param res The HTTP response to write events to.
|
|
86
|
+
* @param topics Topics this connection may receive (enforced server-side).
|
|
87
|
+
* @param meta Optional user / tenant context.
|
|
88
|
+
* @returns The generated connection ID.
|
|
89
|
+
*/
|
|
90
|
+
connect(res: Response, topics: string[], meta?: {
|
|
91
|
+
userId?: string;
|
|
92
|
+
tenantId?: string;
|
|
93
|
+
}): string;
|
|
94
|
+
/**
|
|
95
|
+
* Broadcast a `StreamEvent` to all connections subscribed to `topic`.
|
|
96
|
+
* If a distributor is configured, the event is published to it for
|
|
97
|
+
* cross-instance delivery.
|
|
98
|
+
*/
|
|
99
|
+
broadcast<T = unknown>(topic: string, event: Omit<StreamEvent<T>, 'id' | 'timestamp' | 'topic'> & {
|
|
100
|
+
id?: string;
|
|
101
|
+
timestamp?: string;
|
|
102
|
+
}): void;
|
|
103
|
+
/**
|
|
104
|
+
* Broadcast an event to ONLY the local connections.
|
|
105
|
+
* This is typically called by the distributor's subscription callback.
|
|
106
|
+
*/
|
|
107
|
+
private broadcastLocal;
|
|
108
|
+
/**
|
|
109
|
+
* Close and remove a connection by its ID.
|
|
110
|
+
*/
|
|
111
|
+
disconnect(connectionId: string): void;
|
|
112
|
+
/**
|
|
113
|
+
* Number of currently open connections.
|
|
114
|
+
*/
|
|
115
|
+
get connectionCount(): number;
|
|
116
|
+
private write;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=sse-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-manager.d.ts","sourceRoot":"","sources":["../../src/tools/sse-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAEnC,OAAO,EAAE,eAAe,EAAE,MAAM,yCAAyC,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,OAAO;IACtC,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IACX,yBAAyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,4BAA4B;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,0BAA0B;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAiBD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B;;;OAGG;IACH,WAAW,CAAC,EAAE,eAAe,CAAC;IAE9B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,WAAW,CAAoC;IACvD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAkB;IAE/C;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;gBAElB,OAAO,CAAC,EAAE,iBAAiB;IAYvC;;;;;;;;OAQG;IACH,OAAO,CACL,GAAG,EAAE,QAAQ,EACb,MAAM,EAAE,MAAM,EAAE,EAChB,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5C,MAAM;IA6CT;;;;OAIG;IACH,SAAS,CAAC,CAAC,GAAG,OAAO,EACnB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,CAAC,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,GAC9F,IAAI;IAkBP;;;OAGG;IACH,OAAO,CAAC,cAAc;IAmBtB;;OAEG;IACH,UAAU,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI;IAYtC;;OAEG;IACH,IAAI,eAAe,IAAI,MAAM,CAE5B;IAMD,OAAO,CAAC,KAAK;CAKd"}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SseManager = void 0;
|
|
4
|
+
const crypto_1 = require("crypto");
|
|
5
|
+
/**
|
|
6
|
+
* Manages Server-Sent Events connections.
|
|
7
|
+
*
|
|
8
|
+
* Tracks open HTTP streams and broadcasts `StreamEvent` objects to all
|
|
9
|
+
* subscribers matching a given topic. Topics follow the hierarchical
|
|
10
|
+
* channel scheme:
|
|
11
|
+
*
|
|
12
|
+
* ```
|
|
13
|
+
* global
|
|
14
|
+
* tenant:{tenantId}
|
|
15
|
+
* tenant:{tenantId}:role:{role}
|
|
16
|
+
* tenant:{tenantId}:group:{groupId}
|
|
17
|
+
* user:{userId}
|
|
18
|
+
* session:{sessionId}
|
|
19
|
+
* custom:{namespace}
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* The server controls which topics a connection is allowed to subscribe to —
|
|
23
|
+
* clients cannot self-declare channels.
|
|
24
|
+
*/
|
|
25
|
+
class SseManager {
|
|
26
|
+
constructor(options) {
|
|
27
|
+
this.connections = new Map();
|
|
28
|
+
this.heartbeatIntervalMs = options?.heartbeatIntervalMs ?? 30000;
|
|
29
|
+
this.deduplicate = options?.deduplicate !== false;
|
|
30
|
+
this.distributor = options?.distributor;
|
|
31
|
+
if (this.distributor) {
|
|
32
|
+
this.distributor.subscribe((topic, event) => {
|
|
33
|
+
this.broadcastLocal(topic, event);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Attach an SSE response to a new connection and register its authorised
|
|
39
|
+
* topics.
|
|
40
|
+
*
|
|
41
|
+
* @param res The HTTP response to write events to.
|
|
42
|
+
* @param topics Topics this connection may receive (enforced server-side).
|
|
43
|
+
* @param meta Optional user / tenant context.
|
|
44
|
+
* @returns The generated connection ID.
|
|
45
|
+
*/
|
|
46
|
+
connect(res, topics, meta) {
|
|
47
|
+
const id = (0, crypto_1.randomUUID)();
|
|
48
|
+
// SSE headers
|
|
49
|
+
res.setHeader('Content-Type', 'text/event-stream');
|
|
50
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
51
|
+
res.setHeader('Connection', 'keep-alive');
|
|
52
|
+
res.setHeader('X-Accel-Buffering', 'no');
|
|
53
|
+
res.flushHeaders?.();
|
|
54
|
+
// Send initial connection event
|
|
55
|
+
this.write(res, {
|
|
56
|
+
id: (0, crypto_1.randomUUID)(),
|
|
57
|
+
type: 'connected',
|
|
58
|
+
timestamp: new Date().toISOString(),
|
|
59
|
+
topic: 'meta',
|
|
60
|
+
data: { connectionId: id, topics },
|
|
61
|
+
});
|
|
62
|
+
const conn = {
|
|
63
|
+
id,
|
|
64
|
+
res,
|
|
65
|
+
topics: new Set(topics),
|
|
66
|
+
userId: meta?.userId,
|
|
67
|
+
tenantId: meta?.tenantId,
|
|
68
|
+
};
|
|
69
|
+
if (this.heartbeatIntervalMs > 0) {
|
|
70
|
+
conn.heartbeatTimer = setInterval(() => {
|
|
71
|
+
try {
|
|
72
|
+
res.write(': heartbeat\n\n');
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
this.disconnect(id);
|
|
76
|
+
}
|
|
77
|
+
}, this.heartbeatIntervalMs);
|
|
78
|
+
}
|
|
79
|
+
this.connections.set(id, conn);
|
|
80
|
+
// Clean up when the client disconnects
|
|
81
|
+
res.on('close', () => this.disconnect(id));
|
|
82
|
+
return id;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Broadcast a `StreamEvent` to all connections subscribed to `topic`.
|
|
86
|
+
* If a distributor is configured, the event is published to it for
|
|
87
|
+
* cross-instance delivery.
|
|
88
|
+
*/
|
|
89
|
+
broadcast(topic, event) {
|
|
90
|
+
const full = {
|
|
91
|
+
id: event.id ?? (0, crypto_1.randomUUID)(),
|
|
92
|
+
timestamp: event.timestamp ?? new Date().toISOString(),
|
|
93
|
+
topic,
|
|
94
|
+
...event,
|
|
95
|
+
};
|
|
96
|
+
if (this.distributor) {
|
|
97
|
+
this.distributor.publish(topic, full).catch(() => {
|
|
98
|
+
// Fallback to local broadcast if distribution fails
|
|
99
|
+
this.broadcastLocal(topic, full);
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
this.broadcastLocal(topic, full);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Broadcast an event to ONLY the local connections.
|
|
108
|
+
* This is typically called by the distributor's subscription callback.
|
|
109
|
+
*/
|
|
110
|
+
broadcastLocal(topic, event) {
|
|
111
|
+
for (const conn of this.connections.values()) {
|
|
112
|
+
if (!conn.topics.has(topic))
|
|
113
|
+
continue;
|
|
114
|
+
// Tenant isolation: if the event has a tenantId the connection must
|
|
115
|
+
// belong to the same tenant (unless it is a global connection with no
|
|
116
|
+
// tenantId set).
|
|
117
|
+
if (event.tenantId && conn.tenantId && conn.tenantId !== event.tenantId)
|
|
118
|
+
continue;
|
|
119
|
+
try {
|
|
120
|
+
if (this.deduplicate && event.id === conn.lastEventId)
|
|
121
|
+
continue;
|
|
122
|
+
conn.lastEventId = event.id;
|
|
123
|
+
this.write(conn.res, event);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
this.disconnect(conn.id);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Close and remove a connection by its ID.
|
|
132
|
+
*/
|
|
133
|
+
disconnect(connectionId) {
|
|
134
|
+
const conn = this.connections.get(connectionId);
|
|
135
|
+
if (!conn)
|
|
136
|
+
return;
|
|
137
|
+
if (conn.heartbeatTimer)
|
|
138
|
+
clearInterval(conn.heartbeatTimer);
|
|
139
|
+
this.connections.delete(connectionId);
|
|
140
|
+
try {
|
|
141
|
+
conn.res.end();
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
// already closed
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Number of currently open connections.
|
|
149
|
+
*/
|
|
150
|
+
get connectionCount() {
|
|
151
|
+
return this.connections.size;
|
|
152
|
+
}
|
|
153
|
+
// ---------------------------------------------------------------------------
|
|
154
|
+
// Private helpers
|
|
155
|
+
// ---------------------------------------------------------------------------
|
|
156
|
+
write(res, event) {
|
|
157
|
+
res.write(`id: ${event.id}\n`);
|
|
158
|
+
res.write(`event: ${event.type}\n`);
|
|
159
|
+
res.write(`data: ${JSON.stringify({ ...event, data: undefined, rawData: event.data })}\n\n`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.SseManager = SseManager;
|
|
163
|
+
//# sourceMappingURL=sse-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-manager.js","sourceRoot":"","sources":["../../src/tools/sse-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { SseManager } from './sse-manager';
|
|
2
|
+
/**
|
|
3
|
+
* Options for the `@sseNotify` decorator.
|
|
4
|
+
*/
|
|
5
|
+
export interface SseNotifyOptions {
|
|
6
|
+
/**
|
|
7
|
+
* The SSE topic to broadcast to. Can be a static string or a function
|
|
8
|
+
* that resolves the topic based on method arguments and execution result.
|
|
9
|
+
*/
|
|
10
|
+
topic: string | ((args: any[], result: any) => string);
|
|
11
|
+
/**
|
|
12
|
+
* The event type name. Defaults to `'notification'`.
|
|
13
|
+
*/
|
|
14
|
+
event?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Optional payload transformer. By default, the method's return value is sent.
|
|
17
|
+
*/
|
|
18
|
+
payload?: (result: any, args: any[]) => any;
|
|
19
|
+
/**
|
|
20
|
+
* Optional tenant ID resolver.
|
|
21
|
+
*/
|
|
22
|
+
tenantId?: (result: any, args: any[]) => string | undefined;
|
|
23
|
+
/**
|
|
24
|
+
* Optional user ID resolver.
|
|
25
|
+
*/
|
|
26
|
+
userId?: (result: any, args: any[]) => string | undefined;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Global registry and dispatcher for decorated SSE notifications.
|
|
30
|
+
*/
|
|
31
|
+
export declare class SseNotifyRegistry {
|
|
32
|
+
private static manager;
|
|
33
|
+
/**
|
|
34
|
+
* Set the active SSE manager used for broadcasts. Should be called
|
|
35
|
+
* during application initialization.
|
|
36
|
+
*/
|
|
37
|
+
static setManager(manager: SseManager | null): void;
|
|
38
|
+
/**
|
|
39
|
+
* Perform a broadcast if a manager is registered.
|
|
40
|
+
*/
|
|
41
|
+
static notify(topic: string, event: {
|
|
42
|
+
type: string;
|
|
43
|
+
data: any;
|
|
44
|
+
tenantId?: string;
|
|
45
|
+
userId?: string;
|
|
46
|
+
}): void;
|
|
47
|
+
/**
|
|
48
|
+
* Internal helper to execute notification logic.
|
|
49
|
+
* Can be called manually to bypass decorators.
|
|
50
|
+
*/
|
|
51
|
+
static executeNotify(options: SseNotifyOptions, args: any[], result: any): Promise<void>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Method decorator that automatically triggers an SSE broadcast after
|
|
55
|
+
* successful execution.
|
|
56
|
+
*
|
|
57
|
+
* Uses the **TC39 Stage 3** decorator syntax (TypeScript 5.x+).
|
|
58
|
+
* For legacy environments, use manual notification via `SseNotifyRegistry.notify()`.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```ts
|
|
62
|
+
* class UserService {
|
|
63
|
+
* @sseNotify({
|
|
64
|
+
* topic: (_args, user) => `user:${user.id}`,
|
|
65
|
+
* event: 'user.updated',
|
|
66
|
+
* })
|
|
67
|
+
* async updateProfile(userId: string, data: any) {
|
|
68
|
+
* return await db.users.update(userId, data);
|
|
69
|
+
* }
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function sseNotify(options: SseNotifyOptions): <This, Args extends unknown[], Return>(target: (this: This, ...args: Args) => Promise<Return> | Return, _context: ClassMethodDecoratorContext<This, (this: This, ...args: Args) => Promise<Return> | Return>) => (this: This, ...args: Args) => Promise<Return>;
|
|
74
|
+
//# sourceMappingURL=sse-notify.decorator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sse-notify.decorator.d.ts","sourceRoot":"","sources":["../../src/tools/sse-notify.decorator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,GAAG,KAAK,MAAM,CAAC,CAAC;IAEvD;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,CAAC;IAE5C;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,GAAG,SAAS,CAAC;IAE5D;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,MAAM,GAAG,SAAS,CAAC;CAC7D;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC1B,OAAO,CAAC,MAAM,CAAC,OAAO,CAA2B;IAEjD;;;OAGG;IACH,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI;IAInD;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,GAAG,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAK1G;;;OAGG;WACU,aAAa,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;CAkBjG;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,gBAAgB,IAC9B,IAAI,EAAE,IAAI,SAAS,OAAO,EAAE,EAAE,MAAM,EACjD,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,EAC/D,UAAU,2BAA2B,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,MAE7E,MAAM,IAAI,EAAE,GAAG,MAAM,IAAI,KAAG,OAAO,CAAC,MAAM,CAAC,CAMzE"}
|