@friggframework/devtools 2.0.0-next.29 → 2.0.0-next.30

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 (164) hide show
  1. package/frigg-cli/.eslintrc.js +141 -0
  2. package/frigg-cli/__tests__/jest.config.js +102 -0
  3. package/frigg-cli/__tests__/unit/commands/build.test.js +483 -0
  4. package/frigg-cli/__tests__/unit/commands/install.test.js +418 -0
  5. package/frigg-cli/__tests__/unit/commands/ui.test.js +592 -0
  6. package/frigg-cli/__tests__/utils/command-tester.js +170 -0
  7. package/frigg-cli/__tests__/utils/mock-factory.js +270 -0
  8. package/frigg-cli/__tests__/utils/test-fixtures.js +463 -0
  9. package/frigg-cli/__tests__/utils/test-setup.js +286 -0
  10. package/frigg-cli/generate-command/__tests__/generate-command.test.js +312 -0
  11. package/frigg-cli/generate-command/azure-generator.js +43 -0
  12. package/frigg-cli/generate-command/gcp-generator.js +47 -0
  13. package/frigg-cli/generate-command/index.js +332 -0
  14. package/frigg-cli/generate-command/terraform-generator.js +555 -0
  15. package/frigg-cli/index.js +19 -1
  16. package/frigg-cli/init-command/backend-first-handler.js +756 -0
  17. package/frigg-cli/init-command/index.js +93 -0
  18. package/frigg-cli/init-command/template-handler.js +143 -0
  19. package/frigg-cli/package.json +51 -0
  20. package/frigg-cli/test/init-command.test.js +180 -0
  21. package/frigg-cli/test/npm-registry.test.js +319 -0
  22. package/frigg-cli/ui-command/index.js +154 -0
  23. package/frigg-cli/utils/app-resolver.js +319 -0
  24. package/frigg-cli/utils/backend-path.js +25 -0
  25. package/frigg-cli/utils/npm-registry.js +167 -0
  26. package/frigg-cli/utils/process-manager.js +199 -0
  27. package/frigg-cli/utils/repo-detection.js +405 -0
  28. package/infrastructure/serverless-template.js +177 -292
  29. package/management-ui/.eslintrc.js +22 -0
  30. package/management-ui/README.md +203 -0
  31. package/management-ui/components.json +21 -0
  32. package/management-ui/docs/phase2-integration-guide.md +320 -0
  33. package/management-ui/{dist/index.html → index.html} +1 -2
  34. package/management-ui/package-lock.json +16517 -0
  35. package/management-ui/package.json +76 -0
  36. package/management-ui/packages/devtools/frigg-cli/ui-command/index.js +302 -0
  37. package/management-ui/postcss.config.js +6 -0
  38. package/management-ui/server/api/backend.js +256 -0
  39. package/management-ui/server/api/cli.js +315 -0
  40. package/management-ui/server/api/codegen.js +663 -0
  41. package/management-ui/server/api/connections.js +857 -0
  42. package/management-ui/server/api/discovery.js +185 -0
  43. package/management-ui/server/api/environment/index.js +1 -0
  44. package/management-ui/server/api/environment/router.js +378 -0
  45. package/management-ui/server/api/environment.js +328 -0
  46. package/management-ui/server/api/integrations.js +876 -0
  47. package/management-ui/server/api/logs.js +248 -0
  48. package/management-ui/server/api/monitoring.js +282 -0
  49. package/management-ui/server/api/open-ide.js +31 -0
  50. package/management-ui/server/api/project.js +1029 -0
  51. package/management-ui/server/api/users/sessions.js +371 -0
  52. package/management-ui/server/api/users/simulation.js +254 -0
  53. package/management-ui/server/api/users.js +362 -0
  54. package/management-ui/server/api-contract.md +275 -0
  55. package/management-ui/server/index.js +873 -0
  56. package/management-ui/server/middleware/errorHandler.js +93 -0
  57. package/management-ui/server/middleware/security.js +32 -0
  58. package/management-ui/server/processManager.js +296 -0
  59. package/management-ui/server/server.js +346 -0
  60. package/management-ui/server/services/aws-monitor.js +413 -0
  61. package/management-ui/server/services/npm-registry.js +347 -0
  62. package/management-ui/server/services/template-engine.js +538 -0
  63. package/management-ui/server/utils/cliIntegration.js +220 -0
  64. package/management-ui/server/utils/environment/auditLogger.js +471 -0
  65. package/management-ui/server/utils/environment/awsParameterStore.js +264 -0
  66. package/management-ui/server/utils/environment/encryption.js +278 -0
  67. package/management-ui/server/utils/environment/envFileManager.js +286 -0
  68. package/management-ui/server/utils/import-commonjs.js +28 -0
  69. package/management-ui/server/utils/response.js +83 -0
  70. package/management-ui/server/websocket/handler.js +325 -0
  71. package/management-ui/src/App.jsx +109 -0
  72. package/management-ui/src/components/AppRouter.jsx +65 -0
  73. package/management-ui/src/components/Button.jsx +70 -0
  74. package/management-ui/src/components/Card.jsx +97 -0
  75. package/management-ui/src/components/EnvironmentCompare.jsx +400 -0
  76. package/management-ui/src/components/EnvironmentEditor.jsx +372 -0
  77. package/management-ui/src/components/EnvironmentImportExport.jsx +469 -0
  78. package/management-ui/src/components/EnvironmentSchema.jsx +491 -0
  79. package/management-ui/src/components/EnvironmentSecurity.jsx +463 -0
  80. package/management-ui/src/components/ErrorBoundary.jsx +73 -0
  81. package/management-ui/src/components/IntegrationCard.jsx +481 -0
  82. package/management-ui/src/components/IntegrationCardEnhanced.jsx +770 -0
  83. package/management-ui/src/components/IntegrationExplorer.jsx +379 -0
  84. package/management-ui/src/components/IntegrationStatus.jsx +336 -0
  85. package/management-ui/src/components/Layout.jsx +716 -0
  86. package/management-ui/src/components/LoadingSpinner.jsx +113 -0
  87. package/management-ui/src/components/RepositoryPicker.jsx +248 -0
  88. package/management-ui/src/components/SessionMonitor.jsx +350 -0
  89. package/management-ui/src/components/StatusBadge.jsx +208 -0
  90. package/management-ui/src/components/UserContextSwitcher.jsx +212 -0
  91. package/management-ui/src/components/UserSimulation.jsx +327 -0
  92. package/management-ui/src/components/Welcome.jsx +434 -0
  93. package/management-ui/src/components/codegen/APIEndpointGenerator.jsx +637 -0
  94. package/management-ui/src/components/codegen/APIModuleSelector.jsx +227 -0
  95. package/management-ui/src/components/codegen/CodeGenerationWizard.jsx +247 -0
  96. package/management-ui/src/components/codegen/CodePreviewEditor.jsx +316 -0
  97. package/management-ui/src/components/codegen/DynamicModuleForm.jsx +271 -0
  98. package/management-ui/src/components/codegen/FormBuilder.jsx +737 -0
  99. package/management-ui/src/components/codegen/IntegrationGenerator.jsx +855 -0
  100. package/management-ui/src/components/codegen/ProjectScaffoldWizard.jsx +797 -0
  101. package/management-ui/src/components/codegen/SchemaBuilder.jsx +303 -0
  102. package/management-ui/src/components/codegen/TemplateSelector.jsx +586 -0
  103. package/management-ui/src/components/codegen/index.js +10 -0
  104. package/management-ui/src/components/connections/ConnectionConfigForm.jsx +362 -0
  105. package/management-ui/src/components/connections/ConnectionHealthMonitor.jsx +182 -0
  106. package/management-ui/src/components/connections/ConnectionTester.jsx +200 -0
  107. package/management-ui/src/components/connections/EntityRelationshipMapper.jsx +292 -0
  108. package/management-ui/src/components/connections/OAuthFlow.jsx +204 -0
  109. package/management-ui/src/components/connections/index.js +5 -0
  110. package/management-ui/src/components/index.js +21 -0
  111. package/management-ui/src/components/monitoring/APIGatewayMetrics.jsx +222 -0
  112. package/management-ui/src/components/monitoring/LambdaMetrics.jsx +169 -0
  113. package/management-ui/src/components/monitoring/MetricsChart.jsx +197 -0
  114. package/management-ui/src/components/monitoring/MonitoringDashboard.jsx +393 -0
  115. package/management-ui/src/components/monitoring/SQSMetrics.jsx +246 -0
  116. package/management-ui/src/components/monitoring/index.js +6 -0
  117. package/management-ui/src/components/monitoring/monitoring.css +218 -0
  118. package/management-ui/src/components/theme-provider.jsx +52 -0
  119. package/management-ui/src/components/theme-toggle.jsx +39 -0
  120. package/management-ui/src/components/ui/badge.tsx +36 -0
  121. package/management-ui/src/components/ui/button.test.jsx +56 -0
  122. package/management-ui/src/components/ui/button.tsx +57 -0
  123. package/management-ui/src/components/ui/card.tsx +76 -0
  124. package/management-ui/src/components/ui/dropdown-menu.tsx +199 -0
  125. package/management-ui/src/components/ui/select.tsx +157 -0
  126. package/management-ui/src/components/ui/skeleton.jsx +15 -0
  127. package/management-ui/src/hooks/useFrigg.jsx +601 -0
  128. package/management-ui/src/hooks/useSocket.jsx +58 -0
  129. package/management-ui/src/index.css +193 -0
  130. package/management-ui/src/lib/utils.ts +6 -0
  131. package/management-ui/src/main.jsx +10 -0
  132. package/management-ui/src/pages/CodeGeneration.jsx +14 -0
  133. package/management-ui/src/pages/Connections.jsx +252 -0
  134. package/management-ui/src/pages/ConnectionsEnhanced.jsx +633 -0
  135. package/management-ui/src/pages/Dashboard.jsx +311 -0
  136. package/management-ui/src/pages/Environment.jsx +314 -0
  137. package/management-ui/src/pages/IntegrationConfigure.jsx +669 -0
  138. package/management-ui/src/pages/IntegrationDiscovery.jsx +567 -0
  139. package/management-ui/src/pages/IntegrationTest.jsx +742 -0
  140. package/management-ui/src/pages/Integrations.jsx +253 -0
  141. package/management-ui/src/pages/Monitoring.jsx +17 -0
  142. package/management-ui/src/pages/Simulation.jsx +155 -0
  143. package/management-ui/src/pages/Users.jsx +492 -0
  144. package/management-ui/src/services/api.js +41 -0
  145. package/management-ui/src/services/apiModuleService.js +193 -0
  146. package/management-ui/src/services/websocket-handlers.js +120 -0
  147. package/management-ui/src/test/api/project.test.js +273 -0
  148. package/management-ui/src/test/components/Welcome.test.jsx +378 -0
  149. package/management-ui/src/test/mocks/server.js +178 -0
  150. package/management-ui/src/test/setup.js +61 -0
  151. package/management-ui/src/test/utils/test-utils.jsx +134 -0
  152. package/management-ui/src/utils/repository.js +98 -0
  153. package/management-ui/src/utils/repository.test.js +118 -0
  154. package/management-ui/src/workflows/phase2-integration-workflows.js +884 -0
  155. package/management-ui/tailwind.config.js +63 -0
  156. package/management-ui/tsconfig.json +37 -0
  157. package/management-ui/tsconfig.node.json +10 -0
  158. package/management-ui/vite.config.js +26 -0
  159. package/management-ui/vitest.config.js +38 -0
  160. package/package.json +5 -5
  161. package/management-ui/dist/assets/index-BA21WgFa.js +0 -1221
  162. package/management-ui/dist/assets/index-CbM64Oba.js +0 -1221
  163. package/management-ui/dist/assets/index-CkvseXTC.css +0 -1
  164. /package/management-ui/{dist/assets/FriggLogo-B7Xx8ZW1.svg → src/assets/FriggLogo.svg} +0 -0
@@ -94,12 +94,6 @@ const findNodeModulesPath = () => {
94
94
  }
95
95
  };
96
96
 
97
- /**
98
- * Modify handler paths to point to the correct node_modules location
99
- * Only modifies paths when running in offline mode
100
- * @param {Object} functions - Serverless functions configuration object
101
- * @returns {Object} Modified functions object with updated handler paths
102
- */
103
97
  /**
104
98
  * Modify handler paths to point to the correct node_modules location
105
99
  * Only modifies paths when running in offline mode
@@ -126,8 +120,6 @@ const modifyHandlerPaths = (functions) => {
126
120
  // Replace node_modules/ with the actual path to node_modules/
127
121
  const relativePath = path.relative(process.cwd(), nodeModulesPath);
128
122
  functionDef.handler = functionDef.handler.replace('node_modules/', `${relativePath}/`);
129
- const relativePath = path.relative(process.cwd(), nodeModulesPath);
130
- functionDef.handler = functionDef.handler.replace('node_modules/', `${relativePath}/`);
131
123
  console.log(`Updated handler for ${functionName}: ${functionDef.handler}`);
132
124
  }
133
125
  }
@@ -135,14 +127,6 @@ const modifyHandlerPaths = (functions) => {
135
127
  return modifiedFunctions;
136
128
  };
137
129
 
138
- /**
139
- * Create VPC infrastructure resources for CloudFormation
140
- * Creates VPC, subnets, NAT gateway, route tables, and security groups
141
- * @param {Object} AppDefinition - Application definition object
142
- * @param {Object} AppDefinition.vpc - VPC configuration
143
- * @param {string} [AppDefinition.vpc.cidrBlock='10.0.0.0/16'] - CIDR block for VPC
144
- * @returns {Object} CloudFormation resources for VPC infrastructure
145
- */
146
130
  /**
147
131
  * Create VPC infrastructure resources for CloudFormation
148
132
  * Creates VPC, subnets, NAT gateway, route tables, and security groups
@@ -517,7 +501,6 @@ const composeServerlessDefinition = async (AppDefinition) => {
517
501
  runtime: 'nodejs20.x',
518
502
  timeout: 30,
519
503
  region: process.env.AWS_REGION || 'us-east-1',
520
- region: process.env.AWS_REGION || 'us-east-1',
521
504
  stage: '${opt:stage}',
522
505
  environment: {
523
506
  STAGE: '${opt:stage, "dev"}',
@@ -530,14 +513,6 @@ const composeServerlessDefinition = async (AppDefinition) => {
530
513
  ...(discoveredResources.publicSubnetId && { AWS_DISCOVERY_PUBLIC_SUBNET_ID: discoveredResources.publicSubnetId }),
531
514
  ...(discoveredResources.defaultRouteTableId && { AWS_DISCOVERY_ROUTE_TABLE_ID: discoveredResources.defaultRouteTableId }),
532
515
  ...(discoveredResources.defaultKmsKeyId && { AWS_DISCOVERY_KMS_KEY_ID: discoveredResources.defaultKmsKeyId }),
533
- // Add discovered resources to environment if available
534
- ...(discoveredResources.defaultVpcId && { AWS_DISCOVERY_VPC_ID: discoveredResources.defaultVpcId }),
535
- ...(discoveredResources.defaultSecurityGroupId && { AWS_DISCOVERY_SECURITY_GROUP_ID: discoveredResources.defaultSecurityGroupId }),
536
- ...(discoveredResources.privateSubnetId1 && { AWS_DISCOVERY_SUBNET_ID_1: discoveredResources.privateSubnetId1 }),
537
- ...(discoveredResources.privateSubnetId2 && { AWS_DISCOVERY_SUBNET_ID_2: discoveredResources.privateSubnetId2 }),
538
- ...(discoveredResources.publicSubnetId && { AWS_DISCOVERY_PUBLIC_SUBNET_ID: discoveredResources.publicSubnetId }),
539
- ...(discoveredResources.defaultRouteTableId && { AWS_DISCOVERY_ROUTE_TABLE_ID: discoveredResources.defaultRouteTableId }),
540
- ...(discoveredResources.defaultKmsKeyId && { AWS_DISCOVERY_KMS_KEY_ID: discoveredResources.defaultKmsKeyId }),
541
516
  },
542
517
  iamRoleStatements: [
543
518
  {
@@ -600,7 +575,6 @@ const composeServerlessDefinition = async (AppDefinition) => {
600
575
  apiVersion: '2012-11-05',
601
576
  endpoint: 'http://localhost:4566',
602
577
  region: process.env.AWS_REGION || 'us-east-1',
603
- region: process.env.AWS_REGION || 'us-east-1',
604
578
  accessKeyId: 'root',
605
579
  secretAccessKey: 'root',
606
580
  skipCacheInvalidation: false,
@@ -669,7 +643,6 @@ const composeServerlessDefinition = async (AppDefinition) => {
669
643
  Properties: {
670
644
  QueueName:
671
645
  '${self:service}-internal-error-queue-${self:provider.stage}',
672
- '${self:service}-internal-error-queue-${self:provider.stage}',
673
646
  MessageRetentionPeriod: 300,
674
647
  },
675
648
  },
@@ -749,8 +722,6 @@ const composeServerlessDefinition = async (AppDefinition) => {
749
722
  },
750
723
  };
751
724
 
752
-
753
-
754
725
  // KMS Configuration based on App Definition
755
726
  if (AppDefinition.encryption?.useDefaultKMSForFieldLevelEncryption === true) {
756
727
  // Provision a dedicated KMS key and wire it automatically
@@ -783,11 +754,9 @@ const composeServerlessDefinition = async (AppDefinition) => {
783
754
 
784
755
  definition.plugins.push('serverless-kms-grants');
785
756
 
786
- // Configure KMS grants with discovered default key
787
757
  // Configure KMS grants with discovered default key
788
758
  definition.custom.kmsGrants = {
789
759
  kmsKeyId: discoveredResources.defaultKmsKeyId || '${env:AWS_DISCOVERY_KMS_KEY_ID}'
790
- kmsKeyId: discoveredResources.defaultKmsKeyId || '${env:AWS_DISCOVERY_KMS_KEY_ID}'
791
760
  };
792
761
  }
793
762
 
@@ -810,290 +779,231 @@ const composeServerlessDefinition = async (AppDefinition) => {
810
779
  if (AppDefinition.vpc.createNew === true) {
811
780
  // Option 1: Create new VPC infrastructure (explicit opt-in)
812
781
  const vpcConfig = {};
813
- // Add VPC-related IAM permissions
814
- definition.provider.iamRoleStatements.push({
815
- Effect: 'Allow',
816
- Action: [
817
- 'ec2:CreateNetworkInterface',
818
- 'ec2:DescribeNetworkInterfaces',
819
- 'ec2:DeleteNetworkInterface',
820
- 'ec2:AttachNetworkInterface',
821
- 'ec2:DetachNetworkInterface'
822
- ],
823
- Resource: '*'
824
- });
825
-
826
- // Default approach: Use AWS Discovery to find existing VPC resources
827
- if (AppDefinition.vpc.createNew === true) {
828
- // Option 1: Create new VPC infrastructure (explicit opt-in)
829
- const vpcConfig = {};
830
-
831
- if (AppDefinition.vpc.securityGroupIds) {
832
- // User provided custom security groups
833
- vpcConfig.securityGroupIds = AppDefinition.vpc.securityGroupIds;
834
- } else {
835
- // Use auto-created security group
836
- vpcConfig.securityGroupIds = [{ Ref: 'FriggLambdaSecurityGroup' }];
837
- }
838
- if (AppDefinition.vpc.securityGroupIds) {
839
- // User provided custom security groups
840
- vpcConfig.securityGroupIds = AppDefinition.vpc.securityGroupIds;
841
- } else {
842
- // Use auto-created security group
843
- vpcConfig.securityGroupIds = [{ Ref: 'FriggLambdaSecurityGroup' }];
844
- }
845
782
 
846
- if (AppDefinition.vpc.subnetIds) {
847
- // User provided custom subnets
848
- vpcConfig.subnetIds = AppDefinition.vpc.subnetIds;
849
- } else {
850
- // Use auto-created private subnets
851
- vpcConfig.subnetIds = [
852
- { Ref: 'FriggPrivateSubnet1' },
853
- { Ref: 'FriggPrivateSubnet2' }
854
- ];
855
- }
856
- if (AppDefinition.vpc.subnetIds) {
857
- // User provided custom subnets
858
- vpcConfig.subnetIds = AppDefinition.vpc.subnetIds;
859
- } else {
860
- // Use auto-created private subnets
861
- vpcConfig.subnetIds = [
862
- { Ref: 'FriggPrivateSubnet1' },
863
- { Ref: 'FriggPrivateSubnet2' }
864
- ];
865
- }
866
-
867
- // Set VPC config for Lambda functions
868
- definition.provider.vpc = vpcConfig;
869
- // Set VPC config for Lambda functions
870
- definition.provider.vpc = vpcConfig;
783
+ if (AppDefinition.vpc.securityGroupIds) {
784
+ // User provided custom security groups
785
+ vpcConfig.securityGroupIds = AppDefinition.vpc.securityGroupIds;
786
+ } else {
787
+ // Use auto-created security group
788
+ vpcConfig.securityGroupIds = [{ Ref: 'FriggLambdaSecurityGroup' }];
789
+ }
871
790
 
872
- // Add VPC infrastructure resources to CloudFormation
873
- const vpcResources = createVPCInfrastructure(AppDefinition);
874
- Object.assign(definition.resources.Resources, vpcResources);
791
+ if (AppDefinition.vpc.subnetIds) {
792
+ // User provided custom subnets
793
+ vpcConfig.subnetIds = AppDefinition.vpc.subnetIds;
875
794
  } else {
876
- // Option 2: Use AWS Discovery (default behavior)
877
- // VPC configuration using discovered or explicitly provided resources
878
- const vpcConfig = {
879
- securityGroupIds: AppDefinition.vpc.securityGroupIds ||
880
- (discoveredResources.defaultSecurityGroupId ? [discoveredResources.defaultSecurityGroupId] : []),
881
- subnetIds: AppDefinition.vpc.subnetIds ||
882
- (discoveredResources.privateSubnetId1 && discoveredResources.privateSubnetId2 ?
883
- [discoveredResources.privateSubnetId1, discoveredResources.privateSubnetId2] :
884
- [])
885
- };
795
+ // Use auto-created private subnets
796
+ vpcConfig.subnetIds = [
797
+ { Ref: 'FriggPrivateSubnet1' },
798
+ { Ref: 'FriggPrivateSubnet2' }
799
+ ];
800
+ }
886
801
 
887
- // Set VPC config for Lambda functions only if we have valid subnet IDs
888
- if (vpcConfig.subnetIds.length >= 2 && vpcConfig.securityGroupIds.length > 0) {
889
- definition.provider.vpc = vpcConfig;
890
-
891
- // Check if we have an existing NAT Gateway to use
892
- if (!discoveredResources.existingNatGatewayId) {
893
- // No existing NAT Gateway, create new resources
894
-
895
- // Only create EIP if we don't have an existing one available
896
- if (!discoveredResources.existingElasticIpAllocationId) {
897
- definition.resources.Resources.FriggNATGatewayEIP = {
898
- Type: 'AWS::EC2::EIP',
899
- Properties: {
900
- Domain: 'vpc',
901
- Tags: [
902
- { Key: 'Name', Value: '${self:service}-${self:provider.stage}-nat-eip' }
903
- ]
904
- }
905
- };
906
- }
802
+ // Set VPC config for Lambda functions
803
+ definition.provider.vpc = vpcConfig;
804
+
805
+ // Add VPC infrastructure resources to CloudFormation
806
+ const vpcResources = createVPCInfrastructure(AppDefinition);
807
+ Object.assign(definition.resources.Resources, vpcResources);
808
+ } else {
809
+ // Option 2: Use AWS Discovery (default behavior)
810
+ // VPC configuration using discovered or explicitly provided resources
811
+ const vpcConfig = {
812
+ securityGroupIds: AppDefinition.vpc.securityGroupIds ||
813
+ (discoveredResources.defaultSecurityGroupId ? [discoveredResources.defaultSecurityGroupId] : []),
814
+ subnetIds: AppDefinition.vpc.subnetIds ||
815
+ (discoveredResources.privateSubnetId1 && discoveredResources.privateSubnetId2 ?
816
+ [discoveredResources.privateSubnetId1, discoveredResources.privateSubnetId2] :
817
+ [])
818
+ };
819
+
820
+ // Set VPC config for Lambda functions only if we have valid subnet IDs
821
+ if (vpcConfig.subnetIds.length >= 2 && vpcConfig.securityGroupIds.length > 0) {
822
+ definition.provider.vpc = vpcConfig;
823
+
824
+ // Check if we have an existing NAT Gateway to use
825
+ if (!discoveredResources.existingNatGatewayId) {
826
+ // No existing NAT Gateway, create new resources
907
827
 
908
- definition.resources.Resources.FriggNATGateway = {
909
- Type: 'AWS::EC2::NatGateway',
828
+ // Only create EIP if we don't have an existing one available
829
+ if (!discoveredResources.existingElasticIpAllocationId) {
830
+ definition.resources.Resources.FriggNATGatewayEIP = {
831
+ Type: 'AWS::EC2::EIP',
910
832
  Properties: {
911
- AllocationId: discoveredResources.existingElasticIpAllocationId ||
912
- { 'Fn::GetAtt': ['FriggNATGatewayEIP', 'AllocationId'] },
913
- SubnetId: discoveredResources.publicSubnetId || discoveredResources.privateSubnetId1, // Use first discovered subnet if no public subnet found
833
+ Domain: 'vpc',
914
834
  Tags: [
915
- { Key: 'Name', Value: '${self:service}-${self:provider.stage}-nat-gateway' }
835
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-nat-eip' }
916
836
  ]
917
837
  }
918
838
  };
919
839
  }
920
840
 
921
- // Create route table for Lambda subnets to use NAT Gateway
922
- definition.resources.Resources.FriggLambdaRouteTable = {
923
- Type: 'AWS::EC2::RouteTable',
841
+ definition.resources.Resources.FriggNATGateway = {
842
+ Type: 'AWS::EC2::NatGateway',
924
843
  Properties: {
925
- VpcId: discoveredResources.defaultVpcId || { Ref: 'FriggVPC' },
844
+ AllocationId: discoveredResources.existingElasticIpAllocationId ||
845
+ { 'Fn::GetAtt': ['FriggNATGatewayEIP', 'AllocationId'] },
846
+ SubnetId: discoveredResources.publicSubnetId || discoveredResources.privateSubnetId1, // Use first discovered subnet if no public subnet found
926
847
  Tags: [
927
- { Key: 'Name', Value: '${self:service}-${self:provider.stage}-lambda-rt' }
848
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-nat-gateway' }
928
849
  ]
929
850
  }
930
851
  };
852
+ }
931
853
 
932
- definition.resources.Resources.FriggNATRoute = {
933
- Type: 'AWS::EC2::Route',
934
- Properties: {
935
- RouteTableId: { Ref: 'FriggLambdaRouteTable' },
936
- DestinationCidrBlock: '0.0.0.0/0',
937
- NatGatewayId: discoveredResources.existingNatGatewayId || { Ref: 'FriggNATGateway' }
938
- }
939
- };
854
+ // Create route table for Lambda subnets to use NAT Gateway
855
+ definition.resources.Resources.FriggLambdaRouteTable = {
856
+ Type: 'AWS::EC2::RouteTable',
857
+ Properties: {
858
+ VpcId: discoveredResources.defaultVpcId || { Ref: 'FriggVPC' },
859
+ Tags: [
860
+ { Key: 'Name', Value: '${self:service}-${self:provider.stage}-lambda-rt' }
861
+ ]
862
+ }
863
+ };
864
+
865
+ definition.resources.Resources.FriggNATRoute = {
866
+ Type: 'AWS::EC2::Route',
867
+ Properties: {
868
+ RouteTableId: { Ref: 'FriggLambdaRouteTable' },
869
+ DestinationCidrBlock: '0.0.0.0/0',
870
+ NatGatewayId: discoveredResources.existingNatGatewayId || { Ref: 'FriggNATGateway' }
871
+ }
872
+ };
873
+
874
+ // Associate Lambda subnets with NAT Gateway route table
875
+ definition.resources.Resources.FriggSubnet1RouteAssociation = {
876
+ Type: 'AWS::EC2::SubnetRouteTableAssociation',
877
+ Properties: {
878
+ SubnetId: vpcConfig.subnetIds[0],
879
+ RouteTableId: { Ref: 'FriggLambdaRouteTable' }
880
+ }
881
+ };
940
882
 
941
- // Associate Lambda subnets with NAT Gateway route table
942
- definition.resources.Resources.FriggSubnet1RouteAssociation = {
943
- Type: 'AWS::EC2::SubnetRouteTableAssociation',
883
+ definition.resources.Resources.FriggSubnet2RouteAssociation = {
884
+ Type: 'AWS::EC2::SubnetRouteTableAssociation',
885
+ Properties: {
886
+ SubnetId: vpcConfig.subnetIds[1],
887
+ RouteTableId: { Ref: 'FriggLambdaRouteTable' }
888
+ }
889
+ };
890
+
891
+ // Add VPC endpoints for AWS service optimization (optional but recommended)
892
+ if (AppDefinition.vpc.enableVPCEndpoints !== false) {
893
+ definition.resources.Resources.VPCEndpointS3 = {
894
+ Type: 'AWS::EC2::VPCEndpoint',
944
895
  Properties: {
945
- SubnetId: vpcConfig.subnetIds[0],
946
- RouteTableId: { Ref: 'FriggLambdaRouteTable' }
896
+ VpcId: discoveredResources.defaultVpcId,
897
+ ServiceName: 'com.amazonaws.${self:provider.region}.s3',
898
+ VpcEndpointType: 'Gateway',
899
+ RouteTableIds: [{ Ref: 'FriggLambdaRouteTable' }]
947
900
  }
948
901
  };
949
902
 
950
- definition.resources.Resources.FriggSubnet2RouteAssociation = {
951
- Type: 'AWS::EC2::SubnetRouteTableAssociation',
903
+ definition.resources.Resources.VPCEndpointDynamoDB = {
904
+ Type: 'AWS::EC2::VPCEndpoint',
952
905
  Properties: {
953
- SubnetId: vpcConfig.subnetIds[1],
954
- RouteTableId: { Ref: 'FriggLambdaRouteTable' }
906
+ VpcId: discoveredResources.defaultVpcId,
907
+ ServiceName: 'com.amazonaws.${self:provider.region}.dynamodb',
908
+ VpcEndpointType: 'Gateway',
909
+ RouteTableIds: [{ Ref: 'FriggLambdaRouteTable' }]
955
910
  }
956
911
  };
957
-
958
- // Add VPC endpoints for AWS service optimization (optional but recommended)
959
- if (AppDefinition.vpc.enableVPCEndpoints !== false) {
960
- definition.resources.Resources.VPCEndpointS3 = {
961
- Type: 'AWS::EC2::VPCEndpoint',
962
- Properties: {
963
- VpcId: discoveredResources.defaultVpcId,
964
- ServiceName: 'com.amazonaws.${self:provider.region}.s3',
965
- VpcEndpointType: 'Gateway',
966
- RouteTableIds: [{ Ref: 'FriggLambdaRouteTable' }]
967
- }
968
- };
969
-
970
- definition.resources.Resources.VPCEndpointDynamoDB = {
971
- Type: 'AWS::EC2::VPCEndpoint',
972
- Properties: {
973
- VpcId: discoveredResources.defaultVpcId,
974
- ServiceName: 'com.amazonaws.${self:provider.region}.dynamodb',
975
- VpcEndpointType: 'Gateway',
976
- RouteTableIds: [{ Ref: 'FriggLambdaRouteTable' }]
977
- }
978
- };
979
- }
980
912
  }
981
913
  }
982
914
  }
983
915
 
984
- // SSM Parameter Store Configuration based on App Definition
985
- if (AppDefinition.ssm?.enable === true) {
986
- // Add AWS Parameters and Secrets Lambda Extension layer
987
- definition.provider.layers = [
988
- 'arn:aws:lambda:${self:provider.region}:177933569100:layer:AWS-Parameters-and-Secrets-Lambda-Extension:11'
989
- ];
990
-
991
- // Add SSM IAM permissions
992
- definition.provider.iamRoleStatements.push({
993
- Effect: 'Allow',
994
- Action: [
995
- 'ssm:GetParameter',
996
- 'ssm:GetParameters',
997
- 'ssm:GetParametersByPath'
998
- ],
999
- Resource: [
1000
- 'arn:aws:ssm:${self:provider.region}:*:parameter/${self:service}/${self:provider.stage}/*'
1001
- ]
916
+ // SSM Parameter Store Configuration based on App Definition
917
+ if (AppDefinition.ssm?.enable === true) {
918
+ // Add AWS Parameters and Secrets Lambda Extension layer
919
+ definition.provider.layers = [
920
+ 'arn:aws:lambda:${self:provider.region}:177933569100:layer:AWS-Parameters-and-Secrets-Lambda-Extension:11'
921
+ ];
922
+
923
+ // Add SSM IAM permissions
924
+ definition.provider.iamRoleStatements.push({
925
+ Effect: 'Allow',
926
+ Action: [
1002
927
  'ssm:GetParameter',
1003
928
  'ssm:GetParameters',
1004
929
  'ssm:GetParametersByPath'
1005
930
  ],
1006
- Resource: [
1007
- 'arn:aws:ssm:${self:provider.region}:*:parameter/${self:service}/${self:provider.stage}/*'
1008
- ]
931
+ Resource: [
932
+ 'arn:aws:ssm:${self:provider.region}:*:parameter/${self:service}/${self:provider.stage}/*'
933
+ ]
1009
934
  });
1010
935
 
1011
- // Add environment variable for SSM parameter prefix
1012
- definition.provider.environment.SSM_PARAMETER_PREFIX = '/${self:service}/${self:provider.stage}';
1013
- // Add environment variable for SSM parameter prefix
1014
- definition.provider.environment.SSM_PARAMETER_PREFIX = '/${self:service}/${self:provider.stage}';
936
+ // Add environment variable for SSM parameter prefix
937
+ definition.provider.environment.SSM_PARAMETER_PREFIX = '/${self:service}/${self:provider.stage}';
1015
938
  }
1016
939
 
1017
- // Add integration-specific functions and resources
1018
- if (AppDefinition.integrations && Array.isArray(AppDefinition.integrations)) {
1019
- for (const integration of AppDefinition.integrations) {
1020
- if (!integration || !integration.Definition || !integration.Definition.name) {
1021
- throw new Error('Invalid integration: missing Definition or name');
1022
- }
1023
- const integrationName = integration.Definition.name;
1024
- if (AppDefinition.integrations && Array.isArray(AppDefinition.integrations)) {
1025
- for (const integration of AppDefinition.integrations) {
1026
- if (!integration || !integration.Definition || !integration.Definition.name) {
1027
- throw new Error('Invalid integration: missing Definition or name');
1028
- }
1029
- const integrationName = integration.Definition.name;
940
+ // Add integration-specific functions and resources
941
+ if (AppDefinition.integrations && Array.isArray(AppDefinition.integrations)) {
942
+ for (const integration of AppDefinition.integrations) {
943
+ if (!integration || !integration.Definition || !integration.Definition.name) {
944
+ throw new Error('Invalid integration: missing Definition or name');
945
+ }
946
+ const integrationName = integration.Definition.name;
1030
947
 
1031
- // Add function for the integration
1032
- definition.functions[integrationName] = {
1033
- handler: `node_modules/@friggframework/core/handlers/routers/integration-defined-routers.handlers.${integrationName}.handler`,
1034
- events: [
1035
- {
1036
- httpApi: {
1037
- path: `/api/${integrationName}-integration/{proxy+}`,
1038
- method: 'ANY',
1039
- },
948
+ // Add function for the integration
949
+ definition.functions[integrationName] = {
950
+ handler: `node_modules/@friggframework/core/handlers/routers/integration-defined-routers.handlers.${integrationName}.handler`,
951
+ events: [
952
+ {
953
+ httpApi: {
954
+ path: `/api/${integrationName}-integration/{proxy+}`,
955
+ method: 'ANY',
1040
956
  },
1041
- ],
1042
- };
957
+ },
958
+ ],
959
+ };
1043
960
 
1044
- // Add SQS Queue for the integration
1045
- const queueReference = `${integrationName.charAt(0).toUpperCase() + integrationName.slice(1)
1046
- }Queue`;
1047
- const queueName = `\${self:service}--\${self:provider.stage}-${queueReference}`;
1048
- definition.resources.Resources[queueReference] = {
1049
- Type: 'AWS::SQS::Queue',
1050
- Properties: {
1051
- QueueName: `\${self:custom.${queueReference}}`,
1052
- MessageRetentionPeriod: 60,
1053
- VisibilityTimeout: 1800, // 30 minutes
1054
- RedrivePolicy: {
1055
- maxReceiveCount: 1,
1056
- deadLetterTargetArn: {
1057
- 'Fn::GetAtt': ['InternalErrorQueue', 'Arn'],
1058
- },
961
+ // Add SQS Queue for the integration
962
+ const queueReference = `${integrationName.charAt(0).toUpperCase() + integrationName.slice(1)
963
+ }Queue`;
964
+ const queueName = `\${self:service}--\${self:provider.stage}-${queueReference}`;
965
+ definition.resources.Resources[queueReference] = {
966
+ Type: 'AWS::SQS::Queue',
967
+ Properties: {
968
+ QueueName: `\${self:custom.${queueReference}}`,
969
+ MessageRetentionPeriod: 60,
970
+ VisibilityTimeout: 1800, // 30 minutes
971
+ RedrivePolicy: {
972
+ maxReceiveCount: 1,
973
+ deadLetterTargetArn: {
974
+ 'Fn::GetAtt': ['InternalErrorQueue', 'Arn'],
1059
975
  },
1060
976
  },
1061
- };
977
+ },
978
+ };
1062
979
 
1063
- // Add Queue Worker for the integration
1064
- const queueWorkerName = `${integrationName}QueueWorker`;
1065
- definition.functions[queueWorkerName] = {
1066
- handler: `node_modules/@friggframework/core/handlers/workers/integration-defined-workers.handlers.${integrationName}.queueWorker`,
1067
- reservedConcurrency: 5,
1068
- events: [
1069
- {
1070
- sqs: {
1071
- arn: {
1072
- 'Fn::GetAtt': [queueReference, 'Arn'],
1073
- },
1074
- batchSize: 1,
980
+ // Add Queue Worker for the integration
981
+ const queueWorkerName = `${integrationName}QueueWorker`;
982
+ definition.functions[queueWorkerName] = {
983
+ handler: `node_modules/@friggframework/core/handlers/workers/integration-defined-workers.handlers.${integrationName}.queueWorker`,
984
+ reservedConcurrency: 5,
985
+ events: [
986
+ {
987
+ sqs: {
988
+ arn: {
989
+ 'Fn::GetAtt': [queueReference, 'Arn'],
1075
990
  },
991
+ batchSize: 1,
1076
992
  },
1077
- ],
1078
- timeout: 600,
1079
- };
1080
-
1081
- // Add Queue URL for the integration to the ENVironment variables
1082
- definition.provider.environment = {
1083
- ...definition.provider.environment,
1084
- [`${integrationName.toUpperCase()}_QUEUE_URL`]: {
1085
- Ref: queueReference,
1086
- },
1087
- };
1088
- // Add Queue URL for the integration to the ENVironment variables
1089
- definition.provider.environment = {
1090
- ...definition.provider.environment,
1091
- [`${integrationName.toUpperCase()}_QUEUE_URL`]: {
1092
- Ref: queueReference,
1093
993
  },
1094
- };
994
+ ],
995
+ timeout: 600,
996
+ };
1095
997
 
1096
- definition.custom[queueReference] = queueName;
998
+ // Add Queue URL for the integration to the ENVironment variables
999
+ definition.provider.environment = {
1000
+ ...definition.provider.environment,
1001
+ [`${integrationName.toUpperCase()}_QUEUE_URL`]: {
1002
+ Ref: queueReference,
1003
+ },
1004
+ };
1005
+
1006
+ definition.custom[queueReference] = queueName;
1097
1007
  }
1098
1008
  }
1099
1009
 
@@ -1149,7 +1059,6 @@ if (AppDefinition.integrations && Array.isArray(AppDefinition.integrations)) {
1149
1059
  },
1150
1060
  ],
1151
1061
  };
1152
- definition.custom[queueReference] = queueName;
1153
1062
  }
1154
1063
  }
1155
1064
 
@@ -1183,30 +1092,6 @@ if (AppDefinition.integrations && Array.isArray(AppDefinition.integrations)) {
1183
1092
  // Discovery has already run successfully at this point if needed
1184
1093
  // The discoveredResources object contains all the necessary AWS resources
1185
1094
 
1186
- // Add websocket function if enabled
1187
- if (AppDefinition.websockets?.enable === true) {
1188
- definition.functions.defaultWebsocket = {
1189
- handler: 'node_modules/@friggframework/core/handlers/routers/websocket.handler',
1190
- events: [
1191
- {
1192
- websocket: {
1193
- route: '$connect',
1194
- },
1195
- },
1196
- {
1197
- websocket: {
1198
- route: '$default',
1199
- },
1200
- },
1201
- {
1202
- websocket: {
1203
- route: '$disconnect',
1204
- },
1205
- },
1206
- ],
1207
- };
1208
- }
1209
-
1210
1095
  // Modify handler paths to point to the correct node_modules location
1211
1096
  definition.functions = modifyHandlerPaths(definition.functions);
1212
1097
 
@@ -0,0 +1,22 @@
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
+ }