@friggframework/devtools 2.0.0--canary.545.ae2019f.0 ā 2.0.0--canary.549.a579cca.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/README.md +1 -1
- package/frigg-cli/__tests__/unit/commands/build.test.js +1 -1
- package/frigg-cli/__tests__/unit/commands/doctor.test.js +2 -0
- package/frigg-cli/__tests__/unit/commands/install.test.js +19 -23
- package/frigg-cli/__tests__/unit/dependencies.test.js +2 -2
- package/frigg-cli/build-command/index.js +11 -123
- package/frigg-cli/deploy-command/index.js +1 -83
- package/frigg-cli/doctor-command/index.js +16 -37
- package/frigg-cli/generate-iam-command.js +1 -21
- package/frigg-cli/index.js +6 -21
- package/frigg-cli/index.test.js +2 -7
- package/frigg-cli/init-command/backend-first-handler.js +42 -124
- package/frigg-cli/init-command/index.js +1 -2
- package/frigg-cli/init-command/template-handler.js +3 -13
- package/frigg-cli/install-command/backend-js.js +3 -3
- package/frigg-cli/install-command/environment-variables.js +19 -16
- package/frigg-cli/install-command/environment-variables.test.js +13 -12
- package/frigg-cli/install-command/index.js +9 -14
- package/frigg-cli/install-command/integration-file.js +3 -3
- package/frigg-cli/install-command/logger.js +12 -0
- package/frigg-cli/install-command/validate-package.js +9 -5
- package/frigg-cli/jest.config.js +1 -4
- package/frigg-cli/repair-command/index.js +128 -121
- package/frigg-cli/start-command/index.js +2 -324
- package/frigg-cli/ui-command/index.js +36 -58
- package/frigg-cli/utils/repo-detection.js +37 -85
- package/infrastructure/create-frigg-infrastructure.js +0 -93
- package/infrastructure/docs/iam-policy-templates.md +1 -1
- package/infrastructure/domains/networking/vpc-builder.test.js +4 -2
- package/infrastructure/domains/networking/vpc-resolver.test.js +1 -1
- package/infrastructure/domains/shared/resource-discovery.js +5 -5
- package/infrastructure/domains/shared/types/app-definition.js +0 -21
- package/infrastructure/domains/shared/types/discovery-result.test.js +1 -1
- package/infrastructure/domains/shared/utilities/base-definition-factory.js +1 -10
- package/infrastructure/domains/shared/utilities/base-definition-factory.test.js +2 -2
- package/infrastructure/infrastructure-composer.js +0 -2
- package/infrastructure/infrastructure-composer.test.js +2 -2
- package/management-ui/README.md +109 -245
- package/package.json +7 -8
- package/frigg-cli/__tests__/application/use-cases/AddApiModuleToIntegrationUseCase.test.js +0 -326
- package/frigg-cli/__tests__/application/use-cases/CreateApiModuleUseCase.test.js +0 -337
- package/frigg-cli/__tests__/domain/entities/ApiModule.test.js +0 -373
- package/frigg-cli/__tests__/domain/entities/AppDefinition.test.js +0 -313
- package/frigg-cli/__tests__/domain/services/IntegrationValidator.test.js +0 -269
- package/frigg-cli/__tests__/domain/value-objects/IntegrationName.test.js +0 -82
- package/frigg-cli/__tests__/infrastructure/adapters/IntegrationJsUpdater.test.js +0 -408
- package/frigg-cli/__tests__/infrastructure/repositories/FileSystemApiModuleRepository.test.js +0 -583
- package/frigg-cli/__tests__/infrastructure/repositories/FileSystemAppDefinitionRepository.test.js +0 -314
- package/frigg-cli/__tests__/infrastructure/repositories/FileSystemIntegrationRepository.test.js +0 -383
- package/frigg-cli/__tests__/unit/commands/init.test.js +0 -406
- package/frigg-cli/__tests__/unit/commands/provider-dispatch.test.js +0 -383
- package/frigg-cli/__tests__/unit/commands/repair.test.js +0 -275
- package/frigg-cli/__tests__/unit/start-command/application/RunPreflightChecksUseCase.test.js +0 -411
- package/frigg-cli/__tests__/unit/start-command/infrastructure/DatabaseAdapter.test.js +0 -405
- package/frigg-cli/__tests__/unit/start-command/infrastructure/DockerAdapter.test.js +0 -496
- package/frigg-cli/__tests__/unit/start-command/presentation/InteractivePromptAdapter.test.js +0 -474
- package/frigg-cli/__tests__/unit/utils/output.test.js +0 -196
- package/frigg-cli/application/use-cases/AddApiModuleToIntegrationUseCase.js +0 -93
- package/frigg-cli/application/use-cases/CreateApiModuleUseCase.js +0 -93
- package/frigg-cli/application/use-cases/CreateIntegrationUseCase.js +0 -103
- package/frigg-cli/container.js +0 -172
- package/frigg-cli/docs/OUTPUT_MIGRATION_GUIDE.md +0 -286
- package/frigg-cli/domain/entities/ApiModule.js +0 -272
- package/frigg-cli/domain/entities/AppDefinition.js +0 -227
- package/frigg-cli/domain/entities/Integration.js +0 -198
- package/frigg-cli/domain/exceptions/DomainException.js +0 -24
- package/frigg-cli/domain/ports/IApiModuleRepository.js +0 -53
- package/frigg-cli/domain/ports/IAppDefinitionRepository.js +0 -43
- package/frigg-cli/domain/ports/IIntegrationRepository.js +0 -61
- package/frigg-cli/domain/services/IntegrationValidator.js +0 -185
- package/frigg-cli/domain/value-objects/IntegrationId.js +0 -42
- package/frigg-cli/domain/value-objects/IntegrationName.js +0 -60
- package/frigg-cli/domain/value-objects/SemanticVersion.js +0 -70
- package/frigg-cli/infrastructure/UnitOfWork.js +0 -46
- package/frigg-cli/infrastructure/adapters/BackendJsUpdater.js +0 -197
- package/frigg-cli/infrastructure/adapters/FileSystemAdapter.js +0 -224
- package/frigg-cli/infrastructure/adapters/IntegrationJsUpdater.js +0 -249
- package/frigg-cli/infrastructure/adapters/SchemaValidator.js +0 -92
- package/frigg-cli/infrastructure/repositories/FileSystemApiModuleRepository.js +0 -373
- package/frigg-cli/infrastructure/repositories/FileSystemAppDefinitionRepository.js +0 -116
- package/frigg-cli/infrastructure/repositories/FileSystemIntegrationRepository.js +0 -277
- package/frigg-cli/package-lock.json +0 -16226
- package/frigg-cli/start-command/application/RunPreflightChecksUseCase.js +0 -376
- package/frigg-cli/start-command/infrastructure/DatabaseAdapter.js +0 -591
- package/frigg-cli/start-command/infrastructure/DockerAdapter.js +0 -306
- package/frigg-cli/start-command/presentation/InteractivePromptAdapter.js +0 -329
- package/frigg-cli/templates/backend/.env.example +0 -62
- package/frigg-cli/templates/backend/.eslintrc.json +0 -12
- package/frigg-cli/templates/backend/.prettierrc +0 -6
- package/frigg-cli/templates/backend/docker-compose.yml +0 -22
- package/frigg-cli/templates/backend/index.js +0 -96
- package/frigg-cli/templates/backend/infrastructure.js +0 -12
- package/frigg-cli/templates/backend/jest.config.js +0 -17
- package/frigg-cli/templates/backend/package.json +0 -50
- package/frigg-cli/templates/backend/src/api-modules/.gitkeep +0 -10
- package/frigg-cli/templates/backend/src/base/.gitkeep +0 -7
- package/frigg-cli/templates/backend/src/integrations/.gitkeep +0 -10
- package/frigg-cli/templates/backend/src/integrations/ExampleIntegration.js +0 -65
- package/frigg-cli/templates/backend/src/utils/.gitkeep +0 -7
- package/frigg-cli/templates/backend/test/setup.js +0 -30
- package/frigg-cli/templates/backend/ui-extensions/.gitkeep +0 -0
- package/frigg-cli/templates/backend/ui-extensions/README.md +0 -77
- package/frigg-cli/utils/__tests__/provider-helper.test.js +0 -55
- package/frigg-cli/utils/__tests__/repo-detection.test.js +0 -436
- package/frigg-cli/utils/output.js +0 -382
- package/frigg-cli/utils/provider-helper.js +0 -75
- package/frigg-cli/validate-command/__tests__/adapters/validate-command.test.js +0 -205
- package/frigg-cli/validate-command/__tests__/application/validate-app-use-case.test.js +0 -104
- package/frigg-cli/validate-command/__tests__/domain/fix-suggestion.test.js +0 -153
- package/frigg-cli/validate-command/__tests__/domain/validation-error.test.js +0 -162
- package/frigg-cli/validate-command/__tests__/domain/validation-result.test.js +0 -152
- package/frigg-cli/validate-command/__tests__/infrastructure/api-module-validator.test.js +0 -332
- package/frigg-cli/validate-command/__tests__/infrastructure/app-definition-validator.test.js +0 -191
- package/frigg-cli/validate-command/__tests__/infrastructure/integration-class-validator.test.js +0 -146
- package/frigg-cli/validate-command/__tests__/infrastructure/template-validation.test.js +0 -155
- package/frigg-cli/validate-command/adapters/cli/validate-command.js +0 -199
- package/frigg-cli/validate-command/application/use-cases/validate-app-use-case.js +0 -35
- package/frigg-cli/validate-command/domain/entities/validation-result.js +0 -74
- package/frigg-cli/validate-command/domain/value-objects/fix-suggestion.js +0 -74
- package/frigg-cli/validate-command/domain/value-objects/validation-error.js +0 -68
- package/frigg-cli/validate-command/infrastructure/validators/api-module-validator.js +0 -181
- package/frigg-cli/validate-command/infrastructure/validators/app-definition-validator.js +0 -128
- package/frigg-cli/validate-command/infrastructure/validators/integration-class-validator.js +0 -113
- package/infrastructure/domains/admin-scripts/admin-script-builder.js +0 -200
- package/infrastructure/domains/admin-scripts/admin-script-builder.test.js +0 -499
- package/infrastructure/domains/admin-scripts/index.js +0 -5
- package/infrastructure/jest.config.js +0 -16
package/frigg-cli/README.md
CHANGED
|
@@ -1281,7 +1281,7 @@ npm install @friggframework/frigg-cli@latest
|
|
|
1281
1281
|
npm install -g @friggframework/frigg-cli
|
|
1282
1282
|
|
|
1283
1283
|
# Local project dependencies
|
|
1284
|
-
frigg
|
|
1284
|
+
npx create-frigg-app my-app
|
|
1285
1285
|
# (Will automatically include @friggframework/frigg-cli in package.json)
|
|
1286
1286
|
```
|
|
1287
1287
|
|
|
@@ -207,7 +207,7 @@ describe('CLI Command: build', () => {
|
|
|
207
207
|
await buildCommand({ stage: 'dev' });
|
|
208
208
|
|
|
209
209
|
expect(consoleLogSpy).toHaveBeenCalledWith('Building the serverless application...');
|
|
210
|
-
expect(consoleLogSpy).toHaveBeenCalledWith('Packaging serverless application...');
|
|
210
|
+
expect(consoleLogSpy).toHaveBeenCalledWith('š¦ Packaging serverless application...');
|
|
211
211
|
});
|
|
212
212
|
|
|
213
213
|
it('should construct complete valid serverless command', async () => {
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
* Tests stack listing, selection, and health check orchestration
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
const { describe, test, expect, jest, beforeEach } = require('@jest/globals');
|
|
7
|
+
|
|
6
8
|
describe('Doctor Command - Stack Listing and Selection', () => {
|
|
7
9
|
let mockCloudFormationClient;
|
|
8
10
|
let mockSelect;
|
|
@@ -26,7 +26,7 @@ jest.mock('../../../install-command/validate-package', () => ({
|
|
|
26
26
|
validatePackageExists: jest.fn(), // External: npm registry
|
|
27
27
|
searchAndSelectPackage: jest.fn() // External: interactive selection
|
|
28
28
|
}));
|
|
29
|
-
jest.mock('@friggframework/core
|
|
29
|
+
jest.mock('@friggframework/core', () => ({
|
|
30
30
|
findNearestBackendPackageJson: jest.fn(),
|
|
31
31
|
validateBackendPath: jest.fn()
|
|
32
32
|
}));
|
|
@@ -43,13 +43,13 @@ const { installPackage } = require('../../../install-command/install-package');
|
|
|
43
43
|
const { commitChanges } = require('../../../install-command/commit-changes');
|
|
44
44
|
const { handleEnvVariables } = require('../../../install-command/environment-variables');
|
|
45
45
|
const { validatePackageExists, searchAndSelectPackage } = require('../../../install-command/validate-package');
|
|
46
|
-
const { findNearestBackendPackageJson, validateBackendPath } = require('@friggframework/core
|
|
46
|
+
const { findNearestBackendPackageJson, validateBackendPath } = require('@friggframework/core');
|
|
47
47
|
const { installCommand } = require('../../../install-command');
|
|
48
|
-
const output = require('../../../utils/output');
|
|
49
48
|
|
|
50
49
|
describe('CLI Command: install', () => {
|
|
51
50
|
let processExitSpy;
|
|
52
|
-
|
|
51
|
+
let consoleLogSpy;
|
|
52
|
+
let consoleErrorSpy;
|
|
53
53
|
const mockBackendPath = '/mock/backend/package.json';
|
|
54
54
|
const mockBackendDir = '/mock/backend';
|
|
55
55
|
|
|
@@ -59,14 +59,9 @@ describe('CLI Command: install', () => {
|
|
|
59
59
|
// Mock process.exit to prevent actual exit
|
|
60
60
|
processExitSpy = jest.spyOn(process, 'exit').mockImplementation();
|
|
61
61
|
|
|
62
|
-
//
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
output.spinner = jest.fn().mockReturnValue({
|
|
66
|
-
start: jest.fn(),
|
|
67
|
-
succeed: jest.fn(),
|
|
68
|
-
fail: jest.fn()
|
|
69
|
-
});
|
|
62
|
+
// Spy on console for logger (don't mock logger - test it!)
|
|
63
|
+
consoleLogSpy = jest.spyOn(console, 'log').mockImplementation();
|
|
64
|
+
consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation();
|
|
70
65
|
|
|
71
66
|
// Setup fs-extra mocks - Let Frigg code run, just mock I/O
|
|
72
67
|
fs.ensureDirSync = jest.fn();
|
|
@@ -103,7 +98,8 @@ describe('CLI Command: install', () => {
|
|
|
103
98
|
|
|
104
99
|
afterEach(() => {
|
|
105
100
|
processExitSpy.mockRestore();
|
|
106
|
-
|
|
101
|
+
consoleLogSpy.mockRestore();
|
|
102
|
+
consoleErrorSpy.mockRestore();
|
|
107
103
|
jest.resetModules(); // Clear module cache after each test
|
|
108
104
|
});
|
|
109
105
|
|
|
@@ -209,9 +205,9 @@ describe('CLI Command: install', () => {
|
|
|
209
205
|
it('should log info messages during installation', async () => {
|
|
210
206
|
await installCommand('slack');
|
|
211
207
|
|
|
212
|
-
// Verify
|
|
213
|
-
expect(
|
|
214
|
-
expect.stringContaining('
|
|
208
|
+
// Verify logger actually logged (we spy on console)
|
|
209
|
+
expect(consoleLogSpy).toHaveBeenCalledWith(
|
|
210
|
+
expect.stringContaining('Successfully installed @friggframework/api-module-slack')
|
|
215
211
|
);
|
|
216
212
|
});
|
|
217
213
|
|
|
@@ -338,8 +334,8 @@ describe('CLI Command: install', () => {
|
|
|
338
334
|
|
|
339
335
|
await installCommand('slack');
|
|
340
336
|
|
|
341
|
-
// Verify error logged via
|
|
342
|
-
expect(
|
|
337
|
+
// Verify error logged via console.error (we spy on it)
|
|
338
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('An error occurred:', error);
|
|
343
339
|
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
344
340
|
});
|
|
345
341
|
|
|
@@ -349,7 +345,7 @@ describe('CLI Command: install', () => {
|
|
|
349
345
|
|
|
350
346
|
await installCommand('slack');
|
|
351
347
|
|
|
352
|
-
expect(
|
|
348
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('An error occurred:', error);
|
|
353
349
|
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
354
350
|
});
|
|
355
351
|
|
|
@@ -361,7 +357,7 @@ describe('CLI Command: install', () => {
|
|
|
361
357
|
|
|
362
358
|
await installCommand('slack');
|
|
363
359
|
|
|
364
|
-
expect(
|
|
360
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('An error occurred:', error);
|
|
365
361
|
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
366
362
|
});
|
|
367
363
|
|
|
@@ -374,7 +370,7 @@ describe('CLI Command: install', () => {
|
|
|
374
370
|
|
|
375
371
|
await installCommand('slack');
|
|
376
372
|
|
|
377
|
-
expect(
|
|
373
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('An error occurred:', expect.any(Error));
|
|
378
374
|
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
379
375
|
});
|
|
380
376
|
|
|
@@ -387,7 +383,7 @@ describe('CLI Command: install', () => {
|
|
|
387
383
|
|
|
388
384
|
await installCommand('slack');
|
|
389
385
|
|
|
390
|
-
expect(
|
|
386
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('An error occurred:', expect.any(Error));
|
|
391
387
|
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
392
388
|
});
|
|
393
389
|
|
|
@@ -397,7 +393,7 @@ describe('CLI Command: install', () => {
|
|
|
397
393
|
|
|
398
394
|
await installCommand('slack');
|
|
399
395
|
|
|
400
|
-
expect(
|
|
396
|
+
expect(consoleErrorSpy).toHaveBeenCalledWith('An error occurred:', error);
|
|
401
397
|
expect(processExitSpy).toHaveBeenCalledWith(1);
|
|
402
398
|
});
|
|
403
399
|
});
|
|
@@ -51,8 +51,8 @@ describe('frigg-cli dependencies', () => {
|
|
|
51
51
|
expect(packageJson.dependencies.commander).toBeDefined();
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
it('should have @friggframework/devtools
|
|
55
|
-
expect(packageJson.
|
|
54
|
+
it('should have @friggframework/devtools for infrastructure', () => {
|
|
55
|
+
expect(packageJson.dependencies['@friggframework/devtools']).toBeDefined();
|
|
56
56
|
});
|
|
57
57
|
});
|
|
58
58
|
|
|
@@ -1,15 +1,7 @@
|
|
|
1
1
|
const { spawnSync } = require('child_process');
|
|
2
2
|
const path = require('path');
|
|
3
|
-
const fs = require('fs');
|
|
4
3
|
|
|
5
4
|
async function buildCommand(options) {
|
|
6
|
-
// Check if the app uses a non-AWS provider
|
|
7
|
-
const providerResult = loadProviderIfConfigured();
|
|
8
|
-
if (providerResult) {
|
|
9
|
-
return buildWithProvider(providerResult, options);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Default: AWS build via serverless framework
|
|
13
5
|
console.log('Building the serverless application...');
|
|
14
6
|
|
|
15
7
|
// Suppress AWS SDK warning message about maintenance mode
|
|
@@ -18,13 +10,13 @@ async function buildCommand(options) {
|
|
|
18
10
|
// Skip AWS discovery for local builds (unless --production flag is set)
|
|
19
11
|
if (!options.production) {
|
|
20
12
|
process.env.FRIGG_SKIP_AWS_DISCOVERY = 'true';
|
|
21
|
-
console.log('Building in local mode (use --production flag for production builds with AWS discovery)');
|
|
13
|
+
console.log('š Building in local mode (use --production flag for production builds with AWS discovery)');
|
|
22
14
|
} else {
|
|
23
|
-
console.log('Building in production mode with AWS discovery enabled');
|
|
15
|
+
console.log('š Building in production mode with AWS discovery enabled');
|
|
24
16
|
}
|
|
25
17
|
|
|
26
18
|
// AWS discovery is now handled directly in serverless-template.js
|
|
27
|
-
console.log('Packaging serverless application...');
|
|
19
|
+
console.log('š¦ Packaging serverless application...');
|
|
28
20
|
const backendPath = path.resolve(process.cwd());
|
|
29
21
|
const infrastructurePath = 'infrastructure.js';
|
|
30
22
|
const command = 'osls'; // OSS-Serverless (drop-in replacement for serverless v3)
|
|
@@ -59,120 +51,16 @@ async function buildCommand(options) {
|
|
|
59
51
|
console.error(`Serverless build failed with code ${result.status}`);
|
|
60
52
|
process.exit(1);
|
|
61
53
|
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Check if the appDefinition specifies a non-AWS provider and resolve it.
|
|
66
|
-
*/
|
|
67
|
-
function loadProviderIfConfigured() {
|
|
68
|
-
try {
|
|
69
|
-
const { loadProviderForCli } = require('../utils/provider-helper');
|
|
70
|
-
const result = loadProviderForCli();
|
|
71
|
-
if (result && result.provider) {
|
|
72
|
-
return result;
|
|
73
|
-
}
|
|
74
|
-
} catch {
|
|
75
|
-
// Provider helper not available or appDefinition not found ā fall through
|
|
76
|
-
}
|
|
77
|
-
return null;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Build using a provider plugin.
|
|
82
|
-
* Provider build steps:
|
|
83
|
-
* 1. generateConfig() ā generate platform-specific config (netlify.toml, etc.)
|
|
84
|
-
* 2. getFunctionEntryPoints() ā copy function files to the project
|
|
85
|
-
*/
|
|
86
|
-
async function buildWithProvider({ provider, appDefinition, providerName }, options) {
|
|
87
|
-
console.log(`Building for ${providerName} provider...`);
|
|
88
|
-
const projectDir = path.resolve(process.cwd());
|
|
89
|
-
|
|
90
|
-
// 1. Validate
|
|
91
|
-
if (typeof provider.validate === 'function') {
|
|
92
|
-
const validation = provider.validate(appDefinition);
|
|
93
|
-
if (validation.errors?.length > 0) {
|
|
94
|
-
console.error(`\nValidation errors for ${providerName}:`);
|
|
95
|
-
for (const error of validation.errors) {
|
|
96
|
-
console.error(` - ${error}`);
|
|
97
|
-
}
|
|
98
|
-
process.exit(1);
|
|
99
|
-
}
|
|
100
|
-
if (validation.warnings?.length > 0) {
|
|
101
|
-
for (const warning of validation.warnings) {
|
|
102
|
-
console.warn(` Warning: ${warning}`);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// 2. Generate platform config (e.g., netlify.toml)
|
|
108
|
-
if (typeof provider.generateConfig === 'function') {
|
|
109
|
-
console.log(`Generating ${providerName} configuration...`);
|
|
110
|
-
const config = provider.generateConfig(appDefinition);
|
|
111
|
-
|
|
112
|
-
const configFileNames = {
|
|
113
|
-
netlify: 'netlify.toml',
|
|
114
|
-
};
|
|
115
|
-
const configFileName = configFileNames[providerName] || `${providerName}.config`;
|
|
116
|
-
const configPath = path.join(projectDir, configFileName);
|
|
117
|
-
|
|
118
|
-
fs.writeFileSync(configPath, config, 'utf-8');
|
|
119
|
-
console.log(` Written ${configFileName}`);
|
|
120
|
-
}
|
|
121
54
|
|
|
122
|
-
//
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
const entryPoints = provider.getFunctionEntryPoints(appDefinition);
|
|
126
|
-
const functionsDir = path.join(projectDir, 'netlify', 'functions');
|
|
127
|
-
|
|
128
|
-
fs.mkdirSync(functionsDir, { recursive: true });
|
|
129
|
-
|
|
130
|
-
for (const [filename, content] of Object.entries(entryPoints)) {
|
|
131
|
-
const filePath = path.join(functionsDir, filename);
|
|
132
|
-
fs.writeFileSync(filePath, content, 'utf-8');
|
|
133
|
-
if (options.verbose) {
|
|
134
|
-
console.log(` Written ${path.relative(projectDir, filePath)}`);
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
console.log(` Generated ${Object.keys(entryPoints).length} function entry points`);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// 4. Copy lib entry points (re-export shims for runtime dependencies)
|
|
142
|
-
if (typeof provider.getLibEntryPoints === 'function') {
|
|
143
|
-
const libEntryPoints = provider.getLibEntryPoints(appDefinition);
|
|
144
|
-
const libDir = path.join(projectDir, 'netlify', 'lib');
|
|
145
|
-
|
|
146
|
-
fs.mkdirSync(libDir, { recursive: true });
|
|
147
|
-
|
|
148
|
-
for (const [filename, content] of Object.entries(libEntryPoints)) {
|
|
149
|
-
const filePath = path.join(libDir, filename);
|
|
150
|
-
fs.writeFileSync(filePath, content, 'utf-8');
|
|
151
|
-
if (options.verbose) {
|
|
152
|
-
console.log(` Written ${path.relative(projectDir, filePath)}`);
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
console.log(` Generated ${Object.keys(libEntryPoints).length} lib entry points`);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// 5. Generate env template (informational)
|
|
160
|
-
if (typeof provider.generateEnvTemplate === 'function') {
|
|
161
|
-
const envTemplate = provider.generateEnvTemplate(appDefinition);
|
|
162
|
-
const missingEnvVars = Object.entries(envTemplate)
|
|
163
|
-
.filter(([key]) => !process.env[key])
|
|
164
|
-
.map(([key, desc]) => `${key}: ${desc}`);
|
|
165
|
-
|
|
166
|
-
if (missingEnvVars.length > 0) {
|
|
167
|
-
console.log(`\n Required environment variables not set locally:`);
|
|
168
|
-
for (const entry of missingEnvVars) {
|
|
169
|
-
console.log(` - ${entry}`);
|
|
170
|
-
}
|
|
171
|
-
console.log(` Configure these in your ${providerName} dashboard.`);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
55
|
+
// childProcess.on('error', (error) => {
|
|
56
|
+
// console.error(`Error executing command: ${error.message}`);
|
|
57
|
+
// });
|
|
174
58
|
|
|
175
|
-
|
|
59
|
+
// childProcess.on('close', (code) => {
|
|
60
|
+
// if (code !== 0) {
|
|
61
|
+
// console.log(`Child process exited with code ${code}`);
|
|
62
|
+
// }
|
|
63
|
+
// });
|
|
176
64
|
}
|
|
177
65
|
|
|
178
66
|
module.exports = { buildCommand };
|
|
@@ -268,17 +268,9 @@ async function runPostDeploymentHealthCheck(stackName, options) {
|
|
|
268
268
|
}
|
|
269
269
|
|
|
270
270
|
async function deployCommand(options) {
|
|
271
|
-
const appDefinition = loadAppDefinition();
|
|
272
|
-
|
|
273
|
-
// Check if the app uses a non-AWS provider
|
|
274
|
-
const providerResult = loadProviderIfConfigured(appDefinition);
|
|
275
|
-
if (providerResult) {
|
|
276
|
-
return deployWithProvider(providerResult, options);
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
// Default: AWS deployment via serverless framework
|
|
280
271
|
console.log('Deploying the serverless application...');
|
|
281
272
|
|
|
273
|
+
const appDefinition = loadAppDefinition();
|
|
282
274
|
const environment = validateAndBuildEnvironment(appDefinition, options);
|
|
283
275
|
|
|
284
276
|
// Execute deployment
|
|
@@ -310,78 +302,4 @@ async function deployCommand(options) {
|
|
|
310
302
|
}
|
|
311
303
|
}
|
|
312
304
|
|
|
313
|
-
/**
|
|
314
|
-
* Check if the appDefinition specifies a non-AWS provider and resolve it.
|
|
315
|
-
* Returns null for AWS (default) so the caller falls through to existing behavior.
|
|
316
|
-
*
|
|
317
|
-
* @param {Object|null} appDefinition
|
|
318
|
-
* @returns {{ provider: Object, appDefinition: Object, providerName: string } | null}
|
|
319
|
-
*/
|
|
320
|
-
function loadProviderIfConfigured(appDefinition) {
|
|
321
|
-
const providerName = appDefinition?.provider;
|
|
322
|
-
if (!providerName || providerName === 'aws') {
|
|
323
|
-
return null;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
try {
|
|
327
|
-
const { resolveProvider } = require('@friggframework/core/providers/resolve-provider');
|
|
328
|
-
const provider = resolveProvider(appDefinition);
|
|
329
|
-
return { provider, appDefinition, providerName };
|
|
330
|
-
} catch (error) {
|
|
331
|
-
console.error(`Failed to load provider '${providerName}': ${error.message}`);
|
|
332
|
-
process.exit(1);
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* Deploy using a provider plugin (Netlify, etc.).
|
|
338
|
-
* Delegates entirely to the provider's deploy lifecycle:
|
|
339
|
-
* 1. validate() ā check appDefinition for provider-specific issues
|
|
340
|
-
* 2. preflightCheck() ā verify prerequisites (CLI tools, credentials)
|
|
341
|
-
* 3. deploy() ā execute the deployment
|
|
342
|
-
*/
|
|
343
|
-
async function deployWithProvider({ provider, appDefinition, providerName }, options) {
|
|
344
|
-
console.log(`Deploying with ${providerName} provider...`);
|
|
345
|
-
|
|
346
|
-
// 1. Validate appDefinition for this provider
|
|
347
|
-
if (typeof provider.validate === 'function') {
|
|
348
|
-
const validation = provider.validate(appDefinition);
|
|
349
|
-
if (validation.errors?.length > 0) {
|
|
350
|
-
console.error(`\nValidation errors for ${providerName}:`);
|
|
351
|
-
for (const error of validation.errors) {
|
|
352
|
-
console.error(` - ${error}`);
|
|
353
|
-
}
|
|
354
|
-
process.exit(1);
|
|
355
|
-
}
|
|
356
|
-
if (validation.warnings?.length > 0) {
|
|
357
|
-
for (const warning of validation.warnings) {
|
|
358
|
-
console.warn(` Warning: ${warning}`);
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// 2. Deploy via provider
|
|
364
|
-
try {
|
|
365
|
-
const result = await provider.deploy(appDefinition, {
|
|
366
|
-
stage: options.stage,
|
|
367
|
-
prod: options.stage === 'production' || options.stage === 'prod',
|
|
368
|
-
dryRun: options.dryRun || false,
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
console.log(`\nā Deployment completed successfully!`);
|
|
372
|
-
if (result.url) {
|
|
373
|
-
console.log(` URL: ${result.url}`);
|
|
374
|
-
}
|
|
375
|
-
} catch (error) {
|
|
376
|
-
console.error(`\nā Deployment failed: ${error.message}`);
|
|
377
|
-
if (error.missing) {
|
|
378
|
-
console.error(' Missing prerequisites:');
|
|
379
|
-
for (const item of error.missing) {
|
|
380
|
-
console.error(` - ${item}`);
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
process.exit(1);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
|
|
387
305
|
module.exports = { deployCommand };
|
|
@@ -12,9 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
14
|
const path = require('path');
|
|
15
|
-
const output = require('../utils/output');
|
|
16
15
|
const fs = require('fs');
|
|
17
|
-
|
|
16
|
+
const { select } = require('@inquirer/prompts');
|
|
18
17
|
const { CloudFormationClient, ListStacksCommand } = require('@aws-sdk/client-cloudformation');
|
|
19
18
|
|
|
20
19
|
// Domain and Application Layer
|
|
@@ -161,9 +160,9 @@ function formatJsonOutput(report) {
|
|
|
161
160
|
function writeOutputFile(content, filePath) {
|
|
162
161
|
try {
|
|
163
162
|
fs.writeFileSync(filePath, content, 'utf8');
|
|
164
|
-
|
|
163
|
+
console.log(`\nā Report saved to: ${filePath}`);
|
|
165
164
|
} catch (error) {
|
|
166
|
-
|
|
165
|
+
console.error(`\nā Failed to write output file: ${error.message}`);
|
|
167
166
|
process.exit(1);
|
|
168
167
|
}
|
|
169
168
|
}
|
|
@@ -205,17 +204,17 @@ async function listStacks(region) {
|
|
|
205
204
|
* @returns {Promise<string>} Selected stack name
|
|
206
205
|
*/
|
|
207
206
|
async function promptForStackSelection(region) {
|
|
208
|
-
|
|
207
|
+
console.log(`\nš Fetching CloudFormation stacks in ${region}...`);
|
|
209
208
|
|
|
210
209
|
const stacks = await listStacks(region);
|
|
211
210
|
|
|
212
211
|
if (stacks.length === 0) {
|
|
213
|
-
|
|
214
|
-
|
|
212
|
+
console.error(`\nā No CloudFormation stacks found in ${region}`);
|
|
213
|
+
console.log(' Make sure you have stacks deployed and the correct AWS credentials configured.');
|
|
215
214
|
process.exit(1);
|
|
216
215
|
}
|
|
217
216
|
|
|
218
|
-
|
|
217
|
+
console.log(`\nā Found ${stacks.length} stack(s)\n`);
|
|
219
218
|
|
|
220
219
|
// Create choices with stack name and metadata
|
|
221
220
|
const choices = stacks.map(stack => {
|
|
@@ -231,7 +230,7 @@ async function promptForStackSelection(region) {
|
|
|
231
230
|
};
|
|
232
231
|
});
|
|
233
232
|
|
|
234
|
-
const selectedStack = await
|
|
233
|
+
const selectedStack = await select({
|
|
235
234
|
message: 'Select a stack to run health check:',
|
|
236
235
|
choices,
|
|
237
236
|
pageSize: 15,
|
|
@@ -247,13 +246,6 @@ async function promptForStackSelection(region) {
|
|
|
247
246
|
*/
|
|
248
247
|
async function doctorCommand(stackName, options = {}) {
|
|
249
248
|
try {
|
|
250
|
-
// Guard: doctor only works with AWS (CloudFormation stacks)
|
|
251
|
-
if (isNonAwsProvider()) {
|
|
252
|
-
output.error('The doctor command is only available for AWS deployments.');
|
|
253
|
-
output.log('Your appDefinition uses a non-AWS provider.');
|
|
254
|
-
process.exit(1);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
249
|
// Extract options with defaults
|
|
258
250
|
const region = options.region || process.env.AWS_REGION || 'us-east-1';
|
|
259
251
|
const format = options.format || 'console';
|
|
@@ -265,7 +257,7 @@ async function doctorCommand(stackName, options = {}) {
|
|
|
265
257
|
}
|
|
266
258
|
|
|
267
259
|
// Show progress to user (always, not just verbose mode)
|
|
268
|
-
|
|
260
|
+
console.log(`\nš„ Running health check on stack: ${stackName} (${region})\n`);
|
|
269
261
|
|
|
270
262
|
// 1. Create stack identifier
|
|
271
263
|
const stackIdentifier = new StackIdentifier({ stackName, region });
|
|
@@ -289,9 +281,9 @@ async function doctorCommand(stackName, options = {}) {
|
|
|
289
281
|
// Progress callback to show execution status
|
|
290
282
|
const progressCallback = (step, message) => {
|
|
291
283
|
if (verbose) {
|
|
292
|
-
|
|
284
|
+
console.log(` ${message}`);
|
|
293
285
|
} else {
|
|
294
|
-
|
|
286
|
+
console.log(`${step} ${message}`);
|
|
295
287
|
}
|
|
296
288
|
};
|
|
297
289
|
|
|
@@ -300,7 +292,7 @@ async function doctorCommand(stackName, options = {}) {
|
|
|
300
292
|
onProgress: progressCallback
|
|
301
293
|
});
|
|
302
294
|
|
|
303
|
-
|
|
295
|
+
console.log('ā Health check complete!\n');
|
|
304
296
|
|
|
305
297
|
// 5. Format and output results
|
|
306
298
|
if (format === 'json') {
|
|
@@ -309,11 +301,11 @@ async function doctorCommand(stackName, options = {}) {
|
|
|
309
301
|
if (options.output) {
|
|
310
302
|
writeOutputFile(jsonOutput, options.output);
|
|
311
303
|
} else {
|
|
312
|
-
|
|
304
|
+
console.log(jsonOutput);
|
|
313
305
|
}
|
|
314
306
|
} else {
|
|
315
307
|
const consoleOutput = formatConsoleOutput(report, options);
|
|
316
|
-
|
|
308
|
+
console.log(consoleOutput);
|
|
317
309
|
|
|
318
310
|
if (options.output) {
|
|
319
311
|
writeOutputFile(consoleOutput, options.output);
|
|
@@ -330,27 +322,14 @@ async function doctorCommand(stackName, options = {}) {
|
|
|
330
322
|
process.exit(0);
|
|
331
323
|
}
|
|
332
324
|
} catch (error) {
|
|
333
|
-
|
|
325
|
+
console.error(`\nā Health check failed: ${error.message}`);
|
|
334
326
|
|
|
335
327
|
if (options.verbose && error.stack) {
|
|
336
|
-
|
|
328
|
+
console.error(`\nStack trace:\n${error.stack}`);
|
|
337
329
|
}
|
|
338
330
|
|
|
339
331
|
process.exit(1);
|
|
340
332
|
}
|
|
341
333
|
}
|
|
342
334
|
|
|
343
|
-
/**
|
|
344
|
-
* Check if the current appDefinition uses a non-AWS provider.
|
|
345
|
-
*/
|
|
346
|
-
function isNonAwsProvider() {
|
|
347
|
-
try {
|
|
348
|
-
const { loadProviderForCli } = require('../utils/provider-helper');
|
|
349
|
-
const result = loadProviderForCli();
|
|
350
|
-
return result && result.providerName !== 'aws';
|
|
351
|
-
} catch {
|
|
352
|
-
return false;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
335
|
module.exports = { doctorCommand };
|
|
@@ -9,14 +9,7 @@ const { generateIAMCloudFormation, getFeatureSummary } = require('../infrastruct
|
|
|
9
9
|
*/
|
|
10
10
|
async function generateIamCommand(options = {}) {
|
|
11
11
|
try {
|
|
12
|
-
|
|
13
|
-
if (isNonAwsProvider()) {
|
|
14
|
-
console.error('The generate-iam command is only available for AWS deployments.');
|
|
15
|
-
console.log('Your appDefinition uses a non-AWS provider.');
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
console.log('Finding Frigg application...');
|
|
12
|
+
console.log('š Finding Frigg application...');
|
|
20
13
|
|
|
21
14
|
// Find the backend package.json
|
|
22
15
|
const backendPath = findNearestBackendPackageJson();
|
|
@@ -122,17 +115,4 @@ async function generateIamCommand(options = {}) {
|
|
|
122
115
|
}
|
|
123
116
|
}
|
|
124
117
|
|
|
125
|
-
/**
|
|
126
|
-
* Check if the current appDefinition uses a non-AWS provider.
|
|
127
|
-
*/
|
|
128
|
-
function isNonAwsProvider() {
|
|
129
|
-
try {
|
|
130
|
-
const { loadProviderForCli } = require('./utils/provider-helper');
|
|
131
|
-
const result = loadProviderForCli();
|
|
132
|
-
return result && result.providerName !== 'aws';
|
|
133
|
-
} catch {
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
118
|
module.exports = { generateIamCommand };
|
package/frigg-cli/index.js
CHANGED
|
@@ -86,23 +86,15 @@ const { dbSetupCommand } = require('./db-setup-command');
|
|
|
86
86
|
const { doctorCommand } = require('./doctor-command');
|
|
87
87
|
const { repairCommand } = require('./repair-command');
|
|
88
88
|
const { authCommand } = require('./auth-command');
|
|
89
|
-
const { createValidateCommand } = require('./validate-command/adapters/cli/validate-command');
|
|
90
89
|
|
|
91
90
|
const program = new Command();
|
|
92
91
|
|
|
93
|
-
// Add version command using package.json version
|
|
94
|
-
const packageJson = require('./package.json');
|
|
95
92
|
program
|
|
96
|
-
.
|
|
97
|
-
|
|
98
|
-
program
|
|
99
|
-
.command('init <projectName>')
|
|
93
|
+
.command('init [templateName]')
|
|
100
94
|
.description('Initialize a new Frigg application')
|
|
101
|
-
.option('-
|
|
102
|
-
.option('-
|
|
103
|
-
.option('--
|
|
104
|
-
.option('-y, --yes', 'accept defaults without prompting')
|
|
105
|
-
.option('--verbose', 'enable verbose output')
|
|
95
|
+
.option('-t, --template <template>', 'template to use', 'backend-only')
|
|
96
|
+
.option('-n, --name <name>', 'project name')
|
|
97
|
+
.option('-d, --directory <directory>', 'target directory')
|
|
106
98
|
.action(initCommand);
|
|
107
99
|
|
|
108
100
|
program
|
|
@@ -115,8 +107,6 @@ program
|
|
|
115
107
|
.description('Run the backend and optional frontend')
|
|
116
108
|
.option('-s, --stage <stage>', 'deployment stage', 'dev')
|
|
117
109
|
.option('-v, --verbose', 'enable verbose output')
|
|
118
|
-
.option('--ipc', 'enable IPC mode for Management UI communication')
|
|
119
|
-
.option('--no-interactive', 'skip interactive pre-flight prompts')
|
|
120
110
|
.action(startCommand);
|
|
121
111
|
|
|
122
112
|
program
|
|
@@ -179,8 +169,6 @@ program
|
|
|
179
169
|
.option('-v, --verbose', 'enable verbose output')
|
|
180
170
|
.action(repairCommand);
|
|
181
171
|
|
|
182
|
-
createValidateCommand(program);
|
|
183
|
-
|
|
184
172
|
// Auth command group for testing API module authentication
|
|
185
173
|
const authProgram = program
|
|
186
174
|
.command('auth')
|
|
@@ -215,9 +203,6 @@ authProgram
|
|
|
215
203
|
.option('-y, --yes', 'Skip confirmation')
|
|
216
204
|
.action(authCommand.delete);
|
|
217
205
|
|
|
218
|
-
|
|
219
|
-
if (require.main === module) {
|
|
220
|
-
program.parse(process.argv);
|
|
221
|
-
}
|
|
206
|
+
program.parse(process.argv);
|
|
222
207
|
|
|
223
|
-
module.exports = { initCommand, installCommand, startCommand, buildCommand, deployCommand, generateIamCommand, uiCommand, dbSetupCommand, doctorCommand, repairCommand, authCommand
|
|
208
|
+
module.exports = { initCommand, installCommand, startCommand, buildCommand, deployCommand, generateIamCommand, uiCommand, dbSetupCommand, doctorCommand, repairCommand, authCommand };
|
package/frigg-cli/index.test.js
CHANGED
|
@@ -6,14 +6,9 @@ const { installPackage } = require('./install-command/install-package');
|
|
|
6
6
|
const { createIntegrationFile } = require('./install-command/integration-file');
|
|
7
7
|
const { updateBackendJsFile } = require('./install-command/backend-js');
|
|
8
8
|
const { commitChanges } = require('./install-command/commit-changes');
|
|
9
|
+
const { logInfo, logError } = require('./install-command/logger');
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
* @group unit
|
|
12
|
-
* @group infrastructure
|
|
13
|
-
*/
|
|
14
|
-
// TODO: Fix these tests - they have issues with Commander.js mocking
|
|
15
|
-
// The mocks need to be set up before the module is loaded, not inline in tests
|
|
16
|
-
describe.skip('CLI Command Tests', () => {
|
|
11
|
+
describe('CLI Command Tests', () => {
|
|
17
12
|
it('should successfully install an API module when all steps complete without errors', async () => {
|
|
18
13
|
const mockApiModuleName = 'testModule';
|
|
19
14
|
const mockPackageName = `@friggframework/api-module-${mockApiModuleName}`;
|