mongodb-dynamic-api 4.8.0 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +1 -0
  3. package/package.json +2 -1
  4. package/src/index.d.ts +2 -0
  5. package/src/index.js +2 -0
  6. package/src/index.js.map +1 -1
  7. package/src/interfaces/dynamic-api-presence.interface.d.ts +22 -0
  8. package/src/interfaces/dynamic-api-presence.interface.js +6 -0
  9. package/src/interfaces/dynamic-api-presence.interface.js.map +1 -0
  10. package/src/interfaces/index.d.ts +1 -0
  11. package/src/interfaces/index.js +1 -0
  12. package/src/interfaces/index.js.map +1 -1
  13. package/src/modules/presence/adapters/in-memory-presence.adapter.d.ts +10 -0
  14. package/src/modules/presence/adapters/in-memory-presence.adapter.js +64 -0
  15. package/src/modules/presence/adapters/in-memory-presence.adapter.js.map +1 -0
  16. package/src/modules/presence/adapters/redis-presence.adapter.d.ts +17 -0
  17. package/src/modules/presence/adapters/redis-presence.adapter.js +80 -0
  18. package/src/modules/presence/adapters/redis-presence.adapter.js.map +1 -0
  19. package/src/modules/presence/index.d.ts +5 -0
  20. package/src/modules/presence/index.js +22 -0
  21. package/src/modules/presence/index.js.map +1 -0
  22. package/src/modules/presence/presence.controller.d.ts +6 -0
  23. package/src/modules/presence/presence.controller.js +55 -0
  24. package/src/modules/presence/presence.controller.js.map +1 -0
  25. package/src/modules/presence/presence.gateway.d.ts +13 -0
  26. package/src/modules/presence/presence.gateway.js +79 -0
  27. package/src/modules/presence/presence.gateway.js.map +1 -0
  28. package/src/modules/presence/presence.module.d.ts +5 -0
  29. package/src/modules/presence/presence.module.js +50 -0
  30. package/src/modules/presence/presence.module.js.map +1 -0
  31. package/src/version.json +1 -1
  32. package/test/for-feature/presence.e2e-spec.d.ts +1 -0
  33. package/test/for-feature/presence.e2e-spec.js +169 -0
  34. package/test/for-feature/presence.e2e-spec.js.map +1 -0
  35. package/tsconfig.tsbuildinfo +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  Changelog
2
2
 
3
+ ## [4.9.0](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v4.8.0...v4.9.0) (2026-05-25)
4
+
5
+ ### presence
6
+
7
+ * **presence:** add @Public() to PresenceController and fix e2e race conditions ([6245e6d](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/6245e6d265d6a086d3aa6813df3c1cd71fa7303d))
8
+ * **presence:** add DynamicApiPresenceModule with pluggable adapters ([5957c54](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/5957c54b62664f5861123468f50068861aff7b78))
9
+ * **presence:** break circular dependency by moving presence out of modules barrel ([51fad6a](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/51fad6a7fe8b7dd3472bbd27fd25ff6f70a80267))
10
+ * **presence:** replace String(err) with JSON.stringify in gateway error handler ([8dcaa04](https://github.com/MikeDev75015/mongodb-dynamic-api/commit/8dcaa04499ef0dbacb988b9a0acddbf463ac68be))
11
+
3
12
  ## [4.8.0](https://github.com/MikeDev75015/mongodb-dynamic-api/compare/v4.7.0...v4.8.0) (2026-05-24)
4
13
 
5
14
  ### cascade
package/README.md CHANGED
@@ -895,6 +895,7 @@ Explore advanced features and configurations:
895
895
  | 🔐 **Authentication** | JWT dual-token auth (8 endpoints) — access + refresh tokens, cookie mode, server-side revocation | [View Guide](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/main/README/authentication.md) |
896
896
  | 🛡️ **Authorization** | Role-based access control | [View Guide](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/main/README/authorization.md) |
897
897
  | 📡 **WebSockets** | Socket.IO integration for routes | [View Guide](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/main/README/websockets.md) |
898
+ | 🟢 **Presence** | Real-time online/offline tracking for WebSocket users | [View Guide](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/main/README/presence.md) |
898
899
  | 🗂️ **Route Configuration** | All route options: DTOs, interceptors, etc. | [View Guide](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/main/README/route-config.md) |
899
900
  | 🔁 **Callbacks** | beforeSave / afterSave hooks, typed contexts, user access, audit trails | [View Guide](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/main/README/callbacks.md) |
900
901
  | 🎛️ **Controller Configuration** | All `controllerOptions` and `forFeature` options | [View Guide](https://github.com/MikeDev75015/mongodb-dynamic-api/blob/main/README/controller-config.md) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mongodb-dynamic-api",
3
- "version": "4.8.0",
3
+ "version": "4.9.0",
4
4
  "description": "Auto generated CRUD API for MongoDB using NestJS",
5
5
  "readmeFilename": "README.md",
6
6
  "main": "index.js",
@@ -57,6 +57,7 @@
57
57
  "class-validator": "^0.14.1",
58
58
  "cookie-parser": "^1.4.7",
59
59
  "dotenv": "^16.4.5",
60
+ "ioredis": "^5.10.1",
60
61
  "mongodb-pipeline-builder": "^4.0.2",
61
62
  "mongoose": "^8.9.5",
62
63
  "passport": "^0.7.0",
package/src/index.d.ts CHANGED
@@ -10,6 +10,8 @@ export * from './interfaces';
10
10
  export * from './logger';
11
11
  export * from './mixins';
12
12
  export * from './models';
13
+ export * from './modules';
14
+ export * from './modules/presence';
13
15
  export * from './routes';
14
16
  export * from './services';
15
17
  export * from './utils';
package/src/index.js CHANGED
@@ -27,6 +27,8 @@ __exportStar(require("./interfaces"), exports);
27
27
  __exportStar(require("./logger"), exports);
28
28
  __exportStar(require("./mixins"), exports);
29
29
  __exportStar(require("./models"), exports);
30
+ __exportStar(require("./modules"), exports);
31
+ __exportStar(require("./modules/presence"), exports);
30
32
  __exportStar(require("./routes"), exports);
31
33
  __exportStar(require("./services"), exports);
32
34
  __exportStar(require("./utils"), exports);
package/src/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../libs/dynamic-api/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,+CAA6B;AAC7B,yCAAuB;AACvB,4CAA0B;AAC1B,6CAA2B;AAC3B,2CAAyB;AACzB,4CAA0B;AAC1B,iDAA+B;AAC/B,+CAA6B;AAC7B,2CAAyB;AACzB,2CAAyB;AACzB,2CAAyB;AACzB,2CAAyB;AACzB,6CAA2B;AAC3B,0CAAwB;AACxB,uDAAqC;AACrC,gFAAsG;AAAvE,iIAAA,uBAAuB,OAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../libs/dynamic-api/src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,6CAA2B;AAC3B,+CAA6B;AAC7B,yCAAuB;AACvB,4CAA0B;AAC1B,6CAA2B;AAC3B,2CAAyB;AACzB,4CAA0B;AAC1B,iDAA+B;AAC/B,+CAA6B;AAC7B,2CAAyB;AACzB,2CAAyB;AACzB,2CAAyB;AACzB,4CAA0B;AAC1B,qDAAmC;AACnC,2CAAyB;AACzB,6CAA2B;AAC3B,0CAAwB;AACxB,uDAAqC;AACrC,gFAAsG;AAAvE,iIAAA,uBAAuB,OAAA"}
@@ -0,0 +1,22 @@
1
+ declare const DYNAMIC_API_PRESENCE_ADAPTER: unique symbol;
2
+ interface PresenceAdapter {
3
+ setOnline(userId: string, socketId: string, room?: string): Promise<void>;
4
+ setOffline(userId: string, socketId: string): Promise<void>;
5
+ isOnline(userId: string): Promise<boolean>;
6
+ getOnlineUserIds(room?: string): Promise<string[]>;
7
+ getSocketCount(userId: string): Promise<number>;
8
+ }
9
+ interface PresenceRegisterOptions {
10
+ adapter: 'memory' | 'redis';
11
+ redisUrl?: string;
12
+ redisTtlSeconds?: number;
13
+ enableController?: boolean;
14
+ }
15
+ interface PresenceEventPayload {
16
+ userId: string;
17
+ }
18
+ interface PresenceResponse {
19
+ onlineUserIds: string[];
20
+ }
21
+ export type { PresenceAdapter, PresenceRegisterOptions, PresenceEventPayload, PresenceResponse, };
22
+ export { DYNAMIC_API_PRESENCE_ADAPTER };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DYNAMIC_API_PRESENCE_ADAPTER = void 0;
4
+ const DYNAMIC_API_PRESENCE_ADAPTER = Symbol('DYNAMIC_API_PRESENCE_ADAPTER');
5
+ exports.DYNAMIC_API_PRESENCE_ADAPTER = DYNAMIC_API_PRESENCE_ADAPTER;
6
+ //# sourceMappingURL=dynamic-api-presence.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dynamic-api-presence.interface.js","sourceRoot":"","sources":["../../../libs/dynamic-api/src/interfaces/dynamic-api-presence.interface.ts"],"names":[],"mappings":";;;AACA,MAAM,4BAA4B,GAAG,MAAM,CAAC,8BAA8B,CAAC,CAAC;AA4DnE,oEAA4B"}
@@ -20,3 +20,4 @@ export * from './dynamic-api-service-callback.interface';
20
20
  export * from './dynamic-api-service-provider.interface';
21
21
  export * from './dynamic-api-swagger-options.type';
22
22
  export * from './dynamic-api-web-socket.interface';
23
+ export * from './dynamic-api-presence.interface';
@@ -36,4 +36,5 @@ __exportStar(require("./dynamic-api-service-callback.interface"), exports);
36
36
  __exportStar(require("./dynamic-api-service-provider.interface"), exports);
37
37
  __exportStar(require("./dynamic-api-swagger-options.type"), exports);
38
38
  __exportStar(require("./dynamic-api-web-socket.interface"), exports);
39
+ __exportStar(require("./dynamic-api-presence.interface"), exports);
39
40
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../libs/dynamic-api/src/interfaces/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6EAA2D;AAC3D,kEAAgD;AAChD,4EAA0D;AAC1D,wEAAsD;AACtD,kEAAgD;AAChD,2EAAyD;AACzD,yEAAuD;AACvD,yEAAuD;AACvD,uEAAqD;AACrD,kEAAgD;AAChD,yEAAuD;AACvD,uEAAqD;AACrD,uEAAqD;AACrD,kEAAgD;AAChD,oEAAkD;AAClD,gEAA8C;AAC9C,yEAAuD;AACvD,uFAAqE;AACrE,2EAAyD;AACzD,2EAAyD;AACzD,qEAAmD;AACnD,qEAAmD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../libs/dynamic-api/src/interfaces/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6EAA2D;AAC3D,kEAAgD;AAChD,4EAA0D;AAC1D,wEAAsD;AACtD,kEAAgD;AAChD,2EAAyD;AACzD,yEAAuD;AACvD,yEAAuD;AACvD,uEAAqD;AACrD,kEAAgD;AAChD,yEAAuD;AACvD,uEAAqD;AACrD,uEAAqD;AACrD,kEAAgD;AAChD,oEAAkD;AAClD,gEAA8C;AAC9C,yEAAuD;AACvD,uFAAqE;AACrE,2EAAyD;AACzD,2EAAyD;AACzD,qEAAmD;AACnD,qEAAmD;AACnD,mEAAiD"}
@@ -0,0 +1,10 @@
1
+ import { PresenceAdapter } from '../../../interfaces';
2
+ export declare class InMemoryPresenceAdapter implements PresenceAdapter {
3
+ private readonly socketsByUser;
4
+ private readonly roomBySocket;
5
+ setOnline(userId: string, socketId: string, room?: string): Promise<void>;
6
+ setOffline(userId: string, socketId: string): Promise<void>;
7
+ isOnline(userId: string): Promise<boolean>;
8
+ getOnlineUserIds(room?: string): Promise<string[]>;
9
+ getSocketCount(userId: string): Promise<number>;
10
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.InMemoryPresenceAdapter = void 0;
10
+ const common_1 = require("@nestjs/common");
11
+ let InMemoryPresenceAdapter = class InMemoryPresenceAdapter {
12
+ constructor() {
13
+ this.socketsByUser = new Map();
14
+ this.roomBySocket = new Map();
15
+ }
16
+ async setOnline(userId, socketId, room) {
17
+ if (!this.socketsByUser.has(userId)) {
18
+ this.socketsByUser.set(userId, new Set());
19
+ }
20
+ const sockets = this.socketsByUser.get(userId) ?? new Set();
21
+ sockets.add(socketId);
22
+ this.socketsByUser.set(userId, sockets);
23
+ if (room) {
24
+ this.roomBySocket.set(socketId, room);
25
+ }
26
+ }
27
+ async setOffline(userId, socketId) {
28
+ const sockets = this.socketsByUser.get(userId);
29
+ if (sockets) {
30
+ sockets.delete(socketId);
31
+ if (sockets.size === 0) {
32
+ this.socketsByUser.delete(userId);
33
+ }
34
+ }
35
+ this.roomBySocket.delete(socketId);
36
+ }
37
+ async isOnline(userId) {
38
+ const sockets = this.socketsByUser.get(userId);
39
+ return !!(sockets && sockets.size > 0);
40
+ }
41
+ async getOnlineUserIds(room) {
42
+ if (!room) {
43
+ return Array.from(this.socketsByUser.keys());
44
+ }
45
+ const result = [];
46
+ for (const [userId, sockets] of this.socketsByUser.entries()) {
47
+ for (const socketId of sockets) {
48
+ if (this.roomBySocket.get(socketId) === room) {
49
+ result.push(userId);
50
+ break;
51
+ }
52
+ }
53
+ }
54
+ return result;
55
+ }
56
+ async getSocketCount(userId) {
57
+ return this.socketsByUser.get(userId)?.size ?? 0;
58
+ }
59
+ };
60
+ exports.InMemoryPresenceAdapter = InMemoryPresenceAdapter;
61
+ exports.InMemoryPresenceAdapter = InMemoryPresenceAdapter = __decorate([
62
+ (0, common_1.Injectable)()
63
+ ], InMemoryPresenceAdapter);
64
+ //# sourceMappingURL=in-memory-presence.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-presence.adapter.js","sourceRoot":"","sources":["../../../../../libs/dynamic-api/src/modules/presence/adapters/in-memory-presence.adapter.ts"],"names":[],"mappings":";;;;;;;;;AAAA,2CAA4C;AAarC,IAAM,uBAAuB,GAA7B,MAAM,uBAAuB;IAA7B;QAEY,kBAAa,GAAG,IAAI,GAAG,EAAuB,CAAC;QAE/C,iBAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAwD5D,CAAC;IAtDC,KAAK,CAAC,SAAS,CAAC,MAAc,EAAE,QAAgB,EAAE,IAAa;QAC7D,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,EAAU,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAExC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,MAAc,EAAE,QAAgB;QAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAE/C,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACzB,IAAI,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBACvB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,MAAc;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,OAAO,CAAC,CAAC,CAAC,OAAO,IAAI,OAAO,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,IAAa;QAClC,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,EAAE,CAAC;YAC7D,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;gBAC/B,IAAI,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC;oBAC7C,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBACpB,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAAc;QACjC,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;IACnD,CAAC;CACF,CAAA;AA5DY,0DAAuB;kCAAvB,uBAAuB;IADnC,IAAA,mBAAU,GAAE;GACA,uBAAuB,CA4DnC"}
@@ -0,0 +1,17 @@
1
+ import { OnModuleDestroy } from '@nestjs/common';
2
+ import Redis from 'ioredis';
3
+ import { PresenceAdapter } from '../../../interfaces';
4
+ export declare const DEFAULT_REDIS_PRESENCE_TTL = 60;
5
+ export declare class RedisPresenceAdapter implements PresenceAdapter, OnModuleDestroy {
6
+ private readonly redis;
7
+ private readonly ttl;
8
+ constructor(redisUrlOrClient: string | Redis, ttlSeconds?: number);
9
+ onModuleDestroy(): Promise<void>;
10
+ private socketsKey;
11
+ private roomKey;
12
+ setOnline(userId: string, socketId: string, room?: string): Promise<void>;
13
+ setOffline(userId: string, socketId: string): Promise<void>;
14
+ isOnline(userId: string): Promise<boolean>;
15
+ getOnlineUserIds(room?: string): Promise<string[]>;
16
+ getSocketCount(userId: string): Promise<number>;
17
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RedisPresenceAdapter = exports.DEFAULT_REDIS_PRESENCE_TTL = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const ioredis_1 = require("ioredis");
15
+ exports.DEFAULT_REDIS_PRESENCE_TTL = 60;
16
+ const LUA_SREM_DEL_IF_EMPTY = `
17
+ local removed = redis.call('SREM', KEYS[1], ARGV[1])
18
+ if redis.call('SCARD', KEYS[1]) == 0 then
19
+ redis.call('DEL', KEYS[1])
20
+ end
21
+ return removed
22
+ `;
23
+ let RedisPresenceAdapter = class RedisPresenceAdapter {
24
+ constructor(redisUrlOrClient, ttlSeconds = exports.DEFAULT_REDIS_PRESENCE_TTL) {
25
+ this.redis =
26
+ typeof redisUrlOrClient === 'string'
27
+ ? new ioredis_1.default(redisUrlOrClient, { lazyConnect: true })
28
+ : redisUrlOrClient;
29
+ this.ttl = ttlSeconds;
30
+ }
31
+ async onModuleDestroy() {
32
+ await this.redis.quit();
33
+ }
34
+ socketsKey(userId) {
35
+ return `presence:sockets:${userId}`;
36
+ }
37
+ roomKey(roomId) {
38
+ return `presence:room:${roomId}`;
39
+ }
40
+ async setOnline(userId, socketId, room) {
41
+ const sockKey = this.socketsKey(userId);
42
+ await this.redis.sadd(sockKey, socketId);
43
+ await this.redis.expire(sockKey, this.ttl);
44
+ if (room) {
45
+ const rKey = this.roomKey(room);
46
+ await this.redis.sadd(rKey, userId);
47
+ await this.redis.expire(rKey, this.ttl);
48
+ }
49
+ }
50
+ async setOffline(userId, socketId) {
51
+ await this.redis.eval(LUA_SREM_DEL_IF_EMPTY, 1, this.socketsKey(userId), socketId);
52
+ const remaining = await this.redis.scard(this.socketsKey(userId));
53
+ if (remaining === 0) {
54
+ const roomKeys = await this.redis.keys('presence:room:*');
55
+ if (roomKeys.length > 0) {
56
+ await Promise.all(roomKeys.map((k) => this.redis.srem(k, userId)));
57
+ }
58
+ }
59
+ }
60
+ async isOnline(userId) {
61
+ const count = await this.redis.scard(this.socketsKey(userId));
62
+ return count > 0;
63
+ }
64
+ async getOnlineUserIds(room) {
65
+ if (!room) {
66
+ const keys = await this.redis.keys('presence:sockets:*');
67
+ return keys.map((k) => k.replace('presence:sockets:', ''));
68
+ }
69
+ return this.redis.smembers(this.roomKey(room));
70
+ }
71
+ async getSocketCount(userId) {
72
+ return this.redis.scard(this.socketsKey(userId));
73
+ }
74
+ };
75
+ exports.RedisPresenceAdapter = RedisPresenceAdapter;
76
+ exports.RedisPresenceAdapter = RedisPresenceAdapter = __decorate([
77
+ (0, common_1.Injectable)(),
78
+ __metadata("design:paramtypes", [Object, Number])
79
+ ], RedisPresenceAdapter);
80
+ //# sourceMappingURL=redis-presence.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-presence.adapter.js","sourceRoot":"","sources":["../../../../../libs/dynamic-api/src/modules/presence/adapters/redis-presence.adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export * from './adapters/in-memory-presence.adapter';
2
+ export * from './adapters/redis-presence.adapter';
3
+ export * from './presence.controller';
4
+ export * from './presence.gateway';
5
+ export * from './presence.module';
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./adapters/in-memory-presence.adapter"), exports);
18
+ __exportStar(require("./adapters/redis-presence.adapter"), exports);
19
+ __exportStar(require("./presence.controller"), exports);
20
+ __exportStar(require("./presence.gateway"), exports);
21
+ __exportStar(require("./presence.module"), exports);
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/dynamic-api/src/modules/presence/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wEAAsD;AACtD,oEAAkD;AAClD,wDAAsC;AACtC,qDAAmC;AACnC,oDAAkC"}
@@ -0,0 +1,6 @@
1
+ import { PresenceAdapter, PresenceResponse } from '../../interfaces';
2
+ export declare class PresenceController {
3
+ private readonly presenceAdapter;
4
+ constructor(presenceAdapter: PresenceAdapter);
5
+ getOnlineUsers(room?: string): Promise<PresenceResponse>;
6
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.PresenceController = void 0;
16
+ const common_1 = require("@nestjs/common");
17
+ const swagger_1 = require("@nestjs/swagger");
18
+ const decorators_1 = require("../../decorators");
19
+ const interfaces_1 = require("../../interfaces");
20
+ let PresenceController = class PresenceController {
21
+ constructor(presenceAdapter) {
22
+ this.presenceAdapter = presenceAdapter;
23
+ }
24
+ async getOnlineUsers(room) {
25
+ const onlineUserIds = await this.presenceAdapter.getOnlineUserIds(room);
26
+ return { onlineUserIds };
27
+ }
28
+ };
29
+ exports.PresenceController = PresenceController;
30
+ __decorate([
31
+ (0, decorators_1.Public)(),
32
+ (0, common_1.Get)(),
33
+ (0, swagger_1.ApiOperation)({ summary: 'Get online user IDs (optionally filtered by room)' }),
34
+ (0, swagger_1.ApiQuery)({ name: 'room', required: false, type: String }),
35
+ (0, swagger_1.ApiOkResponse)({
36
+ description: 'List of online user IDs.',
37
+ schema: {
38
+ type: 'object',
39
+ properties: {
40
+ onlineUserIds: { type: 'array', items: { type: 'string' } },
41
+ },
42
+ },
43
+ }),
44
+ __param(0, (0, common_1.Query)('room')),
45
+ __metadata("design:type", Function),
46
+ __metadata("design:paramtypes", [String]),
47
+ __metadata("design:returntype", Promise)
48
+ ], PresenceController.prototype, "getOnlineUsers", null);
49
+ exports.PresenceController = PresenceController = __decorate([
50
+ (0, swagger_1.ApiTags)('Presence'),
51
+ (0, common_1.Controller)('presence'),
52
+ __param(0, (0, common_1.Inject)(interfaces_1.DYNAMIC_API_PRESENCE_ADAPTER)),
53
+ __metadata("design:paramtypes", [Object])
54
+ ], PresenceController);
55
+ //# sourceMappingURL=presence.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.controller.js","sourceRoot":"","sources":["../../../../libs/dynamic-api/src/modules/presence/presence.controller.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAgE;AAChE,6CAAiF;AACjF,iDAA0C;AAC1C,iDAI0B;AAgBnB,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,YAEmB,eAAgC;QAAhC,oBAAe,GAAf,eAAe,CAAiB;IAChD,CAAC;IAeE,AAAN,KAAK,CAAC,cAAc,CAAgB,IAAa;QAC/C,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACxE,OAAO,EAAE,aAAa,EAAE,CAAC;IAC3B,CAAC;CACF,CAAA;AAvBY,gDAAkB;AAmBvB;IAbL,IAAA,mBAAM,GAAE;IACR,IAAA,YAAG,GAAE;IACL,IAAA,sBAAY,EAAC,EAAE,OAAO,EAAE,mDAAmD,EAAE,CAAC;IAC9E,IAAA,kBAAQ,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACzD,IAAA,uBAAa,EAAC;QACb,WAAW,EAAE,0BAA0B;QACvC,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,aAAa,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;aAC5D;SACF;KACF,CAAC;IACoB,WAAA,IAAA,cAAK,EAAC,MAAM,CAAC,CAAA;;;;wDAGlC;6BAtBU,kBAAkB;IAF9B,IAAA,iBAAO,EAAC,UAAU,CAAC;IACnB,IAAA,mBAAU,EAAC,UAAU,CAAC;IAGlB,WAAA,IAAA,eAAM,EAAC,yCAA4B,CAAC,CAAA;;GAF5B,kBAAkB,CAuB9B"}
@@ -0,0 +1,13 @@
1
+ import { Server } from 'socket.io';
2
+ import { ExtendedSocket, GatewayOptions, PresenceAdapter } from '../../interfaces';
3
+ import { MongoDBDynamicApiLogger } from '../../logger';
4
+ export declare function createPresenceGateway(options?: GatewayOptions): {
5
+ new (presenceAdapter: PresenceAdapter): {
6
+ readonly logger: MongoDBDynamicApiLogger;
7
+ server: Server;
8
+ readonly presenceAdapter: PresenceAdapter;
9
+ afterInit(server: Server): void;
10
+ onSocketConnection(server: Server, socket: ExtendedSocket): void;
11
+ onSocketDisconnect(server: Server, userId: string, socketId: string): void;
12
+ };
13
+ };
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.createPresenceGateway = createPresenceGateway;
16
+ const common_1 = require("@nestjs/common");
17
+ const websockets_1 = require("@nestjs/websockets");
18
+ const socket_io_1 = require("socket.io");
19
+ const helpers_1 = require("../../helpers");
20
+ const interfaces_1 = require("../../interfaces");
21
+ const logger_1 = require("../../logger");
22
+ function createPresenceGateway(options = {}) {
23
+ let PresenceGateway = class PresenceGateway {
24
+ constructor(presenceAdapter) {
25
+ this.presenceAdapter = presenceAdapter;
26
+ this.logger = new logger_1.MongoDBDynamicApiLogger('PresenceGateway');
27
+ }
28
+ afterInit(server) {
29
+ server.on('connection', (socket) => {
30
+ this.onSocketConnection(server, socket);
31
+ });
32
+ }
33
+ onSocketConnection(server, socket) {
34
+ const userId = socket.user?.id;
35
+ if (!userId) {
36
+ return;
37
+ }
38
+ this.presenceAdapter.setOnline(userId, socket.id).then(() => {
39
+ const payload = { userId };
40
+ server.emit('user:online', payload);
41
+ if (helpers_1.DynamicApiWsConfigStore.debug) {
42
+ this.logger.log(`[Presence] user:online – userId=${userId}, socketId=${socket.id}`);
43
+ }
44
+ socket.on('disconnect', () => {
45
+ this.onSocketDisconnect(server, userId, socket.id);
46
+ });
47
+ });
48
+ }
49
+ onSocketDisconnect(server, userId, socketId) {
50
+ this.presenceAdapter
51
+ .setOffline(userId, socketId)
52
+ .then(() => this.presenceAdapter.getSocketCount(userId))
53
+ .then((count) => {
54
+ if (helpers_1.DynamicApiWsConfigStore.debug) {
55
+ this.logger.log(`[Presence] user:offline – userId=${userId}, socketId=${socketId}, remainingSockets=${count}`);
56
+ }
57
+ if (count === 0) {
58
+ const payload = { userId };
59
+ server.emit('user:offline', payload);
60
+ }
61
+ })
62
+ .catch((err) => {
63
+ const message = err instanceof Error ? err.message : JSON.stringify(err);
64
+ this.logger.error(`[Presence] disconnect handler error: ${message}`);
65
+ });
66
+ }
67
+ };
68
+ __decorate([
69
+ (0, websockets_1.WebSocketServer)(),
70
+ __metadata("design:type", socket_io_1.Server)
71
+ ], PresenceGateway.prototype, "server", void 0);
72
+ PresenceGateway = __decorate([
73
+ (0, websockets_1.WebSocketGateway)(options),
74
+ __param(0, (0, common_1.Inject)(interfaces_1.DYNAMIC_API_PRESENCE_ADAPTER)),
75
+ __metadata("design:paramtypes", [Object])
76
+ ], PresenceGateway);
77
+ return PresenceGateway;
78
+ }
79
+ //# sourceMappingURL=presence.gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.gateway.js","sourceRoot":"","sources":["../../../../libs/dynamic-api/src/modules/presence/presence.gateway.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { PresenceRegisterOptions } from '../../interfaces';
3
+ export declare class DynamicApiPresenceModule {
4
+ static register(options: PresenceRegisterOptions): DynamicModule;
5
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var DynamicApiPresenceModule_1;
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.DynamicApiPresenceModule = void 0;
11
+ const common_1 = require("@nestjs/common");
12
+ const interfaces_1 = require("../../interfaces");
13
+ const dynamic_api_module_1 = require("../../dynamic-api.module");
14
+ const in_memory_presence_adapter_1 = require("./adapters/in-memory-presence.adapter");
15
+ const redis_presence_adapter_1 = require("./adapters/redis-presence.adapter");
16
+ const presence_controller_1 = require("./presence.controller");
17
+ const presence_gateway_1 = require("./presence.gateway");
18
+ let DynamicApiPresenceModule = DynamicApiPresenceModule_1 = class DynamicApiPresenceModule {
19
+ static register(options) {
20
+ const { adapter, redisUrl, redisTtlSeconds, enableController = false, } = options;
21
+ if (adapter === 'redis' && !redisUrl) {
22
+ throw new Error('DynamicApiPresenceModule: `redisUrl` is required when adapter is "redis".');
23
+ }
24
+ const adapterInstance = adapter === 'redis'
25
+ ? new redis_presence_adapter_1.RedisPresenceAdapter(redisUrl, redisTtlSeconds)
26
+ : new in_memory_presence_adapter_1.InMemoryPresenceAdapter();
27
+ const adapterProvider = {
28
+ provide: interfaces_1.DYNAMIC_API_PRESENCE_ADAPTER,
29
+ useValue: adapterInstance,
30
+ };
31
+ const gatewayOptions = dynamic_api_module_1.DynamicApiModule.state.get('gatewayOptions') ??
32
+ dynamic_api_module_1.DynamicApiModule.state.get('broadcastGatewayOptions') ??
33
+ {};
34
+ const GatewayClass = (0, presence_gateway_1.createPresenceGateway)(gatewayOptions);
35
+ return {
36
+ module: DynamicApiPresenceModule_1,
37
+ providers: [
38
+ adapterProvider,
39
+ { provide: GatewayClass, useClass: GatewayClass },
40
+ ],
41
+ controllers: enableController ? [presence_controller_1.PresenceController] : [],
42
+ exports: [interfaces_1.DYNAMIC_API_PRESENCE_ADAPTER],
43
+ };
44
+ }
45
+ };
46
+ exports.DynamicApiPresenceModule = DynamicApiPresenceModule;
47
+ exports.DynamicApiPresenceModule = DynamicApiPresenceModule = DynamicApiPresenceModule_1 = __decorate([
48
+ (0, common_1.Module)({})
49
+ ], DynamicApiPresenceModule);
50
+ //# sourceMappingURL=presence.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.module.js","sourceRoot":"","sources":["../../../../libs/dynamic-api/src/modules/presence/presence.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,iDAG0B;AAC1B,iEAA4D;AAC5D,sFAAgF;AAChF,8EAAyE;AACzE,+DAA2D;AAC3D,yDAA2D;AAwBpD,IAAM,wBAAwB,gCAA9B,MAAM,wBAAwB;IACnC,MAAM,CAAC,QAAQ,CAAC,OAAgC;QAC9C,MAAM,EACJ,OAAO,EACP,QAAQ,EACR,eAAe,EACf,gBAAgB,GAAG,KAAK,GACzB,GAAG,OAAO,CAAC;QAEZ,IAAI,OAAO,KAAK,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CACb,2EAA2E,CAC5E,CAAC;QACJ,CAAC;QAED,MAAM,eAAe,GACnB,OAAO,KAAK,OAAO;YACjB,CAAC,CAAC,IAAI,6CAAoB,CAAC,QAAS,EAAE,eAAe,CAAC;YACtD,CAAC,CAAC,IAAI,oDAAuB,EAAE,CAAC;QAEpC,MAAM,eAAe,GAAG;YACtB,OAAO,EAAE,yCAA4B;YACrC,QAAQ,EAAE,eAAe;SAC1B,CAAC;QAEF,MAAM,cAAc,GAClB,qCAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC;YAC5C,qCAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC;YACrD,EAAE,CAAC;QAEL,MAAM,YAAY,GAAG,IAAA,wCAAqB,EAAC,cAAc,CAAC,CAAC;QAE3D,OAAO;YACL,MAAM,EAAE,0BAAwB;YAChC,SAAS,EAAE;gBACT,eAAe;gBACf,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE;aAClD;YACD,WAAW,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,wCAAkB,CAAC,CAAC,CAAC,CAAC,EAAE;YACzD,OAAO,EAAE,CAAC,yCAA4B,CAAC;SACxC,CAAC;IACJ,CAAC;CACF,CAAA;AA1CY,4DAAwB;mCAAxB,wBAAwB;IADpC,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,wBAAwB,CA0CpC"}
package/src/version.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "version": "4.8.0"
2
+ "version": "4.9.0"
3
3
  }
@@ -0,0 +1 @@
1
+ import 'dotenv/config';