@friggframework/devtools 2.0.0-next.47 → 2.0.0-next.48

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 (69) hide show
  1. package/frigg-cli/README.md +1290 -0
  2. package/frigg-cli/__tests__/unit/commands/build.test.js +279 -0
  3. package/frigg-cli/__tests__/unit/commands/db-setup.test.js +548 -0
  4. package/frigg-cli/__tests__/unit/commands/deploy.test.js +320 -0
  5. package/frigg-cli/__tests__/unit/commands/doctor.test.js +309 -0
  6. package/frigg-cli/__tests__/unit/commands/install.test.js +400 -0
  7. package/frigg-cli/__tests__/unit/commands/ui.test.js +346 -0
  8. package/frigg-cli/__tests__/unit/dependencies.test.js +74 -0
  9. package/frigg-cli/__tests__/unit/utils/database-validator.test.js +366 -0
  10. package/frigg-cli/__tests__/unit/utils/error-messages.test.js +304 -0
  11. package/frigg-cli/__tests__/unit/version-detection.test.js +171 -0
  12. package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
  13. package/frigg-cli/__tests__/utils/prisma-mock.js +194 -0
  14. package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
  15. package/frigg-cli/__tests__/utils/test-setup.js +287 -0
  16. package/frigg-cli/build-command/index.js +66 -0
  17. package/frigg-cli/db-setup-command/index.js +193 -0
  18. package/frigg-cli/deploy-command/SPEC-DEPLOY-DRY-RUN.md +981 -0
  19. package/frigg-cli/deploy-command/index.js +302 -0
  20. package/frigg-cli/doctor-command/index.js +335 -0
  21. package/frigg-cli/generate-command/__tests__/generate-command.test.js +301 -0
  22. package/frigg-cli/generate-command/azure-generator.js +43 -0
  23. package/frigg-cli/generate-command/gcp-generator.js +47 -0
  24. package/frigg-cli/generate-command/index.js +332 -0
  25. package/frigg-cli/generate-command/terraform-generator.js +555 -0
  26. package/frigg-cli/generate-iam-command.js +118 -0
  27. package/frigg-cli/index.js +173 -0
  28. package/frigg-cli/index.test.js +158 -0
  29. package/frigg-cli/init-command/backend-first-handler.js +756 -0
  30. package/frigg-cli/init-command/index.js +93 -0
  31. package/frigg-cli/init-command/template-handler.js +143 -0
  32. package/frigg-cli/install-command/backend-js.js +33 -0
  33. package/frigg-cli/install-command/commit-changes.js +16 -0
  34. package/frigg-cli/install-command/environment-variables.js +127 -0
  35. package/frigg-cli/install-command/environment-variables.test.js +136 -0
  36. package/frigg-cli/install-command/index.js +54 -0
  37. package/frigg-cli/install-command/install-package.js +13 -0
  38. package/frigg-cli/install-command/integration-file.js +30 -0
  39. package/frigg-cli/install-command/logger.js +12 -0
  40. package/frigg-cli/install-command/template.js +90 -0
  41. package/frigg-cli/install-command/validate-package.js +75 -0
  42. package/frigg-cli/jest.config.js +124 -0
  43. package/frigg-cli/package.json +63 -0
  44. package/frigg-cli/repair-command/index.js +564 -0
  45. package/frigg-cli/start-command/index.js +149 -0
  46. package/frigg-cli/start-command/start-command.test.js +297 -0
  47. package/frigg-cli/test/init-command.test.js +180 -0
  48. package/frigg-cli/test/npm-registry.test.js +319 -0
  49. package/frigg-cli/ui-command/index.js +154 -0
  50. package/frigg-cli/utils/app-resolver.js +319 -0
  51. package/frigg-cli/utils/backend-path.js +25 -0
  52. package/frigg-cli/utils/database-validator.js +154 -0
  53. package/frigg-cli/utils/error-messages.js +257 -0
  54. package/frigg-cli/utils/npm-registry.js +167 -0
  55. package/frigg-cli/utils/process-manager.js +199 -0
  56. package/frigg-cli/utils/repo-detection.js +405 -0
  57. package/infrastructure/create-frigg-infrastructure.js +125 -12
  58. package/infrastructure/docs/PRE-DEPLOYMENT-HEALTH-CHECK-SPEC.md +1317 -0
  59. package/infrastructure/domains/shared/resource-discovery.enhanced.test.js +306 -0
  60. package/infrastructure/domains/shared/resource-discovery.js +31 -2
  61. package/infrastructure/domains/shared/utilities/base-definition-factory.js +1 -1
  62. package/infrastructure/domains/shared/utilities/prisma-layer-manager.js +109 -5
  63. package/infrastructure/domains/shared/utilities/prisma-layer-manager.test.js +310 -4
  64. package/infrastructure/domains/shared/validation/plugin-validator.js +187 -0
  65. package/infrastructure/domains/shared/validation/plugin-validator.test.js +323 -0
  66. package/infrastructure/infrastructure-composer.js +22 -0
  67. package/layers/prisma/.build-complete +3 -0
  68. package/package.json +18 -7
  69. package/management-ui/package-lock.json +0 -16517
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Version Detection Tests
3
+ *
4
+ * Tests for the CLI version detection wrapper that prefers local installations
5
+ */
6
+
7
+ const fs = require('fs');
8
+ const path = require('path');
9
+ const semver = require('semver');
10
+
11
+ describe('Version Detection Logic', () => {
12
+ describe('semver comparison', () => {
13
+ test('should prefer local when local version is newer', () => {
14
+ const localVersion = '2.1.0';
15
+ const globalVersion = '2.0.0';
16
+
17
+ const comparison = semver.compare(localVersion, globalVersion);
18
+
19
+ expect(comparison).toBeGreaterThan(0);
20
+ });
21
+
22
+ test('should prefer local when versions are equal', () => {
23
+ const localVersion = '2.0.0';
24
+ const globalVersion = '2.0.0';
25
+
26
+ const comparison = semver.compare(localVersion, globalVersion);
27
+
28
+ expect(comparison).toBe(0);
29
+ });
30
+
31
+ test('should warn when global is newer than local', () => {
32
+ const localVersion = '2.0.0';
33
+ const globalVersion = '2.1.0';
34
+
35
+ const comparison = semver.compare(localVersion, globalVersion);
36
+
37
+ expect(comparison).toBeLessThan(0);
38
+ });
39
+
40
+ test('should handle prerelease versions correctly', () => {
41
+ const localVersion = '2.0.0-next.1';
42
+ const globalVersion = '2.0.0-next.0';
43
+
44
+ const comparison = semver.compare(localVersion, globalVersion);
45
+
46
+ expect(comparison).toBeGreaterThan(0);
47
+ });
48
+
49
+ test('should prefer release over prerelease', () => {
50
+ const localVersion = '2.0.0';
51
+ const globalVersion = '2.0.0-next.0';
52
+
53
+ const comparison = semver.compare(localVersion, globalVersion);
54
+
55
+ expect(comparison).toBeGreaterThan(0);
56
+ });
57
+ });
58
+
59
+ describe('local CLI detection', () => {
60
+ test('should find local installation in node_modules', () => {
61
+ const cwd = process.cwd();
62
+ const localCliPath = path.join(cwd, 'node_modules', '@friggframework', 'frigg-cli');
63
+
64
+ // This test validates the path construction logic
65
+ expect(localCliPath).toContain('node_modules');
66
+ expect(localCliPath).toContain('@friggframework');
67
+ expect(localCliPath).toContain('frigg-cli');
68
+ });
69
+
70
+ test('should construct correct paths for package.json and index.js', () => {
71
+ const cwd = process.cwd();
72
+ const localCliPath = path.join(cwd, 'node_modules', '@friggframework', 'frigg-cli');
73
+ const localCliPackageJson = path.join(localCliPath, 'package.json');
74
+ const localCliIndex = path.join(localCliPath, 'index.js');
75
+
76
+ expect(localCliPackageJson).toContain('package.json');
77
+ expect(localCliIndex).toContain('index.js');
78
+ });
79
+ });
80
+
81
+ describe('environment variable check', () => {
82
+ test('should skip version check when FRIGG_CLI_SKIP_VERSION_CHECK is true', () => {
83
+ const originalEnv = process.env.FRIGG_CLI_SKIP_VERSION_CHECK;
84
+
85
+ process.env.FRIGG_CLI_SKIP_VERSION_CHECK = 'true';
86
+ const shouldSkip = process.env.FRIGG_CLI_SKIP_VERSION_CHECK === 'true';
87
+ expect(shouldSkip).toBe(true);
88
+
89
+ // Restore
90
+ if (originalEnv !== undefined) {
91
+ process.env.FRIGG_CLI_SKIP_VERSION_CHECK = originalEnv;
92
+ } else {
93
+ delete process.env.FRIGG_CLI_SKIP_VERSION_CHECK;
94
+ }
95
+ });
96
+
97
+ test('should not skip when environment variable is not set', () => {
98
+ const originalEnv = process.env.FRIGG_CLI_SKIP_VERSION_CHECK;
99
+ delete process.env.FRIGG_CLI_SKIP_VERSION_CHECK;
100
+
101
+ const shouldSkip = process.env.FRIGG_CLI_SKIP_VERSION_CHECK === 'true';
102
+ expect(shouldSkip).toBe(false);
103
+
104
+ // Restore
105
+ if (originalEnv !== undefined) {
106
+ process.env.FRIGG_CLI_SKIP_VERSION_CHECK = originalEnv;
107
+ }
108
+ });
109
+ });
110
+
111
+ describe('version detection decision matrix', () => {
112
+ const scenarios = [
113
+ {
114
+ name: 'local newer than global',
115
+ local: '2.1.0',
116
+ global: '2.0.0',
117
+ expected: 'use_local',
118
+ },
119
+ {
120
+ name: 'local equal to global',
121
+ local: '2.0.0',
122
+ global: '2.0.0',
123
+ expected: 'use_local',
124
+ },
125
+ {
126
+ name: 'global newer than local',
127
+ local: '2.0.0',
128
+ global: '2.1.0',
129
+ expected: 'warn_and_use_global',
130
+ },
131
+ {
132
+ name: 'local prerelease newer',
133
+ local: '2.0.0-next.1',
134
+ global: '2.0.0-next.0',
135
+ expected: 'use_local',
136
+ },
137
+ ];
138
+
139
+ scenarios.forEach(({ name, local, global, expected }) => {
140
+ test(`should ${expected.replace('_', ' ')} when ${name}`, () => {
141
+ const comparison = semver.compare(local, global);
142
+
143
+ if (expected === 'use_local') {
144
+ expect(comparison).toBeGreaterThanOrEqual(0);
145
+ } else if (expected === 'warn_and_use_global') {
146
+ expect(comparison).toBeLessThan(0);
147
+ }
148
+ });
149
+ });
150
+ });
151
+
152
+ describe('argument forwarding', () => {
153
+ test('should extract arguments correctly from process.argv', () => {
154
+ // Simulate process.argv
155
+ const mockArgv = ['node', '/path/to/frigg', 'doctor', 'my-stack', '--region', 'us-east-1'];
156
+ const args = mockArgv.slice(2);
157
+
158
+ expect(args).toEqual(['doctor', 'my-stack', '--region', 'us-east-1']);
159
+ });
160
+
161
+ test('should forward all arguments to local CLI', () => {
162
+ const mockArgv = ['node', '/path/to/frigg', 'repair', 'my-stack', '--import', '--yes'];
163
+ const args = mockArgv.slice(2);
164
+
165
+ expect(args).toContain('repair');
166
+ expect(args).toContain('my-stack');
167
+ expect(args).toContain('--import');
168
+ expect(args).toContain('--yes');
169
+ });
170
+ });
171
+ });
@@ -0,0 +1,270 @@
1
+ /**
2
+ * MockFactory - Factory for creating standardized mocks
3
+ * Provides consistent mock implementations across all CLI tests
4
+ */
5
+ class MockFactory {
6
+ /**
7
+ * Create a file system mock
8
+ * @returns {object} - Mock fs implementation
9
+ */
10
+ static createFileSystem() {
11
+ return {
12
+ existsSync: jest.fn().mockReturnValue(true),
13
+ readFileSync: jest.fn().mockReturnValue('{}'),
14
+ writeFileSync: jest.fn(),
15
+ mkdirSync: jest.fn(),
16
+ readdirSync: jest.fn().mockReturnValue([]),
17
+ statSync: jest.fn().mockReturnValue({
18
+ isDirectory: () => false,
19
+ isFile: () => true
20
+ }),
21
+ copyFileSync: jest.fn(),
22
+ unlinkSync: jest.fn(),
23
+ rmdirSync: jest.fn(),
24
+ constants: {
25
+ F_OK: 0,
26
+ R_OK: 4,
27
+ W_OK: 2,
28
+ X_OK: 1
29
+ }
30
+ };
31
+ }
32
+
33
+ /**
34
+ * Create a logger mock
35
+ * @returns {object} - Mock logger implementation
36
+ */
37
+ static createLogger() {
38
+ return {
39
+ info: jest.fn(),
40
+ error: jest.fn(),
41
+ debug: jest.fn(),
42
+ warn: jest.fn(),
43
+ logInfo: jest.fn(),
44
+ logError: jest.fn(),
45
+ logDebug: jest.fn(),
46
+ logWarn: jest.fn()
47
+ };
48
+ }
49
+
50
+ /**
51
+ * Create a package manager mock
52
+ * @returns {object} - Mock package manager implementation
53
+ */
54
+ static createPackageManager() {
55
+ return {
56
+ install: jest.fn().mockResolvedValue({ success: true }),
57
+ list: jest.fn().mockResolvedValue([]),
58
+ exists: jest.fn().mockResolvedValue(true),
59
+ getInfo: jest.fn().mockResolvedValue({
60
+ name: 'test-package',
61
+ version: '1.0.0'
62
+ }),
63
+ search: jest.fn().mockResolvedValue([])
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Create a child process mock
69
+ * @returns {object} - Mock child_process implementation
70
+ */
71
+ static createChildProcess() {
72
+ return {
73
+ execSync: jest.fn().mockReturnValue(''),
74
+ exec: jest.fn(),
75
+ spawn: jest.fn().mockReturnValue({
76
+ stdout: { on: jest.fn() },
77
+ stderr: { on: jest.fn() },
78
+ on: jest.fn((event, callback) => {
79
+ if (event === 'close') {
80
+ callback(0);
81
+ }
82
+ })
83
+ }),
84
+ fork: jest.fn()
85
+ };
86
+ }
87
+
88
+ /**
89
+ * Create a git mock
90
+ * @returns {object} - Mock git implementation
91
+ */
92
+ static createGit() {
93
+ return {
94
+ init: jest.fn(),
95
+ add: jest.fn(),
96
+ commit: jest.fn(),
97
+ status: jest.fn().mockReturnValue({
98
+ clean: true,
99
+ files: []
100
+ }),
101
+ branch: jest.fn().mockReturnValue('main'),
102
+ remote: jest.fn().mockReturnValue('origin'),
103
+ isRepo: jest.fn().mockReturnValue(true)
104
+ };
105
+ }
106
+
107
+ /**
108
+ * Create a config loader mock
109
+ * @returns {object} - Mock config loader implementation
110
+ */
111
+ static createConfigLoader() {
112
+ return {
113
+ load: jest.fn().mockReturnValue({
114
+ stage: 'dev',
115
+ region: 'us-east-1',
116
+ profile: 'default'
117
+ }),
118
+ validate: jest.fn().mockReturnValue(true),
119
+ save: jest.fn(),
120
+ merge: jest.fn()
121
+ };
122
+ }
123
+
124
+ /**
125
+ * Create an app resolver mock
126
+ * @returns {object} - Mock app resolver implementation
127
+ */
128
+ static createAppResolver() {
129
+ return {
130
+ resolveAppPath: jest.fn().mockReturnValue('/mock/app/path'),
131
+ findNearestBackendPackageJson: jest.fn().mockReturnValue('/mock/backend/package.json'),
132
+ validateBackendPath: jest.fn().mockReturnValue(true),
133
+ getProjectRoot: jest.fn().mockReturnValue('/mock/project'),
134
+ findConfigFile: jest.fn().mockReturnValue('/mock/config.json')
135
+ };
136
+ }
137
+
138
+ /**
139
+ * Create a network mock
140
+ * @returns {object} - Mock network implementation
141
+ */
142
+ static createNetwork() {
143
+ return {
144
+ get: jest.fn().mockResolvedValue({
145
+ status: 200,
146
+ data: {}
147
+ }),
148
+ post: jest.fn().mockResolvedValue({
149
+ status: 200,
150
+ data: {}
151
+ }),
152
+ put: jest.fn().mockResolvedValue({
153
+ status: 200,
154
+ data: {}
155
+ }),
156
+ delete: jest.fn().mockResolvedValue({
157
+ status: 200,
158
+ data: {}
159
+ })
160
+ };
161
+ }
162
+
163
+ /**
164
+ * Create a comprehensive mock environment
165
+ * @returns {object} - Complete mock environment
166
+ */
167
+ static createMockEnvironment() {
168
+ return {
169
+ fs: this.createFileSystem(),
170
+ logger: this.createLogger(),
171
+ packageManager: this.createPackageManager(),
172
+ childProcess: this.createChildProcess(),
173
+ git: this.createGit(),
174
+ config: this.createConfigLoader(),
175
+ appResolver: this.createAppResolver(),
176
+ network: this.createNetwork()
177
+ };
178
+ }
179
+
180
+ /**
181
+ * Create a mock for process.env
182
+ * @param {object} customEnv - Custom environment variables
183
+ * @returns {object} - Mock environment
184
+ */
185
+ static createProcessEnv(customEnv = {}) {
186
+ return {
187
+ NODE_ENV: 'test',
188
+ HOME: '/mock/home',
189
+ PATH: '/mock/path',
190
+ ...customEnv
191
+ };
192
+ }
193
+
194
+ /**
195
+ * Create success response mock
196
+ * @param {any} data - Response data
197
+ * @returns {object} - Success response
198
+ */
199
+ static createSuccessResponse(data = {}) {
200
+ return {
201
+ success: true,
202
+ data,
203
+ message: 'Operation completed successfully'
204
+ };
205
+ }
206
+
207
+ /**
208
+ * Create error response mock
209
+ * @param {string} message - Error message
210
+ * @param {string} code - Error code
211
+ * @returns {object} - Error response
212
+ */
213
+ static createErrorResponse(message = 'An error occurred', code = 'GENERIC_ERROR') {
214
+ return {
215
+ success: false,
216
+ error: {
217
+ message,
218
+ code,
219
+ stack: 'Mock stack trace'
220
+ }
221
+ };
222
+ }
223
+
224
+ /**
225
+ * Create package.json mock
226
+ * @param {object} overrides - Custom package.json properties
227
+ * @returns {object} - Mock package.json
228
+ */
229
+ static createPackageJson(overrides = {}) {
230
+ return {
231
+ name: 'test-package',
232
+ version: '1.0.0',
233
+ description: 'Test package',
234
+ main: 'index.js',
235
+ scripts: {
236
+ test: 'jest',
237
+ start: 'node index.js'
238
+ },
239
+ dependencies: {},
240
+ devDependencies: {},
241
+ ...overrides
242
+ };
243
+ }
244
+
245
+ /**
246
+ * Create frigg config mock
247
+ * @param {object} overrides - Custom config properties
248
+ * @returns {object} - Mock frigg config
249
+ */
250
+ static createFriggConfig(overrides = {}) {
251
+ return {
252
+ stage: 'dev',
253
+ region: 'us-east-1',
254
+ profile: 'default',
255
+ backend: {
256
+ runtime: 'nodejs18.x',
257
+ timeout: 30,
258
+ memory: 128
259
+ },
260
+ frontend: {
261
+ framework: 'react',
262
+ buildCommand: 'npm run build',
263
+ outputDir: 'dist'
264
+ },
265
+ ...overrides
266
+ };
267
+ }
268
+ }
269
+
270
+ module.exports = { MockFactory };
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Prisma Mock Utilities
3
+ * Standardized mocking for Prisma Client in CLI tests
4
+ * Following official Prisma testing patterns with jest-mock-extended
5
+ */
6
+
7
+ /**
8
+ * Creates a mock Prisma client with common operations
9
+ * @returns {object} Mock Prisma client
10
+ */
11
+ function createMockPrismaClient() {
12
+ return {
13
+ $connect: jest.fn().mockResolvedValue(undefined),
14
+ $disconnect: jest.fn().mockResolvedValue(undefined),
15
+ $queryRaw: jest.fn().mockResolvedValue([{ result: 1 }]),
16
+ $executeRaw: jest.fn().mockResolvedValue(1),
17
+ $runCommandRaw: jest.fn().mockResolvedValue({ ok: 1 }), // MongoDB command support
18
+ $transaction: jest.fn().mockImplementation(async (fn) => fn(createMockPrismaClient())),
19
+ // Common model operations
20
+ user: {
21
+ findMany: jest.fn().mockResolvedValue([]),
22
+ findUnique: jest.fn().mockResolvedValue(null),
23
+ create: jest.fn().mockResolvedValue({}),
24
+ update: jest.fn().mockResolvedValue({}),
25
+ delete: jest.fn().mockResolvedValue({}),
26
+ },
27
+ credential: {
28
+ findMany: jest.fn().mockResolvedValue([]),
29
+ findUnique: jest.fn().mockResolvedValue(null),
30
+ create: jest.fn().mockResolvedValue({}),
31
+ update: jest.fn().mockResolvedValue({}),
32
+ delete: jest.fn().mockResolvedValue({}),
33
+ },
34
+ };
35
+ }
36
+
37
+ /**
38
+ * Creates a mock for successful Prisma connection
39
+ * @param {object} mockClient - Optional pre-configured mock client
40
+ * @returns {jest.Mock} Mock connectPrisma function
41
+ */
42
+ function createMockConnectPrisma(mockClient = null) {
43
+ const client = mockClient || createMockPrismaClient();
44
+ return jest.fn().mockResolvedValue(client);
45
+ }
46
+
47
+ /**
48
+ * Creates a mock for successful Prisma disconnection
49
+ * @returns {jest.Mock} Mock disconnectPrisma function
50
+ */
51
+ function createMockDisconnectPrisma() {
52
+ return jest.fn().mockResolvedValue(undefined);
53
+ }
54
+
55
+ /**
56
+ * Creates a mock for Prisma connection that fails
57
+ * @param {string} errorMessage - Error message to throw
58
+ * @returns {jest.Mock} Mock connectPrisma that throws error
59
+ */
60
+ function createMockConnectPrismaWithError(errorMessage = 'Connection failed') {
61
+ return jest.fn().mockRejectedValue(new Error(errorMessage));
62
+ }
63
+
64
+ /**
65
+ * Creates a mock for Prisma query that times out
66
+ * @param {number} timeout - Timeout in milliseconds
67
+ * @returns {jest.Mock} Mock that times out
68
+ */
69
+ function createMockPrismaTimeout(timeout = 5000) {
70
+ return jest.fn().mockImplementation(() =>
71
+ new Promise((_, reject) =>
72
+ setTimeout(() => reject(new Error('Connection timeout')), timeout)
73
+ )
74
+ );
75
+ }
76
+
77
+ /**
78
+ * Common Prisma error types for testing
79
+ */
80
+ const PrismaErrors = {
81
+ /**
82
+ * Connection error (P1001)
83
+ */
84
+ CONNECTION_ERROR: {
85
+ code: 'P1001',
86
+ message: 'Can\'t reach database server',
87
+ clientVersion: '5.0.0',
88
+ },
89
+
90
+ /**
91
+ * Authentication error (P1002)
92
+ */
93
+ AUTH_ERROR: {
94
+ code: 'P1002',
95
+ message: 'The database server was reached but timed out',
96
+ clientVersion: '5.0.0',
97
+ },
98
+
99
+ /**
100
+ * Database not found error (P1003)
101
+ */
102
+ DATABASE_NOT_FOUND: {
103
+ code: 'P1003',
104
+ message: 'Database does not exist',
105
+ clientVersion: '5.0.0',
106
+ },
107
+
108
+ /**
109
+ * Connection timeout (P1008)
110
+ */
111
+ TIMEOUT_ERROR: {
112
+ code: 'P1008',
113
+ message: 'Operations timed out',
114
+ clientVersion: '5.0.0',
115
+ },
116
+
117
+ /**
118
+ * Invalid credentials
119
+ */
120
+ INVALID_CREDENTIALS: {
121
+ code: 'P1000',
122
+ message: 'Authentication failed against database server',
123
+ clientVersion: '5.0.0',
124
+ },
125
+ };
126
+
127
+ /**
128
+ * Creates a Prisma error object
129
+ * @param {string} errorType - Error type from PrismaErrors
130
+ * @param {object} customFields - Additional custom fields
131
+ * @returns {Error} Prisma-style error object
132
+ */
133
+ function createPrismaError(errorType = 'CONNECTION_ERROR', customFields = {}) {
134
+ const baseError = PrismaErrors[errorType] || PrismaErrors.CONNECTION_ERROR;
135
+ const error = new Error(baseError.message);
136
+ error.code = baseError.code;
137
+ error.clientVersion = baseError.clientVersion;
138
+ Object.assign(error, customFields);
139
+ return error;
140
+ }
141
+
142
+ /**
143
+ * Creates a mock for database validator functions
144
+ * @param {object} overrides - Override specific mock behaviors
145
+ * @returns {object} Mock database validator
146
+ */
147
+ function createMockDatabaseValidator(overrides = {}) {
148
+ return {
149
+ validateDatabaseUrl: jest.fn().mockReturnValue({
150
+ valid: true,
151
+ url: 'mongodb://localhost:27017/test'
152
+ }),
153
+ getDatabaseType: jest.fn().mockReturnValue({
154
+ dbType: 'mongodb'
155
+ }),
156
+ testDatabaseConnection: jest.fn().mockResolvedValue({
157
+ connected: true
158
+ }),
159
+ checkPrismaClientGenerated: jest.fn().mockReturnValue({
160
+ generated: true,
161
+ path: '/mock/path'
162
+ }),
163
+ ...overrides,
164
+ };
165
+ }
166
+
167
+ /**
168
+ * Creates a mock for Prisma runner functions
169
+ * @param {object} overrides - Override specific mock behaviors
170
+ * @returns {object} Mock Prisma runner
171
+ */
172
+ function createMockPrismaRunner(overrides = {}) {
173
+ return {
174
+ getPrismaSchemaPath: jest.fn().mockReturnValue('/mock/schema.prisma'),
175
+ runPrismaGenerate: jest.fn().mockResolvedValue({ success: true }),
176
+ checkDatabaseState: jest.fn().mockResolvedValue({ upToDate: true }),
177
+ runPrismaMigrate: jest.fn().mockResolvedValue({ success: true }),
178
+ runPrismaDbPush: jest.fn().mockResolvedValue({ success: true }),
179
+ getMigrationCommand: jest.fn().mockReturnValue('dev'),
180
+ ...overrides,
181
+ };
182
+ }
183
+
184
+ module.exports = {
185
+ createMockPrismaClient,
186
+ createMockConnectPrisma,
187
+ createMockDisconnectPrisma,
188
+ createMockConnectPrismaWithError,
189
+ createMockPrismaTimeout,
190
+ createPrismaError,
191
+ PrismaErrors,
192
+ createMockDatabaseValidator,
193
+ createMockPrismaRunner,
194
+ };