@friggframework/core 2.0.0--canary.461.61382d8.0 → 2.0.0--canary.461.3d6d8ad.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 (120) hide show
  1. package/database/use-cases/check-migration-status-use-case.js +81 -0
  2. package/generated/prisma-mongodb/client.d.ts +1 -0
  3. package/generated/prisma-mongodb/client.js +4 -0
  4. package/generated/prisma-mongodb/default.d.ts +1 -0
  5. package/generated/prisma-mongodb/default.js +4 -0
  6. package/generated/prisma-mongodb/edge.d.ts +1 -0
  7. package/generated/prisma-mongodb/edge.js +336 -0
  8. package/generated/prisma-mongodb/index-browser.js +318 -0
  9. package/generated/prisma-mongodb/index.d.ts +22993 -0
  10. package/generated/prisma-mongodb/index.js +361 -0
  11. package/generated/prisma-mongodb/package.json +183 -0
  12. package/generated/prisma-mongodb/query-engine-debian-openssl-3.0.x +0 -0
  13. package/generated/prisma-mongodb/query-engine-rhel-openssl-3.0.x +0 -0
  14. package/generated/prisma-mongodb/runtime/binary.d.ts +1 -0
  15. package/generated/prisma-mongodb/runtime/binary.js +289 -0
  16. package/generated/prisma-mongodb/runtime/edge-esm.js +34 -0
  17. package/generated/prisma-mongodb/runtime/edge.js +34 -0
  18. package/generated/prisma-mongodb/runtime/index-browser.d.ts +370 -0
  19. package/generated/prisma-mongodb/runtime/index-browser.js +16 -0
  20. package/generated/prisma-mongodb/runtime/library.d.ts +3977 -0
  21. package/generated/prisma-mongodb/runtime/react-native.js +83 -0
  22. package/generated/prisma-mongodb/runtime/wasm-compiler-edge.js +84 -0
  23. package/generated/prisma-mongodb/runtime/wasm-engine-edge.js +36 -0
  24. package/generated/prisma-mongodb/schema.prisma +364 -0
  25. package/generated/prisma-mongodb/wasm-edge-light-loader.mjs +4 -0
  26. package/generated/prisma-mongodb/wasm-worker-loader.mjs +4 -0
  27. package/generated/prisma-mongodb/wasm.d.ts +1 -0
  28. package/generated/prisma-mongodb/wasm.js +343 -0
  29. package/generated/prisma-postgresql/client.d.ts +1 -0
  30. package/generated/prisma-postgresql/client.js +4 -0
  31. package/generated/prisma-postgresql/default.d.ts +1 -0
  32. package/generated/prisma-postgresql/default.js +4 -0
  33. package/generated/prisma-postgresql/edge.d.ts +1 -0
  34. package/generated/prisma-postgresql/edge.js +358 -0
  35. package/generated/prisma-postgresql/index-browser.js +340 -0
  36. package/generated/prisma-postgresql/index.d.ts +25171 -0
  37. package/generated/prisma-postgresql/index.js +383 -0
  38. package/generated/prisma-postgresql/package.json +183 -0
  39. package/generated/prisma-postgresql/query-engine-debian-openssl-3.0.x +0 -0
  40. package/generated/prisma-postgresql/query-engine-rhel-openssl-3.0.x +0 -0
  41. package/generated/prisma-postgresql/query_engine_bg.js +2 -0
  42. package/generated/prisma-postgresql/query_engine_bg.wasm +0 -0
  43. package/generated/prisma-postgresql/runtime/binary.d.ts +1 -0
  44. package/generated/prisma-postgresql/runtime/binary.js +289 -0
  45. package/generated/prisma-postgresql/runtime/edge-esm.js +34 -0
  46. package/generated/prisma-postgresql/runtime/edge.js +34 -0
  47. package/generated/prisma-postgresql/runtime/index-browser.d.ts +370 -0
  48. package/generated/prisma-postgresql/runtime/index-browser.js +16 -0
  49. package/generated/prisma-postgresql/runtime/library.d.ts +3977 -0
  50. package/generated/prisma-postgresql/runtime/react-native.js +83 -0
  51. package/generated/prisma-postgresql/runtime/wasm-compiler-edge.js +84 -0
  52. package/generated/prisma-postgresql/runtime/wasm-engine-edge.js +36 -0
  53. package/generated/prisma-postgresql/schema.prisma +347 -0
  54. package/generated/prisma-postgresql/wasm-edge-light-loader.mjs +4 -0
  55. package/generated/prisma-postgresql/wasm-worker-loader.mjs +4 -0
  56. package/generated/prisma-postgresql/wasm.d.ts +1 -0
  57. package/generated/prisma-postgresql/wasm.js +365 -0
  58. package/handlers/routers/db-migration.js +52 -0
  59. package/package.json +5 -5
  60. package/application/commands/integration-commands.test.js +0 -123
  61. package/core/Worker.test.js +0 -159
  62. package/database/encryption/encryption-integration.test.js +0 -553
  63. package/database/encryption/encryption-schema-registry.test.js +0 -392
  64. package/database/encryption/field-encryption-service.test.js +0 -525
  65. package/database/encryption/mongo-decryption-fix-verification.test.js +0 -348
  66. package/database/encryption/postgres-decryption-fix-verification.test.js +0 -371
  67. package/database/encryption/postgres-relation-decryption.test.js +0 -245
  68. package/database/encryption/prisma-encryption-extension.test.js +0 -439
  69. package/database/repositories/migration-status-repository-s3.test.js +0 -158
  70. package/database/use-cases/check-encryption-health-use-case.test.js +0 -192
  71. package/database/use-cases/get-migration-status-use-case.test.js +0 -171
  72. package/database/use-cases/run-database-migration-use-case.test.js +0 -310
  73. package/database/use-cases/trigger-database-migration-use-case.test.js +0 -250
  74. package/database/utils/prisma-runner.test.js +0 -486
  75. package/encrypt/Cryptor.test.js +0 -144
  76. package/errors/base-error.test.js +0 -32
  77. package/errors/fetch-error.test.js +0 -79
  78. package/errors/halt-error.test.js +0 -11
  79. package/errors/validation-errors.test.js +0 -120
  80. package/handlers/auth-flow.integration.test.js +0 -147
  81. package/handlers/integration-event-dispatcher.test.js +0 -209
  82. package/handlers/routers/db-migration.test.js +0 -51
  83. package/handlers/routers/health.test.js +0 -210
  84. package/handlers/routers/integration-webhook-routers.test.js +0 -126
  85. package/handlers/use-cases/check-integrations-health-use-case.test.js +0 -125
  86. package/handlers/webhook-flow.integration.test.js +0 -356
  87. package/handlers/workers/db-migration.test.js +0 -50
  88. package/handlers/workers/integration-defined-workers.test.js +0 -184
  89. package/integrations/tests/integration-router-multi-auth.test.js +0 -369
  90. package/integrations/tests/use-cases/create-integration.test.js +0 -131
  91. package/integrations/tests/use-cases/delete-integration-for-user.test.js +0 -150
  92. package/integrations/tests/use-cases/find-integration-context-by-external-entity-id.test.js +0 -92
  93. package/integrations/tests/use-cases/get-integration-for-user.test.js +0 -150
  94. package/integrations/tests/use-cases/get-integration-instance.test.js +0 -176
  95. package/integrations/tests/use-cases/get-integrations-for-user.test.js +0 -176
  96. package/integrations/tests/use-cases/get-possible-integrations.test.js +0 -188
  97. package/integrations/tests/use-cases/update-integration-messages.test.js +0 -142
  98. package/integrations/tests/use-cases/update-integration-status.test.js +0 -103
  99. package/integrations/tests/use-cases/update-integration.test.js +0 -141
  100. package/integrations/use-cases/create-process.test.js +0 -178
  101. package/integrations/use-cases/get-process.test.js +0 -190
  102. package/integrations/use-cases/load-integration-context-full.test.js +0 -329
  103. package/integrations/use-cases/load-integration-context.test.js +0 -114
  104. package/integrations/use-cases/update-process-metrics.test.js +0 -308
  105. package/integrations/use-cases/update-process-state.test.js +0 -256
  106. package/lambda/TimeoutCatcher.test.js +0 -68
  107. package/logs/logger.test.js +0 -76
  108. package/modules/module-hydration.test.js +0 -205
  109. package/modules/requester/requester.test.js +0 -28
  110. package/queues/queuer-util.test.js +0 -132
  111. package/user/tests/use-cases/create-individual-user.test.js +0 -24
  112. package/user/tests/use-cases/create-organization-user.test.js +0 -28
  113. package/user/tests/use-cases/create-token-for-user-id.test.js +0 -19
  114. package/user/tests/use-cases/get-user-from-adopter-jwt.test.js +0 -113
  115. package/user/tests/use-cases/get-user-from-bearer-token.test.js +0 -64
  116. package/user/tests/use-cases/get-user-from-x-frigg-headers.test.js +0 -346
  117. package/user/tests/use-cases/login-user.test.js +0 -220
  118. package/user/tests/user-password-encryption-isolation.test.js +0 -237
  119. package/user/tests/user-password-hashing.test.js +0 -235
  120. package/websocket/repositories/websocket-connection-repository.test.js +0 -227
@@ -1,486 +0,0 @@
1
- // Mock dependencies BEFORE requiring modules
2
- jest.mock('child_process', () => ({
3
- execSync: jest.fn(),
4
- spawn: jest.fn()
5
- }));
6
- jest.mock('fs', () => ({
7
- existsSync: jest.fn(),
8
- readFileSync: jest.fn(),
9
- writeFileSync: jest.fn()
10
- }));
11
-
12
- const { execSync, spawn } = require('child_process');
13
- const fs = require('fs');
14
- const {
15
- getPrismaSchemaPath,
16
- runPrismaGenerate,
17
- checkDatabaseState,
18
- runPrismaMigrate,
19
- runPrismaDbPush,
20
- getMigrationCommand
21
- } = require('./prisma-runner');
22
-
23
- describe('Prisma Runner Utility', () => {
24
- beforeEach(() => {
25
- jest.clearAllMocks();
26
- delete process.env.STAGE;
27
- delete process.env.PRISMA_HIDE_UPDATE_MESSAGE;
28
- });
29
-
30
- afterEach(() => {
31
- delete process.env.STAGE;
32
- delete process.env.PRISMA_HIDE_UPDATE_MESSAGE;
33
- });
34
-
35
- describe('getPrismaSchemaPath()', () => {
36
- it('should return correct path for MongoDB', () => {
37
- fs.existsSync.mockReturnValue(true);
38
-
39
- const path = getPrismaSchemaPath('mongodb');
40
-
41
- expect(path).toContain('prisma-mongodb');
42
- expect(path).toContain('schema.prisma');
43
- expect(path).toContain('@friggframework/core');
44
- });
45
-
46
- it('should return correct path for PostgreSQL', () => {
47
- fs.existsSync.mockReturnValue(true);
48
-
49
- const path = getPrismaSchemaPath('postgresql');
50
-
51
- expect(path).toContain('prisma-postgresql');
52
- expect(path).toContain('schema.prisma');
53
- expect(path).toContain('@friggframework/core');
54
- });
55
-
56
- it('should throw error when schema file does not exist', () => {
57
- fs.existsSync.mockReturnValue(false);
58
-
59
- expect(() => getPrismaSchemaPath('mongodb')).toThrow('Prisma schema not found');
60
- });
61
-
62
- it('should include helpful error message when schema missing', () => {
63
- fs.existsSync.mockReturnValue(false);
64
-
65
- expect(() => getPrismaSchemaPath('mongodb')).toThrow('@friggframework/core');
66
- });
67
-
68
- it('should use process.cwd() for base path', () => {
69
- fs.existsSync.mockReturnValue(true);
70
- const originalCwd = process.cwd();
71
-
72
- const path = getPrismaSchemaPath('mongodb');
73
-
74
- expect(path).toContain(originalCwd);
75
- });
76
-
77
- it('should accept custom project root', () => {
78
- fs.existsSync.mockReturnValue(true);
79
- const customRoot = '/custom/project';
80
-
81
- const path = getPrismaSchemaPath('mongodb', customRoot);
82
-
83
- expect(path).toContain(customRoot);
84
- });
85
- });
86
-
87
- describe('runPrismaGenerate()', () => {
88
- beforeEach(() => {
89
- fs.existsSync.mockReturnValue(true);
90
- });
91
-
92
- it('should execute prisma generate successfully', async () => {
93
- execSync.mockReturnValue('Generated successfully');
94
-
95
- const result = await runPrismaGenerate('mongodb');
96
-
97
- expect(result.success).toBe(true);
98
- expect(execSync).toHaveBeenCalled();
99
- });
100
-
101
- it('should use correct schema path for MongoDB', async () => {
102
- execSync.mockReturnValue('');
103
-
104
- await runPrismaGenerate('mongodb');
105
-
106
- const call = execSync.mock.calls[0][0];
107
- expect(call).toContain('prisma generate');
108
- expect(call).toContain('--schema');
109
- expect(call).toContain('prisma-mongodb');
110
- });
111
-
112
- it('should use correct schema path for PostgreSQL', async () => {
113
- execSync.mockReturnValue('');
114
-
115
- await runPrismaGenerate('postgresql');
116
-
117
- const call = execSync.mock.calls[0][0];
118
- expect(call).toContain('prisma-postgresql');
119
- });
120
-
121
- it('should suppress telemetry when verbose false', async () => {
122
- execSync.mockReturnValue('');
123
-
124
- await runPrismaGenerate('mongodb', false);
125
-
126
- const options = execSync.mock.calls[0][1];
127
- expect(options.env.PRISMA_HIDE_UPDATE_MESSAGE).toBe('1');
128
- });
129
-
130
- it('should show output when verbose true', async () => {
131
- execSync.mockReturnValue('Generated successfully');
132
-
133
- await runPrismaGenerate('mongodb', true);
134
-
135
- const options = execSync.mock.calls[0][1];
136
- expect(options.stdio).toBe('inherit');
137
- });
138
-
139
- it('should hide output when verbose false', async () => {
140
- execSync.mockReturnValue('');
141
-
142
- await runPrismaGenerate('mongodb', false);
143
-
144
- const options = execSync.mock.calls[0][1];
145
- expect(options.stdio).toBe('pipe');
146
- });
147
-
148
- it('should handle generation failures with error details', async () => {
149
- const error = new Error('Generation failed');
150
- error.stdout = 'Schema validation error';
151
- execSync.mockImplementation(() => {
152
- throw error;
153
- });
154
-
155
- const result = await runPrismaGenerate('mongodb');
156
-
157
- expect(result.success).toBe(false);
158
- expect(result.error).toContain('Generation failed');
159
- });
160
-
161
- it('should include stdout in error output', async () => {
162
- const error = new Error('Failed');
163
- error.stdout = Buffer.from('Detailed error info');
164
- execSync.mockImplementation(() => {
165
- throw error;
166
- });
167
-
168
- const result = await runPrismaGenerate('mongodb');
169
-
170
- expect(result.output).toContain('Detailed error info');
171
- });
172
-
173
- it('should handle schema syntax errors', async () => {
174
- execSync.mockImplementation(() => {
175
- throw new Error('Schema parsing failed');
176
- });
177
-
178
- const result = await runPrismaGenerate('mongodb');
179
-
180
- expect(result.success).toBe(false);
181
- expect(result.error).toBeDefined();
182
- });
183
- });
184
-
185
- describe('checkDatabaseState()', () => {
186
- beforeEach(() => {
187
- fs.existsSync.mockReturnValue(true);
188
- });
189
-
190
- it('should return upToDate: true when migrations current (PostgreSQL)', async () => {
191
- execSync.mockReturnValue('Database schema is up to date');
192
-
193
- const result = await checkDatabaseState('postgresql');
194
-
195
- expect(result.upToDate).toBe(true);
196
- });
197
-
198
- it('should return upToDate: true for MongoDB (N/A)', async () => {
199
- const result = await checkDatabaseState('mongodb');
200
-
201
- expect(result.upToDate).toBe(true);
202
- });
203
-
204
- it('should return pendingMigrations count when migrations pending', async () => {
205
- execSync.mockReturnValue('3 migrations have not been applied');
206
-
207
- const result = await checkDatabaseState('postgresql');
208
-
209
- expect(result.upToDate).toBe(false);
210
- expect(result.pendingMigrations).toBe(3);
211
- });
212
-
213
- it('should handle uninitialized database', async () => {
214
- execSync.mockImplementation(() => {
215
- throw new Error('No migrations found');
216
- });
217
-
218
- const result = await checkDatabaseState('postgresql');
219
-
220
- expect(result.upToDate).toBe(false);
221
- expect(result.error).toBeDefined();
222
- });
223
-
224
- it('should handle migrate status command errors', async () => {
225
- execSync.mockImplementation(() => {
226
- throw new Error('Migration status failed');
227
- });
228
-
229
- const result = await checkDatabaseState('postgresql');
230
-
231
- expect(result.upToDate).toBe(false);
232
- expect(result.error).toContain('Migration status failed');
233
- });
234
-
235
- it('should not run migrate status for MongoDB', async () => {
236
- await checkDatabaseState('mongodb');
237
-
238
- expect(execSync).not.toHaveBeenCalled();
239
- });
240
- });
241
-
242
- describe('runPrismaMigrate()', () => {
243
- let mockChildProcess;
244
-
245
- beforeEach(() => {
246
- fs.existsSync.mockReturnValue(true);
247
- mockChildProcess = {
248
- on: jest.fn((event, callback) => {
249
- if (event === 'close') {
250
- callback(0);
251
- }
252
- }),
253
- stdout: { on: jest.fn() },
254
- stderr: { on: jest.fn() }
255
- };
256
- spawn.mockReturnValue(mockChildProcess);
257
- });
258
-
259
- it('should run migrate dev successfully', async () => {
260
- const result = await runPrismaMigrate('dev');
261
-
262
- expect(result.success).toBe(true);
263
- expect(spawn).toHaveBeenCalled();
264
- });
265
-
266
- it('should run migrate deploy successfully', async () => {
267
- const result = await runPrismaMigrate('deploy');
268
-
269
- expect(result.success).toBe(true);
270
- expect(spawn).toHaveBeenCalled();
271
- });
272
-
273
- it('should use correct command for dev mode', async () => {
274
- await runPrismaMigrate('dev');
275
-
276
- const args = spawn.mock.calls[0][1];
277
- expect(args).toContain('migrate');
278
- expect(args).toContain('dev');
279
- });
280
-
281
- it('should use correct command for deploy mode', async () => {
282
- await runPrismaMigrate('deploy');
283
-
284
- const args = spawn.mock.calls[0][1];
285
- expect(args).toContain('migrate');
286
- expect(args).toContain('deploy');
287
- });
288
-
289
- it('should handle migration failures with error', async () => {
290
- mockChildProcess.on.mockImplementation((event, callback) => {
291
- if (event === 'close') {
292
- callback(1); // Exit code 1
293
- }
294
- });
295
-
296
- const result = await runPrismaMigrate('dev');
297
-
298
- expect(result.success).toBe(false);
299
- expect(result.error).toContain('exited with code 1');
300
- });
301
-
302
- it('should respect verbose flag', async () => {
303
- await runPrismaMigrate('dev', true);
304
-
305
- const options = spawn.mock.calls[0][2];
306
- expect(options.stdio).toBe('inherit');
307
- });
308
-
309
- it('should handle process spawn errors', async () => {
310
- mockChildProcess.on.mockImplementation((event, callback) => {
311
- if (event === 'error') {
312
- callback(new Error('Spawn failed'));
313
- }
314
- });
315
-
316
- const result = await runPrismaMigrate('dev');
317
-
318
- expect(result.success).toBe(false);
319
- });
320
-
321
- it('should hide telemetry messages', async () => {
322
- await runPrismaMigrate('dev');
323
-
324
- const options = spawn.mock.calls[0][2];
325
- expect(options.env.PRISMA_HIDE_UPDATE_MESSAGE).toBe('1');
326
- });
327
- });
328
-
329
- describe('runPrismaDbPush()', () => {
330
- let mockChildProcess;
331
-
332
- beforeEach(() => {
333
- fs.existsSync.mockReturnValue(true);
334
- mockChildProcess = {
335
- on: jest.fn((event, callback) => {
336
- if (event === 'close') {
337
- callback(0);
338
- }
339
- }),
340
- stdout: { on: jest.fn() },
341
- stderr: { on: jest.fn() }
342
- };
343
- spawn.mockReturnValue(mockChildProcess);
344
- });
345
-
346
- it('should push schema successfully for MongoDB', async () => {
347
- const result = await runPrismaDbPush();
348
-
349
- expect(result.success).toBe(true);
350
- expect(spawn).toHaveBeenCalled();
351
- });
352
-
353
- it('should use --skip-generate flag', async () => {
354
- await runPrismaDbPush();
355
-
356
- const args = spawn.mock.calls[0][1];
357
- expect(args).toContain('--skip-generate');
358
- });
359
-
360
- it('should use db push command', async () => {
361
- await runPrismaDbPush();
362
-
363
- const args = spawn.mock.calls[0][1];
364
- expect(args).toContain('db');
365
- expect(args).toContain('push');
366
- });
367
-
368
- it('should handle push failures with error', async () => {
369
- mockChildProcess.on.mockImplementation((event, callback) => {
370
- if (event === 'close') {
371
- callback(1);
372
- }
373
- });
374
-
375
- const result = await runPrismaDbPush();
376
-
377
- expect(result.success).toBe(false);
378
- expect(result.error).toContain('exited with code 1');
379
- });
380
-
381
- it('should respect verbose flag', async () => {
382
- await runPrismaDbPush(true);
383
-
384
- const options = spawn.mock.calls[0][2];
385
- expect(options.stdio).toBe('inherit');
386
- });
387
-
388
- it('should use interactive mode (stdio: inherit)', async () => {
389
- await runPrismaDbPush();
390
-
391
- const options = spawn.mock.calls[0][2];
392
- expect(options.stdio).toBe('inherit');
393
- });
394
-
395
- it('should handle schema validation errors', async () => {
396
- mockChildProcess.on.mockImplementation((event, callback) => {
397
- if (event === 'close') {
398
- callback(1);
399
- }
400
- });
401
-
402
- const result = await runPrismaDbPush();
403
-
404
- expect(result.success).toBe(false);
405
- });
406
- });
407
-
408
- describe('getMigrationCommand()', () => {
409
- it('should return dev for development stage', () => {
410
- const command = getMigrationCommand('development');
411
-
412
- expect(command).toBe('dev');
413
- });
414
-
415
- it('should return dev for dev stage', () => {
416
- const command = getMigrationCommand('dev');
417
-
418
- expect(command).toBe('dev');
419
- });
420
-
421
- it('should return dev for local stage', () => {
422
- const command = getMigrationCommand('local');
423
-
424
- expect(command).toBe('dev');
425
- });
426
-
427
- it('should return dev for test stage', () => {
428
- const command = getMigrationCommand('test');
429
-
430
- expect(command).toBe('dev');
431
- });
432
-
433
- it('should return deploy for production stage', () => {
434
- const command = getMigrationCommand('production');
435
-
436
- expect(command).toBe('deploy');
437
- });
438
-
439
- it('should return deploy for prod stage', () => {
440
- const command = getMigrationCommand('prod');
441
-
442
- expect(command).toBe('deploy');
443
- });
444
-
445
- it('should return deploy for staging stage', () => {
446
- const command = getMigrationCommand('staging');
447
-
448
- expect(command).toBe('deploy');
449
- });
450
-
451
- it('should default to dev when stage undefined', () => {
452
- const command = getMigrationCommand();
453
-
454
- expect(command).toBe('dev');
455
- });
456
-
457
- it('should read from STAGE environment variable when no argument', () => {
458
- process.env.STAGE = 'production';
459
-
460
- const command = getMigrationCommand();
461
-
462
- expect(command).toBe('deploy');
463
- });
464
-
465
- it('should prioritize argument over STAGE env var', () => {
466
- process.env.STAGE = 'production';
467
-
468
- const command = getMigrationCommand('development');
469
-
470
- expect(command).toBe('dev');
471
- });
472
-
473
- it('should handle case-insensitive stage names', () => {
474
- expect(getMigrationCommand('DEVELOPMENT')).toBe('dev');
475
- expect(getMigrationCommand('PRODUCTION')).toBe('deploy');
476
- expect(getMigrationCommand('Dev')).toBe('dev');
477
- expect(getMigrationCommand('Prod')).toBe('deploy');
478
- });
479
-
480
- it('should return deploy for unknown stages', () => {
481
- const command = getMigrationCommand('unknown-stage');
482
-
483
- expect(command).toBe('deploy');
484
- });
485
- });
486
- });
@@ -1,144 +0,0 @@
1
- /**
2
- * Tests for Cryptor - AWS SDK v3 Migration
3
- *
4
- * Tests KMS encryption/decryption operations using aws-sdk-client-mock
5
- */
6
-
7
- const { mockClient } = require('aws-sdk-client-mock');
8
- const { KMSClient, GenerateDataKeyCommand, DecryptCommand } = require('@aws-sdk/client-kms');
9
- const { Cryptor } = require('./Cryptor');
10
-
11
- describe('Cryptor - AWS SDK v3', () => {
12
- let kmsMock;
13
- const originalEnv = process.env;
14
-
15
- beforeEach(() => {
16
- kmsMock = mockClient(KMSClient);
17
- jest.clearAllMocks();
18
- process.env = { ...originalEnv };
19
- });
20
-
21
- afterEach(() => {
22
- kmsMock.reset();
23
- process.env = originalEnv;
24
- });
25
-
26
- describe('KMS Mode (shouldUseAws: true)', () => {
27
- beforeEach(() => {
28
- process.env.KMS_KEY_ARN = 'arn:aws:kms:us-east-1:123456789:key/test-key-id';
29
- });
30
-
31
- describe('encrypt()', () => {
32
- it('should encrypt text using KMS data key', async () => {
33
- const mockPlaintext = Buffer.from('mock-plaintext-key-32-bytes-long');
34
- const mockCiphertextBlob = Buffer.from('mock-encrypted-key');
35
-
36
- kmsMock.on(GenerateDataKeyCommand).resolves({
37
- KeyId: 'test-key-id',
38
- Plaintext: mockPlaintext,
39
- CiphertextBlob: mockCiphertextBlob,
40
- });
41
-
42
- const cryptor = new Cryptor({ shouldUseAws: true });
43
- const result = await cryptor.encrypt('sensitive-data');
44
-
45
- // Result should be in format: "keyId:encryptedText:encryptedKey"
46
- expect(result).toBeDefined();
47
- expect(result.split(':').length).toBe(4); // keyId:iv:ciphertext:encryptedKey format from aes
48
-
49
- expect(kmsMock.calls()).toHaveLength(1);
50
- const call = kmsMock.call(0);
51
- expect(call.args[0].input).toMatchObject({
52
- KeyId: process.env.KMS_KEY_ARN,
53
- KeySpec: 'AES_256',
54
- });
55
- });
56
-
57
- it('should handle KMS errors during encryption', async () => {
58
- kmsMock.on(GenerateDataKeyCommand).rejects(new Error('KMS unavailable'));
59
-
60
- const cryptor = new Cryptor({ shouldUseAws: true });
61
-
62
- await expect(cryptor.encrypt('sensitive-data')).rejects.toThrow('KMS unavailable');
63
- });
64
- });
65
-
66
- describe('decrypt()', () => {
67
- it('should decrypt text using KMS', async () => {
68
- const mockPlaintext = Buffer.from('mock-plaintext-key');
69
-
70
- kmsMock.on(DecryptCommand).resolves({
71
- Plaintext: mockPlaintext,
72
- });
73
-
74
- const cryptor = new Cryptor({ shouldUseAws: true });
75
-
76
- // First encrypt some data
77
- const mockDataKey = Buffer.from('test-key-32-bytes-long-exactly');
78
- kmsMock.on(GenerateDataKeyCommand).resolves({
79
- KeyId: 'test-key-id',
80
- Plaintext: mockDataKey,
81
- CiphertextBlob: Buffer.from('encrypted-key'),
82
- });
83
-
84
- const encrypted = await cryptor.encrypt('test-data');
85
-
86
- // Then decrypt
87
- kmsMock.reset();
88
- kmsMock.on(DecryptCommand).resolves({
89
- Plaintext: mockDataKey,
90
- });
91
-
92
- const decrypted = await cryptor.decrypt(encrypted);
93
-
94
- expect(decrypted).toBe('test-data');
95
- expect(kmsMock.calls()).toHaveLength(1);
96
- });
97
-
98
- it('should handle KMS errors during decryption', async () => {
99
- kmsMock.on(DecryptCommand).rejects(new Error('Invalid ciphertext'));
100
-
101
- const cryptor = new Cryptor({ shouldUseAws: true });
102
- const fakeEncrypted = Buffer.from('test-key-id').toString('base64') + ':fake:data:' + Buffer.from('fake-key').toString('base64');
103
-
104
- await expect(cryptor.decrypt(fakeEncrypted)).rejects.toThrow('Invalid ciphertext');
105
- });
106
- });
107
- });
108
-
109
- describe('Local Mode (shouldUseAws: false)', () => {
110
- beforeEach(() => {
111
- process.env.AES_KEY = 'test-aes-key-32-bytes-long-123';
112
- process.env.AES_KEY_ID = 'local-key-id';
113
- });
114
-
115
- it('should encrypt using local AES key', async () => {
116
- const cryptor = new Cryptor({ shouldUseAws: false });
117
- const result = await cryptor.encrypt('sensitive-data');
118
-
119
- expect(result).toBeDefined();
120
- expect(result.split(':').length).toBeGreaterThanOrEqual(3);
121
- expect(kmsMock.calls()).toHaveLength(0); // Should not call KMS
122
- });
123
-
124
- it('should decrypt using local AES key', async () => {
125
- const cryptor = new Cryptor({ shouldUseAws: false });
126
-
127
- const encrypted = await cryptor.encrypt('test-data');
128
- const decrypted = await cryptor.decrypt(encrypted);
129
-
130
- expect(decrypted).toBe('test-data');
131
- expect(kmsMock.calls()).toHaveLength(0); // Should not call KMS
132
- });
133
-
134
- it('should throw error if encryption key not found', async () => {
135
- delete process.env.AES_KEY_ID;
136
-
137
- const cryptor = new Cryptor({ shouldUseAws: false });
138
- const fakeEncrypted = 'unknown-key:data:key';
139
-
140
- await expect(cryptor.decrypt(fakeEncrypted)).rejects.toThrow('Encryption key not found');
141
- });
142
- });
143
- });
144
-
@@ -1,32 +0,0 @@
1
- const { BaseError } = require('./base-error');
2
-
3
- describe('BaseError', () => {
4
- it('can be inherited and instantiated', () => {
5
- class XyzError extends BaseError {}
6
- const error = new XyzError();
7
- expect(error).toHaveProperty('message', '');
8
- expect(error).toHaveProperty('stack');
9
- expect(error.stack).toContain('XyzError');
10
- expect(error.stack).toContain('at new XyzError');
11
- expect(error.stack).toContain('base-error.test.js:');
12
- });
13
-
14
- it('can set the error message', () => {
15
- class TestError extends BaseError {}
16
- const error = new TestError('Goblins!');
17
- expect(error).toHaveProperty('message', 'Goblins!');
18
- });
19
-
20
- it('sets the error name correctly', () => {
21
- class TestError extends BaseError {}
22
- const error = new TestError();
23
- expect(error).toHaveProperty('name', 'TestError');
24
- });
25
-
26
- it('can set the parent cause', () => {
27
- class TestError extends BaseError {}
28
- const rootError = new Error('Davros!');
29
- const error = new TestError('Daleks!', { cause: rootError });
30
- expect(error).toHaveProperty('cause', rootError);
31
- });
32
- });