@friggframework/devtools 2.0.0--canary.400.bed3308.0 → 2.0.0--canary.404.e9d4980.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/build-command/index.js +3 -18
- package/frigg-cli/deploy-command/index.js +3 -19
- package/frigg-cli/index.js +1 -73
- package/frigg-cli/install-command/index.js +2 -15
- package/frigg-cli/start-command/index.js +2 -17
- package/infrastructure/create-frigg-infrastructure.js +2 -2
- package/infrastructure/serverless-template.js +79 -529
- package/package.json +5 -9
- package/frigg-cli/.eslintrc.js +0 -141
- package/frigg-cli/__tests__/jest.config.js +0 -102
- package/frigg-cli/__tests__/unit/commands/build.test.js +0 -483
- package/frigg-cli/__tests__/unit/commands/install.test.js +0 -418
- package/frigg-cli/__tests__/unit/commands/ui.test.js +0 -592
- package/frigg-cli/__tests__/utils/command-tester.js +0 -170
- package/frigg-cli/__tests__/utils/mock-factory.js +0 -270
- package/frigg-cli/__tests__/utils/test-fixtures.js +0 -463
- package/frigg-cli/__tests__/utils/test-setup.js +0 -286
- package/frigg-cli/generate-command/__tests__/generate-command.test.js +0 -312
- package/frigg-cli/generate-command/azure-generator.js +0 -43
- package/frigg-cli/generate-command/gcp-generator.js +0 -47
- package/frigg-cli/generate-command/index.js +0 -350
- package/frigg-cli/generate-command/terraform-generator.js +0 -555
- package/frigg-cli/generate-iam-command.js +0 -115
- package/frigg-cli/package.json +0 -75
- package/frigg-cli/ui-command/index.js +0 -167
- package/frigg-cli/utils/app-resolver.js +0 -319
- package/frigg-cli/utils/backend-path.js +0 -38
- package/frigg-cli/utils/process-manager.js +0 -199
- package/frigg-cli/utils/repo-detection.js +0 -405
- package/infrastructure/AWS-DISCOVERY-TROUBLESHOOTING.md +0 -245
- package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +0 -620
- package/infrastructure/DEPLOYMENT-INSTRUCTIONS.md +0 -268
- package/infrastructure/GENERATE-IAM-DOCS.md +0 -253
- package/infrastructure/IAM-POLICY-TEMPLATES.md +0 -176
- package/infrastructure/README-TESTING.md +0 -332
- package/infrastructure/README.md +0 -421
- package/infrastructure/WEBSOCKET-CONFIGURATION.md +0 -105
- package/infrastructure/__tests__/fixtures/mock-aws-resources.js +0 -391
- package/infrastructure/__tests__/helpers/test-utils.js +0 -277
- package/infrastructure/aws-discovery.js +0 -568
- package/infrastructure/aws-discovery.test.js +0 -373
- package/infrastructure/build-time-discovery.js +0 -206
- package/infrastructure/build-time-discovery.test.js +0 -375
- package/infrastructure/frigg-deployment-iam-stack.yaml +0 -393
- package/infrastructure/iam-generator.js +0 -810
- package/infrastructure/iam-generator.test.js +0 -169
- package/infrastructure/iam-policy-basic.json +0 -236
- package/infrastructure/iam-policy-full.json +0 -305
- package/infrastructure/integration.test.js +0 -383
- package/infrastructure/run-discovery.js +0 -110
- package/infrastructure/serverless-template.test.js +0 -553
- package/management-ui/.eslintrc.js +0 -22
- package/management-ui/README.md +0 -203
- package/management-ui/components.json +0 -21
- package/management-ui/index.html +0 -13
- package/management-ui/merge-conflict-cleaner.py +0 -371
- package/management-ui/package-lock.json +0 -10997
- package/management-ui/package.json +0 -76
- package/management-ui/postcss.config.js +0 -6
- package/management-ui/server/api/backend.js +0 -256
- package/management-ui/server/api/cli.js +0 -315
- package/management-ui/server/api/codegen.js +0 -663
- package/management-ui/server/api/connections.js +0 -857
- package/management-ui/server/api/discovery.js +0 -185
- package/management-ui/server/api/environment/index.js +0 -1
- package/management-ui/server/api/environment/router.js +0 -378
- package/management-ui/server/api/environment.js +0 -328
- package/management-ui/server/api/integrations.js +0 -479
- package/management-ui/server/api/logs.js +0 -248
- package/management-ui/server/api/monitoring.js +0 -282
- package/management-ui/server/api/open-ide.js +0 -31
- package/management-ui/server/api/project.js +0 -553
- package/management-ui/server/api/users/sessions.js +0 -371
- package/management-ui/server/api/users/simulation.js +0 -254
- package/management-ui/server/api/users.js +0 -362
- package/management-ui/server/api-contract.md +0 -275
- package/management-ui/server/index.js +0 -428
- package/management-ui/server/middleware/errorHandler.js +0 -70
- package/management-ui/server/middleware/security.js +0 -32
- package/management-ui/server/processManager.js +0 -296
- package/management-ui/server/server.js +0 -188
- package/management-ui/server/services/aws-monitor.js +0 -413
- package/management-ui/server/services/npm-registry.js +0 -347
- package/management-ui/server/services/template-engine.js +0 -538
- package/management-ui/server/utils/cliIntegration.js +0 -220
- package/management-ui/server/utils/environment/auditLogger.js +0 -471
- package/management-ui/server/utils/environment/awsParameterStore.js +0 -264
- package/management-ui/server/utils/environment/encryption.js +0 -278
- package/management-ui/server/utils/environment/envFileManager.js +0 -286
- package/management-ui/server/utils/import-commonjs.js +0 -28
- package/management-ui/server/utils/response.js +0 -83
- package/management-ui/server/websocket/handler.js +0 -325
- package/management-ui/src/App.jsx +0 -51
- package/management-ui/src/assets/FriggLogo.svg +0 -1
- package/management-ui/src/components/AppRouter.jsx +0 -65
- package/management-ui/src/components/Button.jsx +0 -2
- package/management-ui/src/components/Card.jsx +0 -9
- package/management-ui/src/components/EnvironmentCompare.jsx +0 -400
- package/management-ui/src/components/EnvironmentEditor.jsx +0 -372
- package/management-ui/src/components/EnvironmentImportExport.jsx +0 -469
- package/management-ui/src/components/EnvironmentSchema.jsx +0 -491
- package/management-ui/src/components/EnvironmentSecurity.jsx +0 -463
- package/management-ui/src/components/ErrorBoundary.jsx +0 -73
- package/management-ui/src/components/IntegrationCard.jsx +0 -199
- package/management-ui/src/components/IntegrationCardEnhanced.jsx +0 -490
- package/management-ui/src/components/IntegrationExplorer.jsx +0 -379
- package/management-ui/src/components/IntegrationStatus.jsx +0 -235
- package/management-ui/src/components/Layout.jsx +0 -250
- package/management-ui/src/components/LoadingSpinner.jsx +0 -45
- package/management-ui/src/components/RepositoryPicker.jsx +0 -248
- package/management-ui/src/components/SessionMonitor.jsx +0 -255
- package/management-ui/src/components/StatusBadge.jsx +0 -70
- package/management-ui/src/components/UserContextSwitcher.jsx +0 -154
- package/management-ui/src/components/UserSimulation.jsx +0 -299
- package/management-ui/src/components/Welcome.jsx +0 -434
- package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +0 -637
- package/management-ui/src/components/codegen/APIModuleSelector.jsx +0 -227
- package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +0 -247
- package/management-ui/src/components/codegen/CodePreviewEditor.jsx +0 -316
- package/management-ui/src/components/codegen/DynamicModuleForm.jsx +0 -271
- package/management-ui/src/components/codegen/FormBuilder.jsx +0 -737
- package/management-ui/src/components/codegen/IntegrationGenerator.jsx +0 -855
- package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +0 -797
- package/management-ui/src/components/codegen/SchemaBuilder.jsx +0 -303
- package/management-ui/src/components/codegen/TemplateSelector.jsx +0 -586
- package/management-ui/src/components/codegen/index.js +0 -10
- package/management-ui/src/components/connections/ConnectionConfigForm.jsx +0 -362
- package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +0 -182
- package/management-ui/src/components/connections/ConnectionTester.jsx +0 -200
- package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +0 -292
- package/management-ui/src/components/connections/OAuthFlow.jsx +0 -204
- package/management-ui/src/components/connections/index.js +0 -5
- package/management-ui/src/components/index.js +0 -21
- package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +0 -222
- package/management-ui/src/components/monitoring/LambdaMetrics.jsx +0 -169
- package/management-ui/src/components/monitoring/MetricsChart.jsx +0 -197
- package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +0 -393
- package/management-ui/src/components/monitoring/SQSMetrics.jsx +0 -246
- package/management-ui/src/components/monitoring/index.js +0 -6
- package/management-ui/src/components/monitoring/monitoring.css +0 -218
- package/management-ui/src/components/theme-provider.jsx +0 -52
- package/management-ui/src/components/theme-toggle.jsx +0 -39
- package/management-ui/src/components/ui/badge.tsx +0 -36
- package/management-ui/src/components/ui/button.test.jsx +0 -56
- package/management-ui/src/components/ui/button.tsx +0 -57
- package/management-ui/src/components/ui/card.tsx +0 -76
- package/management-ui/src/components/ui/dropdown-menu.tsx +0 -199
- package/management-ui/src/components/ui/select.tsx +0 -157
- package/management-ui/src/components/ui/skeleton.jsx +0 -15
- package/management-ui/src/hooks/useFrigg.jsx +0 -387
- package/management-ui/src/hooks/useSocket.jsx +0 -58
- package/management-ui/src/index.css +0 -194
- package/management-ui/src/lib/utils.ts +0 -6
- package/management-ui/src/main.jsx +0 -10
- package/management-ui/src/pages/CodeGeneration.jsx +0 -14
- package/management-ui/src/pages/Connections.jsx +0 -252
- package/management-ui/src/pages/ConnectionsEnhanced.jsx +0 -427
- package/management-ui/src/pages/Dashboard.jsx +0 -311
- package/management-ui/src/pages/Environment.jsx +0 -314
- package/management-ui/src/pages/IntegrationConfigure.jsx +0 -544
- package/management-ui/src/pages/IntegrationDiscovery.jsx +0 -479
- package/management-ui/src/pages/IntegrationTest.jsx +0 -494
- package/management-ui/src/pages/Integrations.jsx +0 -254
- package/management-ui/src/pages/Monitoring.jsx +0 -17
- package/management-ui/src/pages/Simulation.jsx +0 -155
- package/management-ui/src/pages/Users.jsx +0 -492
- package/management-ui/src/services/api.js +0 -41
- package/management-ui/src/services/apiModuleService.js +0 -193
- package/management-ui/src/services/websocket-handlers.js +0 -120
- package/management-ui/src/test/api/project.test.js +0 -273
- package/management-ui/src/test/components/Welcome.test.jsx +0 -378
- package/management-ui/src/test/mocks/server.js +0 -178
- package/management-ui/src/test/setup.js +0 -61
- package/management-ui/src/test/utils/test-utils.jsx +0 -134
- package/management-ui/src/utils/repository.js +0 -98
- package/management-ui/src/utils/repository.test.js +0 -118
- package/management-ui/src/workflows/phase2-integration-workflows.js +0 -884
- package/management-ui/tailwind.config.js +0 -63
- package/management-ui/tsconfig.json +0 -37
- package/management-ui/tsconfig.node.json +0 -10
- package/management-ui/vite.config.js +0 -26
- package/management-ui/vitest.config.js +0 -38
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Pre-build script to run AWS discovery and set environment variables
|
|
5
|
-
* This should be run before serverless commands that need AWS resource discovery
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { BuildTimeDiscovery } = require('./build-time-discovery');
|
|
9
|
-
const { findNearestBackendPackageJson } = require('@friggframework/core');
|
|
10
|
-
const path = require('path');
|
|
11
|
-
|
|
12
|
-
async function runDiscovery() {
|
|
13
|
-
let appDefinition;
|
|
14
|
-
|
|
15
|
-
try {
|
|
16
|
-
console.log('🔍 Starting AWS resource discovery...');
|
|
17
|
-
|
|
18
|
-
// Find the backend package.json to get AppDefinition
|
|
19
|
-
const backendPath = findNearestBackendPackageJson();
|
|
20
|
-
if (!backendPath) {
|
|
21
|
-
console.log('⚠️ No backend package.json found, skipping discovery');
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const backendDir = path.dirname(backendPath);
|
|
26
|
-
const backendFilePath = path.join(backendDir, 'index.js');
|
|
27
|
-
|
|
28
|
-
if (!require('fs').existsSync(backendFilePath)) {
|
|
29
|
-
console.log('⚠️ No backend/index.js found, skipping discovery');
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Load the app definition
|
|
34
|
-
const backend = require(backendFilePath);
|
|
35
|
-
appDefinition = backend.Definition;
|
|
36
|
-
|
|
37
|
-
if (!appDefinition) {
|
|
38
|
-
console.log('⚠️ No Definition found in backend/index.js, skipping discovery');
|
|
39
|
-
return;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
// Check if discovery is needed
|
|
43
|
-
const needsDiscovery = appDefinition.vpc?.enable ||
|
|
44
|
-
appDefinition.encryption?.useDefaultKMSForFieldLevelEncryption ||
|
|
45
|
-
appDefinition.ssm?.enable;
|
|
46
|
-
|
|
47
|
-
if (!needsDiscovery) {
|
|
48
|
-
console.log('ℹ️ No AWS discovery needed based on app definition');
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
console.log('📋 App requires AWS discovery for:');
|
|
53
|
-
if (appDefinition.vpc?.enable) console.log(' ✅ VPC support');
|
|
54
|
-
if (appDefinition.encryption?.useDefaultKMSForFieldLevelEncryption) console.log(' ✅ KMS encryption');
|
|
55
|
-
if (appDefinition.ssm?.enable) console.log(' ✅ SSM parameters');
|
|
56
|
-
|
|
57
|
-
// Run discovery
|
|
58
|
-
const discovery = new BuildTimeDiscovery();
|
|
59
|
-
const resources = await discovery.preBuildHook(appDefinition, process.env.AWS_REGION || 'us-east-1');
|
|
60
|
-
|
|
61
|
-
if (resources) {
|
|
62
|
-
console.log('✅ AWS discovery completed successfully!');
|
|
63
|
-
console.log(` VPC: ${resources.defaultVpcId}`);
|
|
64
|
-
console.log(` Subnets: ${resources.privateSubnetId1}, ${resources.privateSubnetId2}`);
|
|
65
|
-
console.log(` Public Subnet: ${resources.publicSubnetId}`);
|
|
66
|
-
console.log(` Security Group: ${resources.defaultSecurityGroupId}`);
|
|
67
|
-
console.log(` Route Table: ${resources.privateRouteTableId}`);
|
|
68
|
-
console.log(` KMS Key: ${resources.defaultKmsKeyId}`);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
} catch (error) {
|
|
72
|
-
console.error('❌ AWS discovery failed:', error.message);
|
|
73
|
-
console.error('');
|
|
74
|
-
|
|
75
|
-
// Check if this is an AWS SDK missing error
|
|
76
|
-
if (error.message.includes('Cannot find module') && error.message.includes('@aws-sdk')) {
|
|
77
|
-
console.error('🚨 AWS SDK not installed!');
|
|
78
|
-
console.error('');
|
|
79
|
-
console.error('💡 Install AWS SDK dependencies:');
|
|
80
|
-
console.error(' npm install @aws-sdk/client-ec2 @aws-sdk/client-kms @aws-sdk/client-sts');
|
|
81
|
-
console.error('');
|
|
82
|
-
} else {
|
|
83
|
-
console.error('🚨 Discovery is required because your AppDefinition has these features enabled:');
|
|
84
|
-
if (appDefinition.vpc?.enable) console.error(' ❌ VPC support (vpc.enable: true)');
|
|
85
|
-
if (appDefinition.encryption?.useDefaultKMSForFieldLevelEncryption) console.error(' ❌ KMS encryption (encryption.useDefaultKMSForFieldLevelEncryption: true)');
|
|
86
|
-
if (appDefinition.ssm?.enable) console.error(' ❌ SSM parameters (ssm.enable: true)');
|
|
87
|
-
console.error('');
|
|
88
|
-
console.error('💡 To fix this issue:');
|
|
89
|
-
console.error(' 1. Check AWS credentials: aws sts get-caller-identity');
|
|
90
|
-
console.error(' 2. Verify IAM permissions (see AWS-IAM-CREDENTIAL-NEEDS.md)');
|
|
91
|
-
console.error(' 3. Ensure default VPC exists: aws ec2 describe-vpcs');
|
|
92
|
-
console.error(' 4. Check AWS region: aws configure get region');
|
|
93
|
-
console.error('');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
console.error('🔧 Or disable features in backend/index.js:');
|
|
97
|
-
console.error(' vpc: { enable: false }');
|
|
98
|
-
console.error(' encryption: { useDefaultKMSForFieldLevelEncryption: false }');
|
|
99
|
-
console.error(' ssm: { enable: false }');
|
|
100
|
-
|
|
101
|
-
process.exit(1);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Run if called directly
|
|
106
|
-
if (require.main === module) {
|
|
107
|
-
runDiscovery();
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
module.exports = { runDiscovery };
|
|
@@ -1,553 +0,0 @@
|
|
|
1
|
-
const { composeServerlessDefinition } = require('./serverless-template');
|
|
2
|
-
|
|
3
|
-
// Mock AWS Discovery to prevent actual AWS calls
|
|
4
|
-
jest.mock('./aws-discovery', () => {
|
|
5
|
-
return {
|
|
6
|
-
AWSDiscovery: jest.fn().mockImplementation(() => {
|
|
7
|
-
return {
|
|
8
|
-
discoverResources: jest.fn().mockResolvedValue({
|
|
9
|
-
defaultVpcId: 'vpc-123456',
|
|
10
|
-
defaultSecurityGroupId: 'sg-123456',
|
|
11
|
-
privateSubnetId1: 'subnet-123456',
|
|
12
|
-
privateSubnetId2: 'subnet-789012',
|
|
13
|
-
publicSubnetId: 'subnet-public',
|
|
14
|
-
defaultRouteTableId: 'rtb-123456',
|
|
15
|
-
defaultKmsKeyId: 'arn:aws:kms:us-east-1:123456789012:key/12345678-1234-1234-1234-123456789012'
|
|
16
|
-
})
|
|
17
|
-
};
|
|
18
|
-
})
|
|
19
|
-
};
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
describe('composeServerlessDefinition', () => {
|
|
23
|
-
let mockIntegration;
|
|
24
|
-
|
|
25
|
-
beforeEach(() => {
|
|
26
|
-
mockIntegration = {
|
|
27
|
-
Definition: {
|
|
28
|
-
name: 'testIntegration'
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// Mock process.argv to avoid offline mode during tests
|
|
33
|
-
process.argv = ['node', 'test'];
|
|
34
|
-
<<<<<<< HEAD
|
|
35
|
-
=======
|
|
36
|
-
|
|
37
|
-
>>>>>>> 37c4892ee8a686eb7acfcd17c333b0ed73e1f120
|
|
38
|
-
// Clear AWS_REGION for tests
|
|
39
|
-
delete process.env.AWS_REGION;
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
afterEach(() => {
|
|
43
|
-
jest.restoreAllMocks();
|
|
44
|
-
// Restore env
|
|
45
|
-
delete process.env.AWS_REGION;
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
describe('Basic Configuration', () => {
|
|
49
|
-
it('should create basic serverless definition with minimal app definition', async () => {
|
|
50
|
-
const appDefinition = {
|
|
51
|
-
name: 'test-app',
|
|
52
|
-
integrations: []
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
56
|
-
|
|
57
|
-
expect(result.service).toBe('test-app');
|
|
58
|
-
expect(result.provider.name).toBe('aws');
|
|
59
|
-
expect(result.provider.runtime).toBe('nodejs20.x');
|
|
60
|
-
expect(result.provider.region).toBe('us-east-1');
|
|
61
|
-
expect(result.provider.stage).toBe('${opt:stage}');
|
|
62
|
-
expect(result.frameworkVersion).toBe('>=3.17.0');
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
it('should use default service name when name not provided', async () => {
|
|
66
|
-
const appDefinition = {
|
|
67
|
-
integrations: []
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
71
|
-
|
|
72
|
-
expect(result.service).toBe('create-frigg-app');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should use custom provider when specified', async () => {
|
|
76
|
-
const appDefinition = {
|
|
77
|
-
provider: 'custom-provider',
|
|
78
|
-
integrations: []
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
82
|
-
|
|
83
|
-
expect(result.provider.name).toBe('custom-provider');
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should use AWS_REGION environment variable when set', async () => {
|
|
87
|
-
process.env.AWS_REGION = 'eu-west-1';
|
|
88
|
-
<<<<<<< HEAD
|
|
89
|
-
=======
|
|
90
|
-
|
|
91
|
-
>>>>>>> 37c4892ee8a686eb7acfcd17c333b0ed73e1f120
|
|
92
|
-
const appDefinition = {
|
|
93
|
-
name: 'test-app',
|
|
94
|
-
integrations: []
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
98
|
-
|
|
99
|
-
expect(result.provider.region).toBe('eu-west-1');
|
|
100
|
-
expect(result.custom['serverless-offline-sqs'].region).toBe('eu-west-1');
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it('should default to us-east-1 when AWS_REGION is not set', async () => {
|
|
104
|
-
delete process.env.AWS_REGION;
|
|
105
|
-
<<<<<<< HEAD
|
|
106
|
-
=======
|
|
107
|
-
|
|
108
|
-
>>>>>>> 37c4892ee8a686eb7acfcd17c333b0ed73e1f120
|
|
109
|
-
const appDefinition = {
|
|
110
|
-
name: 'test-app',
|
|
111
|
-
integrations: []
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
115
|
-
|
|
116
|
-
expect(result.provider.region).toBe('us-east-1');
|
|
117
|
-
expect(result.custom['serverless-offline-sqs'].region).toBe('us-east-1');
|
|
118
|
-
});
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
describe('VPC Configuration', () => {
|
|
122
|
-
it('should add VPC configuration when vpc.enable is true', async () => {
|
|
123
|
-
const appDefinition = {
|
|
124
|
-
vpc: { enable: true },
|
|
125
|
-
integrations: []
|
|
126
|
-
};
|
|
127
|
-
|
|
128
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
129
|
-
|
|
130
|
-
expect(result.provider.vpc).toBe('${self:custom.vpc.${self:provider.stage}}');
|
|
131
|
-
expect(result.custom.vpc).toEqual({
|
|
132
|
-
'${self:provider.stage}': {
|
|
133
|
-
securityGroupIds: ['${env:AWS_DISCOVERY_SECURITY_GROUP_ID}'],
|
|
134
|
-
subnetIds: [
|
|
135
|
-
'${env:AWS_DISCOVERY_SUBNET_ID_1}',
|
|
136
|
-
'${env:AWS_DISCOVERY_SUBNET_ID_2}'
|
|
137
|
-
]
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
it('should add VPC endpoint for S3 when VPC is enabled', async () => {
|
|
143
|
-
const appDefinition = {
|
|
144
|
-
vpc: { enable: true },
|
|
145
|
-
integrations: []
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
149
|
-
|
|
150
|
-
expect(result.resources.Resources.VPCEndpointS3).toEqual({
|
|
151
|
-
Type: 'AWS::EC2::VPCEndpoint',
|
|
152
|
-
Properties: {
|
|
153
|
-
VpcId: '${env:AWS_DISCOVERY_VPC_ID}',
|
|
154
|
-
ServiceName: 'com.amazonaws.${self:provider.region}.s3',
|
|
155
|
-
VpcEndpointType: 'Gateway',
|
|
156
|
-
RouteTableIds: ['${env:AWS_DISCOVERY_ROUTE_TABLE_ID}']
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
it('should not add VPC configuration when vpc.enable is false', async () => {
|
|
162
|
-
const appDefinition = {
|
|
163
|
-
vpc: { enable: false },
|
|
164
|
-
integrations: []
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
168
|
-
|
|
169
|
-
expect(result.provider.vpc).toBeUndefined();
|
|
170
|
-
expect(result.custom.vpc).toBeUndefined();
|
|
171
|
-
expect(result.resources.Resources.VPCEndpointS3).toBeUndefined();
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it('should not add VPC configuration when vpc is not defined', async () => {
|
|
175
|
-
const appDefinition = {
|
|
176
|
-
integrations: []
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
180
|
-
|
|
181
|
-
expect(result.provider.vpc).toBeUndefined();
|
|
182
|
-
expect(result.custom.vpc).toBeUndefined();
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
describe('KMS Configuration', () => {
|
|
187
|
-
it('should add KMS configuration when encryption is enabled', async () => {
|
|
188
|
-
const appDefinition = {
|
|
189
|
-
encryption: { useDefaultKMSForFieldLevelEncryption: true },
|
|
190
|
-
integrations: []
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
194
|
-
|
|
195
|
-
// Check IAM permissions
|
|
196
|
-
const kmsPermission = result.provider.iamRoleStatements.find(
|
|
197
|
-
statement => statement.Action.includes('kms:GenerateDataKey')
|
|
198
|
-
);
|
|
199
|
-
expect(kmsPermission).toEqual({
|
|
200
|
-
Effect: 'Allow',
|
|
201
|
-
Action: [
|
|
202
|
-
'kms:GenerateDataKey',
|
|
203
|
-
'kms:Decrypt'
|
|
204
|
-
],
|
|
205
|
-
Resource: ['${self:custom.kmsGrants.kmsKeyId}']
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
// Check environment variable
|
|
209
|
-
expect(result.provider.environment.KMS_KEY_ARN).toBe('${self:custom.kmsGrants.kmsKeyId}');
|
|
210
|
-
|
|
211
|
-
// Check plugin
|
|
212
|
-
expect(result.plugins).toContain('serverless-kms-grants');
|
|
213
|
-
|
|
214
|
-
// Check custom configuration
|
|
215
|
-
expect(result.custom.kmsGrants).toEqual({
|
|
216
|
-
kmsKeyId: '${env:AWS_DISCOVERY_KMS_KEY_ID}'
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it('should not add KMS configuration when encryption is disabled', async () => {
|
|
221
|
-
const appDefinition = {
|
|
222
|
-
encryption: { useDefaultKMSForFieldLevelEncryption: false },
|
|
223
|
-
integrations: []
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
227
|
-
|
|
228
|
-
const kmsPermission = result.provider.iamRoleStatements.find(
|
|
229
|
-
statement => statement.Action && statement.Action.includes('kms:GenerateDataKey')
|
|
230
|
-
);
|
|
231
|
-
expect(kmsPermission).toBeUndefined();
|
|
232
|
-
expect(result.provider.environment.KMS_KEY_ARN).toBeUndefined();
|
|
233
|
-
expect(result.plugins).not.toContain('serverless-kms-grants');
|
|
234
|
-
expect(result.custom.kmsGrants).toBeUndefined();
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('should not add KMS configuration when encryption is not defined', async () => {
|
|
238
|
-
const appDefinition = {
|
|
239
|
-
integrations: []
|
|
240
|
-
};
|
|
241
|
-
|
|
242
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
243
|
-
|
|
244
|
-
const kmsPermission = result.provider.iamRoleStatements.find(
|
|
245
|
-
statement => statement.Action && statement.Action.includes('kms:GenerateDataKey')
|
|
246
|
-
);
|
|
247
|
-
expect(kmsPermission).toBeUndefined();
|
|
248
|
-
expect(result.custom.kmsGrants).toBeUndefined();
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
describe('SSM Configuration', () => {
|
|
253
|
-
it('should add SSM configuration when ssm.enable is true', async () => {
|
|
254
|
-
const appDefinition = {
|
|
255
|
-
ssm: { enable: true },
|
|
256
|
-
integrations: []
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
260
|
-
|
|
261
|
-
// Check lambda layers
|
|
262
|
-
expect(result.provider.layers).toEqual([
|
|
263
|
-
'arn:aws:lambda:${self:provider.region}:177933569100:layer:AWS-Parameters-and-Secrets-Lambda-Extension:11'
|
|
264
|
-
]);
|
|
265
|
-
|
|
266
|
-
// Check IAM permissions
|
|
267
|
-
const ssmPermission = result.provider.iamRoleStatements.find(
|
|
268
|
-
statement => statement.Action.includes('ssm:GetParameter')
|
|
269
|
-
);
|
|
270
|
-
expect(ssmPermission).toEqual({
|
|
271
|
-
Effect: 'Allow',
|
|
272
|
-
Action: [
|
|
273
|
-
'ssm:GetParameter',
|
|
274
|
-
'ssm:GetParameters',
|
|
275
|
-
'ssm:GetParametersByPath'
|
|
276
|
-
],
|
|
277
|
-
Resource: [
|
|
278
|
-
'arn:aws:ssm:${self:provider.region}:*:parameter/${self:service}/${self:provider.stage}/*'
|
|
279
|
-
]
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
// Check environment variable
|
|
283
|
-
expect(result.provider.environment.SSM_PARAMETER_PREFIX).toBe('/${self:service}/${self:provider.stage}');
|
|
284
|
-
});
|
|
285
|
-
|
|
286
|
-
it('should not add SSM configuration when ssm.enable is false', async () => {
|
|
287
|
-
const appDefinition = {
|
|
288
|
-
ssm: { enable: false },
|
|
289
|
-
integrations: []
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
293
|
-
|
|
294
|
-
expect(result.provider.layers).toBeUndefined();
|
|
295
|
-
<<<<<<< HEAD
|
|
296
|
-
=======
|
|
297
|
-
|
|
298
|
-
>>>>>>> 37c4892ee8a686eb7acfcd17c333b0ed73e1f120
|
|
299
|
-
const ssmPermission = result.provider.iamRoleStatements.find(
|
|
300
|
-
statement => statement.Action && statement.Action.includes('ssm:GetParameter')
|
|
301
|
-
);
|
|
302
|
-
expect(ssmPermission).toBeUndefined();
|
|
303
|
-
expect(result.provider.environment.SSM_PARAMETER_PREFIX).toBeUndefined();
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
it('should not add SSM configuration when ssm is not defined', async () => {
|
|
307
|
-
const appDefinition = {
|
|
308
|
-
integrations: []
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
312
|
-
|
|
313
|
-
expect(result.provider.layers).toBeUndefined();
|
|
314
|
-
expect(result.provider.environment.SSM_PARAMETER_PREFIX).toBeUndefined();
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
describe('Integration Configuration', () => {
|
|
319
|
-
it('should add integration-specific resources and functions', async () => {
|
|
320
|
-
const appDefinition = {
|
|
321
|
-
integrations: [mockIntegration]
|
|
322
|
-
};
|
|
323
|
-
|
|
324
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
325
|
-
|
|
326
|
-
// Check integration function
|
|
327
|
-
expect(result.functions.testIntegration).toEqual({
|
|
328
|
-
handler: 'node_modules/@friggframework/core/handlers/routers/integration-defined-routers.handlers.testIntegration.handler',
|
|
329
|
-
events: [{
|
|
330
|
-
http: {
|
|
331
|
-
path: '/api/testIntegration-integration/{proxy+}',
|
|
332
|
-
method: 'ANY',
|
|
333
|
-
cors: true
|
|
334
|
-
}
|
|
335
|
-
}]
|
|
336
|
-
});
|
|
337
|
-
|
|
338
|
-
// Check SQS Queue
|
|
339
|
-
expect(result.resources.Resources.TestIntegrationQueue).toEqual({
|
|
340
|
-
Type: 'AWS::SQS::Queue',
|
|
341
|
-
Properties: {
|
|
342
|
-
QueueName: '${self:custom.TestIntegrationQueue}',
|
|
343
|
-
MessageRetentionPeriod: 60,
|
|
344
|
-
VisibilityTimeout: 1800,
|
|
345
|
-
RedrivePolicy: {
|
|
346
|
-
maxReceiveCount: 1,
|
|
347
|
-
deadLetterTargetArn: {
|
|
348
|
-
'Fn::GetAtt': ['InternalErrorQueue', 'Arn']
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
|
|
354
|
-
// Check Queue Worker
|
|
355
|
-
expect(result.functions.testIntegrationQueueWorker).toEqual({
|
|
356
|
-
handler: 'node_modules/@friggframework/core/handlers/workers/integration-defined-workers.handlers.testIntegration.queueWorker',
|
|
357
|
-
reservedConcurrency: 5,
|
|
358
|
-
events: [{
|
|
359
|
-
sqs: {
|
|
360
|
-
arn: {
|
|
361
|
-
'Fn::GetAtt': ['TestIntegrationQueue', 'Arn']
|
|
362
|
-
},
|
|
363
|
-
batchSize: 1
|
|
364
|
-
}
|
|
365
|
-
}],
|
|
366
|
-
timeout: 600
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
// Check environment variable
|
|
370
|
-
expect(result.provider.environment.TESTINTEGRATION_QUEUE_URL).toEqual({
|
|
371
|
-
Ref: 'TestIntegrationQueue'
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
// Check custom queue name
|
|
375
|
-
expect(result.custom.TestIntegrationQueue).toBe('${self:service}--${self:provider.stage}-TestIntegrationQueue');
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
it('should handle multiple integrations', async () => {
|
|
379
|
-
const secondIntegration = {
|
|
380
|
-
Definition: {
|
|
381
|
-
name: 'secondIntegration'
|
|
382
|
-
}
|
|
383
|
-
};
|
|
384
|
-
|
|
385
|
-
const appDefinition = {
|
|
386
|
-
integrations: [mockIntegration, secondIntegration]
|
|
387
|
-
};
|
|
388
|
-
|
|
389
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
390
|
-
|
|
391
|
-
expect(result.functions.testIntegration).toBeDefined();
|
|
392
|
-
expect(result.functions.secondIntegration).toBeDefined();
|
|
393
|
-
expect(result.functions.testIntegrationQueueWorker).toBeDefined();
|
|
394
|
-
expect(result.functions.secondIntegrationQueueWorker).toBeDefined();
|
|
395
|
-
expect(result.resources.Resources.TestIntegrationQueue).toBeDefined();
|
|
396
|
-
expect(result.resources.Resources.SecondIntegrationQueue).toBeDefined();
|
|
397
|
-
});
|
|
398
|
-
});
|
|
399
|
-
|
|
400
|
-
describe('Combined Configurations', () => {
|
|
401
|
-
it('should combine VPC, KMS, and SSM configurations', async () => {
|
|
402
|
-
const appDefinition = {
|
|
403
|
-
vpc: { enable: true },
|
|
404
|
-
encryption: { useDefaultKMSForFieldLevelEncryption: true },
|
|
405
|
-
ssm: { enable: true },
|
|
406
|
-
integrations: [mockIntegration]
|
|
407
|
-
};
|
|
408
|
-
|
|
409
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
410
|
-
|
|
411
|
-
// VPC
|
|
412
|
-
expect(result.provider.vpc).toBeDefined();
|
|
413
|
-
expect(result.custom.vpc).toBeDefined();
|
|
414
|
-
expect(result.resources.Resources.VPCEndpointS3).toBeDefined();
|
|
415
|
-
|
|
416
|
-
// KMS
|
|
417
|
-
expect(result.plugins).toContain('serverless-kms-grants');
|
|
418
|
-
expect(result.provider.environment.KMS_KEY_ARN).toBeDefined();
|
|
419
|
-
expect(result.custom.kmsGrants).toBeDefined();
|
|
420
|
-
|
|
421
|
-
// SSM
|
|
422
|
-
expect(result.provider.layers).toBeDefined();
|
|
423
|
-
expect(result.provider.environment.SSM_PARAMETER_PREFIX).toBeDefined();
|
|
424
|
-
|
|
425
|
-
// Integration
|
|
426
|
-
expect(result.functions.testIntegration).toBeDefined();
|
|
427
|
-
expect(result.resources.Resources.TestIntegrationQueue).toBeDefined();
|
|
428
|
-
|
|
429
|
-
// All plugins should be present
|
|
430
|
-
expect(result.plugins).toEqual([
|
|
431
|
-
'serverless-jetpack',
|
|
432
|
-
'serverless-dotenv-plugin',
|
|
433
|
-
'serverless-offline-sqs',
|
|
434
|
-
'serverless-offline',
|
|
435
|
-
'@friggframework/serverless-plugin',
|
|
436
|
-
'serverless-kms-grants'
|
|
437
|
-
]);
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
it('should handle partial configuration combinations', async () => {
|
|
441
|
-
const appDefinition = {
|
|
442
|
-
vpc: { enable: true },
|
|
443
|
-
encryption: { useDefaultKMSForFieldLevelEncryption: true },
|
|
444
|
-
integrations: []
|
|
445
|
-
};
|
|
446
|
-
|
|
447
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
448
|
-
|
|
449
|
-
// VPC and KMS should be present
|
|
450
|
-
expect(result.provider.vpc).toBeDefined();
|
|
451
|
-
expect(result.custom.kmsGrants).toBeDefined();
|
|
452
|
-
|
|
453
|
-
// SSM should not be present
|
|
454
|
-
expect(result.provider.layers).toBeUndefined();
|
|
455
|
-
expect(result.provider.environment.SSM_PARAMETER_PREFIX).toBeUndefined();
|
|
456
|
-
});
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
describe('Default Resources', () => {
|
|
460
|
-
it('should always include default resources', async () => {
|
|
461
|
-
const appDefinition = {
|
|
462
|
-
integrations: []
|
|
463
|
-
};
|
|
464
|
-
|
|
465
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
466
|
-
|
|
467
|
-
// Check default resources are always present
|
|
468
|
-
expect(result.resources.Resources.InternalErrorQueue).toBeDefined();
|
|
469
|
-
expect(result.resources.Resources.InternalErrorBridgeTopic).toBeDefined();
|
|
470
|
-
expect(result.resources.Resources.InternalErrorBridgePolicy).toBeDefined();
|
|
471
|
-
expect(result.resources.Resources.ApiGatewayAlarm5xx).toBeDefined();
|
|
472
|
-
|
|
473
|
-
// Check default functions
|
|
474
|
-
expect(result.functions.defaultWebsocket).toBeDefined();
|
|
475
|
-
expect(result.functions.auth).toBeDefined();
|
|
476
|
-
expect(result.functions.user).toBeDefined();
|
|
477
|
-
|
|
478
|
-
// Check default plugins
|
|
479
|
-
expect(result.plugins).toContain('serverless-jetpack');
|
|
480
|
-
expect(result.plugins).toContain('serverless-dotenv-plugin');
|
|
481
|
-
expect(result.plugins).toContain('@friggframework/serverless-plugin');
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
it('should always include default IAM permissions', async () => {
|
|
485
|
-
const appDefinition = {
|
|
486
|
-
integrations: []
|
|
487
|
-
};
|
|
488
|
-
|
|
489
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
490
|
-
|
|
491
|
-
// Check SNS publish permission
|
|
492
|
-
const snsPermission = result.provider.iamRoleStatements.find(
|
|
493
|
-
statement => statement.Action.includes('sns:Publish')
|
|
494
|
-
);
|
|
495
|
-
expect(snsPermission).toBeDefined();
|
|
496
|
-
|
|
497
|
-
// Check SQS permissions
|
|
498
|
-
const sqsPermission = result.provider.iamRoleStatements.find(
|
|
499
|
-
statement => statement.Action.includes('sqs:SendMessage')
|
|
500
|
-
);
|
|
501
|
-
expect(sqsPermission).toBeDefined();
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
it('should include default environment variables', async () => {
|
|
505
|
-
const appDefinition = {
|
|
506
|
-
integrations: []
|
|
507
|
-
};
|
|
508
|
-
|
|
509
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
510
|
-
|
|
511
|
-
expect(result.provider.environment.STAGE).toBe('${opt:stage}');
|
|
512
|
-
expect(result.provider.environment.AWS_NODEJS_CONNECTION_REUSE_ENABLED).toBe(1);
|
|
513
|
-
});
|
|
514
|
-
});
|
|
515
|
-
|
|
516
|
-
describe('Edge Cases', () => {
|
|
517
|
-
it('should handle empty app definition', async () => {
|
|
518
|
-
const appDefinition = {};
|
|
519
|
-
|
|
520
|
-
await expect(composeServerlessDefinition(appDefinition)).resolves.not.toThrow();
|
|
521
|
-
const result = await composeServerlessDefinition(appDefinition);
|
|
522
|
-
expect(result.service).toBe('create-frigg-app');
|
|
523
|
-
});
|
|
524
|
-
|
|
525
|
-
it('should handle null/undefined integrations', async () => {
|
|
526
|
-
const appDefinition = {
|
|
527
|
-
integrations: null
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
await expect(composeServerlessDefinition(appDefinition)).rejects.toThrow();
|
|
531
|
-
});
|
|
532
|
-
|
|
533
|
-
it('should handle integration with missing Definition', async () => {
|
|
534
|
-
const invalidIntegration = {};
|
|
535
|
-
const appDefinition = {
|
|
536
|
-
integrations: [invalidIntegration]
|
|
537
|
-
};
|
|
538
|
-
|
|
539
|
-
await expect(composeServerlessDefinition(appDefinition)).rejects.toThrow();
|
|
540
|
-
});
|
|
541
|
-
|
|
542
|
-
it('should handle integration with missing name', async () => {
|
|
543
|
-
const invalidIntegration = {
|
|
544
|
-
Definition: {}
|
|
545
|
-
};
|
|
546
|
-
const appDefinition = {
|
|
547
|
-
integrations: [invalidIntegration]
|
|
548
|
-
};
|
|
549
|
-
|
|
550
|
-
await expect(composeServerlessDefinition(appDefinition)).rejects.toThrow();
|
|
551
|
-
});
|
|
552
|
-
});
|
|
553
|
-
});
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
root: true,
|
|
3
|
-
env: { browser: true, es2020: true },
|
|
4
|
-
extends: [
|
|
5
|
-
'eslint:recommended',
|
|
6
|
-
'@eslint/js/recommended',
|
|
7
|
-
'plugin:react/recommended',
|
|
8
|
-
'plugin:react/jsx-runtime',
|
|
9
|
-
'plugin:react-hooks/recommended',
|
|
10
|
-
],
|
|
11
|
-
ignorePatterns: ['dist', '.eslintrc.js'],
|
|
12
|
-
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
|
13
|
-
settings: { react: { version: '18.3' } },
|
|
14
|
-
plugins: ['react-refresh'],
|
|
15
|
-
rules: {
|
|
16
|
-
'react/jsx-no-target-blank': 'off',
|
|
17
|
-
'react-refresh/only-export-components': [
|
|
18
|
-
'warn',
|
|
19
|
-
{ allowConstantExport: true },
|
|
20
|
-
],
|
|
21
|
-
},
|
|
22
|
-
}
|