@friggframework/devtools 2.0.0--canary.395.495dc7d.0 → 2.0.0--canary.395.ada1d9d.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.
- package/frigg-cli/__tests__/unit/commands/build.test.js +173 -405
- package/frigg-cli/__tests__/unit/commands/db-setup.test.js +112 -0
- package/frigg-cli/__tests__/unit/commands/install.test.js +359 -377
- package/frigg-cli/__tests__/unit/commands/ui.test.js +266 -512
- package/frigg-cli/__tests__/unit/utils/database-validator.test.js +4 -4
- package/frigg-cli/__tests__/unit/utils/error-messages.test.js +2 -2
- package/frigg-cli/__tests__/unit/utils/prisma-runner.test.js +13 -7
- package/frigg-cli/__tests__/utils/test-setup.js +22 -21
- package/frigg-cli/db-setup-command/index.js +33 -26
- package/frigg-cli/generate-command/__tests__/generate-command.test.js +151 -162
- package/frigg-cli/generate-iam-command.js +7 -4
- package/frigg-cli/install-command/index.js +1 -1
- package/frigg-cli/{__tests__/jest.config.js → jest.config.js} +30 -32
- package/frigg-cli/start-command/index.js +7 -20
- package/frigg-cli/start-command/start-command.test.js +17 -27
- package/frigg-cli/utils/database-validator.js +12 -8
- package/frigg-cli/utils/error-messages.js +1 -1
- package/frigg-cli/utils/prisma-runner.js +19 -15
- package/infrastructure/IAM-POLICY-TEMPLATES.md +30 -12
- package/infrastructure/iam-generator.js +18 -38
- package/infrastructure/iam-generator.test.js +40 -8
- package/package.json +6 -6
- package/frigg-cli/__tests__/utils/command-tester.js +0 -170
|
@@ -308,7 +308,7 @@ describe('Database Validator Utility', () => {
|
|
|
308
308
|
const result = checkPrismaClientGenerated('mongodb', '/nonexistent/path');
|
|
309
309
|
|
|
310
310
|
expect(result.generated).toBe(false);
|
|
311
|
-
expect(result.error).toContain('@prisma-
|
|
311
|
+
expect(result.error).toContain('@prisma-mongodb/client');
|
|
312
312
|
});
|
|
313
313
|
|
|
314
314
|
it('should use correct package name for PostgreSQL', () => {
|
|
@@ -316,7 +316,7 @@ describe('Database Validator Utility', () => {
|
|
|
316
316
|
const result = checkPrismaClientGenerated('postgresql', '/nonexistent/path');
|
|
317
317
|
|
|
318
318
|
expect(result.generated).toBe(false);
|
|
319
|
-
expect(result.error).toContain('@prisma-
|
|
319
|
+
expect(result.error).toContain('@prisma-postgresql/client');
|
|
320
320
|
});
|
|
321
321
|
|
|
322
322
|
it('should return error when MongoDB client not found', () => {
|
|
@@ -325,7 +325,7 @@ describe('Database Validator Utility', () => {
|
|
|
325
325
|
expect(result.generated).toBe(false);
|
|
326
326
|
expect(result.error).toBeDefined();
|
|
327
327
|
expect(result.error).toContain('not found');
|
|
328
|
-
expect(result.error).toContain('@prisma-
|
|
328
|
+
expect(result.error).toContain('@prisma-mongodb/client');
|
|
329
329
|
expect(result.error).toContain('frigg db:setup');
|
|
330
330
|
});
|
|
331
331
|
|
|
@@ -335,7 +335,7 @@ describe('Database Validator Utility', () => {
|
|
|
335
335
|
expect(result.generated).toBe(false);
|
|
336
336
|
expect(result.error).toBeDefined();
|
|
337
337
|
expect(result.error).toContain('not found');
|
|
338
|
-
expect(result.error).toContain('@prisma-
|
|
338
|
+
expect(result.error).toContain('@prisma-postgresql/client');
|
|
339
339
|
expect(result.error).toContain('frigg db:setup');
|
|
340
340
|
});
|
|
341
341
|
|
|
@@ -184,13 +184,13 @@ describe('Error Messages Utility', () => {
|
|
|
184
184
|
it('should include correct client package name for MongoDB', () => {
|
|
185
185
|
const message = getPrismaClientNotGeneratedError('mongodb');
|
|
186
186
|
|
|
187
|
-
expect(message).toContain('@prisma-
|
|
187
|
+
expect(message).toContain('@prisma-mongodb/client');
|
|
188
188
|
});
|
|
189
189
|
|
|
190
190
|
it('should include correct client package name for PostgreSQL', () => {
|
|
191
191
|
const message = getPrismaClientNotGeneratedError('postgresql');
|
|
192
192
|
|
|
193
|
-
expect(message).toContain('@prisma-
|
|
193
|
+
expect(message).toContain('@prisma-postgresql/client');
|
|
194
194
|
});
|
|
195
195
|
|
|
196
196
|
it('should suggest running frigg db:setup', () => {
|
|
@@ -1,3 +1,16 @@
|
|
|
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');
|
|
1
14
|
const {
|
|
2
15
|
getPrismaSchemaPath,
|
|
3
16
|
runPrismaGenerate,
|
|
@@ -7,13 +20,6 @@ const {
|
|
|
7
20
|
getMigrationCommand
|
|
8
21
|
} = require('../../../utils/prisma-runner');
|
|
9
22
|
|
|
10
|
-
// Mock dependencies
|
|
11
|
-
jest.mock('child_process');
|
|
12
|
-
jest.mock('fs');
|
|
13
|
-
|
|
14
|
-
const { execSync, spawn } = require('child_process');
|
|
15
|
-
const fs = require('fs');
|
|
16
|
-
|
|
17
23
|
describe('Prisma Runner Utility', () => {
|
|
18
24
|
beforeEach(() => {
|
|
19
25
|
jest.clearAllMocks();
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
// Store original environment
|
|
7
7
|
const originalEnv = process.env;
|
|
8
8
|
const originalConsole = { ...console };
|
|
9
|
-
|
|
9
|
+
// Store original process methods (not entire object due to read-only properties)
|
|
10
|
+
const originalProcessExit = process.exit;
|
|
11
|
+
const originalProcessCwd = process.cwd;
|
|
10
12
|
|
|
11
13
|
// Mock console to prevent noisy output during tests
|
|
12
14
|
global.console = {
|
|
@@ -37,14 +39,10 @@ beforeEach(() => {
|
|
|
37
39
|
|
|
38
40
|
// Reset modules
|
|
39
41
|
jest.resetModules();
|
|
40
|
-
|
|
41
|
-
// Restore original process methods
|
|
42
|
-
process.exit = originalProcess.exit;
|
|
43
|
-
process.cwd = originalProcess.cwd;
|
|
44
|
-
|
|
42
|
+
|
|
45
43
|
// Mock process.exit to prevent actual exit
|
|
46
44
|
process.exit = jest.fn();
|
|
47
|
-
|
|
45
|
+
|
|
48
46
|
// Mock process.cwd to return predictable path
|
|
49
47
|
process.cwd = jest.fn().mockReturnValue('/mock/cwd');
|
|
50
48
|
|
|
@@ -60,14 +58,14 @@ beforeEach(() => {
|
|
|
60
58
|
afterEach(() => {
|
|
61
59
|
// Restore environment
|
|
62
60
|
process.env = { ...originalEnv };
|
|
63
|
-
|
|
61
|
+
|
|
64
62
|
// Restore process methods
|
|
65
|
-
process.exit =
|
|
66
|
-
process.cwd =
|
|
67
|
-
|
|
63
|
+
process.exit = originalProcessExit;
|
|
64
|
+
process.cwd = originalProcessCwd;
|
|
65
|
+
|
|
68
66
|
// Clear any remaining timers
|
|
69
67
|
jest.clearAllTimers();
|
|
70
|
-
|
|
68
|
+
|
|
71
69
|
// Unmock all modules
|
|
72
70
|
jest.restoreAllMocks();
|
|
73
71
|
});
|
|
@@ -76,12 +74,13 @@ afterEach(() => {
|
|
|
76
74
|
afterAll(() => {
|
|
77
75
|
// Restore original environment completely
|
|
78
76
|
process.env = originalEnv;
|
|
79
|
-
|
|
77
|
+
|
|
80
78
|
// Restore original console
|
|
81
79
|
global.console = originalConsole;
|
|
82
|
-
|
|
83
|
-
// Restore original process
|
|
84
|
-
|
|
80
|
+
|
|
81
|
+
// Restore original process methods
|
|
82
|
+
process.exit = originalProcessExit;
|
|
83
|
+
process.cwd = originalProcessCwd;
|
|
85
84
|
});
|
|
86
85
|
|
|
87
86
|
// Custom matchers for CLI testing
|
|
@@ -274,13 +273,15 @@ global.TestHelpers = {
|
|
|
274
273
|
jest.setTimeout(30000);
|
|
275
274
|
|
|
276
275
|
// Suppress specific warnings during tests
|
|
277
|
-
|
|
278
|
-
|
|
276
|
+
// Note: console.warn is already mocked above, so we keep the mock
|
|
277
|
+
// and just suppress certain warnings in the implementation
|
|
278
|
+
const originalWarnMock = global.console.warn;
|
|
279
|
+
global.console.warn = jest.fn((...args) => {
|
|
279
280
|
// Suppress specific warnings that are expected during testing
|
|
280
281
|
const message = args.join(' ');
|
|
281
|
-
if (message.includes('ExperimentalWarning') ||
|
|
282
|
+
if (message.includes('ExperimentalWarning') ||
|
|
282
283
|
message.includes('DeprecationWarning')) {
|
|
283
284
|
return;
|
|
284
285
|
}
|
|
285
|
-
|
|
286
|
-
};
|
|
286
|
+
// Still track the call in the mock
|
|
287
|
+
});
|
|
@@ -4,7 +4,7 @@ const dotenv = require('dotenv');
|
|
|
4
4
|
const {
|
|
5
5
|
validateDatabaseUrl,
|
|
6
6
|
getDatabaseType,
|
|
7
|
-
|
|
7
|
+
checkPrismaClientGenerated
|
|
8
8
|
} = require('../utils/database-validator');
|
|
9
9
|
const {
|
|
10
10
|
runPrismaGenerate,
|
|
@@ -16,7 +16,6 @@ const {
|
|
|
16
16
|
const {
|
|
17
17
|
getDatabaseUrlMissingError,
|
|
18
18
|
getDatabaseTypeNotConfiguredError,
|
|
19
|
-
getDatabaseConnectionError,
|
|
20
19
|
getPrismaCommandError,
|
|
21
20
|
getDatabaseSetupSuccess
|
|
22
21
|
} = require('../utils/error-messages');
|
|
@@ -75,44 +74,52 @@ async function dbSetupCommand(options = {}) {
|
|
|
75
74
|
console.log(chalk.green(`✓ Using ${dbType}\n`));
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
// Step 3:
|
|
77
|
+
// Step 3: Check if Prisma client exists, generate if needed
|
|
79
78
|
if (verbose) {
|
|
80
|
-
console.log(chalk.gray('Step 3:
|
|
79
|
+
console.log(chalk.gray('Step 3: Checking Prisma client...'));
|
|
81
80
|
}
|
|
82
81
|
|
|
83
|
-
|
|
84
|
-
const
|
|
82
|
+
const clientCheck = checkPrismaClientGenerated(dbType);
|
|
83
|
+
const forceRegenerate = options.force || false;
|
|
85
84
|
|
|
86
|
-
if (!
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
85
|
+
if (clientCheck.generated && !forceRegenerate) {
|
|
86
|
+
// Client already exists and --force not specified
|
|
87
|
+
console.log(chalk.green('✓ Prisma client already exists (skipping generation)\n'));
|
|
88
|
+
if (verbose) {
|
|
89
|
+
console.log(chalk.gray(` Client location: ${clientCheck.path}\n`));
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
// Client doesn't exist OR --force specified - generate it
|
|
93
|
+
if (forceRegenerate && clientCheck.generated) {
|
|
94
|
+
console.log(chalk.yellow('⚠️ Forcing Prisma client regeneration...'));
|
|
95
|
+
} else {
|
|
96
|
+
console.log(chalk.cyan('Generating Prisma client...'));
|
|
97
|
+
}
|
|
95
98
|
|
|
96
|
-
|
|
99
|
+
const generateResult = await runPrismaGenerate(dbType, verbose);
|
|
97
100
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
101
|
+
if (!generateResult.success) {
|
|
102
|
+
console.error(getPrismaCommandError('generate', generateResult.error));
|
|
103
|
+
if (generateResult.output) {
|
|
104
|
+
console.error(chalk.gray(generateResult.output));
|
|
105
|
+
}
|
|
106
|
+
process.exit(1);
|
|
102
107
|
}
|
|
103
|
-
process.exit(1);
|
|
104
|
-
}
|
|
105
108
|
|
|
106
|
-
|
|
109
|
+
console.log(chalk.green('✓ Prisma client generated\n'));
|
|
110
|
+
}
|
|
107
111
|
|
|
108
|
-
// Step
|
|
112
|
+
// Step 4: Check database state
|
|
113
|
+
// Note: We skip connection testing in db:setup because when using frigg:local,
|
|
114
|
+
// the CLI code runs from tmp/frigg but the client is in backend/node_modules,
|
|
115
|
+
// causing module resolution mismatches. Connection testing happens in frigg start.
|
|
109
116
|
if (verbose) {
|
|
110
|
-
console.log(chalk.gray('Step
|
|
117
|
+
console.log(chalk.gray('Step 4: Checking database state...'));
|
|
111
118
|
}
|
|
112
119
|
|
|
113
120
|
const stateCheck = await checkDatabaseState(dbType);
|
|
114
121
|
|
|
115
|
-
// Step
|
|
122
|
+
// Step 5: Run migrations or db push
|
|
116
123
|
if (dbType === 'postgresql') {
|
|
117
124
|
console.log(chalk.cyan('Running database migrations...'));
|
|
118
125
|
|