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
@@ -0,0 +1,169 @@
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
+ const mongoose_1 = require("@nestjs/mongoose");
13
+ const testing_1 = require("@nestjs/testing");
14
+ const socket_io_client_1 = require("socket.io-client");
15
+ const mongoose_2 = require("mongoose");
16
+ require("dotenv/config");
17
+ const src_1 = require("../../src");
18
+ const e2e_setup_1 = require("../e2e.setup");
19
+ let PresenceUserEntity = class PresenceUserEntity extends src_1.BaseEntity {
20
+ };
21
+ __decorate([
22
+ (0, mongoose_1.Prop)({ type: String, required: true }),
23
+ __metadata("design:type", String)
24
+ ], PresenceUserEntity.prototype, "email", void 0);
25
+ __decorate([
26
+ (0, mongoose_1.Prop)({ type: String, required: true }),
27
+ __metadata("design:type", String)
28
+ ], PresenceUserEntity.prototype, "password", void 0);
29
+ PresenceUserEntity = __decorate([
30
+ (0, mongoose_1.Schema)({ collection: 'presence-users' })
31
+ ], PresenceUserEntity);
32
+ const DEFAULT_TIMEOUT_MS = 6000;
33
+ async function connectSocket(baseUrl, accessToken) {
34
+ return new Promise((resolve, reject) => {
35
+ const socket = (0, socket_io_client_1.io)(baseUrl, {
36
+ query: accessToken ? { accessToken } : {},
37
+ reconnection: false,
38
+ });
39
+ const timeout = setTimeout(() => {
40
+ socket.close();
41
+ reject(new Error('Socket connection timed out'));
42
+ }, DEFAULT_TIMEOUT_MS);
43
+ socket.once('connect', () => {
44
+ clearTimeout(timeout);
45
+ resolve(socket);
46
+ });
47
+ socket.once('connect_error', (err) => {
48
+ clearTimeout(timeout);
49
+ reject(err);
50
+ });
51
+ });
52
+ }
53
+ function waitForEvent(socket, event, timeoutMs = DEFAULT_TIMEOUT_MS) {
54
+ return new Promise((resolve, reject) => {
55
+ const timeout = setTimeout(() => reject(new Error(`Timeout waiting for "${event}" after ${timeoutMs}ms`)), timeoutMs);
56
+ socket.once(event, (data) => {
57
+ clearTimeout(timeout);
58
+ resolve(data);
59
+ });
60
+ });
61
+ }
62
+ const delay = (ms) => new Promise((r) => setTimeout(r, ms));
63
+ describe('DynamicApiPresenceModule (e2e)', () => {
64
+ jest.setTimeout(20000);
65
+ let accessToken;
66
+ beforeEach(() => {
67
+ src_1.DynamicApiModule.state['resetState']();
68
+ });
69
+ afterEach(async () => {
70
+ await (0, e2e_setup_1.closeTestingApp)(mongoose_2.default.connections);
71
+ });
72
+ async function initPresenceApp(enableController = false) {
73
+ const uri = process.env.MONGO_DB_URL;
74
+ const moduleRef = await testing_1.Test.createTestingModule({
75
+ imports: [
76
+ src_1.DynamicApiModule.forRoot(uri, {
77
+ useAuth: {
78
+ userEntity: PresenceUserEntity,
79
+ jwt: { secret: 'presence-e2e-secret', expiresIn: '1h' },
80
+ login: {},
81
+ webSocket: true,
82
+ },
83
+ }),
84
+ src_1.DynamicApiPresenceModule.register({
85
+ adapter: 'memory',
86
+ enableController,
87
+ }),
88
+ ],
89
+ }).compile();
90
+ return (0, e2e_setup_1.createTestingApp)(moduleRef, undefined, async (app) => {
91
+ (0, src_1.enableDynamicAPIWebSockets)(app);
92
+ });
93
+ }
94
+ async function registerAndLogin(email = 'presence@test.co', password = 'P@ssw0rd!') {
95
+ await e2e_setup_1.server.post('/auth/register', { email, password });
96
+ const { body } = await e2e_setup_1.server.post('/auth/login', { email, password });
97
+ return body.accessToken;
98
+ }
99
+ it('should emit user:online when an authenticated socket connects', async () => {
100
+ await initPresenceApp();
101
+ accessToken = await registerAndLogin();
102
+ const observer = await connectSocket(global.appBaseUrl);
103
+ const onlinePromise = waitForEvent(observer, 'user:online');
104
+ const authenticated = await connectSocket(global.appBaseUrl, accessToken);
105
+ const payload = await onlinePromise;
106
+ expect(payload).toMatchObject({ userId: expect.any(String) });
107
+ authenticated.disconnect();
108
+ observer.disconnect();
109
+ });
110
+ it('should emit user:offline when the last authenticated socket disconnects', async () => {
111
+ await initPresenceApp();
112
+ accessToken = await registerAndLogin();
113
+ const observer = await connectSocket(global.appBaseUrl);
114
+ const onlinePromise = waitForEvent(observer, 'user:online', 5000);
115
+ const authenticated = await connectSocket(global.appBaseUrl, accessToken);
116
+ await onlinePromise;
117
+ const offlinePromise = waitForEvent(observer, 'user:offline', 5000);
118
+ authenticated.disconnect();
119
+ const payload = await offlinePromise;
120
+ expect(payload).toMatchObject({ userId: expect.any(String) });
121
+ observer.disconnect();
122
+ });
123
+ it('should NOT emit user:offline while the user has another active socket (multi-tab)', async () => {
124
+ await initPresenceApp();
125
+ accessToken = await registerAndLogin();
126
+ const observer = await connectSocket(global.appBaseUrl);
127
+ const tab1 = await connectSocket(global.appBaseUrl, accessToken);
128
+ const tab2 = await connectSocket(global.appBaseUrl, accessToken);
129
+ await delay(300);
130
+ let offlineReceived = false;
131
+ observer.on('user:offline', () => { offlineReceived = true; });
132
+ tab1.disconnect();
133
+ await delay(500);
134
+ expect(offlineReceived).toBe(false);
135
+ tab2.disconnect();
136
+ observer.disconnect();
137
+ });
138
+ it('should NOT emit user:online for anonymous (unauthenticated) connections', async () => {
139
+ await initPresenceApp();
140
+ const observer = await connectSocket(global.appBaseUrl);
141
+ let onlineReceived = false;
142
+ observer.on('user:online', () => { onlineReceived = true; });
143
+ const anon = await connectSocket(global.appBaseUrl);
144
+ await delay(300);
145
+ expect(onlineReceived).toBe(false);
146
+ anon.disconnect();
147
+ observer.disconnect();
148
+ });
149
+ it('GET /presence should return online user IDs when enableController is true', async () => {
150
+ await initPresenceApp(true);
151
+ accessToken = await registerAndLogin();
152
+ const observer = await connectSocket(global.appBaseUrl);
153
+ const onlinePromise = waitForEvent(observer, 'user:online', 5000);
154
+ const authenticated = await connectSocket(global.appBaseUrl, accessToken);
155
+ await onlinePromise;
156
+ const res = await e2e_setup_1.server.get('/presence');
157
+ const onlineIds = res.body?.onlineUserIds ?? [];
158
+ expect(onlineIds.length).toBeGreaterThan(0);
159
+ authenticated.disconnect();
160
+ observer.disconnect();
161
+ });
162
+ it('GET /presence?room=nonexistent should return empty array', async () => {
163
+ await initPresenceApp(true);
164
+ const res = await e2e_setup_1.server.get('/presence', { query: { room: 'nonexistent-room' } });
165
+ const onlineIds = res.body?.onlineUserIds ?? [];
166
+ expect(onlineIds).toEqual([]);
167
+ });
168
+ });
169
+ //# sourceMappingURL=presence.e2e-spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"presence.e2e-spec.js","sourceRoot":"","sources":["../../../libs/dynamic-api/test/for-feature/presence.e2e-spec.ts"],"names":[],"mappings":"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"}