@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,279 @@
1
+ /**
2
+ * Test suite for build command
3
+ *
4
+ * Tests the serverless package build functionality including:
5
+ * - Command execution with spawnSync
6
+ * - Stage option handling
7
+ * - Verbose flag support
8
+ * - Environment variable setup
9
+ * - Error handling and process exit
10
+ */
11
+
12
+ // Mock dependencies BEFORE requiring modules
13
+ jest.mock('child_process', () => ({
14
+ spawnSync: jest.fn()
15
+ }));
16
+
17
+ // Require after mocks
18
+ const { spawnSync } = require('child_process');
19
+ const { buildCommand } = require('../../../build-command');
20
+
21
+ describe('CLI Command: build', () => {
22
+ let consoleLogSpy;
23
+ let consoleErrorSpy;
24
+ let processExitSpy;
25
+ let originalCwd;
26
+
27
+ beforeEach(() => {
28
+ jest.clearAllMocks();
29
+
30
+ // Mock console methods
31
+ consoleLogSpy = jest.spyOn(console, 'log').mockImplementation();
32
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
33
+
34
+ // Mock process.exit to prevent actual exit
35
+ processExitSpy = jest.spyOn(process, 'exit').mockImplementation();
36
+
37
+ // Mock successful serverless execution by default
38
+ spawnSync.mockReturnValue({ status: 0 });
39
+
40
+ // Store original cwd for restoration
41
+ originalCwd = process.cwd();
42
+ });
43
+
44
+ afterEach(() => {
45
+ consoleLogSpy.mockRestore();
46
+ consoleErrorSpy.mockRestore();
47
+ processExitSpy.mockRestore();
48
+ });
49
+
50
+ describe('Success Cases', () => {
51
+ it('should spawn serverless with default stage', async () => {
52
+ await buildCommand({ stage: 'dev' });
53
+
54
+ expect(spawnSync).toHaveBeenCalledWith(
55
+ 'osls',
56
+ ['package', '--config', 'infrastructure.js', '--stage', 'dev'],
57
+ expect.objectContaining({
58
+ cwd: expect.any(String),
59
+ stdio: 'inherit',
60
+ shell: true
61
+ })
62
+ );
63
+ });
64
+
65
+ it('should spawn serverless with production stage', async () => {
66
+ await buildCommand({ stage: 'production' });
67
+
68
+ expect(spawnSync).toHaveBeenCalledWith(
69
+ 'osls',
70
+ expect.arrayContaining(['--stage', 'production']),
71
+ expect.any(Object)
72
+ );
73
+ });
74
+
75
+ it('should spawn serverless with staging stage', async () => {
76
+ await buildCommand({ stage: 'staging' });
77
+
78
+ expect(spawnSync).toHaveBeenCalledWith(
79
+ 'osls',
80
+ expect.arrayContaining(['--stage', 'staging']),
81
+ expect.any(Object)
82
+ );
83
+ });
84
+
85
+ it('should append verbose flag when verbose option is true', async () => {
86
+ await buildCommand({ stage: 'dev', verbose: true });
87
+
88
+ expect(spawnSync).toHaveBeenCalledWith(
89
+ 'osls',
90
+ expect.arrayContaining(['--verbose']),
91
+ expect.any(Object)
92
+ );
93
+ });
94
+
95
+ it('should NOT append verbose flag when verbose option is false', async () => {
96
+ await buildCommand({ stage: 'dev', verbose: false });
97
+
98
+ const call = spawnSync.mock.calls[0];
99
+ const args = call[1];
100
+
101
+ expect(args).not.toContain('--verbose');
102
+ });
103
+
104
+ it('should use process.cwd() as working directory', async () => {
105
+ await buildCommand({ stage: 'dev' });
106
+
107
+ const call = spawnSync.mock.calls[0];
108
+ const options = call[2];
109
+
110
+ // Verify ACTUAL cwd value, not generic check
111
+ expect(options.cwd).toBe(process.cwd());
112
+ });
113
+
114
+ it('should use stdio inherit for output streaming', async () => {
115
+ await buildCommand({ stage: 'dev' });
116
+
117
+ const call = spawnSync.mock.calls[0];
118
+ const options = call[2];
119
+
120
+ expect(options.stdio).toBe('inherit');
121
+ });
122
+
123
+ it('should use shell mode for execution', async () => {
124
+ await buildCommand({ stage: 'dev' });
125
+
126
+ const call = spawnSync.mock.calls[0];
127
+ const options = call[2];
128
+
129
+ expect(options.shell).toBe(true);
130
+ });
131
+
132
+ it('should set NODE_PATH environment variable with actual resolved path', async () => {
133
+ await buildCommand({ stage: 'dev' });
134
+
135
+ const call = spawnSync.mock.calls[0];
136
+ const options = call[2];
137
+
138
+ // Verify ACTUAL resolved path, not just "contains node_modules"
139
+ const path = require('path');
140
+ const expectedNodePath = path.resolve(process.cwd(), 'node_modules');
141
+
142
+ expect(options.env.NODE_PATH).toBe(expectedNodePath);
143
+ });
144
+
145
+ it('should pass through all process.env variables', async () => {
146
+ // Set a test env var
147
+ process.env.TEST_VAR = 'test-value';
148
+
149
+ await buildCommand({ stage: 'dev' });
150
+
151
+ const call = spawnSync.mock.calls[0];
152
+ const options = call[2];
153
+
154
+ // Verify parent env vars are passed through
155
+ expect(options.env.TEST_VAR).toBe('test-value');
156
+
157
+ delete process.env.TEST_VAR;
158
+ });
159
+
160
+ it('should set SLS_STAGE environment variable to match stage option', async () => {
161
+ await buildCommand({ stage: 'qa' });
162
+
163
+ const call = spawnSync.mock.calls[0];
164
+ const options = call[2];
165
+
166
+ // Verify SLS_STAGE is set for discovery to use
167
+ expect(options.env.SLS_STAGE).toBe('qa');
168
+ });
169
+
170
+ it('should set SLS_STAGE for production stage', async () => {
171
+ await buildCommand({ stage: 'production' });
172
+
173
+ const call = spawnSync.mock.calls[0];
174
+ const options = call[2];
175
+
176
+ expect(options.env.SLS_STAGE).toBe('production');
177
+ });
178
+
179
+ it('should set SLS_STAGE for dev stage', async () => {
180
+ await buildCommand({ stage: 'dev' });
181
+
182
+ const call = spawnSync.mock.calls[0];
183
+ const options = call[2];
184
+
185
+ expect(options.env.SLS_STAGE).toBe('dev');
186
+ });
187
+
188
+ it('should use infrastructure.js as config file', async () => {
189
+ await buildCommand({ stage: 'dev' });
190
+
191
+ expect(spawnSync).toHaveBeenCalledWith(
192
+ 'osls',
193
+ expect.arrayContaining(['--config', 'infrastructure.js']),
194
+ expect.any(Object)
195
+ );
196
+ });
197
+
198
+ it('should NOT call process.exit when build succeeds', async () => {
199
+ spawnSync.mockReturnValue({ status: 0 });
200
+
201
+ await buildCommand({ stage: 'dev' });
202
+
203
+ expect(processExitSpy).not.toHaveBeenCalled();
204
+ });
205
+
206
+ it('should log build start messages', async () => {
207
+ await buildCommand({ stage: 'dev' });
208
+
209
+ expect(consoleLogSpy).toHaveBeenCalledWith('Building the serverless application...');
210
+ expect(consoleLogSpy).toHaveBeenCalledWith('📦 Packaging serverless application...');
211
+ });
212
+
213
+ it('should construct complete valid serverless command', async () => {
214
+ await buildCommand({ stage: 'production', verbose: true });
215
+
216
+ const [cmd, args, opts] = spawnSync.mock.calls[0];
217
+
218
+ // Verify complete command structure
219
+ expect(cmd).toBe('osls');
220
+ expect(args).toEqual([
221
+ 'package',
222
+ '--config',
223
+ 'infrastructure.js',
224
+ '--stage',
225
+ 'production',
226
+ '--verbose'
227
+ ]);
228
+
229
+ // Verify all required options present
230
+ expect(opts.cwd).toBeDefined();
231
+ expect(opts.stdio).toBe('inherit');
232
+ expect(opts.shell).toBe(true);
233
+ expect(opts.env).toBeDefined();
234
+ expect(opts.env.NODE_PATH).toBeDefined();
235
+ });
236
+
237
+ it('should build command without verbose when verbose=false', async () => {
238
+ await buildCommand({ stage: 'dev', verbose: false });
239
+
240
+ const [, args] = spawnSync.mock.calls[0];
241
+
242
+ // Verify exact args without verbose
243
+ expect(args).toEqual([
244
+ 'package',
245
+ '--config',
246
+ 'infrastructure.js',
247
+ '--stage',
248
+ 'dev'
249
+ ]);
250
+ });
251
+ });
252
+
253
+ describe('Error Handling', () => {
254
+ it('should exit with code 1 when serverless fails', async () => {
255
+ spawnSync.mockReturnValue({ status: 1 });
256
+
257
+ await buildCommand({ stage: 'dev' });
258
+
259
+ expect(processExitSpy).toHaveBeenCalledWith(1);
260
+ });
261
+
262
+ it('should log error message when build fails', async () => {
263
+ spawnSync.mockReturnValue({ status: 2 });
264
+
265
+ await buildCommand({ stage: 'dev' });
266
+
267
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Serverless build failed with code 2');
268
+ });
269
+
270
+ it('should exit with code 1 for any non-zero status', async () => {
271
+ spawnSync.mockReturnValue({ status: 127 });
272
+
273
+ await buildCommand({ stage: 'dev' });
274
+
275
+ expect(processExitSpy).toHaveBeenCalledWith(1);
276
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Serverless build failed with code 127');
277
+ });
278
+ });
279
+ });