@dismissible/nestjs-api 0.0.2-canary.8976e84.0 → 0.0.2-canary.b0d8bfe.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.

Potentially problematic release.


This version of @dismissible/nestjs-api might be problematic. Click here for more details.

Files changed (45) hide show
  1. package/config/.env.yaml +34 -1
  2. package/jest.config.ts +23 -1
  3. package/jest.e2e-config.ts +2 -1
  4. package/package.json +22 -13
  5. package/project.json +7 -4
  6. package/scripts/performance-test.config.json +29 -0
  7. package/scripts/performance-test.ts +845 -0
  8. package/src/app-test.factory.ts +8 -1
  9. package/src/app.module.ts +13 -1
  10. package/src/app.setup.ts +40 -5
  11. package/src/bootstrap.ts +8 -3
  12. package/src/config/app.config.spec.ts +117 -0
  13. package/src/config/app.config.ts +5 -0
  14. package/src/config/config.module.spec.ts +0 -2
  15. package/src/config/default-app.config.spec.ts +74 -0
  16. package/src/config/default-app.config.ts +15 -0
  17. package/src/cors/cors.config.spec.ts +162 -0
  18. package/src/cors/cors.config.ts +37 -0
  19. package/src/cors/index.ts +1 -0
  20. package/src/health/health.controller.spec.ts +7 -31
  21. package/src/health/health.controller.ts +4 -5
  22. package/src/health/health.module.ts +2 -3
  23. package/src/health/index.ts +0 -1
  24. package/src/helmet/helmet.config.spec.ts +197 -0
  25. package/src/helmet/helmet.config.ts +60 -0
  26. package/src/helmet/index.ts +1 -0
  27. package/src/server/server.config.spec.ts +65 -0
  28. package/src/swagger/swagger.config.spec.ts +113 -0
  29. package/src/swagger/swagger.config.ts +2 -10
  30. package/src/swagger/swagger.factory.spec.ts +125 -0
  31. package/src/swagger/swagger.factory.ts +0 -1
  32. package/src/validation/index.ts +1 -0
  33. package/src/validation/validation.config.ts +47 -0
  34. package/test/config/.env.yaml +23 -0
  35. package/test/config-jwt-auth/.env.yaml +26 -0
  36. package/test/dismiss.e2e-spec.ts +61 -0
  37. package/test/full-cycle.e2e-spec.ts +55 -0
  38. package/test/get-or-create.e2e-spec.ts +51 -0
  39. package/test/jwt-auth.e2e-spec.ts +335 -0
  40. package/test/restore.e2e-spec.ts +61 -0
  41. package/tsconfig.e2e.json +12 -0
  42. package/tsconfig.spec.json +12 -0
  43. package/src/app.e2e-spec.ts +0 -221
  44. package/src/health/health.service.spec.ts +0 -46
  45. package/src/health/health.service.ts +0 -16
@@ -1,221 +0,0 @@
1
- import { INestApplication } from '@nestjs/common';
2
- import request from 'supertest';
3
- import { join } from 'path';
4
- import { createTestApp, cleanupTestData } from './app-test.factory';
5
-
6
- describe('Dismissible API (e2e)', () => {
7
- let app: INestApplication;
8
-
9
- beforeAll(async () => {
10
- app = await createTestApp({
11
- moduleOptions: {
12
- configPath: join(__dirname, '../config'),
13
- },
14
- });
15
- await cleanupTestData(app);
16
- });
17
-
18
- afterAll(async () => {
19
- await app.close();
20
- await cleanupTestData(app);
21
- });
22
-
23
- describe('GET /v1/user/:userId/dismissible-item/:id (get-or-create)', () => {
24
- it('should create a new item on first request', async () => {
25
- const response = await request(app.getHttpServer())
26
- .get('/v1/user/user-123/dismissible-item/test-banner-1')
27
- .expect(200);
28
-
29
- expect(response.body.data).toBeDefined();
30
- expect(response.body.data.itemId).toBe('test-banner-1');
31
- expect(response.body.data.userId).toBe('user-123');
32
- expect(response.body.data.createdAt).toBeDefined();
33
- expect(response.body.data.dismissedAt).toBeUndefined();
34
- });
35
-
36
- it('should return existing item on subsequent requests', async () => {
37
- // First request - creates the item
38
- const firstResponse = await request(app.getHttpServer())
39
- .get('/v1/user/user-456/dismissible-item/test-banner-2')
40
- .expect(200);
41
-
42
- const createdAt = firstResponse.body.data.createdAt;
43
-
44
- // Second request - returns existing item
45
- const secondResponse = await request(app.getHttpServer())
46
- .get('/v1/user/user-456/dismissible-item/test-banner-2')
47
- .expect(200);
48
-
49
- expect(secondResponse.body.data.itemId).toBe('test-banner-2');
50
- expect(secondResponse.body.data.createdAt).toBe(createdAt);
51
- });
52
-
53
- it('should store and retrieve metadata', async () => {
54
- const response = await request(app.getHttpServer())
55
- .get('/v1/user/user-789/dismissible-item/test-banner-metadata')
56
- .query({ metadata: ['version:2', 'category:promo'] })
57
- .expect(200);
58
-
59
- expect(response.body.data.metadata).toEqual({
60
- version: 2,
61
- category: 'promo',
62
- });
63
- });
64
- });
65
-
66
- describe('DELETE /v1/user/:userId/dismissible-item/:id (dismiss)', () => {
67
- it('should dismiss an existing item', async () => {
68
- const userId = 'user-dismiss-1';
69
- // First create the item
70
- await request(app.getHttpServer())
71
- .get(`/v1/user/${userId}/dismissible-item/dismiss-test-1`)
72
- .expect(200);
73
-
74
- // Then dismiss it
75
- const response = await request(app.getHttpServer())
76
- .delete(`/v1/user/${userId}/dismissible-item/dismiss-test-1`)
77
- .expect(200);
78
-
79
- expect(response.body.data).toBeDefined();
80
- expect(response.body.data.dismissedAt).toBeDefined();
81
- });
82
-
83
- it('should return 400 when dismissing non-existent item', async () => {
84
- const response = await request(app.getHttpServer())
85
- .delete('/v1/user/user-123/dismissible-item/non-existent-item')
86
- .expect(400);
87
-
88
- expect(response.body.error).toBeDefined();
89
- expect(response.body.error.message).toContain('not found');
90
- });
91
-
92
- it('should return 400 when dismissing already dismissed item', async () => {
93
- const userId = 'user-dismiss-2';
94
- // Create the item
95
- await request(app.getHttpServer())
96
- .get(`/v1/user/${userId}/dismissible-item/dismiss-test-2`)
97
- .expect(200);
98
-
99
- // Dismiss it first time
100
- await request(app.getHttpServer())
101
- .delete(`/v1/user/${userId}/dismissible-item/dismiss-test-2`)
102
- .expect(200);
103
-
104
- // Try to dismiss again
105
- const response = await request(app.getHttpServer())
106
- .delete(`/v1/user/${userId}/dismissible-item/dismiss-test-2`)
107
- .expect(400);
108
-
109
- expect(response.body.error).toBeDefined();
110
- expect(response.body.error.message).toContain('already dismissed');
111
- });
112
- });
113
-
114
- describe('POST /v1/user/:userId/dismissible-item/:id (restore)', () => {
115
- it('should restore a dismissed item', async () => {
116
- const userId = 'user-restore-1';
117
- // Create and dismiss the item
118
- await request(app.getHttpServer())
119
- .get(`/v1/user/${userId}/dismissible-item/restore-test-1`)
120
- .expect(200);
121
-
122
- await request(app.getHttpServer())
123
- .delete(`/v1/user/${userId}/dismissible-item/restore-test-1`)
124
- .expect(200);
125
-
126
- // Restore it
127
- const response = await request(app.getHttpServer())
128
- .post(`/v1/user/${userId}/dismissible-item/restore-test-1`)
129
- .expect(201);
130
-
131
- expect(response.body.data).toBeDefined();
132
- expect(response.body.data.dismissedAt).toBeUndefined();
133
- });
134
-
135
- it('should return 400 when restoring non-existent item', async () => {
136
- const response = await request(app.getHttpServer())
137
- .post('/v1/user/user-123/dismissible-item/non-existent-restore')
138
- .expect(400);
139
-
140
- expect(response.body.error).toBeDefined();
141
- expect(response.body.error.message).toContain('not found');
142
- });
143
-
144
- it('should return 400 when restoring non-dismissed item', async () => {
145
- const userId = 'user-restore-2';
146
- // Create item but don't dismiss it
147
- await request(app.getHttpServer())
148
- .get(`/v1/user/${userId}/dismissible-item/restore-test-2`)
149
- .expect(200);
150
-
151
- // Try to restore
152
- const response = await request(app.getHttpServer())
153
- .post(`/v1/user/${userId}/dismissible-item/restore-test-2`)
154
- .expect(400);
155
-
156
- expect(response.body.error).toBeDefined();
157
- expect(response.body.error.message).toContain('not dismissed');
158
- });
159
- });
160
-
161
- describe('Full lifecycle flow', () => {
162
- it('should handle create -> dismiss -> restore -> dismiss cycle', async () => {
163
- const userId = 'lifecycle-user';
164
- const itemId = 'lifecycle-test';
165
-
166
- // Create
167
- const createResponse = await request(app.getHttpServer())
168
- .get(`/v1/user/${userId}/dismissible-item/${itemId}`)
169
- .expect(200);
170
-
171
- expect(createResponse.body.data.dismissedAt).toBeUndefined();
172
-
173
- // Dismiss
174
- const dismissResponse = await request(app.getHttpServer())
175
- .delete(`/v1/user/${userId}/dismissible-item/${itemId}`)
176
- .expect(200);
177
-
178
- expect(dismissResponse.body.data.dismissedAt).toBeDefined();
179
-
180
- // Restore
181
- const restoreResponse = await request(app.getHttpServer())
182
- .post(`/v1/user/${userId}/dismissible-item/${itemId}`)
183
- .expect(201);
184
-
185
- expect(restoreResponse.body.data.dismissedAt).toBeUndefined();
186
-
187
- // Dismiss again
188
- const dismissAgainResponse = await request(app.getHttpServer())
189
- .delete(`/v1/user/${userId}/dismissible-item/${itemId}`)
190
- .expect(200);
191
-
192
- expect(dismissAgainResponse.body.data.dismissedAt).toBeDefined();
193
- });
194
-
195
- it('should preserve metadata through dismiss and restore', async () => {
196
- const userId = 'user-metadata';
197
- const itemId = 'metadata-preserve-test';
198
-
199
- // Create with metadata
200
- await request(app.getHttpServer())
201
- .get(`/v1/user/${userId}/dismissible-item/${itemId}`)
202
- .query({ metadata: ['key:value', 'count:42'] })
203
- .expect(200);
204
-
205
- // Dismiss
206
- await request(app.getHttpServer())
207
- .delete(`/v1/user/${userId}/dismissible-item/${itemId}`)
208
- .expect(200);
209
-
210
- // Restore and verify metadata
211
- const restoreResponse = await request(app.getHttpServer())
212
- .post(`/v1/user/${userId}/dismissible-item/${itemId}`)
213
- .expect(201);
214
-
215
- expect(restoreResponse.body.data.metadata).toEqual({
216
- key: 'value',
217
- count: 42,
218
- });
219
- });
220
- });
221
- });
@@ -1,46 +0,0 @@
1
- import { HealthService } from './health.service';
2
-
3
- describe('HealthService', () => {
4
- let service: HealthService;
5
-
6
- beforeEach(() => {
7
- service = new HealthService();
8
- });
9
-
10
- describe('getHealth', () => {
11
- it('should return health status with ok status', () => {
12
- const result = service.getHealth();
13
-
14
- expect(result.status).toBe('ok');
15
- expect(result).toHaveProperty('timestamp');
16
- expect(result).toHaveProperty('uptime');
17
- });
18
-
19
- it('should return a valid ISO timestamp', () => {
20
- const result = service.getHealth();
21
- const timestamp = new Date(result.timestamp);
22
-
23
- expect(timestamp.toISOString()).toBe(result.timestamp);
24
- expect(timestamp.getTime()).toBeGreaterThan(0);
25
- });
26
-
27
- it('should return process uptime', () => {
28
- const result = service.getHealth();
29
-
30
- expect(typeof result.uptime).toBe('number');
31
- expect(result.uptime).toBeGreaterThanOrEqual(0);
32
- // Uptime should be approximately equal to process.uptime() (within 0.1 seconds)
33
- expect(Math.abs(result.uptime - process.uptime())).toBeLessThan(0.1);
34
- });
35
-
36
- it('should return current timestamp', () => {
37
- const before = new Date();
38
- const result = service.getHealth();
39
- const after = new Date();
40
- const timestamp = new Date(result.timestamp);
41
-
42
- expect(timestamp.getTime()).toBeGreaterThanOrEqual(before.getTime());
43
- expect(timestamp.getTime()).toBeLessThanOrEqual(after.getTime());
44
- });
45
- });
46
- });
@@ -1,16 +0,0 @@
1
- import { Injectable } from '@nestjs/common';
2
-
3
- @Injectable()
4
- export class HealthService {
5
- getHealth(): {
6
- status: string;
7
- timestamp: string;
8
- uptime: number;
9
- } {
10
- return {
11
- status: 'ok',
12
- timestamp: new Date().toISOString(),
13
- uptime: process.uptime(),
14
- };
15
- }
16
- }