@friggframework/devtools 2.0.0-next.27 → 2.0.0-next.29
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 +4 -2
- package/frigg-cli/deploy-command/index.js +5 -2
- package/frigg-cli/generate-iam-command.js +115 -0
- package/frigg-cli/index.js +11 -1
- package/infrastructure/AWS-DISCOVERY-TROUBLESHOOTING.md +245 -0
- package/infrastructure/AWS-IAM-CREDENTIAL-NEEDS.md +596 -0
- package/infrastructure/DEPLOYMENT-INSTRUCTIONS.md +268 -0
- package/infrastructure/GENERATE-IAM-DOCS.md +253 -0
- package/infrastructure/IAM-POLICY-TEMPLATES.md +176 -0
- package/infrastructure/README-TESTING.md +332 -0
- package/infrastructure/README.md +421 -0
- package/infrastructure/WEBSOCKET-CONFIGURATION.md +105 -0
- package/infrastructure/__tests__/fixtures/mock-aws-resources.js +391 -0
- package/infrastructure/__tests__/helpers/test-utils.js +277 -0
- package/infrastructure/aws-discovery.js +568 -0
- package/infrastructure/aws-discovery.test.js +373 -0
- package/infrastructure/build-time-discovery.js +206 -0
- package/infrastructure/build-time-discovery.test.js +375 -0
- package/infrastructure/create-frigg-infrastructure.js +2 -2
- package/infrastructure/frigg-deployment-iam-stack.yaml +379 -0
- package/infrastructure/iam-generator.js +687 -0
- package/infrastructure/iam-generator.test.js +169 -0
- package/infrastructure/iam-policy-basic.json +212 -0
- package/infrastructure/iam-policy-full.json +282 -0
- package/infrastructure/integration.test.js +383 -0
- package/infrastructure/run-discovery.js +110 -0
- package/infrastructure/serverless-template.js +537 -212
- package/infrastructure/serverless-template.test.js +541 -0
- package/management-ui/dist/assets/FriggLogo-B7Xx8ZW1.svg +1 -0
- package/management-ui/dist/assets/index-BA21WgFa.js +1221 -0
- package/management-ui/dist/assets/index-CbM64Oba.js +1221 -0
- package/management-ui/dist/assets/index-CkvseXTC.css +1 -0
- package/management-ui/dist/index.html +14 -0
- package/package.json +9 -5
|
@@ -1,7 +1,26 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const fs = require('fs');
|
|
3
|
+
const { AWSDiscovery } = require('./aws-discovery');
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Check if AWS discovery should run based on AppDefinition
|
|
7
|
+
* @param {Object} AppDefinition - Application definition
|
|
8
|
+
* @returns {boolean} True if discovery should run
|
|
9
|
+
*/
|
|
10
|
+
const shouldRunDiscovery = (AppDefinition) => {
|
|
11
|
+
return AppDefinition.vpc?.enable === true ||
|
|
12
|
+
AppDefinition.encryption?.useDefaultKMSForFieldLevelEncryption === true ||
|
|
13
|
+
AppDefinition.ssm?.enable === true;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Find the actual path to node_modules directory
|
|
18
|
+
* Tries multiple methods to locate node_modules:
|
|
19
|
+
* 1. Traversing up from current directory
|
|
20
|
+
* 2. Using npm root command
|
|
21
|
+
* 3. Looking for package.json and adjacent node_modules
|
|
22
|
+
* @returns {string} Path to node_modules directory
|
|
23
|
+
*/
|
|
5
24
|
const findNodeModulesPath = () => {
|
|
6
25
|
try {
|
|
7
26
|
// Method 1: Try to find node_modules by traversing up from current directory
|
|
@@ -75,7 +94,18 @@ const findNodeModulesPath = () => {
|
|
|
75
94
|
}
|
|
76
95
|
};
|
|
77
96
|
|
|
78
|
-
|
|
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
|
+
/**
|
|
104
|
+
* Modify handler paths to point to the correct node_modules location
|
|
105
|
+
* Only modifies paths when running in offline mode
|
|
106
|
+
* @param {Object} functions - Serverless functions configuration object
|
|
107
|
+
* @returns {Object} Modified functions object with updated handler paths
|
|
108
|
+
*/
|
|
79
109
|
const modifyHandlerPaths = (functions) => {
|
|
80
110
|
// Check if we're running in offline mode
|
|
81
111
|
const isOffline = process.argv.includes('offline');
|
|
@@ -94,7 +124,10 @@ const modifyHandlerPaths = (functions) => {
|
|
|
94
124
|
const functionDef = modifiedFunctions[functionName];
|
|
95
125
|
if (functionDef?.handler?.includes('node_modules/')) {
|
|
96
126
|
// Replace node_modules/ with the actual path to node_modules/
|
|
97
|
-
|
|
127
|
+
const relativePath = path.relative(process.cwd(), nodeModulesPath);
|
|
128
|
+
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}/`);
|
|
98
131
|
console.log(`Updated handler for ${functionName}: ${functionDef.handler}`);
|
|
99
132
|
}
|
|
100
133
|
}
|
|
@@ -102,7 +135,22 @@ const modifyHandlerPaths = (functions) => {
|
|
|
102
135
|
return modifiedFunctions;
|
|
103
136
|
};
|
|
104
137
|
|
|
105
|
-
|
|
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
|
+
/**
|
|
147
|
+
* Create VPC infrastructure resources for CloudFormation
|
|
148
|
+
* Creates VPC, subnets, NAT gateway, route tables, and security groups
|
|
149
|
+
* @param {Object} AppDefinition - Application definition object
|
|
150
|
+
* @param {Object} AppDefinition.vpc - VPC configuration
|
|
151
|
+
* @param {string} [AppDefinition.vpc.cidrBlock='10.0.0.0/16'] - CIDR block for VPC
|
|
152
|
+
* @returns {Object} CloudFormation resources for VPC infrastructure
|
|
153
|
+
*/
|
|
106
154
|
const createVPCInfrastructure = (AppDefinition) => {
|
|
107
155
|
const vpcResources = {
|
|
108
156
|
// VPC
|
|
@@ -292,13 +340,6 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
292
340
|
CidrIp: '0.0.0.0/0',
|
|
293
341
|
Description: 'HTTP outbound'
|
|
294
342
|
},
|
|
295
|
-
{
|
|
296
|
-
IpProtocol: 'tcp',
|
|
297
|
-
FromPort: 27017,
|
|
298
|
-
ToPort: 27017,
|
|
299
|
-
CidrIp: '0.0.0.0/0',
|
|
300
|
-
Description: 'MongoDB Atlas TLS outbound'
|
|
301
|
-
},
|
|
302
343
|
{
|
|
303
344
|
IpProtocol: 'tcp',
|
|
304
345
|
FromPort: 53,
|
|
@@ -412,15 +453,57 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
412
453
|
return vpcResources;
|
|
413
454
|
};
|
|
414
455
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
456
|
+
/**
|
|
457
|
+
* Compose a complete serverless framework configuration from app definition
|
|
458
|
+
* @param {Object} AppDefinition - Application definition object
|
|
459
|
+
* @param {string} [AppDefinition.name] - Application name
|
|
460
|
+
* @param {string} [AppDefinition.provider='aws'] - Cloud provider
|
|
461
|
+
* @param {Array} AppDefinition.integrations - Array of integration definitions
|
|
462
|
+
* @param {Object} [AppDefinition.vpc] - VPC configuration
|
|
463
|
+
* @param {Object} [AppDefinition.encryption] - KMS encryption configuration
|
|
464
|
+
* @param {Object} [AppDefinition.ssm] - SSM parameter store configuration
|
|
465
|
+
* @param {Object} [AppDefinition.websockets] - WebSocket configuration
|
|
466
|
+
* @param {boolean} [AppDefinition.websockets.enable=false] - Enable WebSocket support for live update streaming
|
|
467
|
+
* @returns {Object} Complete serverless framework configuration
|
|
468
|
+
*/
|
|
469
|
+
const composeServerlessDefinition = async (AppDefinition) => {
|
|
470
|
+
// Store discovered resources
|
|
471
|
+
let discoveredResources = {};
|
|
472
|
+
|
|
473
|
+
// Run AWS discovery if needed
|
|
474
|
+
if (shouldRunDiscovery(AppDefinition)) {
|
|
475
|
+
console.log('🔍 Running AWS resource discovery for serverless template...');
|
|
476
|
+
try {
|
|
477
|
+
const region = process.env.AWS_REGION || 'us-east-1';
|
|
478
|
+
const discovery = new AWSDiscovery(region);
|
|
479
|
+
|
|
480
|
+
const config = {
|
|
481
|
+
vpc: AppDefinition.vpc || {},
|
|
482
|
+
encryption: AppDefinition.encryption || {},
|
|
483
|
+
ssm: AppDefinition.ssm || {}
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
discoveredResources = await discovery.discoverResources(config);
|
|
487
|
+
|
|
488
|
+
console.log('✅ AWS discovery completed successfully!');
|
|
489
|
+
if (discoveredResources.defaultVpcId) {
|
|
490
|
+
console.log(` VPC: ${discoveredResources.defaultVpcId}`);
|
|
491
|
+
}
|
|
492
|
+
if (discoveredResources.privateSubnetId1 && discoveredResources.privateSubnetId2) {
|
|
493
|
+
console.log(` Subnets: ${discoveredResources.privateSubnetId1}, ${discoveredResources.privateSubnetId2}`);
|
|
494
|
+
}
|
|
495
|
+
if (discoveredResources.defaultSecurityGroupId) {
|
|
496
|
+
console.log(` Security Group: ${discoveredResources.defaultSecurityGroupId}`);
|
|
497
|
+
}
|
|
498
|
+
if (discoveredResources.defaultKmsKeyId) {
|
|
499
|
+
console.log(` KMS Key: ${discoveredResources.defaultKmsKeyId}`);
|
|
500
|
+
}
|
|
501
|
+
} catch (error) {
|
|
502
|
+
console.error('❌ AWS discovery failed:', error.message);
|
|
503
|
+
throw new Error(`AWS discovery failed: ${error.message}`);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
|
|
424
507
|
const definition = {
|
|
425
508
|
frameworkVersion: '>=3.17.0',
|
|
426
509
|
service: AppDefinition.name || 'create-frigg-app',
|
|
@@ -433,11 +516,28 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
433
516
|
name: AppDefinition.provider || 'aws',
|
|
434
517
|
runtime: 'nodejs20.x',
|
|
435
518
|
timeout: 30,
|
|
436
|
-
region: 'us-east-1',
|
|
519
|
+
region: process.env.AWS_REGION || 'us-east-1',
|
|
520
|
+
region: process.env.AWS_REGION || 'us-east-1',
|
|
437
521
|
stage: '${opt:stage}',
|
|
438
522
|
environment: {
|
|
439
|
-
STAGE: '${opt:stage}',
|
|
523
|
+
STAGE: '${opt:stage, "dev"}',
|
|
440
524
|
AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1,
|
|
525
|
+
// Add discovered resources to environment if available
|
|
526
|
+
...(discoveredResources.defaultVpcId && { AWS_DISCOVERY_VPC_ID: discoveredResources.defaultVpcId }),
|
|
527
|
+
...(discoveredResources.defaultSecurityGroupId && { AWS_DISCOVERY_SECURITY_GROUP_ID: discoveredResources.defaultSecurityGroupId }),
|
|
528
|
+
...(discoveredResources.privateSubnetId1 && { AWS_DISCOVERY_SUBNET_ID_1: discoveredResources.privateSubnetId1 }),
|
|
529
|
+
...(discoveredResources.privateSubnetId2 && { AWS_DISCOVERY_SUBNET_ID_2: discoveredResources.privateSubnetId2 }),
|
|
530
|
+
...(discoveredResources.publicSubnetId && { AWS_DISCOVERY_PUBLIC_SUBNET_ID: discoveredResources.publicSubnetId }),
|
|
531
|
+
...(discoveredResources.defaultRouteTableId && { AWS_DISCOVERY_ROUTE_TABLE_ID: discoveredResources.defaultRouteTableId }),
|
|
532
|
+
...(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 }),
|
|
441
541
|
},
|
|
442
542
|
iamRoleStatements: [
|
|
443
543
|
{
|
|
@@ -470,6 +570,17 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
470
570
|
],
|
|
471
571
|
}
|
|
472
572
|
],
|
|
573
|
+
httpApi: {
|
|
574
|
+
payload: '2.0',
|
|
575
|
+
cors: {
|
|
576
|
+
allowedOrigins: ['*'],
|
|
577
|
+
allowedHeaders: ['*'],
|
|
578
|
+
allowedMethods: ['*'],
|
|
579
|
+
allowCredentials: false,
|
|
580
|
+
},
|
|
581
|
+
name: '${opt:stage, "dev"}-${self:service}',
|
|
582
|
+
disableDefaultEndpoint: false,
|
|
583
|
+
}
|
|
473
584
|
},
|
|
474
585
|
plugins: [
|
|
475
586
|
'serverless-jetpack',
|
|
@@ -488,7 +599,8 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
488
599
|
autoCreate: false,
|
|
489
600
|
apiVersion: '2012-11-05',
|
|
490
601
|
endpoint: 'http://localhost:4566',
|
|
491
|
-
region: 'us-east-1',
|
|
602
|
+
region: process.env.AWS_REGION || 'us-east-1',
|
|
603
|
+
region: process.env.AWS_REGION || 'us-east-1',
|
|
492
604
|
accessKeyId: 'root',
|
|
493
605
|
secretAccessKey: 'root',
|
|
494
606
|
skipCacheInvalidation: false,
|
|
@@ -498,48 +610,25 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
498
610
|
},
|
|
499
611
|
},
|
|
500
612
|
functions: {
|
|
501
|
-
defaultWebsocket: {
|
|
502
|
-
handler: 'node_modules/@friggframework/core/handlers/routers/websocket.handler',
|
|
503
|
-
events: [
|
|
504
|
-
{
|
|
505
|
-
websocket: {
|
|
506
|
-
route: '$connect',
|
|
507
|
-
},
|
|
508
|
-
},
|
|
509
|
-
{
|
|
510
|
-
websocket: {
|
|
511
|
-
route: '$default',
|
|
512
|
-
},
|
|
513
|
-
},
|
|
514
|
-
{
|
|
515
|
-
websocket: {
|
|
516
|
-
route: '$disconnect',
|
|
517
|
-
},
|
|
518
|
-
},
|
|
519
|
-
],
|
|
520
|
-
},
|
|
521
613
|
auth: {
|
|
522
614
|
handler: 'node_modules/@friggframework/core/handlers/routers/auth.handler',
|
|
523
615
|
events: [
|
|
524
616
|
{
|
|
525
|
-
|
|
617
|
+
httpApi: {
|
|
526
618
|
path: '/api/integrations',
|
|
527
619
|
method: 'ANY',
|
|
528
|
-
cors: corsConfig,
|
|
529
620
|
},
|
|
530
621
|
},
|
|
531
622
|
{
|
|
532
|
-
|
|
623
|
+
httpApi: {
|
|
533
624
|
path: '/api/integrations/{proxy+}',
|
|
534
625
|
method: 'ANY',
|
|
535
|
-
cors: corsConfig,
|
|
536
626
|
},
|
|
537
627
|
},
|
|
538
628
|
{
|
|
539
|
-
|
|
629
|
+
httpApi: {
|
|
540
630
|
path: '/api/authorize',
|
|
541
631
|
method: 'ANY',
|
|
542
|
-
cors: corsConfig,
|
|
543
632
|
},
|
|
544
633
|
},
|
|
545
634
|
],
|
|
@@ -548,10 +637,9 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
548
637
|
handler: 'node_modules/@friggframework/core/handlers/routers/user.handler',
|
|
549
638
|
events: [
|
|
550
639
|
{
|
|
551
|
-
|
|
640
|
+
httpApi: {
|
|
552
641
|
path: '/user/{proxy+}',
|
|
553
642
|
method: 'ANY',
|
|
554
|
-
cors: corsConfig,
|
|
555
643
|
},
|
|
556
644
|
},
|
|
557
645
|
],
|
|
@@ -560,17 +648,15 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
560
648
|
handler: 'node_modules/@friggframework/core/handlers/routers/health.handler',
|
|
561
649
|
events: [
|
|
562
650
|
{
|
|
563
|
-
|
|
651
|
+
httpApi: {
|
|
564
652
|
path: '/health',
|
|
565
653
|
method: 'GET',
|
|
566
|
-
cors: corsConfig,
|
|
567
654
|
},
|
|
568
655
|
},
|
|
569
656
|
{
|
|
570
|
-
|
|
657
|
+
httpApi: {
|
|
571
658
|
path: '/health/{proxy+}',
|
|
572
659
|
method: 'GET',
|
|
573
|
-
cors: corsConfig,
|
|
574
660
|
},
|
|
575
661
|
},
|
|
576
662
|
],
|
|
@@ -582,7 +668,8 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
582
668
|
Type: 'AWS::SQS::Queue',
|
|
583
669
|
Properties: {
|
|
584
670
|
QueueName:
|
|
585
|
-
'internal-error-queue-${self:provider.stage}',
|
|
671
|
+
'${self:service}-internal-error-queue-${self:provider.stage}',
|
|
672
|
+
'${self:service}-internal-error-queue-${self:provider.stage}',
|
|
586
673
|
MessageRetentionPeriod: 300,
|
|
587
674
|
},
|
|
588
675
|
},
|
|
@@ -648,16 +735,12 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
648
735
|
AlarmActions: [{ Ref: 'InternalErrorBridgeTopic' }],
|
|
649
736
|
Dimensions: [
|
|
650
737
|
{
|
|
651
|
-
Name: '
|
|
652
|
-
Value: {
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
'${self:service}',
|
|
658
|
-
],
|
|
659
|
-
],
|
|
660
|
-
},
|
|
738
|
+
Name: 'ApiId',
|
|
739
|
+
Value: { Ref: 'HttpApi' },
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
Name: 'Stage',
|
|
743
|
+
Value: '${self:provider.stage}',
|
|
661
744
|
},
|
|
662
745
|
],
|
|
663
746
|
},
|
|
@@ -666,76 +749,7 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
666
749
|
},
|
|
667
750
|
};
|
|
668
751
|
|
|
669
|
-
|
|
670
|
-
if (process.env.CUSTOM_DOMAIN) {
|
|
671
|
-
|
|
672
|
-
// Configure custom domain
|
|
673
|
-
definition.custom.customDomain = {
|
|
674
|
-
domainName: process.env.CUSTOM_DOMAIN,
|
|
675
|
-
basePath: process.env.CUSTOM_BASE_PATH || '',
|
|
676
|
-
stage: '${self:provider.stage}',
|
|
677
|
-
createRoute53Record: process.env.CREATE_ROUTE53_RECORD !== 'false', // Default true
|
|
678
|
-
certificateName: process.env.CERTIFICATE_NAME || process.env.CUSTOM_DOMAIN,
|
|
679
|
-
endpointType: process.env.ENDPOINT_TYPE || 'edge', // edge, regional, or private
|
|
680
|
-
securityPolicy: process.env.SECURITY_POLICY || 'tls_1_2',
|
|
681
|
-
apiType: 'rest',
|
|
682
|
-
autoDomain: process.env.AUTO_DOMAIN === 'true', // Auto create domain if it doesn't exist
|
|
683
|
-
};
|
|
684
|
-
|
|
685
|
-
// Set BASE_URL to custom domain
|
|
686
|
-
definition.provider.environment.BASE_URL = `https://${process.env.CUSTOM_DOMAIN}`;
|
|
687
|
-
} else {
|
|
688
|
-
// Default BASE_URL using API Gateway generated URL
|
|
689
|
-
definition.provider.environment.BASE_URL = {
|
|
690
|
-
'Fn::Join': [
|
|
691
|
-
'',
|
|
692
|
-
[
|
|
693
|
-
'https://',
|
|
694
|
-
{ Ref: 'ApiGatewayRestApi' },
|
|
695
|
-
'.execute-api.',
|
|
696
|
-
{ Ref: 'AWS::Region' },
|
|
697
|
-
'.amazonaws.com/',
|
|
698
|
-
'${self:provider.stage}',
|
|
699
|
-
],
|
|
700
|
-
],
|
|
701
|
-
};
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// REDIRECT_PATH is required for OAuth integrations
|
|
705
|
-
if (!process.env.REDIRECT_PATH) {
|
|
706
|
-
throw new Error(
|
|
707
|
-
'REDIRECT_PATH environment variable is required. ' +
|
|
708
|
-
'Please set REDIRECT_PATH in your .env file (e.g., REDIRECT_PATH=/oauth/callback)'
|
|
709
|
-
);
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
// Set REDIRECT_URI based on domain configuration
|
|
713
|
-
if (process.env.CUSTOM_DOMAIN) {
|
|
714
|
-
definition.provider.environment.REDIRECT_URI = `https://${process.env.CUSTOM_DOMAIN}${process.env.REDIRECT_PATH}`;
|
|
715
|
-
} else {
|
|
716
|
-
definition.provider.environment.REDIRECT_URI = {
|
|
717
|
-
'Fn::Join': [
|
|
718
|
-
'',
|
|
719
|
-
[
|
|
720
|
-
'https://',
|
|
721
|
-
{ Ref: 'ApiGatewayRestApi' },
|
|
722
|
-
'.execute-api.',
|
|
723
|
-
{ Ref: 'AWS::Region' },
|
|
724
|
-
'.amazonaws.com/',
|
|
725
|
-
'${self:provider.stage}',
|
|
726
|
-
process.env.REDIRECT_PATH,
|
|
727
|
-
],
|
|
728
|
-
],
|
|
729
|
-
};
|
|
730
|
-
}
|
|
731
|
-
|
|
732
|
-
// Add REDIRECT_URI to CloudFormation outputs
|
|
733
|
-
definition.resources.Outputs = {
|
|
734
|
-
RedirectURI: {
|
|
735
|
-
Description: 'OAuth Redirect URI to register with providers',
|
|
736
|
-
Value: definition.provider.environment.REDIRECT_URI,
|
|
737
|
-
},
|
|
738
|
-
};
|
|
752
|
+
|
|
739
753
|
|
|
740
754
|
// KMS Configuration based on App Definition
|
|
741
755
|
if (AppDefinition.encryption?.useDefaultKMSForFieldLevelEncryption === true) {
|
|
@@ -768,36 +782,17 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
768
782
|
definition.provider.environment.KMS_KEY_ARN = { 'Fn::GetAtt': ['FriggKMSKey', 'Arn'] };
|
|
769
783
|
|
|
770
784
|
definition.plugins.push('serverless-kms-grants');
|
|
771
|
-
|
|
785
|
+
|
|
786
|
+
// Configure KMS grants with discovered default key
|
|
787
|
+
// Configure KMS grants with discovered default key
|
|
788
|
+
definition.custom.kmsGrants = {
|
|
789
|
+
kmsKeyId: discoveredResources.defaultKmsKeyId || '${env:AWS_DISCOVERY_KMS_KEY_ID}'
|
|
790
|
+
kmsKeyId: discoveredResources.defaultKmsKeyId || '${env:AWS_DISCOVERY_KMS_KEY_ID}'
|
|
791
|
+
};
|
|
772
792
|
}
|
|
773
793
|
|
|
774
794
|
// VPC Configuration based on App Definition
|
|
775
795
|
if (AppDefinition.vpc?.enable === true) {
|
|
776
|
-
// Create VPC config from App Definition or use auto-created resources
|
|
777
|
-
const vpcConfig = {};
|
|
778
|
-
|
|
779
|
-
if (AppDefinition.vpc.securityGroupIds) {
|
|
780
|
-
// User provided custom security groups
|
|
781
|
-
vpcConfig.securityGroupIds = AppDefinition.vpc.securityGroupIds;
|
|
782
|
-
} else {
|
|
783
|
-
// Use auto-created security group
|
|
784
|
-
vpcConfig.securityGroupIds = [{ Ref: 'FriggLambdaSecurityGroup' }];
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
if (AppDefinition.vpc.subnetIds) {
|
|
788
|
-
// User provided custom subnets
|
|
789
|
-
vpcConfig.subnetIds = AppDefinition.vpc.subnetIds;
|
|
790
|
-
} else {
|
|
791
|
-
// Use auto-created private subnets
|
|
792
|
-
vpcConfig.subnetIds = [
|
|
793
|
-
{ Ref: 'FriggPrivateSubnet1' },
|
|
794
|
-
{ Ref: 'FriggPrivateSubnet2' }
|
|
795
|
-
];
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
// Set VPC config for Lambda functions
|
|
799
|
-
definition.provider.vpc = vpcConfig;
|
|
800
|
-
|
|
801
796
|
// Add VPC-related IAM permissions
|
|
802
797
|
definition.provider.iamRoleStatements.push({
|
|
803
798
|
Effect: 'Allow',
|
|
@@ -811,75 +806,405 @@ const composeServerlessDefinition = (AppDefinition) => {
|
|
|
811
806
|
Resource: '*'
|
|
812
807
|
});
|
|
813
808
|
|
|
814
|
-
//
|
|
815
|
-
|
|
816
|
-
|
|
809
|
+
// Default approach: Use AWS Discovery to find existing VPC resources
|
|
810
|
+
if (AppDefinition.vpc.createNew === true) {
|
|
811
|
+
// Option 1: Create new VPC infrastructure (explicit opt-in)
|
|
812
|
+
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
|
+
|
|
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;
|
|
871
|
+
|
|
872
|
+
// Add VPC infrastructure resources to CloudFormation
|
|
873
|
+
const vpcResources = createVPCInfrastructure(AppDefinition);
|
|
874
|
+
Object.assign(definition.resources.Resources, vpcResources);
|
|
875
|
+
} 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
|
+
};
|
|
886
|
+
|
|
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
|
+
}
|
|
907
|
+
|
|
908
|
+
definition.resources.Resources.FriggNATGateway = {
|
|
909
|
+
Type: 'AWS::EC2::NatGateway',
|
|
910
|
+
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
|
|
914
|
+
Tags: [
|
|
915
|
+
{ Key: 'Name', Value: '${self:service}-${self:provider.stage}-nat-gateway' }
|
|
916
|
+
]
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// Create route table for Lambda subnets to use NAT Gateway
|
|
922
|
+
definition.resources.Resources.FriggLambdaRouteTable = {
|
|
923
|
+
Type: 'AWS::EC2::RouteTable',
|
|
924
|
+
Properties: {
|
|
925
|
+
VpcId: discoveredResources.defaultVpcId || { Ref: 'FriggVPC' },
|
|
926
|
+
Tags: [
|
|
927
|
+
{ Key: 'Name', Value: '${self:service}-${self:provider.stage}-lambda-rt' }
|
|
928
|
+
]
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
|
|
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
|
+
};
|
|
940
|
+
|
|
941
|
+
// Associate Lambda subnets with NAT Gateway route table
|
|
942
|
+
definition.resources.Resources.FriggSubnet1RouteAssociation = {
|
|
943
|
+
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
|
944
|
+
Properties: {
|
|
945
|
+
SubnetId: vpcConfig.subnetIds[0],
|
|
946
|
+
RouteTableId: { Ref: 'FriggLambdaRouteTable' }
|
|
947
|
+
}
|
|
948
|
+
};
|
|
949
|
+
|
|
950
|
+
definition.resources.Resources.FriggSubnet2RouteAssociation = {
|
|
951
|
+
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
|
952
|
+
Properties: {
|
|
953
|
+
SubnetId: vpcConfig.subnetIds[1],
|
|
954
|
+
RouteTableId: { Ref: 'FriggLambdaRouteTable' }
|
|
955
|
+
}
|
|
956
|
+
};
|
|
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
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
|
|
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
|
+
]
|
|
1002
|
+
'ssm:GetParameter',
|
|
1003
|
+
'ssm:GetParameters',
|
|
1004
|
+
'ssm:GetParametersByPath'
|
|
1005
|
+
],
|
|
1006
|
+
Resource: [
|
|
1007
|
+
'arn:aws:ssm:${self:provider.region}:*:parameter/${self:service}/${self:provider.stage}/*'
|
|
1008
|
+
]
|
|
1009
|
+
});
|
|
1010
|
+
|
|
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}';
|
|
817
1015
|
}
|
|
818
1016
|
|
|
819
|
-
|
|
1017
|
+
// Add integration-specific functions and resources
|
|
1018
|
+
if (AppDefinition.integrations && Array.isArray(AppDefinition.integrations)) {
|
|
820
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
|
+
}
|
|
821
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;
|
|
1030
|
+
|
|
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
|
+
},
|
|
1040
|
+
},
|
|
1041
|
+
],
|
|
1042
|
+
};
|
|
1043
|
+
|
|
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
|
+
},
|
|
1059
|
+
},
|
|
1060
|
+
},
|
|
1061
|
+
};
|
|
1062
|
+
|
|
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,
|
|
1075
|
+
},
|
|
1076
|
+
},
|
|
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
|
+
},
|
|
1094
|
+
};
|
|
1095
|
+
|
|
1096
|
+
definition.custom[queueReference] = queueName;
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// Discovery has already run successfully at this point if needed
|
|
1101
|
+
// The discoveredResources object contains all the necessary AWS resources
|
|
1102
|
+
|
|
1103
|
+
// Add websocket function if enabled
|
|
1104
|
+
if (AppDefinition.websockets?.enable === true) {
|
|
1105
|
+
definition.functions.defaultWebsocket = {
|
|
1106
|
+
handler: 'node_modules/@friggframework/core/handlers/routers/websocket.handler',
|
|
1107
|
+
events: [
|
|
1108
|
+
{
|
|
1109
|
+
websocket: {
|
|
1110
|
+
route: '$connect',
|
|
1111
|
+
},
|
|
1112
|
+
},
|
|
1113
|
+
{
|
|
1114
|
+
websocket: {
|
|
1115
|
+
route: '$default',
|
|
1116
|
+
},
|
|
1117
|
+
},
|
|
1118
|
+
{
|
|
1119
|
+
websocket: {
|
|
1120
|
+
route: '$disconnect',
|
|
1121
|
+
},
|
|
1122
|
+
},
|
|
1123
|
+
],
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
// Discovery has already run successfully at this point if needed
|
|
1128
|
+
// The discoveredResources object contains all the necessary AWS resources
|
|
1129
|
+
|
|
1130
|
+
// Add websocket function if enabled
|
|
1131
|
+
if (AppDefinition.websockets?.enable === true) {
|
|
1132
|
+
definition.functions.defaultWebsocket = {
|
|
1133
|
+
handler: 'node_modules/@friggframework/core/handlers/routers/websocket.handler',
|
|
1134
|
+
events: [
|
|
1135
|
+
{
|
|
1136
|
+
websocket: {
|
|
1137
|
+
route: '$connect',
|
|
1138
|
+
},
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
websocket: {
|
|
1142
|
+
route: '$default',
|
|
1143
|
+
},
|
|
1144
|
+
},
|
|
1145
|
+
{
|
|
1146
|
+
websocket: {
|
|
1147
|
+
route: '$disconnect',
|
|
1148
|
+
},
|
|
1149
|
+
},
|
|
1150
|
+
],
|
|
1151
|
+
};
|
|
1152
|
+
definition.custom[queueReference] = queueName;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
// Discovery has already run successfully at this point if needed
|
|
1157
|
+
// The discoveredResources object contains all the necessary AWS resources
|
|
822
1158
|
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
1159
|
+
// Add websocket function if enabled
|
|
1160
|
+
if (AppDefinition.websockets?.enable === true) {
|
|
1161
|
+
definition.functions.defaultWebsocket = {
|
|
1162
|
+
handler: 'node_modules/@friggframework/core/handlers/routers/websocket.handler',
|
|
826
1163
|
events: [
|
|
827
1164
|
{
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
method: 'ANY',
|
|
831
|
-
cors: corsConfig,
|
|
1165
|
+
websocket: {
|
|
1166
|
+
route: '$connect',
|
|
832
1167
|
},
|
|
833
1168
|
},
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
// Add SQS Queue for the integration
|
|
838
|
-
const queueReference = `${integrationName.charAt(0).toUpperCase() + integrationName.slice(1)
|
|
839
|
-
}Queue`;
|
|
840
|
-
const queueName = `\${self:service}--\${self:provider.stage}-${queueReference}`;
|
|
841
|
-
definition.resources.Resources[queueReference] = {
|
|
842
|
-
Type: 'AWS::SQS::Queue',
|
|
843
|
-
Properties: {
|
|
844
|
-
QueueName: `\${self:custom.${queueReference}}`,
|
|
845
|
-
MessageRetentionPeriod: 60,
|
|
846
|
-
VisibilityTimeout: 1800, // 30 minutes
|
|
847
|
-
RedrivePolicy: {
|
|
848
|
-
maxReceiveCount: 1,
|
|
849
|
-
deadLetterTargetArn: {
|
|
850
|
-
'Fn::GetAtt': ['InternalErrorQueue', 'Arn'],
|
|
1169
|
+
{
|
|
1170
|
+
websocket: {
|
|
1171
|
+
route: '$default',
|
|
851
1172
|
},
|
|
852
1173
|
},
|
|
853
|
-
|
|
1174
|
+
{
|
|
1175
|
+
websocket: {
|
|
1176
|
+
route: '$disconnect',
|
|
1177
|
+
},
|
|
1178
|
+
},
|
|
1179
|
+
],
|
|
854
1180
|
};
|
|
1181
|
+
}
|
|
855
1182
|
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
1183
|
+
// Discovery has already run successfully at this point if needed
|
|
1184
|
+
// The discoveredResources object contains all the necessary AWS resources
|
|
1185
|
+
|
|
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',
|
|
861
1190
|
events: [
|
|
862
1191
|
{
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
1192
|
+
websocket: {
|
|
1193
|
+
route: '$connect',
|
|
1194
|
+
},
|
|
1195
|
+
},
|
|
1196
|
+
{
|
|
1197
|
+
websocket: {
|
|
1198
|
+
route: '$default',
|
|
1199
|
+
},
|
|
1200
|
+
},
|
|
1201
|
+
{
|
|
1202
|
+
websocket: {
|
|
1203
|
+
route: '$disconnect',
|
|
868
1204
|
},
|
|
869
1205
|
},
|
|
870
1206
|
],
|
|
871
|
-
timeout: 600,
|
|
872
|
-
};
|
|
873
|
-
|
|
874
|
-
// Add Queue URL for the integration to the ENVironment variables
|
|
875
|
-
definition.provider.environment = {
|
|
876
|
-
...definition.provider.environment,
|
|
877
|
-
[`${integrationName.toUpperCase()}_QUEUE_URL`]: {
|
|
878
|
-
Ref: queueReference,
|
|
879
|
-
},
|
|
880
1207
|
};
|
|
881
|
-
|
|
882
|
-
definition.custom[queueReference] = queueName;
|
|
883
1208
|
}
|
|
884
1209
|
|
|
885
1210
|
// Modify handler paths to point to the correct node_modules location
|