@friggframework/devtools 2.0.0--canary.413.52695f8.0 → 2.0.0--canary.413.ad943eb.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/infrastructure/serverless-template.js +404 -243
- package/package.json +6 -6
|
@@ -8,9 +8,12 @@ const { AWSDiscovery } = require('./aws-discovery');
|
|
|
8
8
|
* @returns {boolean} True if discovery should run
|
|
9
9
|
*/
|
|
10
10
|
const shouldRunDiscovery = (AppDefinition) => {
|
|
11
|
-
return
|
|
12
|
-
AppDefinition.
|
|
13
|
-
AppDefinition.
|
|
11
|
+
return (
|
|
12
|
+
AppDefinition.vpc?.enable === true ||
|
|
13
|
+
AppDefinition.encryption?.useDefaultKMSForFieldLevelEncryption ===
|
|
14
|
+
true ||
|
|
15
|
+
AppDefinition.ssm?.enable === true
|
|
16
|
+
);
|
|
14
17
|
};
|
|
15
18
|
|
|
16
19
|
/**
|
|
@@ -32,7 +35,9 @@ const findNodeModulesPath = () => {
|
|
|
32
35
|
const potentialPath = path.join(currentDir, 'node_modules');
|
|
33
36
|
if (fs.existsSync(potentialPath)) {
|
|
34
37
|
nodeModulesPath = potentialPath;
|
|
35
|
-
console.log(
|
|
38
|
+
console.log(
|
|
39
|
+
`Found node_modules at: ${nodeModulesPath} (method 1)`
|
|
40
|
+
);
|
|
36
41
|
break;
|
|
37
42
|
}
|
|
38
43
|
// Move up one directory
|
|
@@ -49,10 +54,14 @@ const findNodeModulesPath = () => {
|
|
|
49
54
|
try {
|
|
50
55
|
// This requires child_process, so let's require it here
|
|
51
56
|
const { execSync } = require('node:child_process');
|
|
52
|
-
const npmRoot = execSync('npm root', {
|
|
57
|
+
const npmRoot = execSync('npm root', {
|
|
58
|
+
encoding: 'utf8',
|
|
59
|
+
}).trim();
|
|
53
60
|
if (fs.existsSync(npmRoot)) {
|
|
54
61
|
nodeModulesPath = npmRoot;
|
|
55
|
-
console.log(
|
|
62
|
+
console.log(
|
|
63
|
+
`Found node_modules at: ${nodeModulesPath} (method 2)`
|
|
64
|
+
);
|
|
56
65
|
}
|
|
57
66
|
} catch (npmError) {
|
|
58
67
|
console.error('Error executing npm root:', npmError);
|
|
@@ -65,10 +74,15 @@ const findNodeModulesPath = () => {
|
|
|
65
74
|
for (let i = 0; i < 5; i++) {
|
|
66
75
|
const packageJsonPath = path.join(currentDir, 'package.json');
|
|
67
76
|
if (fs.existsSync(packageJsonPath)) {
|
|
68
|
-
const potentialNodeModules = path.join(
|
|
77
|
+
const potentialNodeModules = path.join(
|
|
78
|
+
currentDir,
|
|
79
|
+
'node_modules'
|
|
80
|
+
);
|
|
69
81
|
if (fs.existsSync(potentialNodeModules)) {
|
|
70
82
|
nodeModulesPath = potentialNodeModules;
|
|
71
|
-
console.log(
|
|
83
|
+
console.log(
|
|
84
|
+
`Found node_modules at: ${nodeModulesPath} (method 3)`
|
|
85
|
+
);
|
|
72
86
|
break;
|
|
73
87
|
}
|
|
74
88
|
}
|
|
@@ -86,7 +100,9 @@ const findNodeModulesPath = () => {
|
|
|
86
100
|
return nodeModulesPath;
|
|
87
101
|
}
|
|
88
102
|
|
|
89
|
-
console.warn(
|
|
103
|
+
console.warn(
|
|
104
|
+
'Could not find node_modules path, falling back to default'
|
|
105
|
+
);
|
|
90
106
|
return path.resolve(process.cwd(), '../node_modules');
|
|
91
107
|
} catch (error) {
|
|
92
108
|
console.error('Error finding node_modules path:', error);
|
|
@@ -119,8 +135,13 @@ const modifyHandlerPaths = (functions) => {
|
|
|
119
135
|
if (functionDef?.handler?.includes('node_modules/')) {
|
|
120
136
|
// Replace node_modules/ with the actual path to node_modules/
|
|
121
137
|
const relativePath = path.relative(process.cwd(), nodeModulesPath);
|
|
122
|
-
functionDef.handler = functionDef.handler.replace(
|
|
123
|
-
|
|
138
|
+
functionDef.handler = functionDef.handler.replace(
|
|
139
|
+
'node_modules/',
|
|
140
|
+
`${relativePath}/`
|
|
141
|
+
);
|
|
142
|
+
console.log(
|
|
143
|
+
`Updated handler for ${functionName}: ${functionDef.handler}`
|
|
144
|
+
);
|
|
124
145
|
}
|
|
125
146
|
}
|
|
126
147
|
|
|
@@ -145,9 +166,12 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
145
166
|
EnableDnsHostnames: true,
|
|
146
167
|
EnableDnsSupport: true,
|
|
147
168
|
Tags: [
|
|
148
|
-
{
|
|
149
|
-
|
|
150
|
-
|
|
169
|
+
{
|
|
170
|
+
Key: 'Name',
|
|
171
|
+
Value: '${self:service}-${self:provider.stage}-vpc',
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
},
|
|
151
175
|
},
|
|
152
176
|
|
|
153
177
|
// Internet Gateway
|
|
@@ -155,9 +179,12 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
155
179
|
Type: 'AWS::EC2::InternetGateway',
|
|
156
180
|
Properties: {
|
|
157
181
|
Tags: [
|
|
158
|
-
{
|
|
159
|
-
|
|
160
|
-
|
|
182
|
+
{
|
|
183
|
+
Key: 'Name',
|
|
184
|
+
Value: '${self:service}-${self:provider.stage}-igw',
|
|
185
|
+
},
|
|
186
|
+
],
|
|
187
|
+
},
|
|
161
188
|
},
|
|
162
189
|
|
|
163
190
|
// Attach Internet Gateway to VPC
|
|
@@ -165,8 +192,8 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
165
192
|
Type: 'AWS::EC2::VPCGatewayAttachment',
|
|
166
193
|
Properties: {
|
|
167
194
|
VpcId: { Ref: 'FriggVPC' },
|
|
168
|
-
InternetGatewayId: { Ref: 'FriggInternetGateway' }
|
|
169
|
-
}
|
|
195
|
+
InternetGatewayId: { Ref: 'FriggInternetGateway' },
|
|
196
|
+
},
|
|
170
197
|
},
|
|
171
198
|
|
|
172
199
|
// Public Subnet for NAT Gateway
|
|
@@ -178,9 +205,12 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
178
205
|
AvailabilityZone: { 'Fn::Select': [0, { 'Fn::GetAZs': '' }] },
|
|
179
206
|
MapPublicIpOnLaunch: true,
|
|
180
207
|
Tags: [
|
|
181
|
-
{
|
|
182
|
-
|
|
183
|
-
|
|
208
|
+
{
|
|
209
|
+
Key: 'Name',
|
|
210
|
+
Value: '${self:service}-${self:provider.stage}-public-subnet',
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
184
214
|
},
|
|
185
215
|
|
|
186
216
|
// Private Subnet 1 for Lambda
|
|
@@ -191,9 +221,12 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
191
221
|
CidrBlock: '10.0.2.0/24',
|
|
192
222
|
AvailabilityZone: { 'Fn::Select': [0, { 'Fn::GetAZs': '' }] },
|
|
193
223
|
Tags: [
|
|
194
|
-
{
|
|
195
|
-
|
|
196
|
-
|
|
224
|
+
{
|
|
225
|
+
Key: 'Name',
|
|
226
|
+
Value: '${self:service}-${self:provider.stage}-private-subnet-1',
|
|
227
|
+
},
|
|
228
|
+
],
|
|
229
|
+
},
|
|
197
230
|
},
|
|
198
231
|
|
|
199
232
|
// Private Subnet 2 for Lambda (different AZ for redundancy)
|
|
@@ -204,9 +237,12 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
204
237
|
CidrBlock: '10.0.3.0/24',
|
|
205
238
|
AvailabilityZone: { 'Fn::Select': [1, { 'Fn::GetAZs': '' }] },
|
|
206
239
|
Tags: [
|
|
207
|
-
{
|
|
208
|
-
|
|
209
|
-
|
|
240
|
+
{
|
|
241
|
+
Key: 'Name',
|
|
242
|
+
Value: '${self:service}-${self:provider.stage}-private-subnet-2',
|
|
243
|
+
},
|
|
244
|
+
],
|
|
245
|
+
},
|
|
210
246
|
},
|
|
211
247
|
|
|
212
248
|
// Elastic IP for NAT Gateway
|
|
@@ -215,22 +251,30 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
215
251
|
Properties: {
|
|
216
252
|
Domain: 'vpc',
|
|
217
253
|
Tags: [
|
|
218
|
-
{
|
|
219
|
-
|
|
254
|
+
{
|
|
255
|
+
Key: 'Name',
|
|
256
|
+
Value: '${self:service}-${self:provider.stage}-nat-eip',
|
|
257
|
+
},
|
|
258
|
+
],
|
|
220
259
|
},
|
|
221
|
-
DependsOn: 'FriggVPCGatewayAttachment'
|
|
260
|
+
DependsOn: 'FriggVPCGatewayAttachment',
|
|
222
261
|
},
|
|
223
262
|
|
|
224
263
|
// NAT Gateway for private subnet internet access
|
|
225
264
|
FriggNATGateway: {
|
|
226
265
|
Type: 'AWS::EC2::NatGateway',
|
|
227
266
|
Properties: {
|
|
228
|
-
AllocationId: {
|
|
267
|
+
AllocationId: {
|
|
268
|
+
'Fn::GetAtt': ['FriggNATGatewayEIP', 'AllocationId'],
|
|
269
|
+
},
|
|
229
270
|
SubnetId: { Ref: 'FriggPublicSubnet' },
|
|
230
271
|
Tags: [
|
|
231
|
-
{
|
|
232
|
-
|
|
233
|
-
|
|
272
|
+
{
|
|
273
|
+
Key: 'Name',
|
|
274
|
+
Value: '${self:service}-${self:provider.stage}-nat-gateway',
|
|
275
|
+
},
|
|
276
|
+
],
|
|
277
|
+
},
|
|
234
278
|
},
|
|
235
279
|
|
|
236
280
|
// Public Route Table
|
|
@@ -239,9 +283,12 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
239
283
|
Properties: {
|
|
240
284
|
VpcId: { Ref: 'FriggVPC' },
|
|
241
285
|
Tags: [
|
|
242
|
-
{
|
|
243
|
-
|
|
244
|
-
|
|
286
|
+
{
|
|
287
|
+
Key: 'Name',
|
|
288
|
+
Value: '${self:service}-${self:provider.stage}-public-rt',
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
},
|
|
245
292
|
},
|
|
246
293
|
|
|
247
294
|
// Public Route to Internet Gateway
|
|
@@ -250,9 +297,9 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
250
297
|
Properties: {
|
|
251
298
|
RouteTableId: { Ref: 'FriggPublicRouteTable' },
|
|
252
299
|
DestinationCidrBlock: '0.0.0.0/0',
|
|
253
|
-
GatewayId: { Ref: 'FriggInternetGateway' }
|
|
300
|
+
GatewayId: { Ref: 'FriggInternetGateway' },
|
|
254
301
|
},
|
|
255
|
-
DependsOn: 'FriggVPCGatewayAttachment'
|
|
302
|
+
DependsOn: 'FriggVPCGatewayAttachment',
|
|
256
303
|
},
|
|
257
304
|
|
|
258
305
|
// Associate Public Subnet with Public Route Table
|
|
@@ -260,8 +307,8 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
260
307
|
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
|
261
308
|
Properties: {
|
|
262
309
|
SubnetId: { Ref: 'FriggPublicSubnet' },
|
|
263
|
-
RouteTableId: { Ref: 'FriggPublicRouteTable' }
|
|
264
|
-
}
|
|
310
|
+
RouteTableId: { Ref: 'FriggPublicRouteTable' },
|
|
311
|
+
},
|
|
265
312
|
},
|
|
266
313
|
|
|
267
314
|
// Private Route Table
|
|
@@ -270,9 +317,12 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
270
317
|
Properties: {
|
|
271
318
|
VpcId: { Ref: 'FriggVPC' },
|
|
272
319
|
Tags: [
|
|
273
|
-
{
|
|
274
|
-
|
|
275
|
-
|
|
320
|
+
{
|
|
321
|
+
Key: 'Name',
|
|
322
|
+
Value: '${self:service}-${self:provider.stage}-private-rt',
|
|
323
|
+
},
|
|
324
|
+
],
|
|
325
|
+
},
|
|
276
326
|
},
|
|
277
327
|
|
|
278
328
|
// Private Route to NAT Gateway
|
|
@@ -281,8 +331,8 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
281
331
|
Properties: {
|
|
282
332
|
RouteTableId: { Ref: 'FriggPrivateRouteTable' },
|
|
283
333
|
DestinationCidrBlock: '0.0.0.0/0',
|
|
284
|
-
NatGatewayId: { Ref: 'FriggNATGateway' }
|
|
285
|
-
}
|
|
334
|
+
NatGatewayId: { Ref: 'FriggNATGateway' },
|
|
335
|
+
},
|
|
286
336
|
},
|
|
287
337
|
|
|
288
338
|
// Associate Private Subnet 1 with Private Route Table
|
|
@@ -290,8 +340,8 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
290
340
|
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
|
291
341
|
Properties: {
|
|
292
342
|
SubnetId: { Ref: 'FriggPrivateSubnet1' },
|
|
293
|
-
RouteTableId: { Ref: 'FriggPrivateRouteTable' }
|
|
294
|
-
}
|
|
343
|
+
RouteTableId: { Ref: 'FriggPrivateRouteTable' },
|
|
344
|
+
},
|
|
295
345
|
},
|
|
296
346
|
|
|
297
347
|
// Associate Private Subnet 2 with Private Route Table
|
|
@@ -299,8 +349,8 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
299
349
|
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
|
300
350
|
Properties: {
|
|
301
351
|
SubnetId: { Ref: 'FriggPrivateSubnet2' },
|
|
302
|
-
RouteTableId: { Ref: 'FriggPrivateRouteTable' }
|
|
303
|
-
}
|
|
352
|
+
RouteTableId: { Ref: 'FriggPrivateRouteTable' },
|
|
353
|
+
},
|
|
304
354
|
},
|
|
305
355
|
|
|
306
356
|
// Security Group for Lambda functions
|
|
@@ -315,35 +365,38 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
315
365
|
FromPort: 443,
|
|
316
366
|
ToPort: 443,
|
|
317
367
|
CidrIp: '0.0.0.0/0',
|
|
318
|
-
Description: 'HTTPS outbound'
|
|
368
|
+
Description: 'HTTPS outbound',
|
|
319
369
|
},
|
|
320
370
|
{
|
|
321
371
|
IpProtocol: 'tcp',
|
|
322
372
|
FromPort: 80,
|
|
323
373
|
ToPort: 80,
|
|
324
374
|
CidrIp: '0.0.0.0/0',
|
|
325
|
-
Description: 'HTTP outbound'
|
|
375
|
+
Description: 'HTTP outbound',
|
|
326
376
|
},
|
|
327
377
|
{
|
|
328
378
|
IpProtocol: 'tcp',
|
|
329
379
|
FromPort: 53,
|
|
330
380
|
ToPort: 53,
|
|
331
381
|
CidrIp: '0.0.0.0/0',
|
|
332
|
-
Description: 'DNS TCP'
|
|
382
|
+
Description: 'DNS TCP',
|
|
333
383
|
},
|
|
334
384
|
{
|
|
335
385
|
IpProtocol: 'udp',
|
|
336
386
|
FromPort: 53,
|
|
337
387
|
ToPort: 53,
|
|
338
388
|
CidrIp: '0.0.0.0/0',
|
|
339
|
-
Description: 'DNS UDP'
|
|
340
|
-
}
|
|
389
|
+
Description: 'DNS UDP',
|
|
390
|
+
},
|
|
341
391
|
],
|
|
342
392
|
Tags: [
|
|
343
|
-
{
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
393
|
+
{
|
|
394
|
+
Key: 'Name',
|
|
395
|
+
Value: '${self:service}-${self:provider.stage}-lambda-sg',
|
|
396
|
+
},
|
|
397
|
+
],
|
|
398
|
+
},
|
|
399
|
+
},
|
|
347
400
|
};
|
|
348
401
|
|
|
349
402
|
// Add VPC Endpoints for cost optimization
|
|
@@ -355,10 +408,8 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
355
408
|
VpcId: { Ref: 'FriggVPC' },
|
|
356
409
|
ServiceName: 'com.amazonaws.${self:provider.region}.s3',
|
|
357
410
|
VpcEndpointType: 'Gateway',
|
|
358
|
-
RouteTableIds: [
|
|
359
|
-
|
|
360
|
-
]
|
|
361
|
-
}
|
|
411
|
+
RouteTableIds: [{ Ref: 'FriggPrivateRouteTable' }],
|
|
412
|
+
},
|
|
362
413
|
};
|
|
363
414
|
|
|
364
415
|
// DynamoDB Gateway Endpoint (free)
|
|
@@ -368,14 +419,15 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
368
419
|
VpcId: { Ref: 'FriggVPC' },
|
|
369
420
|
ServiceName: 'com.amazonaws.${self:provider.region}.dynamodb',
|
|
370
421
|
VpcEndpointType: 'Gateway',
|
|
371
|
-
RouteTableIds: [
|
|
372
|
-
|
|
373
|
-
]
|
|
374
|
-
}
|
|
422
|
+
RouteTableIds: [{ Ref: 'FriggPrivateRouteTable' }],
|
|
423
|
+
},
|
|
375
424
|
};
|
|
376
425
|
|
|
377
426
|
// KMS Interface Endpoint (paid, but useful if using KMS)
|
|
378
|
-
if (
|
|
427
|
+
if (
|
|
428
|
+
AppDefinition.encryption?.useDefaultKMSForFieldLevelEncryption ===
|
|
429
|
+
true
|
|
430
|
+
) {
|
|
379
431
|
vpcResources.FriggKMSVPCEndpoint = {
|
|
380
432
|
Type: 'AWS::EC2::VPCEndpoint',
|
|
381
433
|
Properties: {
|
|
@@ -384,13 +436,13 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
384
436
|
VpcEndpointType: 'Interface',
|
|
385
437
|
SubnetIds: [
|
|
386
438
|
{ Ref: 'FriggPrivateSubnet1' },
|
|
387
|
-
{ Ref: 'FriggPrivateSubnet2' }
|
|
439
|
+
{ Ref: 'FriggPrivateSubnet2' },
|
|
388
440
|
],
|
|
389
441
|
SecurityGroupIds: [
|
|
390
|
-
{ Ref: 'FriggVPCEndpointSecurityGroup' }
|
|
442
|
+
{ Ref: 'FriggVPCEndpointSecurityGroup' },
|
|
391
443
|
],
|
|
392
|
-
PrivateDnsEnabled: true
|
|
393
|
-
}
|
|
444
|
+
PrivateDnsEnabled: true,
|
|
445
|
+
},
|
|
394
446
|
};
|
|
395
447
|
}
|
|
396
448
|
|
|
@@ -399,17 +451,16 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
399
451
|
Type: 'AWS::EC2::VPCEndpoint',
|
|
400
452
|
Properties: {
|
|
401
453
|
VpcId: { Ref: 'FriggVPC' },
|
|
402
|
-
ServiceName:
|
|
454
|
+
ServiceName:
|
|
455
|
+
'com.amazonaws.${self:provider.region}.secretsmanager',
|
|
403
456
|
VpcEndpointType: 'Interface',
|
|
404
457
|
SubnetIds: [
|
|
405
458
|
{ Ref: 'FriggPrivateSubnet1' },
|
|
406
|
-
{ Ref: 'FriggPrivateSubnet2' }
|
|
459
|
+
{ Ref: 'FriggPrivateSubnet2' },
|
|
407
460
|
],
|
|
408
|
-
SecurityGroupIds: [
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
PrivateDnsEnabled: true
|
|
412
|
-
}
|
|
461
|
+
SecurityGroupIds: [{ Ref: 'FriggVPCEndpointSecurityGroup' }],
|
|
462
|
+
PrivateDnsEnabled: true,
|
|
463
|
+
},
|
|
413
464
|
};
|
|
414
465
|
|
|
415
466
|
// Security Group for VPC Endpoints
|
|
@@ -423,14 +474,19 @@ const createVPCInfrastructure = (AppDefinition) => {
|
|
|
423
474
|
IpProtocol: 'tcp',
|
|
424
475
|
FromPort: 443,
|
|
425
476
|
ToPort: 443,
|
|
426
|
-
SourceSecurityGroupId: {
|
|
427
|
-
|
|
428
|
-
|
|
477
|
+
SourceSecurityGroupId: {
|
|
478
|
+
Ref: 'FriggLambdaSecurityGroup',
|
|
479
|
+
},
|
|
480
|
+
Description: 'HTTPS from Lambda',
|
|
481
|
+
},
|
|
429
482
|
],
|
|
430
483
|
Tags: [
|
|
431
|
-
{
|
|
432
|
-
|
|
433
|
-
|
|
484
|
+
{
|
|
485
|
+
Key: 'Name',
|
|
486
|
+
Value: '${self:service}-${self:provider.stage}-vpc-endpoint-sg',
|
|
487
|
+
},
|
|
488
|
+
],
|
|
489
|
+
},
|
|
434
490
|
};
|
|
435
491
|
}
|
|
436
492
|
|
|
@@ -456,7 +512,9 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
456
512
|
|
|
457
513
|
// Run AWS discovery if needed
|
|
458
514
|
if (shouldRunDiscovery(AppDefinition)) {
|
|
459
|
-
console.log(
|
|
515
|
+
console.log(
|
|
516
|
+
'🔍 Running AWS resource discovery for serverless template...'
|
|
517
|
+
);
|
|
460
518
|
try {
|
|
461
519
|
const region = process.env.AWS_REGION || 'us-east-1';
|
|
462
520
|
const discovery = new AWSDiscovery(region);
|
|
@@ -464,7 +522,7 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
464
522
|
const config = {
|
|
465
523
|
vpc: AppDefinition.vpc || {},
|
|
466
524
|
encryption: AppDefinition.encryption || {},
|
|
467
|
-
ssm: AppDefinition.ssm || {}
|
|
525
|
+
ssm: AppDefinition.ssm || {},
|
|
468
526
|
};
|
|
469
527
|
|
|
470
528
|
discoveredResources = await discovery.discoverResources(config);
|
|
@@ -473,14 +531,23 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
473
531
|
if (discoveredResources.defaultVpcId) {
|
|
474
532
|
console.log(` VPC: ${discoveredResources.defaultVpcId}`);
|
|
475
533
|
}
|
|
476
|
-
if (
|
|
477
|
-
|
|
534
|
+
if (
|
|
535
|
+
discoveredResources.privateSubnetId1 &&
|
|
536
|
+
discoveredResources.privateSubnetId2
|
|
537
|
+
) {
|
|
538
|
+
console.log(
|
|
539
|
+
` Subnets: ${discoveredResources.privateSubnetId1}, ${discoveredResources.privateSubnetId2}`
|
|
540
|
+
);
|
|
478
541
|
}
|
|
479
542
|
if (discoveredResources.defaultSecurityGroupId) {
|
|
480
|
-
console.log(
|
|
543
|
+
console.log(
|
|
544
|
+
` Security Group: ${discoveredResources.defaultSecurityGroupId}`
|
|
545
|
+
);
|
|
481
546
|
}
|
|
482
547
|
if (discoveredResources.defaultKmsKeyId) {
|
|
483
|
-
console.log(
|
|
548
|
+
console.log(
|
|
549
|
+
` KMS Key: ${discoveredResources.defaultKmsKeyId}`
|
|
550
|
+
);
|
|
484
551
|
}
|
|
485
552
|
} catch (error) {
|
|
486
553
|
console.error('❌ AWS discovery failed:', error.message);
|
|
@@ -493,7 +560,11 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
493
560
|
service: AppDefinition.name || 'create-frigg-app',
|
|
494
561
|
package: {
|
|
495
562
|
individually: true,
|
|
496
|
-
exclude: [
|
|
563
|
+
exclude: [
|
|
564
|
+
'!**/node_modules/aws-sdk/**',
|
|
565
|
+
'!**/node_modules/@aws-sdk/**',
|
|
566
|
+
'!package.json',
|
|
567
|
+
],
|
|
497
568
|
},
|
|
498
569
|
useDotenv: true,
|
|
499
570
|
provider: {
|
|
@@ -505,14 +576,36 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
505
576
|
environment: {
|
|
506
577
|
STAGE: '${opt:stage, "dev"}',
|
|
507
578
|
AWS_NODEJS_CONNECTION_REUSE_ENABLED: 1,
|
|
579
|
+
// Pass through all environment variables from the deployment process
|
|
580
|
+
...process.env,
|
|
508
581
|
// Add discovered resources to environment if available
|
|
509
|
-
...(discoveredResources.defaultVpcId && {
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
...(discoveredResources.
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
582
|
+
...(discoveredResources.defaultVpcId && {
|
|
583
|
+
AWS_DISCOVERY_VPC_ID: discoveredResources.defaultVpcId,
|
|
584
|
+
}),
|
|
585
|
+
...(discoveredResources.defaultSecurityGroupId && {
|
|
586
|
+
AWS_DISCOVERY_SECURITY_GROUP_ID:
|
|
587
|
+
discoveredResources.defaultSecurityGroupId,
|
|
588
|
+
}),
|
|
589
|
+
...(discoveredResources.privateSubnetId1 && {
|
|
590
|
+
AWS_DISCOVERY_SUBNET_ID_1:
|
|
591
|
+
discoveredResources.privateSubnetId1,
|
|
592
|
+
}),
|
|
593
|
+
...(discoveredResources.privateSubnetId2 && {
|
|
594
|
+
AWS_DISCOVERY_SUBNET_ID_2:
|
|
595
|
+
discoveredResources.privateSubnetId2,
|
|
596
|
+
}),
|
|
597
|
+
...(discoveredResources.publicSubnetId && {
|
|
598
|
+
AWS_DISCOVERY_PUBLIC_SUBNET_ID:
|
|
599
|
+
discoveredResources.publicSubnetId,
|
|
600
|
+
}),
|
|
601
|
+
...(discoveredResources.defaultRouteTableId && {
|
|
602
|
+
AWS_DISCOVERY_ROUTE_TABLE_ID:
|
|
603
|
+
discoveredResources.defaultRouteTableId,
|
|
604
|
+
}),
|
|
605
|
+
...(discoveredResources.defaultKmsKeyId && {
|
|
606
|
+
AWS_DISCOVERY_KMS_KEY_ID:
|
|
607
|
+
discoveredResources.defaultKmsKeyId,
|
|
608
|
+
}),
|
|
516
609
|
},
|
|
517
610
|
iamRoleStatements: [
|
|
518
611
|
{
|
|
@@ -528,22 +621,22 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
528
621
|
'sqs:SendMessage',
|
|
529
622
|
'sqs:SendMessageBatch',
|
|
530
623
|
'sqs:GetQueueUrl',
|
|
531
|
-
'sqs:GetQueueAttributes'
|
|
624
|
+
'sqs:GetQueueAttributes',
|
|
532
625
|
],
|
|
533
626
|
Resource: [
|
|
534
627
|
{
|
|
535
|
-
'Fn::GetAtt': ['InternalErrorQueue', 'Arn']
|
|
628
|
+
'Fn::GetAtt': ['InternalErrorQueue', 'Arn'],
|
|
536
629
|
},
|
|
537
630
|
{
|
|
538
631
|
'Fn::Join': [
|
|
539
632
|
':',
|
|
540
633
|
[
|
|
541
|
-
'arn:aws:sqs:${self:provider.region}:*:${self:service}--${self:provider.stage}-*Queue'
|
|
542
|
-
]
|
|
543
|
-
]
|
|
544
|
-
}
|
|
634
|
+
'arn:aws:sqs:${self:provider.region}:*:${self:service}--${self:provider.stage}-*Queue',
|
|
635
|
+
],
|
|
636
|
+
],
|
|
637
|
+
},
|
|
545
638
|
],
|
|
546
|
-
}
|
|
639
|
+
},
|
|
547
640
|
],
|
|
548
641
|
httpApi: {
|
|
549
642
|
payload: '2.0',
|
|
@@ -555,7 +648,7 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
555
648
|
},
|
|
556
649
|
name: '${opt:stage, "dev"}-${self:service}',
|
|
557
650
|
disableDefaultEndpoint: false,
|
|
558
|
-
}
|
|
651
|
+
},
|
|
559
652
|
},
|
|
560
653
|
plugins: [
|
|
561
654
|
'serverless-jetpack',
|
|
@@ -585,7 +678,8 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
585
678
|
},
|
|
586
679
|
functions: {
|
|
587
680
|
auth: {
|
|
588
|
-
handler:
|
|
681
|
+
handler:
|
|
682
|
+
'node_modules/@friggframework/core/handlers/routers/auth.handler',
|
|
589
683
|
events: [
|
|
590
684
|
{
|
|
591
685
|
httpApi: {
|
|
@@ -608,7 +702,8 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
608
702
|
],
|
|
609
703
|
},
|
|
610
704
|
user: {
|
|
611
|
-
handler:
|
|
705
|
+
handler:
|
|
706
|
+
'node_modules/@friggframework/core/handlers/routers/user.handler',
|
|
612
707
|
events: [
|
|
613
708
|
{
|
|
614
709
|
httpApi: {
|
|
@@ -619,7 +714,8 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
619
714
|
],
|
|
620
715
|
},
|
|
621
716
|
health: {
|
|
622
|
-
handler:
|
|
717
|
+
handler:
|
|
718
|
+
'node_modules/@friggframework/core/handlers/routers/health.handler',
|
|
623
719
|
events: [
|
|
624
720
|
{
|
|
625
721
|
httpApi: {
|
|
@@ -723,23 +819,28 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
723
819
|
};
|
|
724
820
|
|
|
725
821
|
// KMS Configuration based on App Definition
|
|
726
|
-
if (
|
|
822
|
+
if (
|
|
823
|
+
AppDefinition.encryption?.useDefaultKMSForFieldLevelEncryption === true
|
|
824
|
+
) {
|
|
727
825
|
// Check if a KMS key was discovered
|
|
728
826
|
if (discoveredResources.defaultKmsKeyId) {
|
|
729
827
|
// Use the existing discovered KMS key
|
|
730
|
-
console.log(
|
|
731
|
-
|
|
828
|
+
console.log(
|
|
829
|
+
`Using existing KMS key: ${discoveredResources.defaultKmsKeyId}`
|
|
830
|
+
);
|
|
831
|
+
|
|
732
832
|
definition.provider.iamRoleStatements.push({
|
|
733
833
|
Effect: 'Allow',
|
|
734
834
|
Action: ['kms:GenerateDataKey', 'kms:Decrypt'],
|
|
735
|
-
Resource: [discoveredResources.defaultKmsKeyId]
|
|
835
|
+
Resource: [discoveredResources.defaultKmsKeyId],
|
|
736
836
|
});
|
|
737
837
|
|
|
738
|
-
definition.provider.environment.KMS_KEY_ARN =
|
|
838
|
+
definition.provider.environment.KMS_KEY_ARN =
|
|
839
|
+
discoveredResources.defaultKmsKeyId;
|
|
739
840
|
} else {
|
|
740
841
|
// No existing key found, provision a dedicated KMS key
|
|
741
842
|
console.log('No existing KMS key found, creating a new one...');
|
|
742
|
-
|
|
843
|
+
|
|
743
844
|
definition.resources.Resources.FriggKMSKey = {
|
|
744
845
|
Type: 'AWS::KMS::Key',
|
|
745
846
|
Properties: {
|
|
@@ -750,29 +851,38 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
750
851
|
{
|
|
751
852
|
Sid: 'AllowRootAccountAdmin',
|
|
752
853
|
Effect: 'Allow',
|
|
753
|
-
Principal: {
|
|
854
|
+
Principal: {
|
|
855
|
+
AWS: {
|
|
856
|
+
'Fn::Sub':
|
|
857
|
+
'arn:aws:iam::${AWS::AccountId}:root',
|
|
858
|
+
},
|
|
859
|
+
},
|
|
754
860
|
Action: 'kms:*',
|
|
755
|
-
Resource: '*'
|
|
756
|
-
}
|
|
757
|
-
]
|
|
758
|
-
}
|
|
759
|
-
}
|
|
861
|
+
Resource: '*',
|
|
862
|
+
},
|
|
863
|
+
],
|
|
864
|
+
},
|
|
865
|
+
},
|
|
760
866
|
};
|
|
761
867
|
|
|
762
868
|
definition.provider.iamRoleStatements.push({
|
|
763
869
|
Effect: 'Allow',
|
|
764
870
|
Action: ['kms:GenerateDataKey', 'kms:Decrypt'],
|
|
765
|
-
Resource: [{ 'Fn::GetAtt': ['FriggKMSKey', 'Arn'] }]
|
|
871
|
+
Resource: [{ 'Fn::GetAtt': ['FriggKMSKey', 'Arn'] }],
|
|
766
872
|
});
|
|
767
873
|
|
|
768
|
-
definition.provider.environment.KMS_KEY_ARN = {
|
|
874
|
+
definition.provider.environment.KMS_KEY_ARN = {
|
|
875
|
+
'Fn::GetAtt': ['FriggKMSKey', 'Arn'],
|
|
876
|
+
};
|
|
769
877
|
}
|
|
770
878
|
|
|
771
879
|
definition.plugins.push('serverless-kms-grants');
|
|
772
880
|
|
|
773
881
|
// Configure KMS grants with discovered default key or environment variable
|
|
774
882
|
definition.custom.kmsGrants = {
|
|
775
|
-
kmsKeyId:
|
|
883
|
+
kmsKeyId:
|
|
884
|
+
discoveredResources.defaultKmsKeyId ||
|
|
885
|
+
'${env:AWS_DISCOVERY_KMS_KEY_ID}',
|
|
776
886
|
};
|
|
777
887
|
}
|
|
778
888
|
|
|
@@ -786,9 +896,9 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
786
896
|
'ec2:DescribeNetworkInterfaces',
|
|
787
897
|
'ec2:DeleteNetworkInterface',
|
|
788
898
|
'ec2:AttachNetworkInterface',
|
|
789
|
-
'ec2:DetachNetworkInterface'
|
|
899
|
+
'ec2:DetachNetworkInterface',
|
|
790
900
|
],
|
|
791
|
-
Resource: '*'
|
|
901
|
+
Resource: '*',
|
|
792
902
|
});
|
|
793
903
|
|
|
794
904
|
// Default approach: Use AWS Discovery to find existing VPC resources
|
|
@@ -801,7 +911,9 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
801
911
|
vpcConfig.securityGroupIds = AppDefinition.vpc.securityGroupIds;
|
|
802
912
|
} else {
|
|
803
913
|
// Use auto-created security group
|
|
804
|
-
vpcConfig.securityGroupIds = [
|
|
914
|
+
vpcConfig.securityGroupIds = [
|
|
915
|
+
{ Ref: 'FriggLambdaSecurityGroup' },
|
|
916
|
+
];
|
|
805
917
|
}
|
|
806
918
|
|
|
807
919
|
if (AppDefinition.vpc.subnetIds) {
|
|
@@ -811,7 +923,7 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
811
923
|
// Use auto-created private subnets
|
|
812
924
|
vpcConfig.subnetIds = [
|
|
813
925
|
{ Ref: 'FriggPrivateSubnet1' },
|
|
814
|
-
{ Ref: 'FriggPrivateSubnet2' }
|
|
926
|
+
{ Ref: 'FriggPrivateSubnet2' },
|
|
815
927
|
];
|
|
816
928
|
}
|
|
817
929
|
|
|
@@ -825,16 +937,27 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
825
937
|
// Option 2: Use AWS Discovery (default behavior)
|
|
826
938
|
// VPC configuration using discovered or explicitly provided resources
|
|
827
939
|
const vpcConfig = {
|
|
828
|
-
securityGroupIds:
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
[
|
|
833
|
-
|
|
940
|
+
securityGroupIds:
|
|
941
|
+
AppDefinition.vpc.securityGroupIds ||
|
|
942
|
+
(discoveredResources.defaultSecurityGroupId
|
|
943
|
+
? [discoveredResources.defaultSecurityGroupId]
|
|
944
|
+
: []),
|
|
945
|
+
subnetIds:
|
|
946
|
+
AppDefinition.vpc.subnetIds ||
|
|
947
|
+
(discoveredResources.privateSubnetId1 &&
|
|
948
|
+
discoveredResources.privateSubnetId2
|
|
949
|
+
? [
|
|
950
|
+
discoveredResources.privateSubnetId1,
|
|
951
|
+
discoveredResources.privateSubnetId2,
|
|
952
|
+
]
|
|
953
|
+
: []),
|
|
834
954
|
};
|
|
835
955
|
|
|
836
956
|
// Set VPC config for Lambda functions only if we have valid subnet IDs
|
|
837
|
-
if (
|
|
957
|
+
if (
|
|
958
|
+
vpcConfig.subnetIds.length >= 2 &&
|
|
959
|
+
vpcConfig.securityGroupIds.length > 0
|
|
960
|
+
) {
|
|
838
961
|
definition.provider.vpc = vpcConfig;
|
|
839
962
|
|
|
840
963
|
// Check if we have an existing NAT Gateway to use
|
|
@@ -848,22 +971,35 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
848
971
|
Properties: {
|
|
849
972
|
Domain: 'vpc',
|
|
850
973
|
Tags: [
|
|
851
|
-
{
|
|
852
|
-
|
|
853
|
-
|
|
974
|
+
{
|
|
975
|
+
Key: 'Name',
|
|
976
|
+
Value: '${self:service}-${self:provider.stage}-nat-eip',
|
|
977
|
+
},
|
|
978
|
+
],
|
|
979
|
+
},
|
|
854
980
|
};
|
|
855
981
|
}
|
|
856
982
|
|
|
857
983
|
definition.resources.Resources.FriggNATGateway = {
|
|
858
984
|
Type: 'AWS::EC2::NatGateway',
|
|
859
985
|
Properties: {
|
|
860
|
-
AllocationId:
|
|
861
|
-
|
|
862
|
-
|
|
986
|
+
AllocationId:
|
|
987
|
+
discoveredResources.existingElasticIpAllocationId || {
|
|
988
|
+
'Fn::GetAtt': [
|
|
989
|
+
'FriggNATGatewayEIP',
|
|
990
|
+
'AllocationId',
|
|
991
|
+
],
|
|
992
|
+
},
|
|
993
|
+
SubnetId:
|
|
994
|
+
discoveredResources.publicSubnetId ||
|
|
995
|
+
discoveredResources.privateSubnetId1, // Use first discovered subnet if no public subnet found
|
|
863
996
|
Tags: [
|
|
864
|
-
{
|
|
865
|
-
|
|
866
|
-
|
|
997
|
+
{
|
|
998
|
+
Key: 'Name',
|
|
999
|
+
Value: '${self:service}-${self:provider.stage}-nat-gateway',
|
|
1000
|
+
},
|
|
1001
|
+
],
|
|
1002
|
+
},
|
|
867
1003
|
};
|
|
868
1004
|
}
|
|
869
1005
|
|
|
@@ -871,11 +1007,16 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
871
1007
|
definition.resources.Resources.FriggLambdaRouteTable = {
|
|
872
1008
|
Type: 'AWS::EC2::RouteTable',
|
|
873
1009
|
Properties: {
|
|
874
|
-
VpcId: discoveredResources.defaultVpcId || {
|
|
1010
|
+
VpcId: discoveredResources.defaultVpcId || {
|
|
1011
|
+
Ref: 'FriggVPC',
|
|
1012
|
+
},
|
|
875
1013
|
Tags: [
|
|
876
|
-
{
|
|
877
|
-
|
|
878
|
-
|
|
1014
|
+
{
|
|
1015
|
+
Key: 'Name',
|
|
1016
|
+
Value: '${self:service}-${self:provider.stage}-lambda-rt',
|
|
1017
|
+
},
|
|
1018
|
+
],
|
|
1019
|
+
},
|
|
879
1020
|
};
|
|
880
1021
|
|
|
881
1022
|
definition.resources.Resources.FriggNATRoute = {
|
|
@@ -883,8 +1024,11 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
883
1024
|
Properties: {
|
|
884
1025
|
RouteTableId: { Ref: 'FriggLambdaRouteTable' },
|
|
885
1026
|
DestinationCidrBlock: '0.0.0.0/0',
|
|
886
|
-
NatGatewayId:
|
|
887
|
-
|
|
1027
|
+
NatGatewayId:
|
|
1028
|
+
discoveredResources.existingNatGatewayId || {
|
|
1029
|
+
Ref: 'FriggNATGateway',
|
|
1030
|
+
},
|
|
1031
|
+
},
|
|
888
1032
|
};
|
|
889
1033
|
|
|
890
1034
|
// Associate Lambda subnets with NAT Gateway route table
|
|
@@ -892,16 +1036,16 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
892
1036
|
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
|
893
1037
|
Properties: {
|
|
894
1038
|
SubnetId: vpcConfig.subnetIds[0],
|
|
895
|
-
RouteTableId: { Ref: 'FriggLambdaRouteTable' }
|
|
896
|
-
}
|
|
1039
|
+
RouteTableId: { Ref: 'FriggLambdaRouteTable' },
|
|
1040
|
+
},
|
|
897
1041
|
};
|
|
898
1042
|
|
|
899
1043
|
definition.resources.Resources.FriggSubnet2RouteAssociation = {
|
|
900
1044
|
Type: 'AWS::EC2::SubnetRouteTableAssociation',
|
|
901
1045
|
Properties: {
|
|
902
1046
|
SubnetId: vpcConfig.subnetIds[1],
|
|
903
|
-
RouteTableId: { Ref: 'FriggLambdaRouteTable' }
|
|
904
|
-
}
|
|
1047
|
+
RouteTableId: { Ref: 'FriggLambdaRouteTable' },
|
|
1048
|
+
},
|
|
905
1049
|
};
|
|
906
1050
|
|
|
907
1051
|
// Add VPC endpoints for AWS service optimization (optional but recommended)
|
|
@@ -910,116 +1054,130 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
910
1054
|
Type: 'AWS::EC2::VPCEndpoint',
|
|
911
1055
|
Properties: {
|
|
912
1056
|
VpcId: discoveredResources.defaultVpcId,
|
|
913
|
-
ServiceName:
|
|
1057
|
+
ServiceName:
|
|
1058
|
+
'com.amazonaws.${self:provider.region}.s3',
|
|
914
1059
|
VpcEndpointType: 'Gateway',
|
|
915
|
-
RouteTableIds: [{ Ref: 'FriggLambdaRouteTable' }]
|
|
916
|
-
}
|
|
1060
|
+
RouteTableIds: [{ Ref: 'FriggLambdaRouteTable' }],
|
|
1061
|
+
},
|
|
917
1062
|
};
|
|
918
1063
|
|
|
919
1064
|
definition.resources.Resources.VPCEndpointDynamoDB = {
|
|
920
1065
|
Type: 'AWS::EC2::VPCEndpoint',
|
|
921
1066
|
Properties: {
|
|
922
1067
|
VpcId: discoveredResources.defaultVpcId,
|
|
923
|
-
ServiceName:
|
|
1068
|
+
ServiceName:
|
|
1069
|
+
'com.amazonaws.${self:provider.region}.dynamodb',
|
|
924
1070
|
VpcEndpointType: 'Gateway',
|
|
925
|
-
RouteTableIds: [{ Ref: 'FriggLambdaRouteTable' }]
|
|
926
|
-
}
|
|
1071
|
+
RouteTableIds: [{ Ref: 'FriggLambdaRouteTable' }],
|
|
1072
|
+
},
|
|
927
1073
|
};
|
|
928
1074
|
}
|
|
929
1075
|
}
|
|
930
1076
|
}
|
|
931
1077
|
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
1078
|
+
// SSM Parameter Store Configuration based on App Definition
|
|
1079
|
+
if (AppDefinition.ssm?.enable === true) {
|
|
1080
|
+
// Add AWS Parameters and Secrets Lambda Extension layer
|
|
1081
|
+
definition.provider.layers = [
|
|
1082
|
+
'arn:aws:lambda:${self:provider.region}:177933569100:layer:AWS-Parameters-and-Secrets-Lambda-Extension:11',
|
|
1083
|
+
];
|
|
938
1084
|
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
1085
|
+
// Add SSM IAM permissions
|
|
1086
|
+
definition.provider.iamRoleStatements.push({
|
|
1087
|
+
Effect: 'Allow',
|
|
1088
|
+
Action: [
|
|
1089
|
+
'ssm:GetParameter',
|
|
1090
|
+
'ssm:GetParameters',
|
|
1091
|
+
'ssm:GetParametersByPath',
|
|
1092
|
+
],
|
|
1093
|
+
Resource: [
|
|
1094
|
+
'arn:aws:ssm:${self:provider.region}:*:parameter/${self:service}/${self:provider.stage}/*',
|
|
1095
|
+
],
|
|
1096
|
+
});
|
|
951
1097
|
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1098
|
+
// Add environment variable for SSM parameter prefix
|
|
1099
|
+
definition.provider.environment.SSM_PARAMETER_PREFIX =
|
|
1100
|
+
'/${self:service}/${self:provider.stage}';
|
|
1101
|
+
}
|
|
955
1102
|
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
1103
|
+
// Add integration-specific functions and resources
|
|
1104
|
+
if (
|
|
1105
|
+
AppDefinition.integrations &&
|
|
1106
|
+
Array.isArray(AppDefinition.integrations)
|
|
1107
|
+
) {
|
|
1108
|
+
for (const integration of AppDefinition.integrations) {
|
|
1109
|
+
if (
|
|
1110
|
+
!integration ||
|
|
1111
|
+
!integration.Definition ||
|
|
1112
|
+
!integration.Definition.name
|
|
1113
|
+
) {
|
|
1114
|
+
throw new Error(
|
|
1115
|
+
'Invalid integration: missing Definition or name'
|
|
1116
|
+
);
|
|
1117
|
+
}
|
|
1118
|
+
const integrationName = integration.Definition.name;
|
|
963
1119
|
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1120
|
+
// Add function for the integration
|
|
1121
|
+
definition.functions[integrationName] = {
|
|
1122
|
+
handler: `node_modules/@friggframework/core/handlers/routers/integration-defined-routers.handlers.${integrationName}.handler`,
|
|
1123
|
+
events: [
|
|
1124
|
+
{
|
|
1125
|
+
httpApi: {
|
|
1126
|
+
path: `/api/${integrationName}-integration/{proxy+}`,
|
|
1127
|
+
method: 'ANY',
|
|
1128
|
+
},
|
|
972
1129
|
},
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
};
|
|
1130
|
+
],
|
|
1131
|
+
};
|
|
976
1132
|
|
|
977
|
-
|
|
978
|
-
|
|
1133
|
+
// Add SQS Queue for the integration
|
|
1134
|
+
const queueReference = `${
|
|
1135
|
+
integrationName.charAt(0).toUpperCase() +
|
|
1136
|
+
integrationName.slice(1)
|
|
979
1137
|
}Queue`;
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
1138
|
+
const queueName = `\${self:service}--\${self:provider.stage}-${queueReference}`;
|
|
1139
|
+
definition.resources.Resources[queueReference] = {
|
|
1140
|
+
Type: 'AWS::SQS::Queue',
|
|
1141
|
+
Properties: {
|
|
1142
|
+
QueueName: `\${self:custom.${queueReference}}`,
|
|
1143
|
+
MessageRetentionPeriod: 60,
|
|
1144
|
+
VisibilityTimeout: 1800, // 30 minutes
|
|
1145
|
+
RedrivePolicy: {
|
|
1146
|
+
maxReceiveCount: 1,
|
|
1147
|
+
deadLetterTargetArn: {
|
|
1148
|
+
'Fn::GetAtt': ['InternalErrorQueue', 'Arn'],
|
|
1149
|
+
},
|
|
991
1150
|
},
|
|
992
1151
|
},
|
|
993
|
-
}
|
|
994
|
-
};
|
|
1152
|
+
};
|
|
995
1153
|
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1154
|
+
// Add Queue Worker for the integration
|
|
1155
|
+
const queueWorkerName = `${integrationName}QueueWorker`;
|
|
1156
|
+
definition.functions[queueWorkerName] = {
|
|
1157
|
+
handler: `node_modules/@friggframework/core/handlers/workers/integration-defined-workers.handlers.${integrationName}.queueWorker`,
|
|
1158
|
+
reservedConcurrency: 5,
|
|
1159
|
+
events: [
|
|
1160
|
+
{
|
|
1161
|
+
sqs: {
|
|
1162
|
+
arn: {
|
|
1163
|
+
'Fn::GetAtt': [queueReference, 'Arn'],
|
|
1164
|
+
},
|
|
1165
|
+
batchSize: 1,
|
|
1006
1166
|
},
|
|
1007
|
-
batchSize: 1,
|
|
1008
1167
|
},
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
};
|
|
1168
|
+
],
|
|
1169
|
+
timeout: 600,
|
|
1170
|
+
};
|
|
1013
1171
|
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1172
|
+
// Add Queue URL for the integration to the ENVironment variables
|
|
1173
|
+
definition.provider.environment = {
|
|
1174
|
+
...definition.provider.environment,
|
|
1175
|
+
[`${integrationName.toUpperCase()}_QUEUE_URL`]: {
|
|
1176
|
+
Ref: queueReference,
|
|
1177
|
+
},
|
|
1178
|
+
};
|
|
1021
1179
|
|
|
1022
|
-
|
|
1180
|
+
definition.custom[queueReference] = queueName;
|
|
1023
1181
|
}
|
|
1024
1182
|
}
|
|
1025
1183
|
|
|
@@ -1029,7 +1187,8 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
1029
1187
|
// Add websocket function if enabled
|
|
1030
1188
|
if (AppDefinition.websockets?.enable === true) {
|
|
1031
1189
|
definition.functions.defaultWebsocket = {
|
|
1032
|
-
handler:
|
|
1190
|
+
handler:
|
|
1191
|
+
'node_modules/@friggframework/core/handlers/routers/websocket.handler',
|
|
1033
1192
|
events: [
|
|
1034
1193
|
{
|
|
1035
1194
|
websocket: {
|
|
@@ -1056,7 +1215,8 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
1056
1215
|
// Add websocket function if enabled
|
|
1057
1216
|
if (AppDefinition.websockets?.enable === true) {
|
|
1058
1217
|
definition.functions.defaultWebsocket = {
|
|
1059
|
-
handler:
|
|
1218
|
+
handler:
|
|
1219
|
+
'node_modules/@friggframework/core/handlers/routers/websocket.handler',
|
|
1060
1220
|
events: [
|
|
1061
1221
|
{
|
|
1062
1222
|
websocket: {
|
|
@@ -1084,7 +1244,8 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
1084
1244
|
// Add websocket function if enabled
|
|
1085
1245
|
if (AppDefinition.websockets?.enable === true) {
|
|
1086
1246
|
definition.functions.defaultWebsocket = {
|
|
1087
|
-
handler:
|
|
1247
|
+
handler:
|
|
1248
|
+
'node_modules/@friggframework/core/handlers/routers/websocket.handler',
|
|
1088
1249
|
events: [
|
|
1089
1250
|
{
|
|
1090
1251
|
websocket: {
|
|
@@ -1114,4 +1275,4 @@ const composeServerlessDefinition = async (AppDefinition) => {
|
|
|
1114
1275
|
return definition;
|
|
1115
1276
|
};
|
|
1116
1277
|
|
|
1117
|
-
module.exports = { composeServerlessDefinition };
|
|
1278
|
+
module.exports = { composeServerlessDefinition };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@friggframework/devtools",
|
|
3
3
|
"prettier": "@friggframework/prettier-config",
|
|
4
|
-
"version": "2.0.0--canary.413.
|
|
4
|
+
"version": "2.0.0--canary.413.ad943eb.0",
|
|
5
5
|
"dependencies": {
|
|
6
6
|
"@aws-sdk/client-ec2": "^3.835.0",
|
|
7
7
|
"@aws-sdk/client-kms": "^3.835.0",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"@babel/eslint-parser": "^7.18.9",
|
|
10
10
|
"@babel/parser": "^7.25.3",
|
|
11
11
|
"@babel/traverse": "^7.25.3",
|
|
12
|
-
"@friggframework/schemas": "2.0.0--canary.413.
|
|
13
|
-
"@friggframework/test": "2.0.0--canary.413.
|
|
12
|
+
"@friggframework/schemas": "2.0.0--canary.413.ad943eb.0",
|
|
13
|
+
"@friggframework/test": "2.0.0--canary.413.ad943eb.0",
|
|
14
14
|
"@hapi/boom": "^10.0.1",
|
|
15
15
|
"@inquirer/prompts": "^5.3.8",
|
|
16
16
|
"axios": "^1.7.2",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"serverless-http": "^2.7.0"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
|
-
"@friggframework/eslint-config": "2.0.0--canary.413.
|
|
36
|
-
"@friggframework/prettier-config": "2.0.0--canary.413.
|
|
35
|
+
"@friggframework/eslint-config": "2.0.0--canary.413.ad943eb.0",
|
|
36
|
+
"@friggframework/prettier-config": "2.0.0--canary.413.ad943eb.0",
|
|
37
37
|
"prettier": "^2.7.1",
|
|
38
38
|
"serverless": "3.39.0",
|
|
39
39
|
"serverless-dotenv-plugin": "^6.0.0",
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"publishConfig": {
|
|
66
66
|
"access": "public"
|
|
67
67
|
},
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "ad943ebba8f61f92527cfa2fb35b54a1e5526e4e"
|
|
69
69
|
}
|