@friggframework/devtools 2.0.0-next.53 → 2.0.0-next.55
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/frigg-cli/README.md +13 -14
- package/frigg-cli/__tests__/unit/commands/db-setup.test.js +267 -166
- package/frigg-cli/__tests__/unit/utils/database-validator.test.js +45 -14
- package/frigg-cli/__tests__/unit/utils/error-messages.test.js +44 -3
- package/frigg-cli/db-setup-command/index.js +75 -22
- package/frigg-cli/deploy-command/index.js +6 -3
- package/frigg-cli/utils/database-validator.js +18 -5
- package/frigg-cli/utils/error-messages.js +84 -12
- package/infrastructure/README.md +28 -0
- package/infrastructure/domains/database/migration-builder.js +26 -20
- package/infrastructure/domains/database/migration-builder.test.js +27 -0
- package/infrastructure/domains/integration/integration-builder.js +17 -13
- package/infrastructure/domains/integration/integration-builder.test.js +23 -0
- package/infrastructure/domains/networking/vpc-builder.js +240 -18
- package/infrastructure/domains/networking/vpc-builder.test.js +711 -13
- package/infrastructure/domains/networking/vpc-resolver.js +221 -40
- package/infrastructure/domains/networking/vpc-resolver.test.js +318 -18
- package/infrastructure/domains/security/kms-builder.js +55 -6
- package/infrastructure/domains/security/kms-builder.test.js +19 -1
- package/infrastructure/domains/shared/cloudformation-discovery.js +310 -13
- package/infrastructure/domains/shared/cloudformation-discovery.test.js +395 -0
- package/infrastructure/domains/shared/providers/aws-provider-adapter.js +41 -6
- package/infrastructure/domains/shared/providers/aws-provider-adapter.test.js +39 -0
- package/infrastructure/domains/shared/resource-discovery.js +17 -5
- package/infrastructure/domains/shared/resource-discovery.test.js +36 -0
- package/infrastructure/domains/shared/utilities/base-definition-factory.js +30 -20
- package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +43 -0
- package/infrastructure/infrastructure-composer.js +11 -3
- package/infrastructure/scripts/build-prisma-layer.js +153 -78
- package/infrastructure/scripts/build-prisma-layer.test.js +27 -11
- package/layers/prisma/.build-complete +3 -0
- package/package.json +7 -7
|
@@ -3,7 +3,7 @@ const mockValidator = {
|
|
|
3
3
|
validateDatabaseUrl: jest.fn(),
|
|
4
4
|
getDatabaseType: jest.fn(),
|
|
5
5
|
testDatabaseConnection: jest.fn(),
|
|
6
|
-
checkPrismaClientGenerated: jest.fn()
|
|
6
|
+
checkPrismaClientGenerated: jest.fn(),
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
const mockRunner = {
|
|
@@ -11,7 +11,7 @@ const mockRunner = {
|
|
|
11
11
|
checkDatabaseState: jest.fn(),
|
|
12
12
|
runPrismaMigrate: jest.fn(),
|
|
13
13
|
runPrismaDbPush: jest.fn(),
|
|
14
|
-
getMigrationCommand: jest.fn()
|
|
14
|
+
getMigrationCommand: jest.fn(),
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const mockErrorMessages = {
|
|
@@ -19,18 +19,21 @@ const mockErrorMessages = {
|
|
|
19
19
|
getDatabaseTypeNotConfiguredError: jest.fn(),
|
|
20
20
|
getDatabaseConnectionError: jest.fn(),
|
|
21
21
|
getPrismaCommandError: jest.fn(),
|
|
22
|
-
getDatabaseSetupSuccess: jest.fn()
|
|
22
|
+
getDatabaseSetupSuccess: jest.fn(),
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
jest.mock('../../../utils/database-validator', () => mockValidator);
|
|
26
|
-
jest.mock(
|
|
26
|
+
jest.mock(
|
|
27
|
+
'@friggframework/core/database/utils/prisma-runner',
|
|
28
|
+
() => mockRunner
|
|
29
|
+
);
|
|
27
30
|
jest.mock('../../../utils/error-messages', () => mockErrorMessages);
|
|
28
31
|
jest.mock('dotenv');
|
|
29
32
|
|
|
30
33
|
const { dbSetupCommand } = require('../../../db-setup-command');
|
|
31
34
|
const {
|
|
32
35
|
createMockDatabaseValidator,
|
|
33
|
-
createMockPrismaRunner
|
|
36
|
+
createMockPrismaRunner,
|
|
34
37
|
} = require('../../utils/prisma-mock');
|
|
35
38
|
|
|
36
39
|
const dotenv = require('dotenv');
|
|
@@ -46,16 +49,34 @@ describe('DB Setup Command', () => {
|
|
|
46
49
|
const defaultRunner = createMockPrismaRunner();
|
|
47
50
|
|
|
48
51
|
// Apply default implementations
|
|
49
|
-
mockValidator.validateDatabaseUrl.mockImplementation(
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
mockValidator.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
mockValidator.validateDatabaseUrl.mockImplementation(
|
|
53
|
+
defaultValidator.validateDatabaseUrl
|
|
54
|
+
);
|
|
55
|
+
mockValidator.getDatabaseType.mockImplementation(
|
|
56
|
+
defaultValidator.getDatabaseType
|
|
57
|
+
);
|
|
58
|
+
mockValidator.testDatabaseConnection.mockImplementation(
|
|
59
|
+
defaultValidator.testDatabaseConnection
|
|
60
|
+
);
|
|
61
|
+
mockValidator.checkPrismaClientGenerated.mockImplementation(
|
|
62
|
+
defaultValidator.checkPrismaClientGenerated
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
mockRunner.runPrismaGenerate.mockImplementation(
|
|
66
|
+
defaultRunner.runPrismaGenerate
|
|
67
|
+
);
|
|
68
|
+
mockRunner.checkDatabaseState.mockImplementation(
|
|
69
|
+
defaultRunner.checkDatabaseState
|
|
70
|
+
);
|
|
71
|
+
mockRunner.runPrismaMigrate.mockImplementation(
|
|
72
|
+
defaultRunner.runPrismaMigrate
|
|
73
|
+
);
|
|
74
|
+
mockRunner.runPrismaDbPush.mockImplementation(
|
|
75
|
+
defaultRunner.runPrismaDbPush
|
|
76
|
+
);
|
|
77
|
+
mockRunner.getMigrationCommand.mockImplementation(
|
|
78
|
+
defaultRunner.getMigrationCommand
|
|
79
|
+
);
|
|
59
80
|
|
|
60
81
|
// Mock dotenv
|
|
61
82
|
dotenv.config = jest.fn();
|
|
@@ -66,11 +87,19 @@ describe('DB Setup Command', () => {
|
|
|
66
87
|
mockProcessExit = jest.spyOn(process, 'exit').mockImplementation();
|
|
67
88
|
|
|
68
89
|
// Mock error message functions with default return values
|
|
69
|
-
mockErrorMessages.getDatabaseUrlMissingError.mockReturnValue(
|
|
70
|
-
|
|
71
|
-
|
|
90
|
+
mockErrorMessages.getDatabaseUrlMissingError.mockReturnValue(
|
|
91
|
+
'DATABASE_URL missing error'
|
|
92
|
+
);
|
|
93
|
+
mockErrorMessages.getDatabaseTypeNotConfiguredError.mockReturnValue(
|
|
94
|
+
'DB type error'
|
|
95
|
+
);
|
|
96
|
+
mockErrorMessages.getDatabaseConnectionError.mockReturnValue(
|
|
97
|
+
'Connection error'
|
|
98
|
+
);
|
|
72
99
|
mockErrorMessages.getPrismaCommandError.mockReturnValue('Prisma error');
|
|
73
|
-
mockErrorMessages.getDatabaseSetupSuccess.mockReturnValue(
|
|
100
|
+
mockErrorMessages.getDatabaseSetupSuccess.mockReturnValue(
|
|
101
|
+
'Success message'
|
|
102
|
+
);
|
|
74
103
|
});
|
|
75
104
|
|
|
76
105
|
afterEach(() => {
|
|
@@ -82,87 +111,157 @@ describe('DB Setup Command', () => {
|
|
|
82
111
|
|
|
83
112
|
describe('Success Cases', () => {
|
|
84
113
|
it('should complete setup successfully for MongoDB', async () => {
|
|
85
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
114
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
115
|
+
dbType: 'mongodb',
|
|
116
|
+
});
|
|
86
117
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
87
|
-
generated: false // Client doesn't exist, will generate
|
|
118
|
+
generated: false, // Client doesn't exist, will generate
|
|
119
|
+
});
|
|
120
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
121
|
+
upToDate: false,
|
|
88
122
|
});
|
|
89
|
-
mockRunner.checkDatabaseState.mockResolvedValue({ upToDate: false });
|
|
90
123
|
|
|
91
124
|
await dbSetupCommand({ verbose: false, stage: 'development' });
|
|
92
125
|
|
|
93
126
|
expect(mockValidator.validateDatabaseUrl).toHaveBeenCalled();
|
|
94
127
|
expect(mockValidator.getDatabaseType).toHaveBeenCalled();
|
|
95
|
-
expect(
|
|
96
|
-
|
|
97
|
-
|
|
128
|
+
expect(
|
|
129
|
+
mockValidator.checkPrismaClientGenerated
|
|
130
|
+
).toHaveBeenCalledWith('mongodb');
|
|
131
|
+
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
132
|
+
'mongodb',
|
|
133
|
+
false
|
|
134
|
+
);
|
|
98
135
|
expect(mockRunner.runPrismaDbPush).toHaveBeenCalled();
|
|
99
136
|
expect(mockProcessExit).not.toHaveBeenCalled();
|
|
100
137
|
});
|
|
101
138
|
|
|
139
|
+
it('should treat DocumentDB as Mongo-compatible for schema pushes', async () => {
|
|
140
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
141
|
+
dbType: 'documentdb',
|
|
142
|
+
});
|
|
143
|
+
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
144
|
+
generated: false,
|
|
145
|
+
});
|
|
146
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
147
|
+
upToDate: false,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
await dbSetupCommand({ verbose: false, stage: 'development' });
|
|
151
|
+
|
|
152
|
+
expect(
|
|
153
|
+
mockValidator.checkPrismaClientGenerated
|
|
154
|
+
).toHaveBeenCalledWith('documentdb');
|
|
155
|
+
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
156
|
+
'mongodb',
|
|
157
|
+
false
|
|
158
|
+
);
|
|
159
|
+
expect(mockRunner.runPrismaDbPush).toHaveBeenCalled();
|
|
160
|
+
expect(mockConsoleLog).toHaveBeenCalledWith(
|
|
161
|
+
expect.stringContaining('AWS DocumentDB (MongoDB-compatible)')
|
|
162
|
+
);
|
|
163
|
+
});
|
|
164
|
+
|
|
102
165
|
it('should complete setup successfully for PostgreSQL', async () => {
|
|
103
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
166
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
167
|
+
dbType: 'postgresql',
|
|
168
|
+
});
|
|
104
169
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
105
|
-
generated: false // Client doesn't exist, will generate
|
|
170
|
+
generated: false, // Client doesn't exist, will generate
|
|
171
|
+
});
|
|
172
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
173
|
+
upToDate: false,
|
|
106
174
|
});
|
|
107
|
-
mockRunner.checkDatabaseState.mockResolvedValue({ upToDate: false });
|
|
108
175
|
|
|
109
176
|
await dbSetupCommand({ verbose: false, stage: 'development' });
|
|
110
177
|
|
|
111
|
-
expect(
|
|
112
|
-
|
|
178
|
+
expect(
|
|
179
|
+
mockValidator.checkPrismaClientGenerated
|
|
180
|
+
).toHaveBeenCalledWith('postgresql');
|
|
181
|
+
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
182
|
+
'postgresql',
|
|
183
|
+
false
|
|
184
|
+
);
|
|
113
185
|
expect(mockRunner.runPrismaMigrate).toHaveBeenCalled();
|
|
114
186
|
expect(mockProcessExit).not.toHaveBeenCalled();
|
|
115
187
|
});
|
|
116
188
|
|
|
117
189
|
it('should skip migrations when already up-to-date (PostgreSQL)', async () => {
|
|
118
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
190
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
191
|
+
dbType: 'postgresql',
|
|
192
|
+
});
|
|
119
193
|
mockRunner.checkDatabaseState.mockResolvedValue({ upToDate: true });
|
|
120
194
|
mockRunner.getMigrationCommand.mockReturnValue('deploy');
|
|
121
195
|
|
|
122
196
|
await dbSetupCommand({ verbose: false, stage: 'production' });
|
|
123
197
|
|
|
124
198
|
expect(mockRunner.runPrismaMigrate).not.toHaveBeenCalled();
|
|
125
|
-
expect(mockConsoleLog).toHaveBeenCalledWith(
|
|
199
|
+
expect(mockConsoleLog).toHaveBeenCalledWith(
|
|
200
|
+
expect.stringContaining('already up-to-date')
|
|
201
|
+
);
|
|
126
202
|
});
|
|
127
203
|
|
|
128
204
|
it('should use migrate dev in development stage', async () => {
|
|
129
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
205
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
206
|
+
dbType: 'postgresql',
|
|
207
|
+
});
|
|
130
208
|
mockRunner.getMigrationCommand.mockReturnValue('dev');
|
|
131
|
-
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
209
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
210
|
+
upToDate: false,
|
|
211
|
+
});
|
|
132
212
|
|
|
133
213
|
await dbSetupCommand({ verbose: false, stage: 'development' });
|
|
134
214
|
|
|
135
|
-
expect(mockRunner.getMigrationCommand).toHaveBeenCalledWith(
|
|
136
|
-
|
|
215
|
+
expect(mockRunner.getMigrationCommand).toHaveBeenCalledWith(
|
|
216
|
+
'development'
|
|
217
|
+
);
|
|
218
|
+
expect(mockRunner.runPrismaMigrate).toHaveBeenCalledWith(
|
|
219
|
+
'dev',
|
|
220
|
+
false
|
|
221
|
+
);
|
|
137
222
|
});
|
|
138
223
|
|
|
139
224
|
it('should use migrate deploy in production stage', async () => {
|
|
140
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
225
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
226
|
+
dbType: 'postgresql',
|
|
227
|
+
});
|
|
141
228
|
mockRunner.getMigrationCommand.mockReturnValue('deploy');
|
|
142
|
-
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
229
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
230
|
+
upToDate: false,
|
|
231
|
+
});
|
|
143
232
|
|
|
144
233
|
await dbSetupCommand({ verbose: false, stage: 'production' });
|
|
145
234
|
|
|
146
|
-
expect(mockRunner.getMigrationCommand).toHaveBeenCalledWith(
|
|
147
|
-
|
|
235
|
+
expect(mockRunner.getMigrationCommand).toHaveBeenCalledWith(
|
|
236
|
+
'production'
|
|
237
|
+
);
|
|
238
|
+
expect(mockRunner.runPrismaMigrate).toHaveBeenCalledWith(
|
|
239
|
+
'deploy',
|
|
240
|
+
false
|
|
241
|
+
);
|
|
148
242
|
});
|
|
149
243
|
|
|
150
244
|
it('should respect --verbose flag', async () => {
|
|
151
245
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
152
|
-
generated: false // Client doesn't exist, will generate
|
|
246
|
+
generated: false, // Client doesn't exist, will generate
|
|
153
247
|
});
|
|
154
248
|
|
|
155
249
|
await dbSetupCommand({ verbose: true, stage: 'development' });
|
|
156
250
|
|
|
157
|
-
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
251
|
+
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
252
|
+
'mongodb',
|
|
253
|
+
true
|
|
254
|
+
);
|
|
158
255
|
});
|
|
159
256
|
|
|
160
257
|
it('should load .env file from project root', async () => {
|
|
161
258
|
await dbSetupCommand({ verbose: false, stage: 'development' });
|
|
162
259
|
|
|
163
|
-
expect(dotenv.config).toHaveBeenCalledWith(
|
|
164
|
-
|
|
165
|
-
|
|
260
|
+
expect(dotenv.config).toHaveBeenCalledWith(
|
|
261
|
+
expect.objectContaining({
|
|
262
|
+
path: expect.stringContaining('.env'),
|
|
263
|
+
})
|
|
264
|
+
);
|
|
166
265
|
});
|
|
167
266
|
});
|
|
168
267
|
|
|
@@ -171,17 +270,17 @@ describe('DB Setup Command', () => {
|
|
|
171
270
|
// Client exists
|
|
172
271
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
173
272
|
generated: true,
|
|
174
|
-
path: '/path/to/client'
|
|
273
|
+
path: '/path/to/client',
|
|
175
274
|
});
|
|
176
275
|
|
|
177
276
|
await dbSetupCommand({ verbose: false, stage: 'development' });
|
|
178
277
|
|
|
179
278
|
// Should check if client exists
|
|
180
|
-
expect(
|
|
279
|
+
expect(
|
|
280
|
+
mockValidator.checkPrismaClientGenerated
|
|
281
|
+
).toHaveBeenCalledWith('mongodb');
|
|
181
282
|
// Should NOT call generate
|
|
182
283
|
expect(mockRunner.runPrismaGenerate).not.toHaveBeenCalled();
|
|
183
|
-
// Should still test connection and complete setup
|
|
184
|
-
expect(mockValidator.testDatabaseConnection).toHaveBeenCalled();
|
|
185
284
|
expect(mockProcessExit).not.toHaveBeenCalled();
|
|
186
285
|
});
|
|
187
286
|
|
|
@@ -189,15 +288,20 @@ describe('DB Setup Command', () => {
|
|
|
189
288
|
// Client does NOT exist
|
|
190
289
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
191
290
|
generated: false,
|
|
192
|
-
error: 'Client not found'
|
|
291
|
+
error: 'Client not found',
|
|
193
292
|
});
|
|
194
293
|
|
|
195
294
|
await dbSetupCommand({ verbose: false, stage: 'development' });
|
|
196
295
|
|
|
197
296
|
// Should check if client exists
|
|
198
|
-
expect(
|
|
297
|
+
expect(
|
|
298
|
+
mockValidator.checkPrismaClientGenerated
|
|
299
|
+
).toHaveBeenCalledWith('mongodb');
|
|
199
300
|
// Should call generate
|
|
200
|
-
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
301
|
+
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
302
|
+
'mongodb',
|
|
303
|
+
false
|
|
304
|
+
);
|
|
201
305
|
// Should complete setup
|
|
202
306
|
expect(mockProcessExit).not.toHaveBeenCalled();
|
|
203
307
|
});
|
|
@@ -206,15 +310,24 @@ describe('DB Setup Command', () => {
|
|
|
206
310
|
// Client exists
|
|
207
311
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
208
312
|
generated: true,
|
|
209
|
-
path: '/path/to/client'
|
|
313
|
+
path: '/path/to/client',
|
|
210
314
|
});
|
|
211
315
|
|
|
212
|
-
await dbSetupCommand({
|
|
316
|
+
await dbSetupCommand({
|
|
317
|
+
verbose: false,
|
|
318
|
+
stage: 'development',
|
|
319
|
+
force: true,
|
|
320
|
+
});
|
|
213
321
|
|
|
214
322
|
// Should check if client exists
|
|
215
|
-
expect(
|
|
323
|
+
expect(
|
|
324
|
+
mockValidator.checkPrismaClientGenerated
|
|
325
|
+
).toHaveBeenCalledWith('mongodb');
|
|
216
326
|
// Should STILL call generate because of --force
|
|
217
|
-
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
327
|
+
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
328
|
+
'mongodb',
|
|
329
|
+
false
|
|
330
|
+
);
|
|
218
331
|
// Should complete setup
|
|
219
332
|
expect(mockProcessExit).not.toHaveBeenCalled();
|
|
220
333
|
});
|
|
@@ -222,7 +335,7 @@ describe('DB Setup Command', () => {
|
|
|
222
335
|
it('should show client location in verbose mode when skipping generation', async () => {
|
|
223
336
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
224
337
|
generated: true,
|
|
225
|
-
path: '/path/to/prisma/client'
|
|
338
|
+
path: '/path/to/prisma/client',
|
|
226
339
|
});
|
|
227
340
|
|
|
228
341
|
await dbSetupCommand({ verbose: true, stage: 'development' });
|
|
@@ -236,16 +349,25 @@ describe('DB Setup Command', () => {
|
|
|
236
349
|
|
|
237
350
|
it('should generate for different database types', async () => {
|
|
238
351
|
// Test PostgreSQL
|
|
239
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
352
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
353
|
+
dbType: 'postgresql',
|
|
354
|
+
});
|
|
240
355
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
241
|
-
generated: false
|
|
356
|
+
generated: false,
|
|
357
|
+
});
|
|
358
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
359
|
+
upToDate: false,
|
|
242
360
|
});
|
|
243
|
-
mockRunner.checkDatabaseState.mockResolvedValue({ upToDate: false });
|
|
244
361
|
|
|
245
362
|
await dbSetupCommand({ verbose: false, stage: 'development' });
|
|
246
363
|
|
|
247
|
-
expect(
|
|
248
|
-
|
|
364
|
+
expect(
|
|
365
|
+
mockValidator.checkPrismaClientGenerated
|
|
366
|
+
).toHaveBeenCalledWith('postgresql');
|
|
367
|
+
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
368
|
+
'postgresql',
|
|
369
|
+
false
|
|
370
|
+
);
|
|
249
371
|
});
|
|
250
372
|
});
|
|
251
373
|
|
|
@@ -253,7 +375,7 @@ describe('DB Setup Command', () => {
|
|
|
253
375
|
it('should fail when DATABASE_URL missing', async () => {
|
|
254
376
|
mockValidator.validateDatabaseUrl.mockReturnValue({
|
|
255
377
|
valid: false,
|
|
256
|
-
error: 'DATABASE_URL not found'
|
|
378
|
+
error: 'DATABASE_URL not found',
|
|
257
379
|
});
|
|
258
380
|
|
|
259
381
|
await dbSetupCommand({});
|
|
@@ -265,68 +387,33 @@ describe('DB Setup Command', () => {
|
|
|
265
387
|
it('should fail when DATABASE_URL is empty', async () => {
|
|
266
388
|
mockValidator.validateDatabaseUrl.mockReturnValue({
|
|
267
389
|
valid: false,
|
|
268
|
-
error: 'DATABASE_URL is empty'
|
|
390
|
+
error: 'DATABASE_URL is empty',
|
|
269
391
|
});
|
|
270
392
|
|
|
271
393
|
await dbSetupCommand({});
|
|
272
394
|
|
|
273
|
-
expect(
|
|
395
|
+
expect(
|
|
396
|
+
mockErrorMessages.getDatabaseUrlMissingError
|
|
397
|
+
).toHaveBeenCalled();
|
|
274
398
|
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
|
275
399
|
});
|
|
276
400
|
|
|
277
401
|
it('should fail when database type not configured', async () => {
|
|
278
402
|
mockValidator.getDatabaseType.mockReturnValue({
|
|
279
|
-
error: 'Database not configured'
|
|
403
|
+
error: 'Database not configured',
|
|
280
404
|
});
|
|
281
405
|
|
|
282
406
|
await dbSetupCommand({});
|
|
283
407
|
|
|
284
|
-
expect(
|
|
408
|
+
expect(
|
|
409
|
+
mockErrorMessages.getDatabaseTypeNotConfiguredError
|
|
410
|
+
).toHaveBeenCalled();
|
|
285
411
|
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
|
286
412
|
});
|
|
287
413
|
|
|
288
414
|
it('should fail when backend definition not found', async () => {
|
|
289
415
|
mockValidator.getDatabaseType.mockReturnValue({
|
|
290
|
-
error: 'Backend not found'
|
|
291
|
-
});
|
|
292
|
-
|
|
293
|
-
await dbSetupCommand({});
|
|
294
|
-
|
|
295
|
-
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
describe('Failure Cases - Connection', () => {
|
|
300
|
-
it('should fail when database connection times out', async () => {
|
|
301
|
-
mockValidator.testDatabaseConnection.mockResolvedValue({
|
|
302
|
-
connected: false,
|
|
303
|
-
error: 'Connection timeout'
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
await dbSetupCommand({});
|
|
307
|
-
|
|
308
|
-
expect(mockErrorMessages.getDatabaseConnectionError).toHaveBeenCalledWith(
|
|
309
|
-
'Connection timeout',
|
|
310
|
-
'mongodb'
|
|
311
|
-
);
|
|
312
|
-
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
|
313
|
-
});
|
|
314
|
-
|
|
315
|
-
it('should fail when database credentials invalid', async () => {
|
|
316
|
-
mockValidator.testDatabaseConnection.mockResolvedValue({
|
|
317
|
-
connected: false,
|
|
318
|
-
error: 'Authentication failed'
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
await dbSetupCommand({});
|
|
322
|
-
|
|
323
|
-
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
it('should fail when database not accessible', async () => {
|
|
327
|
-
mockValidator.testDatabaseConnection.mockResolvedValue({
|
|
328
|
-
connected: false,
|
|
329
|
-
error: 'Connection refused'
|
|
416
|
+
error: 'Backend not found',
|
|
330
417
|
});
|
|
331
418
|
|
|
332
419
|
await dbSetupCommand({});
|
|
@@ -338,47 +425,53 @@ describe('DB Setup Command', () => {
|
|
|
338
425
|
describe('Failure Cases - Prisma Operations', () => {
|
|
339
426
|
it('should fail when prisma generate fails', async () => {
|
|
340
427
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
341
|
-
generated: false // Client doesn't exist, will attempt generation
|
|
428
|
+
generated: false, // Client doesn't exist, will attempt generation
|
|
342
429
|
});
|
|
343
430
|
mockRunner.runPrismaGenerate.mockResolvedValue({
|
|
344
431
|
success: false,
|
|
345
|
-
error: 'Generation failed'
|
|
432
|
+
error: 'Generation failed',
|
|
346
433
|
});
|
|
347
434
|
|
|
348
435
|
await dbSetupCommand({});
|
|
349
436
|
|
|
350
|
-
expect(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
);
|
|
437
|
+
expect(
|
|
438
|
+
mockErrorMessages.getPrismaCommandError
|
|
439
|
+
).toHaveBeenCalledWith('generate', 'Generation failed');
|
|
354
440
|
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
|
355
441
|
});
|
|
356
442
|
|
|
357
443
|
it('should fail when migrate dev fails (PostgreSQL)', async () => {
|
|
358
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
444
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
445
|
+
dbType: 'postgresql',
|
|
446
|
+
});
|
|
359
447
|
mockRunner.getMigrationCommand.mockReturnValue('dev');
|
|
360
|
-
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
448
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
449
|
+
upToDate: false,
|
|
450
|
+
});
|
|
361
451
|
mockRunner.runPrismaMigrate.mockResolvedValue({
|
|
362
452
|
success: false,
|
|
363
|
-
error: 'Migration failed'
|
|
453
|
+
error: 'Migration failed',
|
|
364
454
|
});
|
|
365
455
|
|
|
366
456
|
await dbSetupCommand({ stage: 'development' });
|
|
367
457
|
|
|
368
|
-
expect(
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
);
|
|
458
|
+
expect(
|
|
459
|
+
mockErrorMessages.getPrismaCommandError
|
|
460
|
+
).toHaveBeenCalledWith('migrate', 'Migration failed');
|
|
372
461
|
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
|
373
462
|
});
|
|
374
463
|
|
|
375
464
|
it('should fail when migrate deploy fails (PostgreSQL)', async () => {
|
|
376
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
465
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
466
|
+
dbType: 'postgresql',
|
|
467
|
+
});
|
|
377
468
|
mockRunner.getMigrationCommand.mockReturnValue('deploy');
|
|
378
|
-
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
469
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
470
|
+
upToDate: false,
|
|
471
|
+
});
|
|
379
472
|
mockRunner.runPrismaMigrate.mockResolvedValue({
|
|
380
473
|
success: false,
|
|
381
|
-
error: 'Deploy failed'
|
|
474
|
+
error: 'Deploy failed',
|
|
382
475
|
});
|
|
383
476
|
|
|
384
477
|
await dbSetupCommand({ stage: 'production' });
|
|
@@ -389,25 +482,24 @@ describe('DB Setup Command', () => {
|
|
|
389
482
|
it('should fail when db push fails (MongoDB)', async () => {
|
|
390
483
|
mockRunner.runPrismaDbPush.mockResolvedValue({
|
|
391
484
|
success: false,
|
|
392
|
-
error: 'Push failed'
|
|
485
|
+
error: 'Push failed',
|
|
393
486
|
});
|
|
394
487
|
|
|
395
488
|
await dbSetupCommand({});
|
|
396
489
|
|
|
397
|
-
expect(
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
);
|
|
490
|
+
expect(
|
|
491
|
+
mockErrorMessages.getPrismaCommandError
|
|
492
|
+
).toHaveBeenCalledWith('db push', 'Push failed');
|
|
401
493
|
expect(mockProcessExit).toHaveBeenCalledWith(1);
|
|
402
494
|
});
|
|
403
495
|
|
|
404
496
|
it('should fail when schema file missing', async () => {
|
|
405
497
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
406
|
-
generated: false // Client doesn't exist, will attempt generation
|
|
498
|
+
generated: false, // Client doesn't exist, will attempt generation
|
|
407
499
|
});
|
|
408
500
|
mockRunner.runPrismaGenerate.mockResolvedValue({
|
|
409
501
|
success: false,
|
|
410
|
-
error: 'Schema not found'
|
|
502
|
+
error: 'Schema not found',
|
|
411
503
|
});
|
|
412
504
|
|
|
413
505
|
await dbSetupCommand({});
|
|
@@ -420,36 +512,24 @@ describe('DB Setup Command', () => {
|
|
|
420
512
|
it('should display helpful error for missing DATABASE_URL', async () => {
|
|
421
513
|
mockValidator.validateDatabaseUrl.mockReturnValue({
|
|
422
514
|
valid: false,
|
|
423
|
-
error: 'Not found'
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
await dbSetupCommand({});
|
|
427
|
-
|
|
428
|
-
expect(mockErrorMessages.getDatabaseUrlMissingError).toHaveBeenCalled();
|
|
429
|
-
});
|
|
430
|
-
|
|
431
|
-
it('should display helpful error for connection failure', async () => {
|
|
432
|
-
mockValidator.testDatabaseConnection.mockResolvedValue({
|
|
433
|
-
connected: false,
|
|
434
|
-
error: 'Network error'
|
|
515
|
+
error: 'Not found',
|
|
435
516
|
});
|
|
436
517
|
|
|
437
518
|
await dbSetupCommand({});
|
|
438
519
|
|
|
439
|
-
expect(
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
);
|
|
520
|
+
expect(
|
|
521
|
+
mockErrorMessages.getDatabaseUrlMissingError
|
|
522
|
+
).toHaveBeenCalled();
|
|
443
523
|
});
|
|
444
524
|
|
|
445
525
|
it('should display helpful error for Prisma failures', async () => {
|
|
446
526
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
447
|
-
generated: false // Client doesn't exist, will attempt generation
|
|
527
|
+
generated: false, // Client doesn't exist, will attempt generation
|
|
448
528
|
});
|
|
449
529
|
mockRunner.runPrismaGenerate.mockResolvedValue({
|
|
450
530
|
success: false,
|
|
451
531
|
error: 'Some error',
|
|
452
|
-
output: 'Detailed output'
|
|
532
|
+
output: 'Detailed output',
|
|
453
533
|
});
|
|
454
534
|
|
|
455
535
|
await dbSetupCommand({});
|
|
@@ -459,7 +539,7 @@ describe('DB Setup Command', () => {
|
|
|
459
539
|
|
|
460
540
|
it('should exit with code 1 on failure', async () => {
|
|
461
541
|
mockValidator.validateDatabaseUrl.mockReturnValue({
|
|
462
|
-
valid: false
|
|
542
|
+
valid: false,
|
|
463
543
|
});
|
|
464
544
|
|
|
465
545
|
await dbSetupCommand({});
|
|
@@ -469,7 +549,7 @@ describe('DB Setup Command', () => {
|
|
|
469
549
|
|
|
470
550
|
it('should not exit with code 0 on failure', async () => {
|
|
471
551
|
mockValidator.validateDatabaseUrl.mockReturnValue({
|
|
472
|
-
valid: false
|
|
552
|
+
valid: false,
|
|
473
553
|
});
|
|
474
554
|
|
|
475
555
|
await dbSetupCommand({});
|
|
@@ -480,10 +560,9 @@ describe('DB Setup Command', () => {
|
|
|
480
560
|
it('should display success message on completion', async () => {
|
|
481
561
|
await dbSetupCommand({ stage: 'development' });
|
|
482
562
|
|
|
483
|
-
expect(
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
);
|
|
563
|
+
expect(
|
|
564
|
+
mockErrorMessages.getDatabaseSetupSuccess
|
|
565
|
+
).toHaveBeenCalledWith('mongodb', 'development');
|
|
487
566
|
});
|
|
488
567
|
});
|
|
489
568
|
|
|
@@ -497,39 +576,55 @@ describe('DB Setup Command', () => {
|
|
|
497
576
|
|
|
498
577
|
it('should pass verbose flag to Prisma commands', async () => {
|
|
499
578
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
500
|
-
generated: false // Client doesn't exist, will generate
|
|
579
|
+
generated: false, // Client doesn't exist, will generate
|
|
501
580
|
});
|
|
502
581
|
|
|
503
582
|
await dbSetupCommand({ verbose: true });
|
|
504
583
|
|
|
505
|
-
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
584
|
+
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
585
|
+
'mongodb',
|
|
586
|
+
true
|
|
587
|
+
);
|
|
506
588
|
expect(mockRunner.runPrismaDbPush).toHaveBeenCalledWith(true);
|
|
507
589
|
});
|
|
508
590
|
|
|
509
591
|
it('should not show verbose output when flag disabled', async () => {
|
|
510
592
|
mockValidator.checkPrismaClientGenerated.mockReturnValue({
|
|
511
|
-
generated: false // Client doesn't exist, will generate
|
|
593
|
+
generated: false, // Client doesn't exist, will generate
|
|
512
594
|
});
|
|
513
595
|
|
|
514
596
|
await dbSetupCommand({ verbose: false });
|
|
515
597
|
|
|
516
|
-
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
598
|
+
expect(mockRunner.runPrismaGenerate).toHaveBeenCalledWith(
|
|
599
|
+
'mongodb',
|
|
600
|
+
false
|
|
601
|
+
);
|
|
517
602
|
});
|
|
518
603
|
});
|
|
519
604
|
|
|
520
605
|
describe('Stage Handling', () => {
|
|
521
606
|
it('should use provided stage option', async () => {
|
|
522
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
523
|
-
|
|
607
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
608
|
+
dbType: 'postgresql',
|
|
609
|
+
});
|
|
610
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
611
|
+
upToDate: false,
|
|
612
|
+
});
|
|
524
613
|
|
|
525
614
|
await dbSetupCommand({ stage: 'production' });
|
|
526
615
|
|
|
527
|
-
expect(mockRunner.getMigrationCommand).toHaveBeenCalledWith(
|
|
616
|
+
expect(mockRunner.getMigrationCommand).toHaveBeenCalledWith(
|
|
617
|
+
'production'
|
|
618
|
+
);
|
|
528
619
|
});
|
|
529
620
|
|
|
530
621
|
it('should default to development when no stage provided', async () => {
|
|
531
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
532
|
-
|
|
622
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
623
|
+
dbType: 'postgresql',
|
|
624
|
+
});
|
|
625
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
626
|
+
upToDate: false,
|
|
627
|
+
});
|
|
533
628
|
|
|
534
629
|
await dbSetupCommand({});
|
|
535
630
|
|
|
@@ -537,12 +632,18 @@ describe('DB Setup Command', () => {
|
|
|
537
632
|
});
|
|
538
633
|
|
|
539
634
|
it('should handle different stage values', async () => {
|
|
540
|
-
mockValidator.getDatabaseType.mockReturnValue({
|
|
541
|
-
|
|
635
|
+
mockValidator.getDatabaseType.mockReturnValue({
|
|
636
|
+
dbType: 'postgresql',
|
|
637
|
+
});
|
|
638
|
+
mockRunner.checkDatabaseState.mockResolvedValue({
|
|
639
|
+
upToDate: false,
|
|
640
|
+
});
|
|
542
641
|
|
|
543
642
|
await dbSetupCommand({ stage: 'staging' });
|
|
544
643
|
|
|
545
|
-
expect(mockRunner.getMigrationCommand).toHaveBeenCalledWith(
|
|
644
|
+
expect(mockRunner.getMigrationCommand).toHaveBeenCalledWith(
|
|
645
|
+
'staging'
|
|
646
|
+
);
|
|
546
647
|
});
|
|
547
648
|
});
|
|
548
649
|
});
|