@awsless/cli 0.0.30 → 0.0.32
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/dist/app.json +1 -1
- package/dist/app.stage.json +1 -1
- package/dist/bin.js +1447 -832
- package/dist/build-json-schema.js +336 -343
- package/dist/prebuild/icon/bundle.zip +0 -0
- package/dist/prebuild/image/bundle.zip +0 -0
- package/dist/prebuild/on-error-log/bundle.zip +0 -0
- package/dist/prebuild/on-failure/bundle.zip +0 -0
- package/dist/prebuild/pubsub-publisher/HASH +1 -0
- package/dist/prebuild/pubsub-publisher/bundle.zip +0 -0
- package/dist/prebuild/pubsub-server/HASH +1 -0
- package/dist/prebuild/pubsub-server/index.mjs +236 -0
- package/dist/prebuild/rpc/bundle.zip +0 -0
- package/dist/prebuild.js +24 -2
- package/dist/stack.json +1 -1
- package/dist/stack.stage.json +1 -1
- package/package.json +16 -15
package/dist/bin.js
CHANGED
|
@@ -1179,7 +1179,7 @@ var LogRetentionSchema = DurationSchema.refine(
|
|
|
1179
1179
|
(duration) => {
|
|
1180
1180
|
return validLogRetentionDays.includes(toDays(duration));
|
|
1181
1181
|
},
|
|
1182
|
-
`Invalid log retention. Valid days are: ${validLogRetentionDays.map((
|
|
1182
|
+
`Invalid log retention. Valid days are: ${validLogRetentionDays.map((days13) => `${days13}`).join(", ")}`
|
|
1183
1183
|
).describe("The log retention duration.");
|
|
1184
1184
|
var LogSchema = z15.union([
|
|
1185
1185
|
z15.boolean().transform((enabled) => ({ retention: enabled ? days(7) : days(0) })),
|
|
@@ -1359,140 +1359,159 @@ var OnFailureDefaultSchema = z19.union([
|
|
|
1359
1359
|
);
|
|
1360
1360
|
|
|
1361
1361
|
// src/feature/pubsub/schema.ts
|
|
1362
|
+
import { days as days4 } from "@awsless/duration";
|
|
1363
|
+
import { z as z22 } from "zod";
|
|
1364
|
+
|
|
1365
|
+
// src/feature/instance/schema.ts
|
|
1366
|
+
import { days as days2, toDays as toDays2 } from "@awsless/duration";
|
|
1367
|
+
import { toMebibytes } from "@awsless/size";
|
|
1362
1368
|
import { z as z20 } from "zod";
|
|
1363
|
-
var
|
|
1364
|
-
|
|
1365
|
-
ResourceIdSchema,
|
|
1366
|
-
z20.object({
|
|
1367
|
-
auth: FunctionSchema,
|
|
1368
|
-
domain: DomainSchema.optional(),
|
|
1369
|
-
subDomain: z20.string().optional()
|
|
1370
|
-
// auth: z.union([
|
|
1371
|
-
// ResourceIdSchema,
|
|
1372
|
-
// z.object({
|
|
1373
|
-
// authorizer: FunctionSchema,
|
|
1374
|
-
// // ttl: AuthorizerTtl.default('1 hour'),
|
|
1375
|
-
// }),
|
|
1376
|
-
// ]),
|
|
1377
|
-
// policy: z
|
|
1378
|
-
// .object({
|
|
1379
|
-
// publish: z.array(z.string()).optional(),
|
|
1380
|
-
// subscribe: z.array(z.string()).optional(),
|
|
1381
|
-
// })
|
|
1382
|
-
// .optional(),
|
|
1383
|
-
})
|
|
1384
|
-
).optional().describe("Define the pubsub subscriber in your stack.");
|
|
1385
|
-
var RetryAttemptsSchema2 = z20.number().int().min(0).max(2).describe(
|
|
1386
|
-
"The maximum number of times to retry when the function returns an error. You can specify a number from 0 to 2."
|
|
1369
|
+
var CpuSchema = z20.union([z20.literal(0.25), z20.literal(0.5), z20.literal(1), z20.literal(2), z20.literal(4), z20.literal(8), z20.literal(16)]).transform((v) => `${v} vCPU`).describe(
|
|
1370
|
+
"The number of virtual CPU units (vCPU) used by the instance. Valid values: 0.25, 0.5, 1, 2, 4, 8, 16 vCPU."
|
|
1387
1371
|
);
|
|
1388
|
-
var
|
|
1389
|
-
|
|
1372
|
+
var validMemorySize = [
|
|
1373
|
+
// 0.25 vCPU
|
|
1374
|
+
512,
|
|
1375
|
+
1024,
|
|
1376
|
+
2048,
|
|
1377
|
+
// 0.5 vCPU
|
|
1378
|
+
1024,
|
|
1379
|
+
2048,
|
|
1380
|
+
3072,
|
|
1381
|
+
4096,
|
|
1382
|
+
// 1 vCPU
|
|
1383
|
+
2048,
|
|
1384
|
+
3072,
|
|
1385
|
+
4096,
|
|
1386
|
+
5120,
|
|
1387
|
+
6144,
|
|
1388
|
+
7168,
|
|
1389
|
+
8192,
|
|
1390
|
+
// 2 vCPU
|
|
1391
|
+
4096,
|
|
1392
|
+
5120,
|
|
1393
|
+
6144,
|
|
1394
|
+
7168,
|
|
1395
|
+
8192,
|
|
1396
|
+
9216,
|
|
1397
|
+
10240,
|
|
1398
|
+
11264,
|
|
1399
|
+
12288,
|
|
1400
|
+
13312,
|
|
1401
|
+
14336,
|
|
1402
|
+
15360,
|
|
1403
|
+
16384
|
|
1404
|
+
];
|
|
1405
|
+
var MemorySizeSchema2 = SizeSchema.refine(
|
|
1406
|
+
(s) => validMemorySize.includes(toMebibytes(s)),
|
|
1407
|
+
`Invalid memory size. Allowed sizes: ${validMemorySize.join(", ")} MiB`
|
|
1408
|
+
).describe("The amount of memory (in MiB) used by the instance. Valid memory values depend on the CPU configuration.");
|
|
1409
|
+
var HealthCheckSchema = z20.object({
|
|
1410
|
+
path: z20.string().describe("The path that the container runs to determine if it is healthy."),
|
|
1411
|
+
interval: DurationSchema.describe("The time period in seconds between each health check execution."),
|
|
1412
|
+
retries: z20.number().int().min(1).max(10).describe(
|
|
1413
|
+
"The number of times to retry a failed health check before the container is considered unhealthy."
|
|
1414
|
+
),
|
|
1415
|
+
startPeriod: DurationSchema.describe(
|
|
1416
|
+
"The optional grace period to provide containers time to bootstrap before failed health checks count towards the maximum number of retries."
|
|
1417
|
+
),
|
|
1418
|
+
timeout: DurationSchema.describe(
|
|
1419
|
+
"The time period in seconds to wait for a health check to succeed before it is considered a failure."
|
|
1420
|
+
)
|
|
1421
|
+
}).describe("The health check command and associated configuration parameters for the container.");
|
|
1422
|
+
var EnvironmentSchema2 = z20.record(z20.string(), z20.string()).optional().describe("Environment variable key-value pairs.");
|
|
1423
|
+
var ArchitectureSchema3 = z20.enum(["x86_64", "arm64"]).describe("The instruction set architecture that the instance supports.");
|
|
1424
|
+
var ActionSchema2 = z20.string();
|
|
1425
|
+
var ActionsSchema2 = z20.union([ActionSchema2.transform((v) => [v]), ActionSchema2.array()]);
|
|
1426
|
+
var ArnSchema2 = z20.string().startsWith("arn:");
|
|
1427
|
+
var WildcardSchema2 = z20.literal("*");
|
|
1428
|
+
var ResourceSchema2 = z20.union([ArnSchema2, WildcardSchema2]);
|
|
1429
|
+
var ResourcesSchema2 = z20.union([ResourceSchema2.transform((v) => [v]), ResourceSchema2.array()]);
|
|
1430
|
+
var PermissionSchema2 = z20.object({
|
|
1431
|
+
effect: z20.enum(["allow", "deny"]).default("allow"),
|
|
1432
|
+
actions: ActionsSchema2,
|
|
1433
|
+
resources: ResourcesSchema2
|
|
1434
|
+
});
|
|
1435
|
+
var PermissionsSchema2 = z20.union([PermissionSchema2.transform((v) => [v]), PermissionSchema2.array()]).describe("Add IAM permissions to your instance.");
|
|
1436
|
+
var DescriptionSchema2 = z20.string().describe("A description of the instance.");
|
|
1437
|
+
var ImageSchema = z20.string().optional().describe("The URL of the container image to use. Default: public.ecr.aws/aws-cli/aws-cli:{architecture}");
|
|
1438
|
+
var validLogRetentionDays2 = [
|
|
1439
|
+
...[1, 3, 5, 7, 14, 30, 60, 90, 120, 150],
|
|
1440
|
+
...[180, 365, 400, 545, 731, 1096, 1827, 2192],
|
|
1441
|
+
...[2557, 2922, 3288, 3653]
|
|
1442
|
+
];
|
|
1443
|
+
var LogRetentionSchema2 = DurationSchema.refine(
|
|
1444
|
+
durationMin(days2(0)),
|
|
1445
|
+
"Minimum log retention is 0 day, which will disable logging."
|
|
1446
|
+
).refine(
|
|
1447
|
+
(duration) => {
|
|
1448
|
+
return validLogRetentionDays2.includes(toDays2(duration));
|
|
1449
|
+
},
|
|
1450
|
+
`Invalid log retention. Valid days are: ${validLogRetentionDays2.map((days13) => `${days13}`).join(", ")}`
|
|
1451
|
+
).describe("The log retention duration.");
|
|
1452
|
+
var LogSchema2 = z20.union([
|
|
1453
|
+
z20.boolean().transform((enabled) => ({ retention: enabled ? days2(7) : days2(0) })),
|
|
1454
|
+
LogRetentionSchema2.transform((retention) => ({ retention })),
|
|
1390
1455
|
z20.object({
|
|
1391
|
-
|
|
1392
|
-
sqlVersion: z20.enum(["2015-10-08", "2016-03-23", "beta"]).default("2016-03-23").describe("The version of the SQL rules engine to use when evaluating the rule."),
|
|
1393
|
-
consumer: FunctionSchema.describe("The consuming lambda function properties."),
|
|
1394
|
-
retryAttempts: RetryAttemptsSchema2.default(2)
|
|
1456
|
+
retention: LogRetentionSchema2.optional()
|
|
1395
1457
|
})
|
|
1396
|
-
).
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
import { days as days2, hours, minutes as minutes2, seconds as seconds2 } from "@awsless/duration";
|
|
1400
|
-
import { kibibytes } from "@awsless/size";
|
|
1401
|
-
import { z as z21 } from "zod";
|
|
1402
|
-
var RetentionPeriodSchema = DurationSchema.refine(durationMin(minutes2(1)), "Minimum retention period is 1 minute").refine(durationMax(days2(14)), "Maximum retention period is 14 days").describe(
|
|
1403
|
-
"The number of seconds that Amazon SQS retains a message. You can specify a duration from 1 minute to 14 days."
|
|
1404
|
-
);
|
|
1405
|
-
var VisibilityTimeoutSchema = DurationSchema.refine(
|
|
1406
|
-
durationMax(hours(12)),
|
|
1407
|
-
"Maximum visibility timeout is 12 hours"
|
|
1408
|
-
).describe(
|
|
1409
|
-
"The length of time during which a message will be unavailable after a message is delivered from the queue. You can specify a duration from 0 to 12 hours."
|
|
1410
|
-
);
|
|
1411
|
-
var ReceiveMessageWaitTimeSchema = DurationSchema.refine(
|
|
1412
|
-
durationMin(seconds2(1)),
|
|
1413
|
-
"Minimum receive message wait time is 1 second"
|
|
1414
|
-
).refine(durationMax(seconds2(20)), "Maximum receive message wait time is 20 seconds").describe("Long-polling wait time. You can specify a duration from 1 to 20 seconds.");
|
|
1415
|
-
var MaxMessageSizeSchema = SizeSchema.refine(sizeMin(kibibytes(1)), "Minimum max message size is 1 KB").refine(sizeMax(kibibytes(256)), "Maximum max message size is 256 KB").describe("Message size limit. You can specify a size from 1 KB to 256 KB.");
|
|
1416
|
-
var BatchSizeSchema = z21.number().int().min(1, "Minimum batch size is 1").max(10, "FIFO queues support a maximum batch size of 10").describe("The maximum number of records per batch. FIFO queues are capped at 10.");
|
|
1417
|
-
var RetryAttemptsSchema3 = z21.number().int().min(0).max(999).describe(
|
|
1418
|
-
"The maximum number of times to retry when the function returns an error. You can specify a number from 0 to 999."
|
|
1419
|
-
);
|
|
1420
|
-
var QueueDefaultSchema = z21.object({
|
|
1421
|
-
retentionPeriod: RetentionPeriodSchema.default("7 days"),
|
|
1422
|
-
visibilityTimeout: VisibilityTimeoutSchema.default("2 minutes"),
|
|
1423
|
-
receiveMessageWaitTime: ReceiveMessageWaitTimeSchema.optional(),
|
|
1424
|
-
maxMessageSize: MaxMessageSizeSchema.default("256 KB"),
|
|
1425
|
-
batchSize: BatchSizeSchema.default(10),
|
|
1426
|
-
retryAttempts: RetryAttemptsSchema3.default(2)
|
|
1427
|
-
}).default({});
|
|
1428
|
-
var QueueSchema = z21.object({
|
|
1429
|
-
consumer: FunctionSchema.optional().describe("The consuming lambda function properties."),
|
|
1430
|
-
retentionPeriod: RetentionPeriodSchema.optional(),
|
|
1431
|
-
visibilityTimeout: VisibilityTimeoutSchema.optional(),
|
|
1432
|
-
receiveMessageWaitTime: ReceiveMessageWaitTimeSchema.optional(),
|
|
1433
|
-
maxMessageSize: MaxMessageSizeSchema.optional(),
|
|
1434
|
-
batchSize: BatchSizeSchema.optional(),
|
|
1435
|
-
retryAttempts: RetryAttemptsSchema3.optional()
|
|
1458
|
+
]).describe("Enable logging to a CloudWatch log group. Providing a duration value will set the log retention time.");
|
|
1459
|
+
var FileCodeSchema2 = z20.object({
|
|
1460
|
+
file: LocalFileSchema.describe("The file path of the instance code.")
|
|
1436
1461
|
});
|
|
1437
|
-
var
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
)
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1462
|
+
var CodeSchema2 = z20.union([
|
|
1463
|
+
LocalFileSchema.transform((file) => ({
|
|
1464
|
+
file
|
|
1465
|
+
})).pipe(FileCodeSchema2),
|
|
1466
|
+
FileCodeSchema2
|
|
1467
|
+
]).describe("Specify the code of your instance.");
|
|
1468
|
+
var StartupCommandSchema = z20.union([z20.string().transform((v) => [v]), z20.string().array()]).describe("Optional shell commands to run before the instance program starts.");
|
|
1469
|
+
var ISchema = z20.object({
|
|
1470
|
+
code: CodeSchema2,
|
|
1471
|
+
description: DescriptionSchema2.optional(),
|
|
1472
|
+
image: ImageSchema.optional(),
|
|
1473
|
+
startupCommand: StartupCommandSchema.optional(),
|
|
1474
|
+
log: LogSchema2.optional(),
|
|
1475
|
+
cpu: CpuSchema.optional(),
|
|
1476
|
+
memorySize: MemorySizeSchema2.optional(),
|
|
1477
|
+
architecture: ArchitectureSchema3.optional(),
|
|
1478
|
+
environment: EnvironmentSchema2.optional(),
|
|
1479
|
+
permissions: PermissionsSchema2.optional(),
|
|
1480
|
+
healthCheck: HealthCheckSchema.optional()
|
|
1481
|
+
// restartPolicy: RestartPolicySchema.optional(),
|
|
1482
|
+
});
|
|
1483
|
+
var InstanceSchema = z20.union([
|
|
1484
|
+
LocalFileSchema.transform((code) => ({
|
|
1485
|
+
code
|
|
1486
|
+
})).pipe(ISchema),
|
|
1487
|
+
ISchema
|
|
1457
1488
|
]);
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
"The REST API route that is comprised by the http method and http path.",
|
|
1473
|
-
"The possible http methods are POST, GET,PUT, DELETE, HEAD, OPTIONS, ANY.",
|
|
1474
|
-
"Example: GET /posts/{id}"
|
|
1475
|
-
].join("\n")
|
|
1476
|
-
),
|
|
1477
|
-
FunctionSchema
|
|
1478
|
-
)
|
|
1479
|
-
).optional().describe("Define routes in your stack for your global REST API.");
|
|
1480
|
-
|
|
1481
|
-
// src/feature/rpc/schema.ts
|
|
1482
|
-
import { minutes as minutes4, seconds as seconds3 } from "@awsless/duration";
|
|
1483
|
-
import { z as z25 } from "zod";
|
|
1489
|
+
var InstancesSchema = z20.record(ResourceIdSchema, InstanceSchema).optional().describe("Define the instances in your stack.");
|
|
1490
|
+
var InstanceDefaultSchema = z20.object({
|
|
1491
|
+
image: ImageSchema.optional(),
|
|
1492
|
+
cpu: CpuSchema.default(0.25),
|
|
1493
|
+
memorySize: MemorySizeSchema2.default("512 MB"),
|
|
1494
|
+
architecture: ArchitectureSchema3.default("arm64"),
|
|
1495
|
+
environment: EnvironmentSchema2.optional(),
|
|
1496
|
+
permissions: PermissionsSchema2.optional(),
|
|
1497
|
+
healthCheck: HealthCheckSchema.optional(),
|
|
1498
|
+
// restartPolicy: RestartPolicySchema.default({ enabled: true }),
|
|
1499
|
+
log: LogSchema2.default(true).transform((log35) => ({
|
|
1500
|
+
retention: log35.retention ?? days2(7)
|
|
1501
|
+
}))
|
|
1502
|
+
}).default({});
|
|
1484
1503
|
|
|
1485
1504
|
// src/feature/router/schema.ts
|
|
1486
|
-
import { days as days3, minutes as
|
|
1487
|
-
import { z as
|
|
1488
|
-
var ErrorResponsePathSchema =
|
|
1505
|
+
import { days as days3, minutes as minutes2, parse as parse3 } from "@awsless/duration";
|
|
1506
|
+
import { z as z21 } from "zod";
|
|
1507
|
+
var ErrorResponsePathSchema = z21.string().describe(
|
|
1489
1508
|
[
|
|
1490
1509
|
"The path to the custom error page that you want to return to the viewer when your origin returns the HTTP status code specified.",
|
|
1491
1510
|
"- We recommend that you store custom error pages in an Amazon S3 bucket.",
|
|
1492
1511
|
"If you store custom error pages on an HTTP server and the server starts to return 5xx errors, CloudFront can't get the files that you want to return to viewers because the origin server is unavailable."
|
|
1493
1512
|
].join("\n")
|
|
1494
1513
|
);
|
|
1495
|
-
var StatusCodeSchema =
|
|
1514
|
+
var StatusCodeSchema = z21.number().int().positive().optional().describe(
|
|
1496
1515
|
[
|
|
1497
1516
|
"The HTTP status code that you want CloudFront to return to the viewer along with the custom error page.",
|
|
1498
1517
|
"There are a variety of reasons that you might want CloudFront to return a status code different from the status code that your origin returned to CloudFront, for example:",
|
|
@@ -1505,26 +1524,26 @@ var StatusCodeSchema = z24.number().int().positive().optional().describe(
|
|
|
1505
1524
|
var MinTTLSchema = DurationSchema.describe(
|
|
1506
1525
|
"The minimum amount of time, that you want to cache the error response. When this time period has elapsed, CloudFront queries your origin to see whether the problem that caused the error has been resolved and the requested object is now available."
|
|
1507
1526
|
);
|
|
1508
|
-
var ErrorResponseSchema =
|
|
1527
|
+
var ErrorResponseSchema = z21.union([
|
|
1509
1528
|
ErrorResponsePathSchema,
|
|
1510
|
-
|
|
1529
|
+
z21.object({
|
|
1511
1530
|
path: ErrorResponsePathSchema,
|
|
1512
1531
|
statusCode: StatusCodeSchema.optional(),
|
|
1513
1532
|
minTTL: MinTTLSchema.optional()
|
|
1514
1533
|
})
|
|
1515
1534
|
]).optional();
|
|
1516
|
-
var
|
|
1517
|
-
var VisibilitySchema =
|
|
1518
|
-
var WafSettingsSchema =
|
|
1519
|
-
rateLimiter:
|
|
1520
|
-
limit:
|
|
1535
|
+
var RouteSchema = z21.string().regex(/^\//, "Route must start with a slash (/)");
|
|
1536
|
+
var VisibilitySchema = z21.boolean().default(false).describe("Whether to enable CloudWatch metrics for the WAF rule.");
|
|
1537
|
+
var WafSettingsSchema = z21.object({
|
|
1538
|
+
rateLimiter: z21.object({
|
|
1539
|
+
limit: z21.number().min(10).max(2e9).default(10).describe(
|
|
1521
1540
|
"The limit on requests during the specified evaluation window for a single aggregation instance for the rate-based rule."
|
|
1522
1541
|
),
|
|
1523
|
-
window:
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1542
|
+
window: z21.union([
|
|
1543
|
+
z21.literal("1 minute"),
|
|
1544
|
+
z21.literal("2 minutes"),
|
|
1545
|
+
z21.literal("5 minutes"),
|
|
1546
|
+
z21.literal("10 minutes")
|
|
1528
1547
|
]).default("5 minutes").transform((v) => parse3(v)).describe(
|
|
1529
1548
|
"The amount of time, in seconds, that AWS WAF should include in its request counts, looking back from the current time."
|
|
1530
1549
|
),
|
|
@@ -1532,39 +1551,39 @@ var WafSettingsSchema = z24.object({
|
|
|
1532
1551
|
}).optional().describe(
|
|
1533
1552
|
"A rate-based rule counts incoming requests and rate limits requests when they are coming at too fast a rate."
|
|
1534
1553
|
),
|
|
1535
|
-
ddosProtection:
|
|
1536
|
-
sensitivity:
|
|
1537
|
-
challenge:
|
|
1538
|
-
block:
|
|
1554
|
+
ddosProtection: z21.object({
|
|
1555
|
+
sensitivity: z21.object({
|
|
1556
|
+
challenge: z21.enum(["low", "medium", "high"]).default("low").transform((v) => v.toUpperCase()).describe("The sensitivity level for challenge requests."),
|
|
1557
|
+
block: z21.enum(["low", "medium", "high"]).default("low").transform((v) => v.toUpperCase()).describe("The sensitivity level for block requests.")
|
|
1539
1558
|
}),
|
|
1540
|
-
exemptUriRegex:
|
|
1559
|
+
exemptUriRegex: z21.string().default("^$"),
|
|
1541
1560
|
visibility: VisibilitySchema
|
|
1542
1561
|
}).optional().describe(
|
|
1543
1562
|
"Provides protection against DDoS attacks targeting the application layer, also known as Layer 7 attacks. Uses 50 WCU."
|
|
1544
1563
|
),
|
|
1545
|
-
botProtection:
|
|
1546
|
-
inspectionLevel:
|
|
1564
|
+
botProtection: z21.object({
|
|
1565
|
+
inspectionLevel: z21.enum(["common", "targeted"]).default("common").transform((v) => v.toUpperCase()),
|
|
1547
1566
|
visibility: VisibilitySchema
|
|
1548
1567
|
}).optional().describe(
|
|
1549
1568
|
"Provides protection against automated bots that can consume excess resources, skew business metrics, cause downtime, or perform malicious activities. Bot Control provides additional visibility through Amazon CloudWatch and generates labels that you can use to control bot traffic to your applications. Uses 50 WCU."
|
|
1550
1569
|
),
|
|
1551
|
-
captchaImmunityTime: DurationSchema.refine(durationMin(
|
|
1570
|
+
captchaImmunityTime: DurationSchema.refine(durationMin(minutes2(1)), "Minimum timeout duration is 1 minute").refine(durationMax(days3(3)), "Maximum timeout duration is 3 days").default("5 minutes").describe(
|
|
1552
1571
|
"The amount of time that a CAPTCHA timestamp is considered valid by AWS WAF. The default setting is 5 minutes."
|
|
1553
1572
|
),
|
|
1554
|
-
challengeImmunityTime: DurationSchema.refine(durationMin(
|
|
1573
|
+
challengeImmunityTime: DurationSchema.refine(durationMin(minutes2(1)), "Minimum timeout duration is 1 minute").refine(durationMax(days3(3)), "Maximum timeout duration is 3 days").default("5 minutes").describe(
|
|
1555
1574
|
"The amount of time that a challenge timestamp is considered valid by AWS WAF. The default setting is 5 minutes."
|
|
1556
1575
|
)
|
|
1557
1576
|
}).describe(
|
|
1558
1577
|
"WAF settings for the router. Each rule consumes Web ACL capacity units (WCUs). The total WCUs for a web ACL can't exceed 5000. Using over 1500 WCUs affects your costs."
|
|
1559
1578
|
);
|
|
1560
|
-
var RouterDefaultSchema =
|
|
1579
|
+
var RouterDefaultSchema = z21.record(
|
|
1561
1580
|
ResourceIdSchema,
|
|
1562
|
-
|
|
1581
|
+
z21.object({
|
|
1563
1582
|
domain: ResourceIdSchema.describe("The domain id to link your Router.").optional(),
|
|
1564
|
-
subDomain:
|
|
1583
|
+
subDomain: z21.string().optional(),
|
|
1565
1584
|
waf: WafSettingsSchema.optional(),
|
|
1566
|
-
geoRestrictions:
|
|
1567
|
-
errors:
|
|
1585
|
+
geoRestrictions: z21.array(z21.string().length(2).toUpperCase()).default([]).describe("Specifies a blacklist of countries that should be blocked."),
|
|
1586
|
+
errors: z21.object({
|
|
1568
1587
|
400: ErrorResponseSchema.describe("Customize a `400 Bad Request` response."),
|
|
1569
1588
|
403: ErrorResponseSchema.describe("Customize a `403 Forbidden` response."),
|
|
1570
1589
|
404: ErrorResponseSchema.describe("Customize a `404 Not Found` response."),
|
|
@@ -1577,26 +1596,26 @@ var RouterDefaultSchema = z24.record(
|
|
|
1577
1596
|
503: ErrorResponseSchema.describe("Customize a `503 Service Unavailable` response."),
|
|
1578
1597
|
504: ErrorResponseSchema.describe("Customize a `504 Gateway Timeout` response.")
|
|
1579
1598
|
}).optional().describe("Customize the error responses for specific HTTP status codes."),
|
|
1580
|
-
cors:
|
|
1581
|
-
override:
|
|
1599
|
+
cors: z21.object({
|
|
1600
|
+
override: z21.boolean().default(false),
|
|
1582
1601
|
maxAge: DurationSchema.default("365 days"),
|
|
1583
|
-
exposeHeaders:
|
|
1584
|
-
credentials:
|
|
1585
|
-
headers:
|
|
1586
|
-
origins:
|
|
1587
|
-
methods:
|
|
1602
|
+
exposeHeaders: z21.string().array().optional(),
|
|
1603
|
+
credentials: z21.boolean().default(false),
|
|
1604
|
+
headers: z21.string().array().default(["*"]),
|
|
1605
|
+
origins: z21.string().array().default(["*"]),
|
|
1606
|
+
methods: z21.enum(["GET", "DELETE", "HEAD", "OPTIONS", "PATCH", "POST", "PUT", "ALL"]).array().default(["ALL"])
|
|
1588
1607
|
}).optional().describe("Specify the cors headers."),
|
|
1589
|
-
passwordAuth:
|
|
1590
|
-
password:
|
|
1608
|
+
passwordAuth: z21.object({
|
|
1609
|
+
password: z21.string().describe("Password.")
|
|
1591
1610
|
}).optional().describe(
|
|
1592
1611
|
[
|
|
1593
1612
|
"Enable password authentication for the router.",
|
|
1594
1613
|
'You can authenicate by adding a "authorization" header with the value "Password [YOUR_PASSWORD]".'
|
|
1595
1614
|
].join("\n")
|
|
1596
1615
|
),
|
|
1597
|
-
basicAuth:
|
|
1598
|
-
username:
|
|
1599
|
-
password:
|
|
1616
|
+
basicAuth: z21.object({
|
|
1617
|
+
username: z21.string().describe("Basic auth username."),
|
|
1618
|
+
password: z21.string().describe("Basic auth password.")
|
|
1600
1619
|
}).optional().describe("Enable basic authentication for the router."),
|
|
1601
1620
|
// security: z
|
|
1602
1621
|
// .object({
|
|
@@ -1643,49 +1662,163 @@ var RouterDefaultSchema = z24.record(
|
|
|
1643
1662
|
// })
|
|
1644
1663
|
// .optional()
|
|
1645
1664
|
// .describe('Specify the security policy.'),
|
|
1646
|
-
cache:
|
|
1647
|
-
cookies:
|
|
1648
|
-
headers:
|
|
1649
|
-
queries:
|
|
1665
|
+
cache: z21.object({
|
|
1666
|
+
cookies: z21.string().array().optional().describe("Specifies the cookies that CloudFront includes in the cache key."),
|
|
1667
|
+
headers: z21.string().array().optional().describe("Specifies the headers that CloudFront includes in the cache key."),
|
|
1668
|
+
queries: z21.string().array().optional().describe("Specifies the query values that CloudFront includes in the cache key.")
|
|
1650
1669
|
}).optional().describe(
|
|
1651
1670
|
"Specifies the cookies, headers, and query values that CloudFront includes in the cache key."
|
|
1652
1671
|
)
|
|
1653
1672
|
})
|
|
1654
1673
|
).optional().describe(`Define the global Router. Backed by AWS CloudFront.`);
|
|
1655
1674
|
|
|
1656
|
-
// src/feature/
|
|
1657
|
-
var
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1675
|
+
// src/feature/pubsub/schema.ts
|
|
1676
|
+
var PubSubDefaultSchema = z22.record(
|
|
1677
|
+
ResourceIdSchema,
|
|
1678
|
+
z22.object({
|
|
1679
|
+
auth: FunctionSchema.describe(
|
|
1680
|
+
"The authorizer that validates the client auth token and returns the allowed topics."
|
|
1681
|
+
),
|
|
1682
|
+
router: ResourceIdSchema.describe("The router id to route pubsub traffic through."),
|
|
1683
|
+
path: RouteSchema.default("/ws").describe("The base path on the router that exposes the pubsub endpoint."),
|
|
1684
|
+
log: LogSchema2.default(true).transform((log35) => ({
|
|
1685
|
+
retention: log35.retention ?? days4(7)
|
|
1686
|
+
}))
|
|
1687
|
+
})
|
|
1688
|
+
).optional().describe("Define the pubsub API for your app. Backed by a websocket server on AWS Fargate.");
|
|
1689
|
+
var PubSubSchema = z22.record(
|
|
1690
|
+
ResourceIdSchema,
|
|
1691
|
+
z22.object({
|
|
1692
|
+
connected: FunctionSchema.optional().describe("Subscribe to the event when a client connects."),
|
|
1693
|
+
disconnected: FunctionSchema.optional().describe("Subscribe to the event when a client disconnects."),
|
|
1694
|
+
subscribed: FunctionSchema.optional().describe(
|
|
1695
|
+
"Subscribe to the event when a client subscribes to topics."
|
|
1696
|
+
),
|
|
1697
|
+
unsubscribed: FunctionSchema.optional().describe(
|
|
1698
|
+
"Subscribe to the event when a client unsubscribes from topics."
|
|
1699
|
+
)
|
|
1700
|
+
})
|
|
1701
|
+
).optional().describe("Define the pubsub event listeners in your stack.");
|
|
1702
|
+
var pubsubEventTypes = ["connected", "disconnected", "subscribed", "unsubscribed"];
|
|
1703
|
+
|
|
1704
|
+
// src/feature/queue/schema.ts
|
|
1705
|
+
import { days as days5, hours, minutes as minutes3, seconds as seconds2 } from "@awsless/duration";
|
|
1706
|
+
import { kibibytes } from "@awsless/size";
|
|
1707
|
+
import { z as z23 } from "zod";
|
|
1708
|
+
var RetentionPeriodSchema = DurationSchema.refine(durationMin(minutes3(1)), "Minimum retention period is 1 minute").refine(durationMax(days5(14)), "Maximum retention period is 14 days").describe(
|
|
1709
|
+
"The number of seconds that Amazon SQS retains a message. You can specify a duration from 1 minute to 14 days."
|
|
1710
|
+
);
|
|
1711
|
+
var VisibilityTimeoutSchema = DurationSchema.refine(
|
|
1712
|
+
durationMax(hours(12)),
|
|
1713
|
+
"Maximum visibility timeout is 12 hours"
|
|
1714
|
+
).describe(
|
|
1715
|
+
"The length of time during which a message will be unavailable after a message is delivered from the queue. You can specify a duration from 0 to 12 hours."
|
|
1716
|
+
);
|
|
1717
|
+
var ReceiveMessageWaitTimeSchema = DurationSchema.refine(
|
|
1718
|
+
durationMin(seconds2(1)),
|
|
1719
|
+
"Minimum receive message wait time is 1 second"
|
|
1720
|
+
).refine(durationMax(seconds2(20)), "Maximum receive message wait time is 20 seconds").describe("Long-polling wait time. You can specify a duration from 1 to 20 seconds.");
|
|
1721
|
+
var MaxMessageSizeSchema = SizeSchema.refine(sizeMin(kibibytes(1)), "Minimum max message size is 1 KB").refine(sizeMax(kibibytes(256)), "Maximum max message size is 256 KB").describe("Message size limit. You can specify a size from 1 KB to 256 KB.");
|
|
1722
|
+
var BatchSizeSchema = z23.number().int().min(1, "Minimum batch size is 1").max(10, "FIFO queues support a maximum batch size of 10").describe("The maximum number of records per batch. FIFO queues are capped at 10.");
|
|
1723
|
+
var RetryAttemptsSchema2 = z23.number().int().min(0).max(999).describe(
|
|
1724
|
+
"The maximum number of times to retry when the function returns an error. You can specify a number from 0 to 999."
|
|
1725
|
+
);
|
|
1726
|
+
var QueueDefaultSchema = z23.object({
|
|
1727
|
+
retentionPeriod: RetentionPeriodSchema.default("7 days"),
|
|
1728
|
+
visibilityTimeout: VisibilityTimeoutSchema.default("2 minutes"),
|
|
1729
|
+
receiveMessageWaitTime: ReceiveMessageWaitTimeSchema.optional(),
|
|
1730
|
+
maxMessageSize: MaxMessageSizeSchema.default("256 KB"),
|
|
1731
|
+
batchSize: BatchSizeSchema.default(10),
|
|
1732
|
+
retryAttempts: RetryAttemptsSchema2.default(2)
|
|
1733
|
+
}).default({});
|
|
1734
|
+
var QueueSchema = z23.object({
|
|
1735
|
+
consumer: FunctionSchema.optional().describe("The consuming lambda function properties."),
|
|
1736
|
+
retentionPeriod: RetentionPeriodSchema.optional(),
|
|
1737
|
+
visibilityTimeout: VisibilityTimeoutSchema.optional(),
|
|
1738
|
+
receiveMessageWaitTime: ReceiveMessageWaitTimeSchema.optional(),
|
|
1739
|
+
maxMessageSize: MaxMessageSizeSchema.optional(),
|
|
1740
|
+
batchSize: BatchSizeSchema.optional(),
|
|
1741
|
+
retryAttempts: RetryAttemptsSchema2.optional()
|
|
1742
|
+
});
|
|
1743
|
+
var QueuesSchema = z23.record(
|
|
1744
|
+
ResourceIdSchema,
|
|
1745
|
+
z23.union([
|
|
1746
|
+
LocalFileSchema.transform((consumer) => ({
|
|
1747
|
+
consumer
|
|
1748
|
+
})).pipe(QueueSchema),
|
|
1749
|
+
QueueSchema
|
|
1750
|
+
])
|
|
1751
|
+
).optional().describe(
|
|
1752
|
+
"Define the queues in your stack. Queues are FIFO with required per-message groupId: messages with the same groupId are processed strictly in order; different groupIds parallelize."
|
|
1663
1753
|
);
|
|
1664
|
-
|
|
1754
|
+
|
|
1755
|
+
// src/feature/rest/schema.ts
|
|
1756
|
+
import { z as z25 } from "zod";
|
|
1757
|
+
|
|
1758
|
+
// src/config/schema/route.ts
|
|
1759
|
+
import { z as z24 } from "zod";
|
|
1760
|
+
var RouteSchema2 = z24.union([
|
|
1761
|
+
z24.string().regex(/^(POST|GET|PUT|DELETE|HEAD|OPTIONS|ANY)(\s\/[a-z0-9\+\_\-\/\{\}]*)$/gi, "Invalid route"),
|
|
1762
|
+
z24.literal("$default")
|
|
1763
|
+
]);
|
|
1764
|
+
|
|
1765
|
+
// src/feature/rest/schema.ts
|
|
1766
|
+
var RestDefaultSchema = z25.record(
|
|
1665
1767
|
ResourceIdSchema,
|
|
1666
1768
|
z25.object({
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
//
|
|
1670
|
-
router: ResourceIdSchema.describe("The router id to link your RPC API with."),
|
|
1671
|
-
path: RouteSchema2.describe("The path inside the router to link your RPC API to."),
|
|
1672
|
-
auth: FunctionSchema.optional().describe("The authentication handler for your RPC API."),
|
|
1673
|
-
log: LogSchema.optional(),
|
|
1674
|
-
timeout: TimeoutSchema2.default("1 minutes")
|
|
1769
|
+
domain: ResourceIdSchema.describe("The domain id to link your API with.").optional(),
|
|
1770
|
+
subDomain: z25.string().optional()
|
|
1675
1771
|
})
|
|
1676
|
-
).describe(
|
|
1677
|
-
var
|
|
1772
|
+
).optional().describe("Define your global REST API's.");
|
|
1773
|
+
var RestSchema = z25.record(
|
|
1678
1774
|
ResourceIdSchema,
|
|
1679
1775
|
z25.record(
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1776
|
+
RouteSchema2.describe(
|
|
1777
|
+
[
|
|
1778
|
+
"The REST API route that is comprised by the http method and http path.",
|
|
1779
|
+
"The possible http methods are POST, GET,PUT, DELETE, HEAD, OPTIONS, ANY.",
|
|
1780
|
+
"Example: GET /posts/{id}"
|
|
1781
|
+
].join("\n")
|
|
1782
|
+
),
|
|
1783
|
+
FunctionSchema
|
|
1784
|
+
)
|
|
1785
|
+
).optional().describe("Define routes in your stack for your global REST API.");
|
|
1786
|
+
|
|
1787
|
+
// src/feature/rpc/schema.ts
|
|
1788
|
+
import { minutes as minutes4, seconds as seconds3 } from "@awsless/duration";
|
|
1789
|
+
import { z as z26 } from "zod";
|
|
1790
|
+
var TimeoutSchema2 = DurationSchema.refine(durationMin(seconds3(10)), "Minimum timeout duration is 10 seconds").refine(durationMax(minutes4(5)), "Maximum timeout duration is 5 minutes").describe(
|
|
1791
|
+
[
|
|
1792
|
+
"The amount of time that the RPC lambda is allowed run before stopping it.",
|
|
1793
|
+
"You can specify a timeout from 10 second to 5 minutes.",
|
|
1794
|
+
"The timeouts of all inner RPC functions will be capped at 80% of this timeout."
|
|
1795
|
+
].join(" ")
|
|
1796
|
+
);
|
|
1797
|
+
var RpcDefaultSchema = z26.record(
|
|
1798
|
+
ResourceIdSchema,
|
|
1799
|
+
z26.object({
|
|
1800
|
+
// domain: ResourceIdSchema.describe('The domain id to link your RPC API with.').optional(),
|
|
1801
|
+
// subDomain: z.string().optional(),
|
|
1802
|
+
//
|
|
1803
|
+
router: ResourceIdSchema.describe("The router id to link your RPC API with."),
|
|
1804
|
+
path: RouteSchema.describe("The path inside the router to link your RPC API to."),
|
|
1805
|
+
auth: FunctionSchema.optional().describe("The authentication handler for your RPC API."),
|
|
1806
|
+
log: LogSchema.optional(),
|
|
1807
|
+
timeout: TimeoutSchema2.default("1 minutes")
|
|
1808
|
+
})
|
|
1809
|
+
).describe(`Define the global RPC API's.`).optional();
|
|
1810
|
+
var RpcSchema = z26.record(
|
|
1811
|
+
ResourceIdSchema,
|
|
1812
|
+
z26.record(
|
|
1813
|
+
z26.string(),
|
|
1814
|
+
z26.union([
|
|
1815
|
+
FunctionSchema.transform((f) => ({
|
|
1816
|
+
function: f,
|
|
1684
1817
|
lock: false
|
|
1685
1818
|
})),
|
|
1686
|
-
|
|
1819
|
+
z26.object({
|
|
1687
1820
|
function: FunctionSchema.describe("The RPC function to execute."),
|
|
1688
|
-
lock:
|
|
1821
|
+
lock: z26.boolean().describe(
|
|
1689
1822
|
[
|
|
1690
1823
|
"Specify if the function should be locked on the `lockKey` returned from the auth function.",
|
|
1691
1824
|
"An example would be returning the user ID as `lockKey`."
|
|
@@ -1697,136 +1830,10 @@ var RpcSchema = z25.record(
|
|
|
1697
1830
|
).describe("Define the schema in your stack for your global RPC API.").optional();
|
|
1698
1831
|
|
|
1699
1832
|
// src/feature/job/schema.ts
|
|
1700
|
-
import { days as
|
|
1701
|
-
import { toMebibytes } from "@awsless/size";
|
|
1702
|
-
import { z as z26 } from "zod";
|
|
1703
|
-
var CpuSchema = z26.union([z26.literal(0.25), z26.literal(0.5), z26.literal(1), z26.literal(2), z26.literal(4), z26.literal(8), z26.literal(16)]).transform((v) => `${v} vCPU`).describe("The number of virtual CPU units (vCPU) used by the job. Valid values: 0.25, 0.5, 1, 2, 4, 8, 16 vCPU.");
|
|
1704
|
-
var validMemorySize = [
|
|
1705
|
-
// 0.25 vCPU
|
|
1706
|
-
512,
|
|
1707
|
-
1024,
|
|
1708
|
-
2048,
|
|
1709
|
-
// 0.5 vCPU
|
|
1710
|
-
1024,
|
|
1711
|
-
2048,
|
|
1712
|
-
3072,
|
|
1713
|
-
4096,
|
|
1714
|
-
// 1 vCPU
|
|
1715
|
-
2048,
|
|
1716
|
-
3072,
|
|
1717
|
-
4096,
|
|
1718
|
-
5120,
|
|
1719
|
-
6144,
|
|
1720
|
-
7168,
|
|
1721
|
-
8192,
|
|
1722
|
-
// 2 vCPU
|
|
1723
|
-
4096,
|
|
1724
|
-
5120,
|
|
1725
|
-
6144,
|
|
1726
|
-
7168,
|
|
1727
|
-
8192,
|
|
1728
|
-
9216,
|
|
1729
|
-
10240,
|
|
1730
|
-
11264,
|
|
1731
|
-
12288,
|
|
1732
|
-
13312,
|
|
1733
|
-
14336,
|
|
1734
|
-
15360,
|
|
1735
|
-
16384
|
|
1736
|
-
];
|
|
1737
|
-
var MemorySizeSchema2 = SizeSchema.refine(
|
|
1738
|
-
(s) => validMemorySize.includes(toMebibytes(s)),
|
|
1739
|
-
`Invalid memory size. Allowed sizes: ${validMemorySize.join(", ")} MiB`
|
|
1740
|
-
).describe("The amount of memory (in MiB) used by the job. Valid memory values depend on the CPU configuration.");
|
|
1741
|
-
var EnvironmentSchema2 = z26.record(z26.string(), z26.string()).optional().describe("Environment variable key-value pairs.");
|
|
1742
|
-
var ArchitectureSchema3 = z26.enum(["x86_64", "arm64"]).describe("The instruction set architecture that the job supports.");
|
|
1743
|
-
var ActionSchema2 = z26.string();
|
|
1744
|
-
var ActionsSchema2 = z26.union([ActionSchema2.transform((v) => [v]), ActionSchema2.array()]);
|
|
1745
|
-
var ArnSchema2 = z26.string().startsWith("arn:");
|
|
1746
|
-
var WildcardSchema2 = z26.literal("*");
|
|
1747
|
-
var ResourceSchema2 = z26.union([ArnSchema2, WildcardSchema2]);
|
|
1748
|
-
var ResourcesSchema2 = z26.union([ResourceSchema2.transform((v) => [v]), ResourceSchema2.array()]);
|
|
1749
|
-
var PermissionSchema2 = z26.object({
|
|
1750
|
-
effect: z26.enum(["allow", "deny"]).default("allow"),
|
|
1751
|
-
actions: ActionsSchema2,
|
|
1752
|
-
resources: ResourcesSchema2
|
|
1753
|
-
});
|
|
1754
|
-
var PermissionsSchema2 = z26.union([PermissionSchema2.transform((v) => [v]), PermissionSchema2.array()]).describe("Add IAM permissions to your job.");
|
|
1755
|
-
var validLogRetentionDays2 = [
|
|
1756
|
-
...[1, 3, 5, 7, 14, 30, 60, 90, 120, 150],
|
|
1757
|
-
...[180, 365, 400, 545, 731, 1096, 1827, 2192],
|
|
1758
|
-
...[2557, 2922, 3288, 3653]
|
|
1759
|
-
];
|
|
1760
|
-
var LogRetentionSchema2 = DurationSchema.refine(
|
|
1761
|
-
durationMin(days4(0)),
|
|
1762
|
-
"Minimum log retention is 0 day, which will disable logging."
|
|
1763
|
-
).refine(
|
|
1764
|
-
(duration) => {
|
|
1765
|
-
return validLogRetentionDays2.includes(toDays2(duration));
|
|
1766
|
-
},
|
|
1767
|
-
`Invalid log retention. Valid days are: ${validLogRetentionDays2.map((days12) => `${days12}`).join(", ")}`
|
|
1768
|
-
).describe("The log retention duration.");
|
|
1769
|
-
var LogSchema2 = z26.union([
|
|
1770
|
-
z26.boolean().transform((enabled) => ({ retention: enabled ? days4(7) : days4(0) })),
|
|
1771
|
-
LogRetentionSchema2.transform((retention) => ({ retention })),
|
|
1772
|
-
z26.object({
|
|
1773
|
-
retention: LogRetentionSchema2.optional()
|
|
1774
|
-
})
|
|
1775
|
-
]).describe("Enable logging to a CloudWatch log group. Providing a duration value will set the log retention time.");
|
|
1776
|
-
var FileCodeSchema2 = z26.object({
|
|
1777
|
-
file: LocalFileSchema.describe("The file path of the job code.")
|
|
1778
|
-
});
|
|
1779
|
-
var CodeSchema2 = z26.union([
|
|
1780
|
-
LocalFileSchema.transform((file) => ({
|
|
1781
|
-
file
|
|
1782
|
-
})).pipe(FileCodeSchema2),
|
|
1783
|
-
FileCodeSchema2
|
|
1784
|
-
]).describe("Specify the code of your job.");
|
|
1785
|
-
var TimeoutSchema3 = DurationSchema.describe("The maximum time the job is allowed to run before being stopped.");
|
|
1786
|
-
var ImageSchema = z26.string().describe("The URL of the container image to use. Default: public.ecr.aws/aws-cli/aws-cli:{architecture}");
|
|
1787
|
-
var PersistentStorageSchema = z26.boolean().describe("Mount persistent storage for the job at a fixed internal path.");
|
|
1788
|
-
var StartupCommandSchema = z26.union([z26.string().transform((v) => [v]), z26.string().array()]).describe("Optional shell commands to run before the job executable is downloaded and started.");
|
|
1789
|
-
var ASchema = z26.object({
|
|
1790
|
-
code: CodeSchema2,
|
|
1791
|
-
image: ImageSchema.optional(),
|
|
1792
|
-
persistentStorage: PersistentStorageSchema.optional(),
|
|
1793
|
-
startupCommand: StartupCommandSchema.optional(),
|
|
1794
|
-
log: LogSchema2.optional(),
|
|
1795
|
-
cpu: CpuSchema.optional(),
|
|
1796
|
-
memorySize: MemorySizeSchema2.optional(),
|
|
1797
|
-
architecture: ArchitectureSchema3.optional(),
|
|
1798
|
-
environment: EnvironmentSchema2.optional(),
|
|
1799
|
-
permissions: PermissionsSchema2.optional(),
|
|
1800
|
-
timeout: TimeoutSchema3.default("30 minutes").describe("The maximum time the job is allowed to run before being stopped. Default: 30 minutes.")
|
|
1801
|
-
});
|
|
1802
|
-
var JobSchema = z26.union([
|
|
1803
|
-
LocalFileSchema.transform((code) => ({
|
|
1804
|
-
code
|
|
1805
|
-
})).pipe(ASchema),
|
|
1806
|
-
ASchema
|
|
1807
|
-
]);
|
|
1808
|
-
var JobsSchema = z26.record(ResourceIdSchema, JobSchema).optional().describe("Define the jobs in your stack.");
|
|
1809
|
-
var JobDefaultSchema = z26.object({
|
|
1810
|
-
image: ImageSchema.optional(),
|
|
1811
|
-
persistentStorage: PersistentStorageSchema.optional(),
|
|
1812
|
-
cpu: CpuSchema.default(0.25),
|
|
1813
|
-
memorySize: MemorySizeSchema2.default("512 MB"),
|
|
1814
|
-
architecture: ArchitectureSchema3.default("arm64"),
|
|
1815
|
-
environment: EnvironmentSchema2.optional(),
|
|
1816
|
-
permissions: PermissionsSchema2.optional(),
|
|
1817
|
-
timeout: TimeoutSchema3.optional(),
|
|
1818
|
-
log: LogSchema2.default(true).transform((log35) => ({
|
|
1819
|
-
retention: log35.retention ?? days4(7)
|
|
1820
|
-
}))
|
|
1821
|
-
}).default({});
|
|
1822
|
-
|
|
1823
|
-
// src/feature/instance/schema.ts
|
|
1824
|
-
import { days as days5, toDays as toDays3 } from "@awsless/duration";
|
|
1833
|
+
import { days as days6, toDays as toDays3 } from "@awsless/duration";
|
|
1825
1834
|
import { toMebibytes as toMebibytes2 } from "@awsless/size";
|
|
1826
1835
|
import { z as z27 } from "zod";
|
|
1827
|
-
var CpuSchema2 = z27.union([z27.literal(0.25), z27.literal(0.5), z27.literal(1), z27.literal(2), z27.literal(4), z27.literal(8), z27.literal(16)]).transform((v) => `${v} vCPU`).describe(
|
|
1828
|
-
"The number of virtual CPU units (vCPU) used by the instance. Valid values: 0.25, 0.5, 1, 2, 4, 8, 16 vCPU."
|
|
1829
|
-
);
|
|
1836
|
+
var CpuSchema2 = z27.union([z27.literal(0.25), z27.literal(0.5), z27.literal(1), z27.literal(2), z27.literal(4), z27.literal(8), z27.literal(16)]).transform((v) => `${v} vCPU`).describe("The number of virtual CPU units (vCPU) used by the job. Valid values: 0.25, 0.5, 1, 2, 4, 8, 16 vCPU.");
|
|
1830
1837
|
var validMemorySize2 = [
|
|
1831
1838
|
// 0.25 vCPU
|
|
1832
1839
|
512,
|
|
@@ -1863,22 +1870,9 @@ var validMemorySize2 = [
|
|
|
1863
1870
|
var MemorySizeSchema3 = SizeSchema.refine(
|
|
1864
1871
|
(s) => validMemorySize2.includes(toMebibytes2(s)),
|
|
1865
1872
|
`Invalid memory size. Allowed sizes: ${validMemorySize2.join(", ")} MiB`
|
|
1866
|
-
).describe("The amount of memory (in MiB) used by the
|
|
1867
|
-
var HealthCheckSchema = z27.object({
|
|
1868
|
-
path: z27.string().describe("The path that the container runs to determine if it is healthy."),
|
|
1869
|
-
interval: DurationSchema.describe("The time period in seconds between each health check execution."),
|
|
1870
|
-
retries: z27.number().int().min(1).max(10).describe(
|
|
1871
|
-
"The number of times to retry a failed health check before the container is considered unhealthy."
|
|
1872
|
-
),
|
|
1873
|
-
startPeriod: DurationSchema.describe(
|
|
1874
|
-
"The optional grace period to provide containers time to bootstrap before failed health checks count towards the maximum number of retries."
|
|
1875
|
-
),
|
|
1876
|
-
timeout: DurationSchema.describe(
|
|
1877
|
-
"The time period in seconds to wait for a health check to succeed before it is considered a failure."
|
|
1878
|
-
)
|
|
1879
|
-
}).describe("The health check command and associated configuration parameters for the container.");
|
|
1873
|
+
).describe("The amount of memory (in MiB) used by the job. Valid memory values depend on the CPU configuration.");
|
|
1880
1874
|
var EnvironmentSchema3 = z27.record(z27.string(), z27.string()).optional().describe("Environment variable key-value pairs.");
|
|
1881
|
-
var ArchitectureSchema4 = z27.enum(["x86_64", "arm64"]).describe("The instruction set architecture that the
|
|
1875
|
+
var ArchitectureSchema4 = z27.enum(["x86_64", "arm64"]).describe("The instruction set architecture that the job supports.");
|
|
1882
1876
|
var ActionSchema3 = z27.string();
|
|
1883
1877
|
var ActionsSchema3 = z27.union([ActionSchema3.transform((v) => [v]), ActionSchema3.array()]);
|
|
1884
1878
|
var ArnSchema3 = z27.string().startsWith("arn:");
|
|
@@ -1890,44 +1884,45 @@ var PermissionSchema3 = z27.object({
|
|
|
1890
1884
|
actions: ActionsSchema3,
|
|
1891
1885
|
resources: ResourcesSchema3
|
|
1892
1886
|
});
|
|
1893
|
-
var PermissionsSchema3 = z27.union([PermissionSchema3.transform((v) => [v]), PermissionSchema3.array()]).describe("Add IAM permissions to your
|
|
1894
|
-
var DescriptionSchema2 = z27.string().describe("A description of the instance.");
|
|
1895
|
-
var ImageSchema2 = z27.string().optional().describe("The URL of the container image to use. Default: public.ecr.aws/aws-cli/aws-cli:{architecture}");
|
|
1887
|
+
var PermissionsSchema3 = z27.union([PermissionSchema3.transform((v) => [v]), PermissionSchema3.array()]).describe("Add IAM permissions to your job.");
|
|
1896
1888
|
var validLogRetentionDays3 = [
|
|
1897
1889
|
...[1, 3, 5, 7, 14, 30, 60, 90, 120, 150],
|
|
1898
1890
|
...[180, 365, 400, 545, 731, 1096, 1827, 2192],
|
|
1899
1891
|
...[2557, 2922, 3288, 3653]
|
|
1900
1892
|
];
|
|
1901
1893
|
var LogRetentionSchema3 = DurationSchema.refine(
|
|
1902
|
-
durationMin(
|
|
1894
|
+
durationMin(days6(0)),
|
|
1903
1895
|
"Minimum log retention is 0 day, which will disable logging."
|
|
1904
1896
|
).refine(
|
|
1905
1897
|
(duration) => {
|
|
1906
1898
|
return validLogRetentionDays3.includes(toDays3(duration));
|
|
1907
1899
|
},
|
|
1908
|
-
`Invalid log retention. Valid days are: ${validLogRetentionDays3.map((
|
|
1900
|
+
`Invalid log retention. Valid days are: ${validLogRetentionDays3.map((days13) => `${days13}`).join(", ")}`
|
|
1909
1901
|
).describe("The log retention duration.");
|
|
1910
1902
|
var LogSchema3 = z27.union([
|
|
1911
|
-
z27.boolean().transform((enabled) => ({ retention: enabled ?
|
|
1903
|
+
z27.boolean().transform((enabled) => ({ retention: enabled ? days6(7) : days6(0) })),
|
|
1912
1904
|
LogRetentionSchema3.transform((retention) => ({ retention })),
|
|
1913
1905
|
z27.object({
|
|
1914
1906
|
retention: LogRetentionSchema3.optional()
|
|
1915
1907
|
})
|
|
1916
1908
|
]).describe("Enable logging to a CloudWatch log group. Providing a duration value will set the log retention time.");
|
|
1917
1909
|
var FileCodeSchema3 = z27.object({
|
|
1918
|
-
file: LocalFileSchema.describe("The file path of the
|
|
1910
|
+
file: LocalFileSchema.describe("The file path of the job code.")
|
|
1919
1911
|
});
|
|
1920
1912
|
var CodeSchema3 = z27.union([
|
|
1921
1913
|
LocalFileSchema.transform((file) => ({
|
|
1922
1914
|
file
|
|
1923
1915
|
})).pipe(FileCodeSchema3),
|
|
1924
1916
|
FileCodeSchema3
|
|
1925
|
-
]).describe("Specify the code of your
|
|
1926
|
-
var
|
|
1927
|
-
var
|
|
1917
|
+
]).describe("Specify the code of your job.");
|
|
1918
|
+
var TimeoutSchema3 = DurationSchema.describe("The maximum time the job is allowed to run before being stopped.");
|
|
1919
|
+
var ImageSchema2 = z27.string().describe("The URL of the container image to use. Default: public.ecr.aws/aws-cli/aws-cli:{architecture}");
|
|
1920
|
+
var PersistentStorageSchema = z27.boolean().describe("Mount persistent storage for the job at a fixed internal path.");
|
|
1921
|
+
var StartupCommandSchema2 = z27.union([z27.string().transform((v) => [v]), z27.string().array()]).describe("Optional shell commands to run before the job executable is downloaded and started.");
|
|
1922
|
+
var ASchema = z27.object({
|
|
1928
1923
|
code: CodeSchema3,
|
|
1929
|
-
description: DescriptionSchema2.optional(),
|
|
1930
1924
|
image: ImageSchema2.optional(),
|
|
1925
|
+
persistentStorage: PersistentStorageSchema.optional(),
|
|
1931
1926
|
startupCommand: StartupCommandSchema2.optional(),
|
|
1932
1927
|
log: LogSchema3.optional(),
|
|
1933
1928
|
cpu: CpuSchema2.optional(),
|
|
@@ -1935,27 +1930,26 @@ var ISchema = z27.object({
|
|
|
1935
1930
|
architecture: ArchitectureSchema4.optional(),
|
|
1936
1931
|
environment: EnvironmentSchema3.optional(),
|
|
1937
1932
|
permissions: PermissionsSchema3.optional(),
|
|
1938
|
-
|
|
1939
|
-
// restartPolicy: RestartPolicySchema.optional(),
|
|
1933
|
+
timeout: TimeoutSchema3.default("30 minutes").describe("The maximum time the job is allowed to run before being stopped. Default: 30 minutes.")
|
|
1940
1934
|
});
|
|
1941
|
-
var
|
|
1935
|
+
var JobSchema = z27.union([
|
|
1942
1936
|
LocalFileSchema.transform((code) => ({
|
|
1943
1937
|
code
|
|
1944
|
-
})).pipe(
|
|
1945
|
-
|
|
1938
|
+
})).pipe(ASchema),
|
|
1939
|
+
ASchema
|
|
1946
1940
|
]);
|
|
1947
|
-
var
|
|
1948
|
-
var
|
|
1941
|
+
var JobsSchema = z27.record(ResourceIdSchema, JobSchema).optional().describe("Define the jobs in your stack.");
|
|
1942
|
+
var JobDefaultSchema = z27.object({
|
|
1949
1943
|
image: ImageSchema2.optional(),
|
|
1944
|
+
persistentStorage: PersistentStorageSchema.optional(),
|
|
1950
1945
|
cpu: CpuSchema2.default(0.25),
|
|
1951
1946
|
memorySize: MemorySizeSchema3.default("512 MB"),
|
|
1952
1947
|
architecture: ArchitectureSchema4.default("arm64"),
|
|
1953
1948
|
environment: EnvironmentSchema3.optional(),
|
|
1954
1949
|
permissions: PermissionsSchema3.optional(),
|
|
1955
|
-
|
|
1956
|
-
// restartPolicy: RestartPolicySchema.default({ enabled: true }),
|
|
1950
|
+
timeout: TimeoutSchema3.optional(),
|
|
1957
1951
|
log: LogSchema3.default(true).transform((log35) => ({
|
|
1958
|
-
retention: log35.retention ??
|
|
1952
|
+
retention: log35.retention ?? days6(7)
|
|
1959
1953
|
}))
|
|
1960
1954
|
}).default({});
|
|
1961
1955
|
|
|
@@ -2153,7 +2147,7 @@ var CronExpressionSchema = z34.custom(
|
|
|
2153
2147
|
var ScheduleExpressionSchema = RateExpressionSchema.or(CronExpressionSchema);
|
|
2154
2148
|
|
|
2155
2149
|
// src/feature/cron/schema/index.ts
|
|
2156
|
-
var
|
|
2150
|
+
var RetryAttemptsSchema3 = z35.number().int().min(0).max(2).describe(
|
|
2157
2151
|
"The maximum number of times to retry when the function returns an error. You can specify a number from 0 to 2."
|
|
2158
2152
|
);
|
|
2159
2153
|
var CronsSchema = z35.record(
|
|
@@ -2165,7 +2159,7 @@ var CronsSchema = z35.record(
|
|
|
2165
2159
|
'The scheduling expression.\n\nexample: "0 20 * * ? *"\nexample: "5 minutes"'
|
|
2166
2160
|
),
|
|
2167
2161
|
payload: z35.unknown().optional().describe("The JSON payload that will be passed to the consumer."),
|
|
2168
|
-
retryAttempts:
|
|
2162
|
+
retryAttempts: RetryAttemptsSchema3.default(2)
|
|
2169
2163
|
})
|
|
2170
2164
|
).optional().describe(`Define the cron jobs in your stack.`);
|
|
2171
2165
|
|
|
@@ -2295,7 +2289,7 @@ var SitesSchema = z38.record(
|
|
|
2295
2289
|
ResourceIdSchema,
|
|
2296
2290
|
z38.object({
|
|
2297
2291
|
router: ResourceIdSchema.describe("The router id to link your site with."),
|
|
2298
|
-
path:
|
|
2292
|
+
path: RouteSchema.describe("The path inside the router to link your site to."),
|
|
2299
2293
|
build: z38.object({
|
|
2300
2294
|
command: z38.string().describe(
|
|
2301
2295
|
`Specifies the files and directories to generate the cache key for your custom build command.`
|
|
@@ -2313,11 +2307,11 @@ var SitesSchema = z38.record(
|
|
|
2313
2307
|
).optional().describe("Define the sites in your stack.");
|
|
2314
2308
|
|
|
2315
2309
|
// src/feature/store/schema.ts
|
|
2316
|
-
import { days as
|
|
2310
|
+
import { days as days7 } from "@awsless/duration";
|
|
2317
2311
|
import { z as z39 } from "zod";
|
|
2318
2312
|
var LifecycleRuleSchema = z39.object({
|
|
2319
2313
|
prefix: z39.string().optional().describe("Object-key prefix this rule applies to. Omit to apply bucket-wide."),
|
|
2320
|
-
expiration: DurationSchema.refine(durationMin(
|
|
2314
|
+
expiration: DurationSchema.refine(durationMin(days7(1)), "Minimum expiration is 1 day").describe(
|
|
2321
2315
|
"How long objects matching this rule live before S3 deletes them."
|
|
2322
2316
|
)
|
|
2323
2317
|
});
|
|
@@ -2381,7 +2375,7 @@ var IconsSchema = z40.record(
|
|
|
2381
2375
|
// domain: ResourceIdSchema.describe('The domain id to link your site with.').optional(),
|
|
2382
2376
|
// subDomain: z.string().optional(),
|
|
2383
2377
|
router: ResourceIdSchema.describe("The router id to link your icon proxy."),
|
|
2384
|
-
path:
|
|
2378
|
+
path: RouteSchema.describe("The path inside the router to link your icon proxy to."),
|
|
2385
2379
|
log: LogSchema.optional(),
|
|
2386
2380
|
cacheDuration: DurationSchema.optional().describe("The cache duration of the cached icons."),
|
|
2387
2381
|
preserveIds: z40.boolean().optional().default(false).describe("Preserve the IDs of the icons."),
|
|
@@ -2438,7 +2432,7 @@ var ImagesSchema = z41.record(
|
|
|
2438
2432
|
// domain: ResourceIdSchema.describe('The domain id to link your site with.').optional(),
|
|
2439
2433
|
// subDomain: z.string().optional(),
|
|
2440
2434
|
router: ResourceIdSchema.describe("The router id to link your image proxy."),
|
|
2441
|
-
path:
|
|
2435
|
+
path: RouteSchema.describe("The path inside the router to link your image proxy to."),
|
|
2442
2436
|
log: LogSchema.optional(),
|
|
2443
2437
|
cacheDuration: DurationSchema.optional().describe("Cache duration of the cached images."),
|
|
2444
2438
|
presets: z41.record(z41.string(), transformationOptionsSchema).describe("Named presets for image transformations"),
|
|
@@ -3690,13 +3684,15 @@ var bundleTypeScriptWithRolldown = async ({
|
|
|
3690
3684
|
file,
|
|
3691
3685
|
nativeDir,
|
|
3692
3686
|
external,
|
|
3687
|
+
externalAwsSdk = true,
|
|
3688
|
+
codeSplitting = true,
|
|
3693
3689
|
importAsString: importAsStringList
|
|
3694
3690
|
}) => {
|
|
3695
3691
|
const bundle = await rolldown({
|
|
3696
3692
|
input: file,
|
|
3697
3693
|
platform: "node",
|
|
3698
3694
|
external: (importee) => {
|
|
3699
|
-
return importee.startsWith("@aws-sdk") || importee.startsWith("aws-sdk") || external?.includes(importee);
|
|
3695
|
+
return externalAwsSdk && (importee.startsWith("@aws-sdk") || importee.startsWith("aws-sdk")) || external?.includes(importee);
|
|
3700
3696
|
},
|
|
3701
3697
|
onwarn: (error) => {
|
|
3702
3698
|
debugError(error.message);
|
|
@@ -3725,6 +3721,7 @@ var bundleTypeScriptWithRolldown = async ({
|
|
|
3725
3721
|
exports: "auto",
|
|
3726
3722
|
entryFileNames: `index.${ext}`,
|
|
3727
3723
|
chunkFileNames: `[name].${ext}`,
|
|
3724
|
+
codeSplitting,
|
|
3728
3725
|
minify
|
|
3729
3726
|
});
|
|
3730
3727
|
const hash = createHash2("sha1");
|
|
@@ -4549,7 +4546,7 @@ var functionFeature = defineFeature({
|
|
|
4549
4546
|
});
|
|
4550
4547
|
|
|
4551
4548
|
// src/feature/function/prebuild.ts
|
|
4552
|
-
import { days as
|
|
4549
|
+
import { days as days8, seconds as seconds5, toDays as toDays6, toSeconds as toSeconds3 } from "@awsless/duration";
|
|
4553
4550
|
import { mebibytes as mebibytes2, toMebibytes as toMebibytes4 } from "@awsless/size";
|
|
4554
4551
|
import { aws as aws8 } from "@terraforge/aws";
|
|
4555
4552
|
import { Output as Output4, findInputDeps as findInputDeps2, resolveInputs as resolveInputs2 } from "@terraforge/core";
|
|
@@ -4614,6 +4611,28 @@ var createPrebuildLambdaFunction = (group, ctx, ns, id, props) => {
|
|
|
4614
4611
|
statementDeps.add(dep);
|
|
4615
4612
|
}
|
|
4616
4613
|
};
|
|
4614
|
+
if (props.vpc) {
|
|
4615
|
+
new aws8.iam.RolePolicy(group, "vpc-policy", {
|
|
4616
|
+
role: role.name,
|
|
4617
|
+
name: "lambda-vpc-policy",
|
|
4618
|
+
policy: JSON.stringify({
|
|
4619
|
+
Version: "2012-10-17",
|
|
4620
|
+
Statement: [
|
|
4621
|
+
{
|
|
4622
|
+
Effect: "Allow",
|
|
4623
|
+
Action: [
|
|
4624
|
+
"ec2:CreateNetworkInterface",
|
|
4625
|
+
"ec2:DescribeNetworkInterfaces",
|
|
4626
|
+
"ec2:DeleteNetworkInterface",
|
|
4627
|
+
"ec2:AssignPrivateIpAddresses",
|
|
4628
|
+
"ec2:UnassignPrivateIpAddresses"
|
|
4629
|
+
],
|
|
4630
|
+
Resource: ["*"]
|
|
4631
|
+
}
|
|
4632
|
+
]
|
|
4633
|
+
})
|
|
4634
|
+
});
|
|
4635
|
+
}
|
|
4617
4636
|
ctx.onPermission((statement) => {
|
|
4618
4637
|
addPermission(statement);
|
|
4619
4638
|
});
|
|
@@ -4662,6 +4681,11 @@ var createPrebuildLambdaFunction = (group, ctx, ns, id, props) => {
|
|
|
4662
4681
|
environment: {
|
|
4663
4682
|
variables
|
|
4664
4683
|
},
|
|
4684
|
+
vpcConfig: props.vpc ? {
|
|
4685
|
+
securityGroupIds: [ctx.shared.get("vpc", "security-group-id")],
|
|
4686
|
+
subnetIds: ctx.shared.get("vpc", "private-subnets"),
|
|
4687
|
+
ipv6AllowedForDualStack: true
|
|
4688
|
+
} : void 0,
|
|
4665
4689
|
loggingConfig: {
|
|
4666
4690
|
logGroup: `/aws/lambda/${name}`,
|
|
4667
4691
|
logFormat: logFormats[props.log && "format" in props.log && props.log.format || "json"],
|
|
@@ -4678,10 +4702,13 @@ var createPrebuildLambdaFunction = (group, ctx, ns, id, props) => {
|
|
|
4678
4702
|
if ("stackConfig" in ctx) {
|
|
4679
4703
|
variables.STACK = ctx.stackConfig.name;
|
|
4680
4704
|
}
|
|
4705
|
+
if (props.vpc) {
|
|
4706
|
+
variables.AWS_USE_DUALSTACK_ENDPOINT = "true";
|
|
4707
|
+
}
|
|
4681
4708
|
if (props.log?.retention && props.log?.retention?.value > 0n) {
|
|
4682
4709
|
const logGroup = new aws8.cloudwatch.LogGroup(group, "log", {
|
|
4683
4710
|
name: `/aws/lambda/${name}`,
|
|
4684
|
-
retentionInDays: toDays6(props.log.retention ??
|
|
4711
|
+
retentionInDays: toDays6(props.log.retention ?? days8(7))
|
|
4685
4712
|
});
|
|
4686
4713
|
addPermission({
|
|
4687
4714
|
actions: ["logs:PutLogEvents", "logs:CreateLogStream"],
|
|
@@ -4738,7 +4765,7 @@ import { Group as Group8 } from "@terraforge/core";
|
|
|
4738
4765
|
import { aws as aws9 } from "@terraforge/aws";
|
|
4739
4766
|
import { join as join10 } from "path";
|
|
4740
4767
|
import { mebibytes as mebibytes3 } from "@awsless/size";
|
|
4741
|
-
import { days as
|
|
4768
|
+
import { days as days9, seconds as seconds6 } from "@awsless/duration";
|
|
4742
4769
|
var onErrorLogFeature = defineFeature({
|
|
4743
4770
|
name: "on-error-log",
|
|
4744
4771
|
onApp(ctx) {
|
|
@@ -4753,7 +4780,7 @@ var onErrorLogFeature = defineFeature({
|
|
|
4753
4780
|
log: {
|
|
4754
4781
|
format: "json",
|
|
4755
4782
|
level: "warn",
|
|
4756
|
-
retention:
|
|
4783
|
+
retention: days9(3),
|
|
4757
4784
|
system: "warn"
|
|
4758
4785
|
}
|
|
4759
4786
|
});
|
|
@@ -4810,7 +4837,7 @@ import { Group as Group9 } from "@terraforge/core";
|
|
|
4810
4837
|
import { aws as aws10 } from "@terraforge/aws";
|
|
4811
4838
|
import { join as join11 } from "path";
|
|
4812
4839
|
import { mebibytes as mebibytes4 } from "@awsless/size";
|
|
4813
|
-
import { days as
|
|
4840
|
+
import { days as days10, toSeconds as toSeconds4 } from "@awsless/duration";
|
|
4814
4841
|
var onFailureFeature = defineFeature({
|
|
4815
4842
|
name: "on-failure",
|
|
4816
4843
|
onApp(ctx) {
|
|
@@ -4821,7 +4848,7 @@ var onFailureFeature = defineFeature({
|
|
|
4821
4848
|
resourceType: "on-failure",
|
|
4822
4849
|
resourceName: "deadletter"
|
|
4823
4850
|
}),
|
|
4824
|
-
messageRetentionSeconds: toSeconds4(
|
|
4851
|
+
messageRetentionSeconds: toSeconds4(days10(14))
|
|
4825
4852
|
});
|
|
4826
4853
|
const queue2 = new aws10.sqs.Queue(group, "on-failure", {
|
|
4827
4854
|
name: formatGlobalResourceName({
|
|
@@ -4969,7 +4996,7 @@ var onFailureFeature = defineFeature({
|
|
|
4969
4996
|
log: {
|
|
4970
4997
|
format: "json",
|
|
4971
4998
|
level: "warn",
|
|
4972
|
-
retention:
|
|
4999
|
+
retention: days10(3),
|
|
4973
5000
|
system: "warn"
|
|
4974
5001
|
}
|
|
4975
5002
|
});
|
|
@@ -5044,9 +5071,14 @@ var onFailureFeature = defineFeature({
|
|
|
5044
5071
|
});
|
|
5045
5072
|
|
|
5046
5073
|
// src/feature/pubsub/index.ts
|
|
5047
|
-
import {
|
|
5048
|
-
import {
|
|
5074
|
+
import { seconds as seconds7 } from "@awsless/duration";
|
|
5075
|
+
import { mebibytes as mebibytes5 } from "@awsless/size";
|
|
5076
|
+
import { aws as aws12 } from "@terraforge/aws";
|
|
5077
|
+
import { Group as Group11 } from "@terraforge/core";
|
|
5049
5078
|
import { constantCase as constantCase5 } from "change-case";
|
|
5079
|
+
import { createHmac as createHmac2 } from "crypto";
|
|
5080
|
+
import { dirname as dirname6, join as join14 } from "path";
|
|
5081
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
5050
5082
|
|
|
5051
5083
|
// src/feature/domain/util.ts
|
|
5052
5084
|
var getDomainNameById = (config2, id) => {
|
|
@@ -5066,103 +5098,739 @@ var formatFullDomainName = (config2, id, subDomain) => {
|
|
|
5066
5098
|
return domain2;
|
|
5067
5099
|
};
|
|
5068
5100
|
|
|
5069
|
-
// src/feature/pubsub/
|
|
5070
|
-
import {
|
|
5071
|
-
|
|
5072
|
-
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5101
|
+
// src/feature/pubsub/util.ts
|
|
5102
|
+
import { toDays as toDays7 } from "@awsless/duration";
|
|
5103
|
+
import { stringify } from "@awsless/json";
|
|
5104
|
+
import { aws as aws11 } from "@terraforge/aws";
|
|
5105
|
+
import { Group as Group10, Output as Output5, findInputDeps as findInputDeps3, resolveInputs as resolveInputs3 } from "@terraforge/core";
|
|
5106
|
+
import { pascalCase as pascalCase3 } from "change-case";
|
|
5107
|
+
import { createHash as createHash4 } from "crypto";
|
|
5108
|
+
import { readFile as readFile5 } from "fs/promises";
|
|
5109
|
+
import { fileURLToPath } from "url";
|
|
5110
|
+
import { dirname as dirname5, join as join13 } from "path";
|
|
5111
|
+
|
|
5112
|
+
// src/feature/instance/build/executable.ts
|
|
5113
|
+
import { createHash as createHash3 } from "crypto";
|
|
5114
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
5115
|
+
import { join as join12 } from "path";
|
|
5116
|
+
var buildExecutable = async (input, outputPath, architecture) => {
|
|
5117
|
+
const filePath = join12(outputPath, "program");
|
|
5118
|
+
const target = architecture === "x86_64" ? "bun-linux-x64" : "bun-linux-arm64";
|
|
5119
|
+
let result;
|
|
5120
|
+
try {
|
|
5121
|
+
result = await Bun.build({
|
|
5122
|
+
entrypoints: [input],
|
|
5123
|
+
compile: {
|
|
5124
|
+
target,
|
|
5125
|
+
outfile: filePath
|
|
5126
|
+
},
|
|
5127
|
+
target: "bun",
|
|
5128
|
+
loader: {
|
|
5129
|
+
".md": "text",
|
|
5130
|
+
".txt": "text",
|
|
5131
|
+
".html": "text",
|
|
5132
|
+
".css": "text",
|
|
5133
|
+
".yaml": "text",
|
|
5134
|
+
".yml": "text",
|
|
5135
|
+
".xml": "text",
|
|
5136
|
+
".csv": "text",
|
|
5137
|
+
".svg": "text",
|
|
5138
|
+
".png": "file",
|
|
5139
|
+
".jpg": "file",
|
|
5140
|
+
".jpeg": "file",
|
|
5141
|
+
".gif": "file",
|
|
5142
|
+
".webp": "file",
|
|
5143
|
+
".wasm": "file"
|
|
5144
|
+
}
|
|
5080
5145
|
});
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5092
|
-
|
|
5093
|
-
|
|
5094
|
-
|
|
5095
|
-
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5146
|
+
} catch (error) {
|
|
5147
|
+
throw new ExpectedError(
|
|
5148
|
+
`Executable build failed: ${error instanceof Error ? error.message : JSON.stringify(error)}`
|
|
5149
|
+
);
|
|
5150
|
+
}
|
|
5151
|
+
if (!result.success) {
|
|
5152
|
+
throw new ExpectedError(`Executable build failed:
|
|
5153
|
+
${result.logs?.map((log35) => log35.message).join("\n")}`);
|
|
5154
|
+
}
|
|
5155
|
+
const file = await readFile4(filePath);
|
|
5156
|
+
return {
|
|
5157
|
+
hash: createHash3("sha1").update(file).update("x86_64").digest("hex"),
|
|
5158
|
+
file
|
|
5159
|
+
};
|
|
5160
|
+
};
|
|
5161
|
+
|
|
5162
|
+
// src/feature/pubsub/util.ts
|
|
5163
|
+
var __dirname2 = dirname5(fileURLToPath(import.meta.url));
|
|
5164
|
+
var WS_PORT = 3e3;
|
|
5165
|
+
var ARCHITECTURE = "arm64";
|
|
5166
|
+
var CPU = "0.25 vCPU";
|
|
5167
|
+
var MEMORY = "512";
|
|
5168
|
+
var MIN_CAPACITY = 1;
|
|
5169
|
+
var MAX_CAPACITY = 10;
|
|
5170
|
+
var createPubSubService = (parentGroup, ctx, id, props, inputs) => {
|
|
5171
|
+
const group = new Group10(parentGroup, "service", id);
|
|
5172
|
+
const name = formatGlobalResourceName({
|
|
5173
|
+
appName: ctx.app.name,
|
|
5174
|
+
resourceType: "pubsub",
|
|
5175
|
+
resourceName: id
|
|
5176
|
+
});
|
|
5177
|
+
const shortName = shortId(`${ctx.app.name}:pubsub:${id}:${ctx.appId}`);
|
|
5178
|
+
const image2 = "public.ecr.aws/aws-cli/aws-cli:arm64";
|
|
5179
|
+
const bundleFile = join13(__dirname2, "prebuild/pubsub-server/index.mjs");
|
|
5180
|
+
const bundleHash = join13(__dirname2, "prebuild/pubsub-server/HASH");
|
|
5181
|
+
ctx.registerBuild("pubsub", name, async (build3) => {
|
|
5182
|
+
const hash = await readFile5(bundleHash, "utf8");
|
|
5183
|
+
const fingerprint = `${hash.trim()}-${ARCHITECTURE}`;
|
|
5184
|
+
return build3(fingerprint, async (write) => {
|
|
5185
|
+
const temp = await createTempFolder(`pubsub--${name}`);
|
|
5186
|
+
const executable = await buildExecutable(bundleFile, temp.path, ARCHITECTURE);
|
|
5187
|
+
await Promise.all([
|
|
5188
|
+
//
|
|
5189
|
+
write("HASH", executable.hash),
|
|
5190
|
+
write("program", executable.file),
|
|
5191
|
+
temp.delete()
|
|
5192
|
+
]);
|
|
5193
|
+
return {
|
|
5194
|
+
size: formatByteSize(executable.file.byteLength)
|
|
5195
|
+
};
|
|
5196
|
+
});
|
|
5197
|
+
});
|
|
5198
|
+
const code = new aws11.s3.BucketObject(group, "code", {
|
|
5199
|
+
bucket: ctx.shared.get("pubsub", "bucket-name"),
|
|
5200
|
+
key: name,
|
|
5201
|
+
source: relativePath(getBuildPath("pubsub", name, "program")),
|
|
5202
|
+
sourceHash: $file(getBuildPath("pubsub", name, "HASH"))
|
|
5203
|
+
});
|
|
5204
|
+
const executionRole = new aws11.iam.Role(group, "execution-role", {
|
|
5205
|
+
name: shortId(`${shortName}:execution-role`),
|
|
5206
|
+
description: name,
|
|
5207
|
+
assumeRolePolicy: JSON.stringify({
|
|
5208
|
+
Version: "2012-10-17",
|
|
5209
|
+
Statement: [
|
|
5210
|
+
{
|
|
5211
|
+
Effect: "Allow",
|
|
5212
|
+
Action: "sts:AssumeRole",
|
|
5213
|
+
Principal: {
|
|
5214
|
+
Service: ["ecs-tasks.amazonaws.com"]
|
|
5215
|
+
}
|
|
5216
|
+
}
|
|
5217
|
+
]
|
|
5218
|
+
}),
|
|
5219
|
+
managedPolicyArns: ["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]
|
|
5220
|
+
});
|
|
5221
|
+
const role = new aws11.iam.Role(
|
|
5222
|
+
group,
|
|
5223
|
+
"task-role",
|
|
5224
|
+
{
|
|
5225
|
+
name: shortId(`${shortName}:task-role`),
|
|
5226
|
+
description: name,
|
|
5227
|
+
assumeRolePolicy: JSON.stringify({
|
|
5228
|
+
Version: "2012-10-17",
|
|
5229
|
+
Statement: [
|
|
5230
|
+
{
|
|
5231
|
+
Effect: "Allow",
|
|
5232
|
+
Action: "sts:AssumeRole",
|
|
5233
|
+
Principal: {
|
|
5234
|
+
Service: ["ecs-tasks.amazonaws.com"]
|
|
5235
|
+
}
|
|
5236
|
+
}
|
|
5237
|
+
]
|
|
5238
|
+
}),
|
|
5239
|
+
inlinePolicy: [
|
|
5240
|
+
{
|
|
5241
|
+
name: "s3-code-access",
|
|
5242
|
+
policy: $resolve([code.bucket, code.key], (bucket, key) => {
|
|
5243
|
+
return JSON.stringify({
|
|
5244
|
+
Version: "2012-10-17",
|
|
5245
|
+
Statement: [
|
|
5246
|
+
{
|
|
5247
|
+
Effect: pascalCase3("allow"),
|
|
5248
|
+
Action: ["s3:getObject", "s3:HeadObject"],
|
|
5249
|
+
Resource: `arn:aws:s3:::${bucket}/${key}`
|
|
5250
|
+
}
|
|
5251
|
+
]
|
|
5252
|
+
});
|
|
5253
|
+
})
|
|
5254
|
+
}
|
|
5255
|
+
]
|
|
5256
|
+
},
|
|
5257
|
+
{
|
|
5258
|
+
dependsOn: [code]
|
|
5259
|
+
}
|
|
5260
|
+
);
|
|
5261
|
+
const statements = [];
|
|
5262
|
+
const statementDeps = /* @__PURE__ */ new Set();
|
|
5263
|
+
const policy = new aws11.iam.RolePolicy(group, "policy", {
|
|
5264
|
+
role: role.name,
|
|
5265
|
+
name: "task-policy",
|
|
5266
|
+
policy: new Output5(statementDeps, async (resolve2) => {
|
|
5267
|
+
const list3 = await resolveInputs3(statements);
|
|
5268
|
+
resolve2(
|
|
5269
|
+
JSON.stringify({
|
|
5270
|
+
Version: "2012-10-17",
|
|
5271
|
+
Statement: list3.map((statement) => ({
|
|
5272
|
+
Effect: pascalCase3(statement.effect ?? "allow"),
|
|
5273
|
+
Action: statement.actions,
|
|
5274
|
+
Resource: statement.resources
|
|
5275
|
+
}))
|
|
5276
|
+
})
|
|
5277
|
+
);
|
|
5278
|
+
})
|
|
5279
|
+
});
|
|
5280
|
+
const addPermission = (...permissions) => {
|
|
5281
|
+
statements.push(...permissions);
|
|
5282
|
+
for (const dep of findInputDeps3(permissions)) {
|
|
5283
|
+
statementDeps.add(dep);
|
|
5284
|
+
}
|
|
5285
|
+
};
|
|
5286
|
+
ctx.onPermission((statement) => {
|
|
5287
|
+
addPermission(statement);
|
|
5288
|
+
});
|
|
5289
|
+
let logGroup;
|
|
5290
|
+
if (props.log.retention && props.log.retention.value > 0n) {
|
|
5291
|
+
logGroup = new aws11.cloudwatch.LogGroup(group, "log", {
|
|
5292
|
+
name: `/aws/ecs/${name}`,
|
|
5293
|
+
retentionInDays: toDays7(props.log.retention)
|
|
5294
|
+
});
|
|
5295
|
+
if (ctx.shared.has("on-error-log", "subscriber-arn")) {
|
|
5296
|
+
new aws11.cloudwatch.LogSubscriptionFilter(group, "on-error-log", {
|
|
5297
|
+
name: "error-log-subscription",
|
|
5298
|
+
destinationArn: ctx.shared.get("on-error-log", "subscriber-arn"),
|
|
5299
|
+
logGroupName: logGroup.name,
|
|
5300
|
+
filterPattern
|
|
5301
|
+
});
|
|
5302
|
+
}
|
|
5303
|
+
}
|
|
5304
|
+
const tags = {
|
|
5305
|
+
APP: ctx.appConfig.name,
|
|
5306
|
+
APP_ID: ctx.appId
|
|
5307
|
+
};
|
|
5308
|
+
const variables = {};
|
|
5309
|
+
const variableDeps = /* @__PURE__ */ new Set();
|
|
5310
|
+
const task2 = new aws11.ecs.TaskDefinition(
|
|
5311
|
+
group,
|
|
5312
|
+
"task",
|
|
5313
|
+
{
|
|
5314
|
+
family: name,
|
|
5315
|
+
networkMode: "awsvpc",
|
|
5316
|
+
cpu: CPU,
|
|
5317
|
+
memory: MEMORY,
|
|
5318
|
+
requiresCompatibilities: ["FARGATE"],
|
|
5319
|
+
executionRoleArn: executionRole.arn,
|
|
5320
|
+
taskRoleArn: role.arn,
|
|
5321
|
+
runtimePlatform: {
|
|
5322
|
+
cpuArchitecture: "ARM64",
|
|
5323
|
+
operatingSystemFamily: "LINUX"
|
|
5324
|
+
},
|
|
5325
|
+
trackLatest: true,
|
|
5326
|
+
containerDefinitions: new Output5(variableDeps, async (resolve2) => {
|
|
5327
|
+
const data = await resolveInputs3(variables);
|
|
5328
|
+
const { s3Bucket, s3Key } = await resolveInputs3({
|
|
5329
|
+
s3Bucket: code.bucket,
|
|
5330
|
+
s3Key: code.key
|
|
5331
|
+
});
|
|
5332
|
+
resolve2(
|
|
5333
|
+
JSON.stringify([
|
|
5334
|
+
{
|
|
5335
|
+
name: `container-${id}`,
|
|
5336
|
+
essential: true,
|
|
5337
|
+
image: image2,
|
|
5338
|
+
protocol: "tcp",
|
|
5339
|
+
workingDirectory: "/usr/app",
|
|
5340
|
+
entryPoint: ["sh", "-c"],
|
|
5341
|
+
command: [
|
|
5342
|
+
[
|
|
5343
|
+
`aws s3 cp s3://${s3Bucket}/${s3Key} /usr/app/program`,
|
|
5344
|
+
`chmod +x /usr/app/program`,
|
|
5345
|
+
`exec /usr/app/program`
|
|
5346
|
+
].join(" && ")
|
|
5347
|
+
],
|
|
5348
|
+
environment: Object.entries(data).map(([name2, value]) => ({
|
|
5349
|
+
name: name2,
|
|
5350
|
+
value
|
|
5351
|
+
})),
|
|
5352
|
+
portMappings: [
|
|
5353
|
+
{
|
|
5354
|
+
name: "ws",
|
|
5355
|
+
protocol: "tcp",
|
|
5356
|
+
appProtocol: "http",
|
|
5357
|
+
containerPort: WS_PORT,
|
|
5358
|
+
hostPort: WS_PORT
|
|
5359
|
+
}
|
|
5360
|
+
],
|
|
5361
|
+
restartPolicy: {
|
|
5362
|
+
enabled: true,
|
|
5363
|
+
restartAttemptPeriod: 60
|
|
5364
|
+
},
|
|
5365
|
+
...logGroup && {
|
|
5366
|
+
logConfiguration: {
|
|
5367
|
+
logDriver: "awslogs",
|
|
5368
|
+
options: {
|
|
5369
|
+
"awslogs-group": `/aws/ecs/${name}`,
|
|
5370
|
+
"awslogs-region": ctx.appConfig.region,
|
|
5371
|
+
"awslogs-stream-prefix": "ecs",
|
|
5372
|
+
mode: "non-blocking"
|
|
5373
|
+
}
|
|
5374
|
+
}
|
|
5375
|
+
}
|
|
5376
|
+
}
|
|
5377
|
+
])
|
|
5378
|
+
);
|
|
5379
|
+
}),
|
|
5380
|
+
tags
|
|
5381
|
+
},
|
|
5382
|
+
{
|
|
5383
|
+
replaceOnChanges: [
|
|
5384
|
+
"containerDefinitions",
|
|
5385
|
+
"cpu",
|
|
5386
|
+
"memory",
|
|
5387
|
+
"runtimePlatform",
|
|
5388
|
+
"executionRoleArn",
|
|
5389
|
+
"taskRoleArn"
|
|
5390
|
+
],
|
|
5391
|
+
dependsOn: [code]
|
|
5392
|
+
}
|
|
5393
|
+
);
|
|
5394
|
+
const service = new aws11.ecs.Service(
|
|
5395
|
+
group,
|
|
5396
|
+
"service",
|
|
5397
|
+
{
|
|
5398
|
+
name,
|
|
5399
|
+
cluster: inputs.clusterArn,
|
|
5400
|
+
taskDefinition: task2.arn,
|
|
5401
|
+
launchType: "FARGATE",
|
|
5402
|
+
networkConfiguration: {
|
|
5403
|
+
subnets: ctx.shared.get("vpc", "public-subnets"),
|
|
5404
|
+
securityGroups: [inputs.securityGroupId],
|
|
5405
|
+
assignPublicIp: true
|
|
5406
|
+
// https://stackoverflow.com/questions/76398247/cannotpullcontainererror-pull-image-manifest-has-been-retried-5-times-failed
|
|
5407
|
+
},
|
|
5408
|
+
loadBalancer: [
|
|
5409
|
+
{
|
|
5410
|
+
containerName: `container-${id}`,
|
|
5411
|
+
containerPort: WS_PORT,
|
|
5412
|
+
targetGroupArn: inputs.targetGroupArn
|
|
5413
|
+
}
|
|
5414
|
+
],
|
|
5415
|
+
healthCheckGracePeriodSeconds: 30,
|
|
5416
|
+
forceNewDeployment: true,
|
|
5417
|
+
forceDelete: true,
|
|
5418
|
+
tags,
|
|
5419
|
+
// ------------------------------------------------------------
|
|
5420
|
+
// Zero-downtime deploys: spin up the new tasks before the old
|
|
5421
|
+
// ones are drained.
|
|
5422
|
+
// The desired count is intentionally not set, so that deploys
|
|
5423
|
+
// never reset the capacity the autoscaler picked.
|
|
5424
|
+
schedulingStrategy: "REPLICA",
|
|
5425
|
+
deploymentMaximumPercent: 200,
|
|
5426
|
+
deploymentMinimumHealthyPercent: 100,
|
|
5427
|
+
deploymentCircuitBreaker: {
|
|
5428
|
+
enable: true,
|
|
5429
|
+
rollback: true
|
|
5430
|
+
},
|
|
5431
|
+
// ------------------------------------------------------------
|
|
5432
|
+
// Tag hygiene: let ECS manage and propagate runtime tags automatically.
|
|
5433
|
+
enableEcsManagedTags: true,
|
|
5434
|
+
propagateTags: "SERVICE"
|
|
5435
|
+
},
|
|
5436
|
+
{
|
|
5437
|
+
replaceOnChanges: ["cluster"]
|
|
5438
|
+
}
|
|
5439
|
+
);
|
|
5440
|
+
const target = new aws11.appautoscaling.Target(
|
|
5441
|
+
group,
|
|
5442
|
+
"autoscaling-target",
|
|
5443
|
+
{
|
|
5444
|
+
serviceNamespace: "ecs",
|
|
5445
|
+
scalableDimension: "ecs:service:DesiredCount",
|
|
5446
|
+
minCapacity: MIN_CAPACITY,
|
|
5447
|
+
maxCapacity: MAX_CAPACITY,
|
|
5448
|
+
resourceId: $resolve([inputs.clusterName, service.name], (clusterName, serviceName) => {
|
|
5449
|
+
return `service/${clusterName}/${serviceName}`;
|
|
5450
|
+
}),
|
|
5451
|
+
tags
|
|
5452
|
+
},
|
|
5453
|
+
{
|
|
5454
|
+
dependsOn: [service]
|
|
5455
|
+
}
|
|
5456
|
+
);
|
|
5457
|
+
new aws11.appautoscaling.Policy(
|
|
5458
|
+
group,
|
|
5459
|
+
"autoscaling-policy",
|
|
5460
|
+
{
|
|
5461
|
+
name: `${name}-cpu`,
|
|
5462
|
+
policyType: "TargetTrackingScaling",
|
|
5463
|
+
serviceNamespace: target.serviceNamespace,
|
|
5464
|
+
scalableDimension: target.scalableDimension,
|
|
5465
|
+
resourceId: target.resourceId,
|
|
5466
|
+
targetTrackingScalingPolicyConfiguration: {
|
|
5467
|
+
predefinedMetricSpecification: {
|
|
5468
|
+
predefinedMetricType: "ECSServiceAverageCPUUtilization"
|
|
5469
|
+
},
|
|
5470
|
+
targetValue: 70,
|
|
5471
|
+
scaleInCooldown: 300,
|
|
5472
|
+
scaleOutCooldown: 60
|
|
5473
|
+
}
|
|
5474
|
+
},
|
|
5475
|
+
{
|
|
5476
|
+
dependsOn: [target]
|
|
5477
|
+
}
|
|
5478
|
+
);
|
|
5479
|
+
ctx.onEnv((name2, value) => {
|
|
5480
|
+
variables[name2] = value;
|
|
5481
|
+
for (const dep of findInputDeps3([value])) {
|
|
5482
|
+
variableDeps.add(dep);
|
|
5483
|
+
}
|
|
5484
|
+
});
|
|
5485
|
+
variables.APP = ctx.appConfig.name;
|
|
5486
|
+
variables.APP_ID = ctx.appId;
|
|
5487
|
+
variables.AWS_ACCOUNT_ID = ctx.accountId;
|
|
5488
|
+
variables.CODE_HASH = code.sourceHash;
|
|
5489
|
+
variables.PUBSUB_CONFIG_HASH = createHash4("sha1").update(stringify(props)).digest("hex");
|
|
5490
|
+
for (const [key, value] of Object.entries(inputs.environment)) {
|
|
5491
|
+
variables[key] = value;
|
|
5492
|
+
for (const dep of findInputDeps3([value])) {
|
|
5493
|
+
variableDeps.add(dep);
|
|
5494
|
+
}
|
|
5495
|
+
}
|
|
5496
|
+
return { name, task: task2, service, policy, code, group, addPermission };
|
|
5497
|
+
};
|
|
5498
|
+
|
|
5499
|
+
// src/feature/pubsub/index.ts
|
|
5500
|
+
var __dirname3 = dirname6(fileURLToPath2(import.meta.url));
|
|
5501
|
+
var typeGenCode4 = `
|
|
5502
|
+
import type { Mock } from 'vitest'
|
|
5503
|
+
|
|
5504
|
+
type Publish = (topic: string, event: string, payload?: unknown) => Promise<void>
|
|
5505
|
+
type PubSubInstance = {
|
|
5506
|
+
readonly publish: Publish
|
|
5507
|
+
}
|
|
5508
|
+
|
|
5509
|
+
type MockHandle = (payload: { topic: string; event: string; payload?: unknown }) => void
|
|
5510
|
+
type MockBuilder = (handle?: MockHandle) => void
|
|
5511
|
+
type MockObject = Mock<[unknown], unknown>
|
|
5512
|
+
`;
|
|
5513
|
+
var pubsubFeature = defineFeature({
|
|
5514
|
+
name: "pubsub",
|
|
5515
|
+
async onTypeGen(ctx) {
|
|
5516
|
+
const gen = new TypeFile("awsless");
|
|
5517
|
+
const resources2 = new TypeObject(1);
|
|
5518
|
+
const mocks = new TypeObject(1);
|
|
5519
|
+
const mockResponses = new TypeObject(1);
|
|
5520
|
+
for (const id of Object.keys(ctx.appConfig.defaults.pubsub ?? {})) {
|
|
5521
|
+
resources2.addType(id, `PubSubInstance`);
|
|
5522
|
+
mocks.addType(id, `MockBuilder`);
|
|
5523
|
+
mockResponses.addType(id, `MockObject`);
|
|
5524
|
+
}
|
|
5525
|
+
gen.addCode(typeGenCode4);
|
|
5526
|
+
gen.addInterface("PubSubResources", resources2);
|
|
5527
|
+
gen.addInterface("PubSubMock", mocks);
|
|
5528
|
+
gen.addInterface("PubSubMockResponse", mockResponses);
|
|
5529
|
+
await ctx.write("pubsub.d.ts", gen, true);
|
|
5530
|
+
},
|
|
5531
|
+
onValidate(ctx) {
|
|
5532
|
+
const pubsubs = ctx.appConfig.defaults.pubsub ?? {};
|
|
5533
|
+
for (const [id, props] of Object.entries(pubsubs)) {
|
|
5534
|
+
if (!(props.router in (ctx.appConfig.defaults.router ?? {}))) {
|
|
5535
|
+
throw new FileError("app.json", `The pubsub "${id}" points to a non existent router "${props.router}"`);
|
|
5536
|
+
}
|
|
5537
|
+
}
|
|
5538
|
+
for (const stack of ctx.stackConfigs) {
|
|
5539
|
+
for (const id of Object.keys(stack.pubsub ?? {})) {
|
|
5540
|
+
if (!(id in pubsubs)) {
|
|
5541
|
+
throw new FileError(stack.file, `Listening to a non existent pubsub "${id}"`);
|
|
5542
|
+
}
|
|
5543
|
+
}
|
|
5544
|
+
}
|
|
5545
|
+
},
|
|
5546
|
+
onBefore(ctx) {
|
|
5547
|
+
const found = Object.keys(ctx.appConfig.defaults.pubsub ?? {}).length > 0;
|
|
5548
|
+
if (!found) {
|
|
5549
|
+
return;
|
|
5550
|
+
}
|
|
5551
|
+
const group = new Group11(ctx.base, "pubsub", "asset");
|
|
5552
|
+
const bucket = new aws12.s3.Bucket(group, "bucket", {
|
|
5553
|
+
bucket: formatGlobalResourceName({
|
|
5554
|
+
appName: ctx.app.name,
|
|
5555
|
+
resourceType: "pubsub",
|
|
5556
|
+
resourceName: "assets",
|
|
5557
|
+
postfix: ctx.appId
|
|
5558
|
+
}),
|
|
5559
|
+
forceDestroy: true
|
|
5560
|
+
});
|
|
5561
|
+
ctx.shared.set("pubsub", "bucket-name", bucket.bucket);
|
|
5562
|
+
},
|
|
5563
|
+
onApp(ctx) {
|
|
5564
|
+
const pubsubs = Object.entries(ctx.appConfig.defaults.pubsub ?? {});
|
|
5565
|
+
if (pubsubs.length === 0) {
|
|
5566
|
+
return;
|
|
5567
|
+
}
|
|
5568
|
+
const clusterGroup = new Group11(ctx.base, "pubsub", "cluster");
|
|
5569
|
+
const cluster = new aws12.ecs.Cluster(
|
|
5570
|
+
clusterGroup,
|
|
5571
|
+
"cluster",
|
|
5572
|
+
{
|
|
5573
|
+
name: `${ctx.app.name}-pubsub`
|
|
5574
|
+
},
|
|
5575
|
+
{
|
|
5576
|
+
replaceOnChanges: ["name"]
|
|
5577
|
+
}
|
|
5578
|
+
);
|
|
5579
|
+
for (const [id, props] of pubsubs) {
|
|
5580
|
+
const group = new Group11(ctx.base, "pubsub", id);
|
|
5581
|
+
const name = formatGlobalResourceName({
|
|
5582
|
+
appName: ctx.app.name,
|
|
5583
|
+
resourceType: "pubsub",
|
|
5584
|
+
resourceName: id
|
|
5585
|
+
});
|
|
5586
|
+
const vpcId = ctx.shared.get("vpc", "id");
|
|
5587
|
+
const auth2 = createLambdaFunction(group, ctx, "pubsub-auth", id, props.auth);
|
|
5588
|
+
const topicName = formatGlobalResourceName({
|
|
5589
|
+
appName: ctx.app.name,
|
|
5590
|
+
resourceType: "pubsub-events",
|
|
5591
|
+
resourceName: id
|
|
5592
|
+
});
|
|
5593
|
+
const topic = new aws12.sns.Topic(group, "events", {
|
|
5594
|
+
name: topicName
|
|
5595
|
+
});
|
|
5596
|
+
ctx.shared.add("pubsub", "events-topic-arn", id, topic.arn);
|
|
5597
|
+
const cacheName = formatGlobalResourceName({
|
|
5598
|
+
appName: ctx.app.name,
|
|
5599
|
+
resourceType: "pubsub-cache",
|
|
5600
|
+
resourceName: id,
|
|
5601
|
+
seperator: "-"
|
|
5602
|
+
});
|
|
5603
|
+
const cacheSecurityGroup = new aws12.security.Group(group, "cache-security", {
|
|
5604
|
+
name: cacheName,
|
|
5605
|
+
vpcId,
|
|
5606
|
+
description: cacheName
|
|
5607
|
+
});
|
|
5608
|
+
const cache = new aws12.elasticache.ServerlessCache(
|
|
5609
|
+
group,
|
|
5610
|
+
"cache",
|
|
5611
|
+
{
|
|
5612
|
+
name: cacheName,
|
|
5613
|
+
engine: "valkey",
|
|
5614
|
+
majorEngineVersion: "8",
|
|
5615
|
+
securityGroupIds: [cacheSecurityGroup.id],
|
|
5616
|
+
subnetIds: ctx.shared.get("vpc", "private-subnets")
|
|
5617
|
+
},
|
|
5618
|
+
{
|
|
5619
|
+
import: ctx.import ? cacheName : void 0
|
|
5620
|
+
}
|
|
5621
|
+
);
|
|
5622
|
+
const redisHost = cache.endpoint.pipe((v) => v.at(0).address);
|
|
5623
|
+
const redisPort = cache.endpoint.pipe((v) => v.at(0).port);
|
|
5624
|
+
new aws12.vpc.SecurityGroupIngressRule(group, "cache-rule-ip-v4", {
|
|
5625
|
+
securityGroupId: cacheSecurityGroup.id,
|
|
5626
|
+
description: redisPort.pipe((port) => `Allow ipv4 on port: ${port}`),
|
|
5627
|
+
ipProtocol: "tcp",
|
|
5628
|
+
cidrIpv4: "0.0.0.0/0",
|
|
5629
|
+
fromPort: redisPort,
|
|
5630
|
+
toPort: redisPort
|
|
5631
|
+
});
|
|
5632
|
+
new aws12.vpc.SecurityGroupIngressRule(group, "cache-rule-ip-v6", {
|
|
5633
|
+
securityGroupId: cacheSecurityGroup.id,
|
|
5634
|
+
description: redisPort.pipe((port) => `Allow ipv6 on port: ${port}`),
|
|
5635
|
+
ipProtocol: "tcp",
|
|
5636
|
+
cidrIpv6: "::/0",
|
|
5637
|
+
fromPort: redisPort,
|
|
5638
|
+
toPort: redisPort
|
|
5639
|
+
});
|
|
5640
|
+
const channel = `pubsub:${id}`;
|
|
5641
|
+
const cloudfrontPrefixList = aws12.ec2.getManagedPrefixList(group, "cloudfront-prefix-list", {
|
|
5642
|
+
name: "com.amazonaws.global.cloudfront.origin-facing"
|
|
5643
|
+
});
|
|
5644
|
+
const lbSecurityGroup = new aws12.security.Group(group, "lb-security", {
|
|
5645
|
+
name: `${name}-lb`,
|
|
5646
|
+
vpcId,
|
|
5647
|
+
description: `${name}-lb`
|
|
5648
|
+
});
|
|
5649
|
+
new aws12.vpc.SecurityGroupIngressRule(group, "lb-ingress", {
|
|
5650
|
+
securityGroupId: lbSecurityGroup.id,
|
|
5651
|
+
description: "Allow http traffic from CloudFront",
|
|
5652
|
+
ipProtocol: "tcp",
|
|
5653
|
+
prefixListId: cloudfrontPrefixList.id,
|
|
5654
|
+
fromPort: 80,
|
|
5655
|
+
toPort: 80
|
|
5656
|
+
});
|
|
5657
|
+
new aws12.vpc.SecurityGroupEgressRule(group, "lb-egress", {
|
|
5658
|
+
securityGroupId: lbSecurityGroup.id,
|
|
5659
|
+
description: "Allow all outbound traffic",
|
|
5660
|
+
ipProtocol: "-1",
|
|
5661
|
+
cidrIpv4: "0.0.0.0/0"
|
|
5662
|
+
});
|
|
5663
|
+
const taskSecurityGroup = new aws12.security.Group(group, "task-security", {
|
|
5664
|
+
name: `${name}-task`,
|
|
5665
|
+
vpcId,
|
|
5666
|
+
description: `${name}-task`
|
|
5667
|
+
});
|
|
5668
|
+
new aws12.vpc.SecurityGroupIngressRule(group, "task-ingress", {
|
|
5669
|
+
securityGroupId: taskSecurityGroup.id,
|
|
5670
|
+
description: "Allow websocket traffic from the load balancer",
|
|
5671
|
+
ipProtocol: "tcp",
|
|
5672
|
+
referencedSecurityGroupId: lbSecurityGroup.id,
|
|
5673
|
+
fromPort: WS_PORT,
|
|
5674
|
+
toPort: WS_PORT
|
|
5675
|
+
});
|
|
5676
|
+
new aws12.vpc.SecurityGroupEgressRule(group, "task-egress", {
|
|
5677
|
+
securityGroupId: taskSecurityGroup.id,
|
|
5678
|
+
description: "Allow all outbound traffic",
|
|
5679
|
+
ipProtocol: "-1",
|
|
5680
|
+
cidrIpv4: "0.0.0.0/0"
|
|
5681
|
+
});
|
|
5682
|
+
const lb = new aws12.Lb(group, "lb", {
|
|
5683
|
+
name: shortId(`${name}:lb:${ctx.appId}`),
|
|
5684
|
+
internal: false,
|
|
5685
|
+
loadBalancerType: "application",
|
|
5686
|
+
subnets: ctx.shared.get("vpc", "public-subnets"),
|
|
5687
|
+
securityGroups: [lbSecurityGroup.id],
|
|
5688
|
+
idleTimeout: 120
|
|
5689
|
+
});
|
|
5690
|
+
const targetGroup = new aws12.lb.TargetGroup(group, "target", {
|
|
5691
|
+
name: shortId(`${name}:target:${ctx.appId}`),
|
|
5692
|
+
targetType: "ip",
|
|
5693
|
+
port: WS_PORT,
|
|
5694
|
+
protocol: "HTTP",
|
|
5695
|
+
vpcId,
|
|
5696
|
+
deregistrationDelay: "30",
|
|
5697
|
+
healthCheck: {
|
|
5698
|
+
enabled: true,
|
|
5699
|
+
path: "/health",
|
|
5700
|
+
interval: 10,
|
|
5701
|
+
timeout: 5,
|
|
5702
|
+
healthyThreshold: 2,
|
|
5703
|
+
unhealthyThreshold: 2,
|
|
5704
|
+
matcher: "200"
|
|
5705
|
+
}
|
|
5706
|
+
});
|
|
5707
|
+
new aws12.lb.Listener(group, "listener", {
|
|
5708
|
+
loadBalancerArn: lb.arn,
|
|
5709
|
+
port: 80,
|
|
5710
|
+
protocol: "HTTP",
|
|
5711
|
+
defaultAction: [
|
|
5712
|
+
{
|
|
5713
|
+
type: "forward",
|
|
5714
|
+
targetGroupArn: targetGroup.arn
|
|
5715
|
+
}
|
|
5716
|
+
]
|
|
5717
|
+
});
|
|
5718
|
+
const secret = createHmac2("sha1", ctx.appId).update(name).digest("hex");
|
|
5719
|
+
const service = createPubSubService(group, ctx, id, props, {
|
|
5720
|
+
clusterName: cluster.name,
|
|
5721
|
+
clusterArn: cluster.arn,
|
|
5722
|
+
targetGroupArn: targetGroup.arn,
|
|
5723
|
+
securityGroupId: taskSecurityGroup.id,
|
|
5724
|
+
environment: {
|
|
5725
|
+
AUTH: auth2.name,
|
|
5726
|
+
EVENTS_TOPIC: topicName,
|
|
5727
|
+
PORT: WS_PORT.toString(),
|
|
5728
|
+
REDIS_HOST: redisHost,
|
|
5729
|
+
REDIS_PORT: redisPort.pipe((port) => port.toString()),
|
|
5730
|
+
CHANNEL: channel,
|
|
5731
|
+
ORIGIN_SECRET: secret
|
|
5732
|
+
}
|
|
5733
|
+
});
|
|
5734
|
+
service.addPermission(
|
|
5735
|
+
{
|
|
5736
|
+
actions: ["lambda:InvokeFunction"],
|
|
5737
|
+
resources: [auth2.lambda.arn]
|
|
5738
|
+
},
|
|
5739
|
+
{
|
|
5740
|
+
actions: ["sns:Publish"],
|
|
5741
|
+
resources: [topic.arn]
|
|
5742
|
+
}
|
|
5743
|
+
);
|
|
5744
|
+
const publisher = createPrebuildLambdaFunction(group, ctx, "pubsub-publisher", id, {
|
|
5745
|
+
bundleFile: join14(__dirname3, "/prebuild/pubsub-publisher/bundle.zip"),
|
|
5746
|
+
bundleHash: join14(__dirname3, "/prebuild/pubsub-publisher/HASH"),
|
|
5747
|
+
memorySize: mebibytes5(256),
|
|
5748
|
+
timeout: seconds7(10),
|
|
5749
|
+
handler: "index.default",
|
|
5750
|
+
runtime: "nodejs24.x",
|
|
5751
|
+
vpc: true,
|
|
5752
|
+
log: props.log
|
|
5101
5753
|
});
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5754
|
+
publisher.setEnvironment("REDIS_HOST", redisHost);
|
|
5755
|
+
publisher.setEnvironment(
|
|
5756
|
+
"REDIS_PORT",
|
|
5757
|
+
redisPort.pipe((port) => port.toString())
|
|
5758
|
+
);
|
|
5759
|
+
publisher.setEnvironment("CHANNEL", channel);
|
|
5760
|
+
ctx.addGlobalPermission({
|
|
5761
|
+
actions: ["lambda:InvokeFunction"],
|
|
5762
|
+
resources: [publisher.lambda.arn]
|
|
5105
5763
|
});
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
new
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
authorizerConfig: {
|
|
5113
|
-
defaultAuthorizerName: authorizer.name
|
|
5114
|
-
}
|
|
5115
|
-
// validationCertificate: ctx.shared.get(`global-certificate-${props.domain}-arn`),
|
|
5116
|
-
});
|
|
5117
|
-
new aws11.route53.Record(group, "record", {
|
|
5118
|
-
zoneId: ctx.shared.entry("domain", `zone-id`, props.domain),
|
|
5119
|
-
name: domainName,
|
|
5120
|
-
type: "CNAME",
|
|
5121
|
-
ttl: toSeconds5(minutes7(5)),
|
|
5122
|
-
records: [endpoint.endpointAddress]
|
|
5123
|
-
});
|
|
5124
|
-
ctx.bind(`PUBSUB_${constantCase5(id)}_ENDPOINT`, domainName);
|
|
5125
|
-
} else {
|
|
5126
|
-
ctx.bind(`PUBSUB_${constantCase5(id)}_ENDPOINT`, endpoint.endpointAddress);
|
|
5764
|
+
const routerProps = ctx.appConfig.defaults.router?.[props.router];
|
|
5765
|
+
if (!routerProps?.domain) {
|
|
5766
|
+
throw new FileError(
|
|
5767
|
+
"app.json",
|
|
5768
|
+
`The pubsub "${id}" requires the "${props.router}" router to have a domain configured.`
|
|
5769
|
+
);
|
|
5127
5770
|
}
|
|
5771
|
+
const addRoutes = ctx.shared.entry("router", "addRoutes", props.router);
|
|
5772
|
+
addRoutes(group, `pubsub-${id}`, {
|
|
5773
|
+
[`${props.path}/*`]: {
|
|
5774
|
+
type: "url",
|
|
5775
|
+
domainName: lb.dnsName,
|
|
5776
|
+
readTimeout: 60,
|
|
5777
|
+
customHeaders: {
|
|
5778
|
+
"x-origin-secret": secret
|
|
5779
|
+
},
|
|
5780
|
+
rewrite: {
|
|
5781
|
+
regex: `^${props.path}/(.*)$`,
|
|
5782
|
+
to: "/$1"
|
|
5783
|
+
}
|
|
5784
|
+
}
|
|
5785
|
+
});
|
|
5786
|
+
const domainName = formatFullDomainName(ctx.appConfig, routerProps.domain, routerProps.subDomain);
|
|
5787
|
+
ctx.bind(`PUBSUB_${constantCase5(id)}_ENDPOINT`, `wss://${domainName}${props.path}/ws`);
|
|
5788
|
+
ctx.bind(`PUBSUB_${constantCase5(id)}_PUBLISHER`, publisher.name);
|
|
5128
5789
|
}
|
|
5129
5790
|
},
|
|
5130
5791
|
onStack(ctx) {
|
|
5131
5792
|
for (const [id, props] of Object.entries(ctx.stackConfig.pubsub ?? {})) {
|
|
5132
|
-
const group = new
|
|
5133
|
-
const
|
|
5134
|
-
const
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5793
|
+
const group = new Group11(ctx.stack, "pubsub", id);
|
|
5794
|
+
const topicArn = ctx.shared.entry("pubsub", "events-topic-arn", id);
|
|
5795
|
+
for (const event of pubsubEventTypes) {
|
|
5796
|
+
const consumer = props[event];
|
|
5797
|
+
if (!consumer) {
|
|
5798
|
+
continue;
|
|
5799
|
+
}
|
|
5800
|
+
const eventGroup = new Group11(group, "event", event);
|
|
5801
|
+
const { lambda } = createAsyncLambdaFunction(eventGroup, ctx, `pubsub`, `${id}-${event}`, {
|
|
5802
|
+
consumer,
|
|
5803
|
+
retryAttempts: 2
|
|
5804
|
+
});
|
|
5805
|
+
new aws12.sns.TopicSubscription(eventGroup, "subscription", {
|
|
5806
|
+
topicArn,
|
|
5807
|
+
protocol: "lambda",
|
|
5808
|
+
endpoint: lambda.arn,
|
|
5809
|
+
filterPolicyScope: "MessageAttributes",
|
|
5810
|
+
filterPolicy: JSON.stringify({
|
|
5811
|
+
event: [event]
|
|
5812
|
+
})
|
|
5813
|
+
});
|
|
5814
|
+
new aws12.lambda.Permission(eventGroup, "permission", {
|
|
5815
|
+
action: "lambda:InvokeFunction",
|
|
5816
|
+
principal: "sns.amazonaws.com",
|
|
5817
|
+
functionName: lambda.functionName,
|
|
5818
|
+
sourceArn: topicArn
|
|
5819
|
+
});
|
|
5820
|
+
}
|
|
5153
5821
|
}
|
|
5154
5822
|
}
|
|
5155
5823
|
});
|
|
5156
5824
|
|
|
5157
5825
|
// src/feature/queue/index.ts
|
|
5158
|
-
import { Group as
|
|
5159
|
-
import { aws as
|
|
5826
|
+
import { Group as Group12 } from "@terraforge/core";
|
|
5827
|
+
import { aws as aws13 } from "@terraforge/aws";
|
|
5160
5828
|
import { camelCase as camelCase5, constantCase as constantCase6 } from "change-case";
|
|
5161
5829
|
import deepmerge3 from "deepmerge";
|
|
5162
5830
|
import { relative as relative5 } from "path";
|
|
5163
|
-
import { seconds as
|
|
5831
|
+
import { seconds as seconds8, toSeconds as toSeconds5 } from "@awsless/duration";
|
|
5164
5832
|
import { toBytes } from "@awsless/size";
|
|
5165
|
-
var
|
|
5833
|
+
var typeGenCode5 = `
|
|
5166
5834
|
import {
|
|
5167
5835
|
SendMessageOptions,
|
|
5168
5836
|
SendMessageBatchOptions,
|
|
@@ -5220,7 +5888,7 @@ var queueFeature = defineFeature({
|
|
|
5220
5888
|
resources2.addType(stack.name, resource);
|
|
5221
5889
|
mockResponses.addType(stack.name, mockResponse);
|
|
5222
5890
|
}
|
|
5223
|
-
gen.addCode(
|
|
5891
|
+
gen.addCode(typeGenCode5);
|
|
5224
5892
|
gen.addInterface("QueueResources", resources2);
|
|
5225
5893
|
gen.addInterface("QueueMock", mocks);
|
|
5226
5894
|
gen.addInterface("QueueMockResponse", mockResponses);
|
|
@@ -5229,34 +5897,33 @@ var queueFeature = defineFeature({
|
|
|
5229
5897
|
onStack(ctx) {
|
|
5230
5898
|
for (const [id, local] of Object.entries(ctx.stackConfig.queues || {})) {
|
|
5231
5899
|
const props = deepmerge3(ctx.appConfig.defaults.queue, typeof local === "object" ? local : {});
|
|
5232
|
-
const group = new
|
|
5900
|
+
const group = new Group12(ctx.stack, "queue", id);
|
|
5233
5901
|
const baseName = formatLocalResourceName({
|
|
5234
5902
|
appName: ctx.app.name,
|
|
5235
5903
|
stackName: ctx.stack.name,
|
|
5236
5904
|
resourceType: "queue",
|
|
5237
5905
|
resourceName: id
|
|
5238
5906
|
});
|
|
5239
|
-
const
|
|
5240
|
-
const queue2 = new aws12.sqs.Queue(group, "queue", {
|
|
5907
|
+
const queue2 = new aws13.sqs.Queue(group, "queue", {
|
|
5241
5908
|
name: `${baseName}.fifo`,
|
|
5242
|
-
visibilityTimeoutSeconds:
|
|
5243
|
-
receiveWaitTimeSeconds:
|
|
5244
|
-
messageRetentionSeconds:
|
|
5909
|
+
visibilityTimeoutSeconds: toSeconds5(props.visibilityTimeout),
|
|
5910
|
+
receiveWaitTimeSeconds: toSeconds5(props.receiveMessageWaitTime ?? seconds8(0)),
|
|
5911
|
+
messageRetentionSeconds: toSeconds5(props.retentionPeriod),
|
|
5245
5912
|
maxMessageSize: toBytes(props.maxMessageSize),
|
|
5246
5913
|
fifoQueue: true,
|
|
5247
5914
|
deduplicationScope: "messageGroup",
|
|
5248
|
-
fifoThroughputLimit: "perMessageGroupId"
|
|
5249
|
-
redrivePolicy: onFailure.pipe(
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
)
|
|
5915
|
+
fifoThroughputLimit: "perMessageGroupId"
|
|
5916
|
+
// redrivePolicy: onFailure.pipe(arn =>
|
|
5917
|
+
// JSON.stringify({
|
|
5918
|
+
// deadLetterTargetArn: arn,
|
|
5919
|
+
// maxReceiveCount: props.retryAttempts + 1,
|
|
5920
|
+
// })
|
|
5921
|
+
// ),
|
|
5255
5922
|
});
|
|
5256
5923
|
if (local.consumer) {
|
|
5257
5924
|
const lambdaConsumer = createLambdaFunction(group, ctx, `queue`, id, local.consumer);
|
|
5258
5925
|
lambdaConsumer.setEnvironment("THROW_EXPECTED_ERRORS", "1");
|
|
5259
|
-
new
|
|
5926
|
+
new aws13.lambda.EventSourceMapping(
|
|
5260
5927
|
group,
|
|
5261
5928
|
"event",
|
|
5262
5929
|
{
|
|
@@ -5290,24 +5957,24 @@ var queueFeature = defineFeature({
|
|
|
5290
5957
|
});
|
|
5291
5958
|
|
|
5292
5959
|
// src/feature/rest/index.ts
|
|
5293
|
-
import { Group as
|
|
5294
|
-
import { aws as
|
|
5960
|
+
import { Group as Group13 } from "@terraforge/core";
|
|
5961
|
+
import { aws as aws14 } from "@terraforge/aws";
|
|
5295
5962
|
import { constantCase as constantCase7 } from "change-case";
|
|
5296
5963
|
var restFeature = defineFeature({
|
|
5297
5964
|
name: "rest",
|
|
5298
5965
|
onApp(ctx) {
|
|
5299
5966
|
for (const [id, props] of Object.entries(ctx.appConfig.defaults?.rest ?? {})) {
|
|
5300
|
-
const group = new
|
|
5967
|
+
const group = new Group13(ctx.base, "rest", id);
|
|
5301
5968
|
const name = formatGlobalResourceName({
|
|
5302
5969
|
appName: ctx.app.name,
|
|
5303
5970
|
resourceType: "rest",
|
|
5304
5971
|
resourceName: id
|
|
5305
5972
|
});
|
|
5306
|
-
const api = new
|
|
5973
|
+
const api = new aws14.apigatewayv2.Api(group, "api", {
|
|
5307
5974
|
name,
|
|
5308
5975
|
protocolType: "HTTP"
|
|
5309
5976
|
});
|
|
5310
|
-
const stage = new
|
|
5977
|
+
const stage = new aws14.apigatewayv2.Stage(group, "stage", {
|
|
5311
5978
|
name: "v1",
|
|
5312
5979
|
apiId: api.id,
|
|
5313
5980
|
autoDeploy: true
|
|
@@ -5317,7 +5984,7 @@ var restFeature = defineFeature({
|
|
|
5317
5984
|
const domainName = formatFullDomainName(ctx.appConfig, props.domain, props.subDomain);
|
|
5318
5985
|
const zoneId = ctx.shared.entry("domain", `zone-id`, props.domain);
|
|
5319
5986
|
const certificateArn = ctx.shared.entry("domain", `certificate-arn`, props.domain);
|
|
5320
|
-
const domain2 = new
|
|
5987
|
+
const domain2 = new aws14.apigatewayv2.DomainName(group, "domain", {
|
|
5321
5988
|
domainName,
|
|
5322
5989
|
domainNameConfiguration: {
|
|
5323
5990
|
certificateArn,
|
|
@@ -5325,12 +5992,12 @@ var restFeature = defineFeature({
|
|
|
5325
5992
|
securityPolicy: "TLS_1_2"
|
|
5326
5993
|
}
|
|
5327
5994
|
});
|
|
5328
|
-
const mapping = new
|
|
5995
|
+
const mapping = new aws14.apigatewayv2.ApiMapping(group, "mapping", {
|
|
5329
5996
|
apiId: api.id,
|
|
5330
5997
|
domainName: domain2.domainName,
|
|
5331
5998
|
stage: stage.name
|
|
5332
5999
|
});
|
|
5333
|
-
new
|
|
6000
|
+
new aws14.route53.Record(
|
|
5334
6001
|
group,
|
|
5335
6002
|
"record",
|
|
5336
6003
|
{
|
|
@@ -5358,21 +6025,21 @@ var restFeature = defineFeature({
|
|
|
5358
6025
|
},
|
|
5359
6026
|
onStack(ctx) {
|
|
5360
6027
|
for (const [id, routes] of Object.entries(ctx.stackConfig.rest ?? {})) {
|
|
5361
|
-
const restGroup = new
|
|
6028
|
+
const restGroup = new Group13(ctx.stack, "rest", id);
|
|
5362
6029
|
for (const [routeKey, props] of Object.entries(routes)) {
|
|
5363
|
-
const group = new
|
|
6030
|
+
const group = new Group13(restGroup, "route", routeKey);
|
|
5364
6031
|
const apiId = ctx.shared.entry("rest", "id", id);
|
|
5365
6032
|
const routeId = shortId(routeKey);
|
|
5366
6033
|
const { lambda } = createLambdaFunction(group, ctx, "rest", `${id}-${routeId}`, {
|
|
5367
6034
|
...props,
|
|
5368
6035
|
description: `${id} ${routeKey}`
|
|
5369
6036
|
});
|
|
5370
|
-
const permission = new
|
|
6037
|
+
const permission = new aws14.lambda.Permission(group, "permission", {
|
|
5371
6038
|
action: "lambda:InvokeFunction",
|
|
5372
6039
|
principal: "apigateway.amazonaws.com",
|
|
5373
6040
|
functionName: lambda.functionName
|
|
5374
6041
|
});
|
|
5375
|
-
const integration = new
|
|
6042
|
+
const integration = new aws14.apigatewayv2.Integration(group, "integration", {
|
|
5376
6043
|
apiId,
|
|
5377
6044
|
description: `${id} ${routeKey}`,
|
|
5378
6045
|
integrationType: "AWS_PROXY",
|
|
@@ -5382,7 +6049,7 @@ var restFeature = defineFeature({
|
|
|
5382
6049
|
return `arn:aws:apigateway:${ctx.appConfig.region}:lambda:path/2015-03-31/functions/${arn}/invocations`;
|
|
5383
6050
|
})
|
|
5384
6051
|
});
|
|
5385
|
-
new
|
|
6052
|
+
new aws14.apigatewayv2.Route(
|
|
5386
6053
|
group,
|
|
5387
6054
|
"route",
|
|
5388
6055
|
{
|
|
@@ -5401,13 +6068,13 @@ var restFeature = defineFeature({
|
|
|
5401
6068
|
|
|
5402
6069
|
// src/feature/rpc/index.ts
|
|
5403
6070
|
import { camelCase as camelCase6, constantCase as constantCase8, kebabCase as kebabCase6 } from "change-case";
|
|
5404
|
-
import { Group as
|
|
5405
|
-
import { aws as
|
|
5406
|
-
import { mebibytes as
|
|
5407
|
-
import { dirname as
|
|
5408
|
-
import { fileURLToPath } from "url";
|
|
5409
|
-
import { toSeconds as
|
|
5410
|
-
var
|
|
6071
|
+
import { Group as Group14 } from "@terraforge/core";
|
|
6072
|
+
import { aws as aws15 } from "@terraforge/aws";
|
|
6073
|
+
import { mebibytes as mebibytes6 } from "@awsless/size";
|
|
6074
|
+
import { dirname as dirname7, join as join15, relative as relative6 } from "path";
|
|
6075
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
6076
|
+
import { toSeconds as toSeconds6 } from "@awsless/duration";
|
|
6077
|
+
var __dirname4 = dirname7(fileURLToPath3(import.meta.url));
|
|
5411
6078
|
var rpcFeature = defineFeature({
|
|
5412
6079
|
name: "rpc",
|
|
5413
6080
|
async onTypeGen(ctx) {
|
|
@@ -5451,8 +6118,8 @@ var rpcFeature = defineFeature({
|
|
|
5451
6118
|
} else {
|
|
5452
6119
|
list3.add(name);
|
|
5453
6120
|
}
|
|
5454
|
-
const timeout =
|
|
5455
|
-
const maxTimeout =
|
|
6121
|
+
const timeout = toSeconds6(props.function.timeout ?? ctx.appConfig.defaults.function.timeout);
|
|
6122
|
+
const maxTimeout = toSeconds6(ctx.appConfig.defaults.rpc[id].timeout) * 0.8;
|
|
5456
6123
|
if (timeout > maxTimeout) {
|
|
5457
6124
|
throw new FileError(
|
|
5458
6125
|
stack.file,
|
|
@@ -5465,19 +6132,19 @@ var rpcFeature = defineFeature({
|
|
|
5465
6132
|
},
|
|
5466
6133
|
onApp(ctx) {
|
|
5467
6134
|
for (const [id, props] of Object.entries(ctx.appConfig.defaults.rpc ?? {})) {
|
|
5468
|
-
const group = new
|
|
6135
|
+
const group = new Group14(ctx.base, "rpc", id);
|
|
5469
6136
|
const result = createPrebuildLambdaFunction(group, ctx, "rpc", id, {
|
|
5470
|
-
bundleFile:
|
|
5471
|
-
bundleHash:
|
|
5472
|
-
memorySize:
|
|
6137
|
+
bundleFile: join15(__dirname4, "/prebuild/rpc/bundle.zip"),
|
|
6138
|
+
bundleHash: join15(__dirname4, "/prebuild/rpc/HASH"),
|
|
6139
|
+
memorySize: mebibytes6(256),
|
|
5473
6140
|
timeout: props.timeout,
|
|
5474
6141
|
handler: "index.default",
|
|
5475
6142
|
runtime: "nodejs24.x",
|
|
5476
6143
|
warm: 3,
|
|
5477
6144
|
log: props.log
|
|
5478
6145
|
});
|
|
5479
|
-
result.setEnvironment("TIMEOUT",
|
|
5480
|
-
const schemaTable = new
|
|
6146
|
+
result.setEnvironment("TIMEOUT", toSeconds6(props.timeout).toString());
|
|
6147
|
+
const schemaTable = new aws15.dynamodb.Table(group, "schema", {
|
|
5481
6148
|
name: formatGlobalResourceName({
|
|
5482
6149
|
appName: ctx.app.name,
|
|
5483
6150
|
resourceType: "rpc-schema",
|
|
@@ -5499,7 +6166,7 @@ var rpcFeature = defineFeature({
|
|
|
5499
6166
|
resources: [schemaTable.arn]
|
|
5500
6167
|
});
|
|
5501
6168
|
ctx.shared.add("rpc", `schema-table`, id, schemaTable);
|
|
5502
|
-
const lockTable = new
|
|
6169
|
+
const lockTable = new aws15.dynamodb.Table(group, "lock", {
|
|
5503
6170
|
name: formatGlobalResourceName({
|
|
5504
6171
|
appName: ctx.app.name,
|
|
5505
6172
|
resourceType: "rpc-lock",
|
|
@@ -5525,7 +6192,7 @@ var rpcFeature = defineFeature({
|
|
|
5525
6192
|
resources: [lockTable.arn]
|
|
5526
6193
|
});
|
|
5527
6194
|
if (props.auth) {
|
|
5528
|
-
const authGroup = new
|
|
6195
|
+
const authGroup = new Group14(group, "auth", "authorizer");
|
|
5529
6196
|
const auth2 = createLambdaFunction(authGroup, ctx, "rpc", `${id}-auth`, props.auth);
|
|
5530
6197
|
result.setEnvironment("AUTH", auth2.name);
|
|
5531
6198
|
for (const [authId, userPoolId] of ctx.shared.list("auth", "user-pool-id")) {
|
|
@@ -5544,14 +6211,14 @@ var rpcFeature = defineFeature({
|
|
|
5544
6211
|
imageUri: result.lambda.imageUri
|
|
5545
6212
|
});
|
|
5546
6213
|
}
|
|
5547
|
-
const permission = new
|
|
6214
|
+
const permission = new aws15.lambda.Permission(group, "permission", {
|
|
5548
6215
|
principal: "cloudfront.amazonaws.com",
|
|
5549
6216
|
action: "lambda:InvokeFunctionUrl",
|
|
5550
6217
|
functionName: result.lambda.functionName,
|
|
5551
6218
|
functionUrlAuthType: "AWS_IAM",
|
|
5552
6219
|
sourceArn: `arn:aws:cloudfront::${ctx.accountId}:distribution/*`
|
|
5553
6220
|
});
|
|
5554
|
-
const url = new
|
|
6221
|
+
const url = new aws15.lambda.FunctionUrl(
|
|
5555
6222
|
group,
|
|
5556
6223
|
"url",
|
|
5557
6224
|
{
|
|
@@ -5586,15 +6253,15 @@ var rpcFeature = defineFeature({
|
|
|
5586
6253
|
throw new FileError(ctx.stackConfig.file, `RPC definition is not defined on app level for "${id}"`);
|
|
5587
6254
|
}
|
|
5588
6255
|
const table = ctx.shared.entry("rpc", "schema-table", id);
|
|
5589
|
-
const group = new
|
|
6256
|
+
const group = new Group14(ctx.stack, "rpc", id);
|
|
5590
6257
|
for (const [name, props] of Object.entries(queries ?? {})) {
|
|
5591
|
-
const queryGroup = new
|
|
6258
|
+
const queryGroup = new Group14(group, "query", name);
|
|
5592
6259
|
const entryId = kebabCase6(`${id}-${shortId(name)}`);
|
|
5593
6260
|
createLambdaFunction(queryGroup, ctx, `rpc`, entryId, {
|
|
5594
6261
|
...props.function,
|
|
5595
6262
|
description: `${id} ${name}`
|
|
5596
6263
|
});
|
|
5597
|
-
new
|
|
6264
|
+
new aws15.dynamodb.TableItem(queryGroup, "query", {
|
|
5598
6265
|
tableName: table.name,
|
|
5599
6266
|
hashKey: table.hashKey,
|
|
5600
6267
|
rangeKey: table.rangeKey,
|
|
@@ -5626,11 +6293,11 @@ var rpcFeature = defineFeature({
|
|
|
5626
6293
|
});
|
|
5627
6294
|
|
|
5628
6295
|
// src/feature/search/index.ts
|
|
5629
|
-
import { Group as
|
|
5630
|
-
import { aws as
|
|
6296
|
+
import { Group as Group15 } from "@terraforge/core";
|
|
6297
|
+
import { aws as aws16 } from "@terraforge/aws";
|
|
5631
6298
|
import { constantCase as constantCase9 } from "change-case";
|
|
5632
6299
|
import { toGibibytes as toGibibytes2 } from "@awsless/size";
|
|
5633
|
-
var
|
|
6300
|
+
var typeGenCode6 = `
|
|
5634
6301
|
import { AnyStruct, Table } from '@awsless/open-search'
|
|
5635
6302
|
|
|
5636
6303
|
type Search = {
|
|
@@ -5650,15 +6317,15 @@ var searchFeature = defineFeature({
|
|
|
5650
6317
|
}
|
|
5651
6318
|
resources2.addType(stack.name, list3);
|
|
5652
6319
|
}
|
|
5653
|
-
gen.addCode(
|
|
6320
|
+
gen.addCode(typeGenCode6);
|
|
5654
6321
|
gen.addInterface("SearchResources", resources2);
|
|
5655
6322
|
await ctx.write("search.d.ts", gen, true);
|
|
5656
6323
|
},
|
|
5657
6324
|
onStack(ctx) {
|
|
5658
6325
|
for (const [id, props] of Object.entries(ctx.stackConfig.searchs ?? {})) {
|
|
5659
|
-
const group = new
|
|
6326
|
+
const group = new Group15(ctx.stack, "search", id);
|
|
5660
6327
|
const name = `${ctx.app.name}-${shortId([ctx.app.name, ctx.stack.name, "search", id].join("--"))}`;
|
|
5661
|
-
const openSearch = new
|
|
6328
|
+
const openSearch = new aws16.opensearch.Domain(
|
|
5662
6329
|
group,
|
|
5663
6330
|
"domain",
|
|
5664
6331
|
{
|
|
@@ -5733,10 +6400,10 @@ var searchFeature = defineFeature({
|
|
|
5733
6400
|
});
|
|
5734
6401
|
|
|
5735
6402
|
// src/feature/site/index.ts
|
|
5736
|
-
import { Group as
|
|
5737
|
-
import { aws as
|
|
6403
|
+
import { Group as Group16 } from "@terraforge/core";
|
|
6404
|
+
import { aws as aws17 } from "@terraforge/aws";
|
|
5738
6405
|
import { glob as glob2 } from "glob";
|
|
5739
|
-
import { dirname as
|
|
6406
|
+
import { dirname as dirname8, join as join16 } from "path";
|
|
5740
6407
|
|
|
5741
6408
|
// src/feature/site/util.ts
|
|
5742
6409
|
import { contentType, lookup } from "mime-types";
|
|
@@ -5764,7 +6431,7 @@ var siteFeature = defineFeature({
|
|
|
5764
6431
|
name: "site",
|
|
5765
6432
|
onStack(ctx) {
|
|
5766
6433
|
for (const [id, props] of Object.entries(ctx.stackConfig.sites ?? {})) {
|
|
5767
|
-
const group = new
|
|
6434
|
+
const group = new Group16(ctx.stack, "site", id);
|
|
5768
6435
|
const name = formatLocalResourceName({
|
|
5769
6436
|
appName: ctx.app.name,
|
|
5770
6437
|
stackName: ctx.stack.name,
|
|
@@ -5782,7 +6449,7 @@ var siteFeature = defineFeature({
|
|
|
5782
6449
|
return build3(fingerprint, async (write) => {
|
|
5783
6450
|
const credentialProvider = await getCredentials(ctx.appConfig.profile);
|
|
5784
6451
|
const credentials = await credentialProvider();
|
|
5785
|
-
const cwd =
|
|
6452
|
+
const cwd = join16(directories.root, dirname8(ctx.stackConfig.file));
|
|
5786
6453
|
const env = {
|
|
5787
6454
|
...process.env,
|
|
5788
6455
|
// Pass the app config name
|
|
@@ -5829,14 +6496,14 @@ var siteFeature = defineFeature({
|
|
|
5829
6496
|
ctx.onBind((name2, value) => {
|
|
5830
6497
|
result.setEnvironment(name2, value);
|
|
5831
6498
|
});
|
|
5832
|
-
new
|
|
6499
|
+
new aws17.lambda.Permission(group, "ssr-permission", {
|
|
5833
6500
|
principal: "cloudfront.amazonaws.com",
|
|
5834
6501
|
action: "lambda:InvokeFunctionUrl",
|
|
5835
6502
|
functionName: result.lambda.functionName,
|
|
5836
6503
|
functionUrlAuthType: "AWS_IAM",
|
|
5837
6504
|
sourceArn: `arn:aws:cloudfront::${ctx.accountId}:distribution/*`
|
|
5838
6505
|
});
|
|
5839
|
-
const functionUrl = new
|
|
6506
|
+
const functionUrl = new aws17.lambda.FunctionUrl(group, "url", {
|
|
5840
6507
|
functionName: result.lambda.functionName,
|
|
5841
6508
|
authorizationType: "AWS_IAM"
|
|
5842
6509
|
});
|
|
@@ -5850,7 +6517,7 @@ var siteFeature = defineFeature({
|
|
|
5850
6517
|
});
|
|
5851
6518
|
}
|
|
5852
6519
|
if (props.static) {
|
|
5853
|
-
const bucket = new
|
|
6520
|
+
const bucket = new aws17.s3.Bucket(group, "bucket", {
|
|
5854
6521
|
bucket: formatLocalResourceName({
|
|
5855
6522
|
appName: ctx.app.name,
|
|
5856
6523
|
stackName: ctx.stack.name,
|
|
@@ -5872,7 +6539,7 @@ var siteFeature = defineFeature({
|
|
|
5872
6539
|
}
|
|
5873
6540
|
]
|
|
5874
6541
|
});
|
|
5875
|
-
new
|
|
6542
|
+
new aws17.s3.BucketPolicy(
|
|
5876
6543
|
group,
|
|
5877
6544
|
`policy`,
|
|
5878
6545
|
{
|
|
@@ -5927,20 +6594,20 @@ var siteFeature = defineFeature({
|
|
|
5927
6594
|
});
|
|
5928
6595
|
const staticRoutes = {};
|
|
5929
6596
|
for (const file of files) {
|
|
5930
|
-
const prefixedFile =
|
|
5931
|
-
const object = new
|
|
6597
|
+
const prefixedFile = join16("/", file);
|
|
6598
|
+
const object = new aws17.s3.BucketObject(group, prefixedFile, {
|
|
5932
6599
|
bucket: bucket.bucket,
|
|
5933
6600
|
key: prefixedFile,
|
|
5934
6601
|
cacheControl: getCacheControl(file),
|
|
5935
6602
|
contentType: getContentType(file),
|
|
5936
|
-
source:
|
|
5937
|
-
sourceHash: $hash(
|
|
6603
|
+
source: join16(props.static, file),
|
|
6604
|
+
sourceHash: $hash(join16(props.static, file))
|
|
5938
6605
|
});
|
|
5939
6606
|
versions.push(object.key);
|
|
5940
6607
|
versions.push(object.sourceHash);
|
|
5941
6608
|
const strippedHtmlFile = file.endsWith("index.html") ? file.slice(0, -11) : file.endsWith(".html") ? file.slice(0, -5) : file;
|
|
5942
6609
|
const urlFriendlyFile = strippedHtmlFile.endsWith("/") ? strippedHtmlFile.slice(0, -1) : strippedHtmlFile;
|
|
5943
|
-
const routeFileKey =
|
|
6610
|
+
const routeFileKey = join16(props.path, urlFriendlyFile);
|
|
5944
6611
|
staticRoutes[routeFileKey] = {
|
|
5945
6612
|
type: "s3",
|
|
5946
6613
|
domainName: bucket.bucketRegionalDomainName,
|
|
@@ -5957,10 +6624,10 @@ var siteFeature = defineFeature({
|
|
|
5957
6624
|
});
|
|
5958
6625
|
|
|
5959
6626
|
// src/feature/store/index.ts
|
|
5960
|
-
import { Group as
|
|
5961
|
-
import { toDays as
|
|
6627
|
+
import { Group as Group17 } from "@terraforge/core";
|
|
6628
|
+
import { toDays as toDays8 } from "@awsless/duration";
|
|
5962
6629
|
import { kebabCase as kebabCase7 } from "change-case";
|
|
5963
|
-
import { aws as
|
|
6630
|
+
import { aws as aws18 } from "@terraforge/aws";
|
|
5964
6631
|
import { glob as glob3 } from "glob";
|
|
5965
6632
|
|
|
5966
6633
|
// src/feature/store/util.ts
|
|
@@ -5984,8 +6651,8 @@ var getContentType2 = (file) => {
|
|
|
5984
6651
|
};
|
|
5985
6652
|
|
|
5986
6653
|
// src/feature/store/index.ts
|
|
5987
|
-
import { join as
|
|
5988
|
-
var
|
|
6654
|
+
import { join as join17 } from "path";
|
|
6655
|
+
var typeGenCode7 = `
|
|
5989
6656
|
import { Body, PutObjectProps, BodyStream } from '@awsless/s3'
|
|
5990
6657
|
|
|
5991
6658
|
type Store<Name extends string> = {
|
|
@@ -6014,7 +6681,7 @@ var storeFeature = defineFeature({
|
|
|
6014
6681
|
}
|
|
6015
6682
|
resources2.addType(stack.name, list3);
|
|
6016
6683
|
}
|
|
6017
|
-
gen.addCode(
|
|
6684
|
+
gen.addCode(typeGenCode7);
|
|
6018
6685
|
gen.addInterface("StoreResources", resources2);
|
|
6019
6686
|
await ctx.write("store.d.ts", gen, true);
|
|
6020
6687
|
},
|
|
@@ -6052,7 +6719,7 @@ var storeFeature = defineFeature({
|
|
|
6052
6719
|
},
|
|
6053
6720
|
onStack(ctx) {
|
|
6054
6721
|
for (const [id, props] of Object.entries(ctx.stackConfig.stores ?? {})) {
|
|
6055
|
-
const group = new
|
|
6722
|
+
const group = new Group17(ctx.stack, "store", id);
|
|
6056
6723
|
const name = formatLocalResourceName({
|
|
6057
6724
|
appName: ctx.app.name,
|
|
6058
6725
|
stackName: ctx.stack.name,
|
|
@@ -6064,9 +6731,9 @@ var storeFeature = defineFeature({
|
|
|
6064
6731
|
id: rule.prefix ? `expire-${kebabCase7(rule.prefix)}` : `expire-rule-${index}`,
|
|
6065
6732
|
enabled: true,
|
|
6066
6733
|
...rule.prefix ? { prefix: rule.prefix } : {},
|
|
6067
|
-
expiration: { days:
|
|
6734
|
+
expiration: { days: toDays8(rule.expiration) }
|
|
6068
6735
|
}));
|
|
6069
|
-
const bucket = new
|
|
6736
|
+
const bucket = new aws18.s3.Bucket(
|
|
6070
6737
|
group,
|
|
6071
6738
|
"store",
|
|
6072
6739
|
{
|
|
@@ -6098,13 +6765,13 @@ var storeFeature = defineFeature({
|
|
|
6098
6765
|
nodir: true
|
|
6099
6766
|
});
|
|
6100
6767
|
for (const file of files) {
|
|
6101
|
-
new
|
|
6768
|
+
new aws18.s3.BucketObject(group, file, {
|
|
6102
6769
|
bucket: bucket.bucket,
|
|
6103
6770
|
key: file,
|
|
6104
6771
|
cacheControl: getCacheControl2(file),
|
|
6105
6772
|
contentType: getContentType2(file),
|
|
6106
|
-
source:
|
|
6107
|
-
sourceHash: $hash(
|
|
6773
|
+
source: join17(props.static, file),
|
|
6774
|
+
sourceHash: $hash(join17(props.static, file))
|
|
6108
6775
|
});
|
|
6109
6776
|
}
|
|
6110
6777
|
}
|
|
@@ -6120,7 +6787,7 @@ var storeFeature = defineFeature({
|
|
|
6120
6787
|
"removed:marker": "s3:ObjectRemoved:DeleteMarkerCreated"
|
|
6121
6788
|
};
|
|
6122
6789
|
for (const [event, taskProps] of Object.entries(props.events ?? {})) {
|
|
6123
|
-
const eventGroup = new
|
|
6790
|
+
const eventGroup = new Group17(group, "event", event);
|
|
6124
6791
|
const eventId = kebabCase7(`${id}-${shortId(event)}`);
|
|
6125
6792
|
const { lambda } = createAsyncLambdaFunction(eventGroup, ctx, `store`, eventId, {
|
|
6126
6793
|
...taskProps,
|
|
@@ -6129,13 +6796,13 @@ var storeFeature = defineFeature({
|
|
|
6129
6796
|
description: `${id} event "${event}"`
|
|
6130
6797
|
}
|
|
6131
6798
|
});
|
|
6132
|
-
new
|
|
6799
|
+
new aws18.lambda.Permission(eventGroup, "permission", {
|
|
6133
6800
|
action: "lambda:InvokeFunction",
|
|
6134
6801
|
principal: "s3.amazonaws.com",
|
|
6135
6802
|
functionName: lambda.functionName,
|
|
6136
6803
|
sourceArn: `arn:aws:s3:::${name}`
|
|
6137
6804
|
});
|
|
6138
|
-
new
|
|
6805
|
+
new aws18.s3.BucketNotification(eventGroup, "notification", {
|
|
6139
6806
|
bucket: bucket.bucket,
|
|
6140
6807
|
lambdaFunction: [
|
|
6141
6808
|
{
|
|
@@ -6174,10 +6841,10 @@ var storeFeature = defineFeature({
|
|
|
6174
6841
|
});
|
|
6175
6842
|
|
|
6176
6843
|
// src/feature/table/index.ts
|
|
6177
|
-
import { Group as
|
|
6178
|
-
import { aws as
|
|
6844
|
+
import { Group as Group18 } from "@terraforge/core";
|
|
6845
|
+
import { aws as aws19 } from "@terraforge/aws";
|
|
6179
6846
|
import { constantCase as constantCase11 } from "change-case";
|
|
6180
|
-
import { toSeconds as
|
|
6847
|
+
import { toSeconds as toSeconds7 } from "@awsless/duration";
|
|
6181
6848
|
var tableFeature = defineFeature({
|
|
6182
6849
|
name: "table",
|
|
6183
6850
|
async onTypeGen(ctx) {
|
|
@@ -6226,7 +6893,7 @@ var tableFeature = defineFeature({
|
|
|
6226
6893
|
},
|
|
6227
6894
|
onStack(ctx) {
|
|
6228
6895
|
for (const [id, props] of Object.entries(ctx.stackConfig.tables ?? {})) {
|
|
6229
|
-
const group = new
|
|
6896
|
+
const group = new Group18(ctx.stack, "table", id);
|
|
6230
6897
|
const name = formatLocalResourceName({
|
|
6231
6898
|
appName: ctx.app.name,
|
|
6232
6899
|
stackName: ctx.stack.name,
|
|
@@ -6255,7 +6922,7 @@ var tableFeature = defineFeature({
|
|
|
6255
6922
|
type: types2[props.fields?.[name2] ?? "string"]
|
|
6256
6923
|
}));
|
|
6257
6924
|
};
|
|
6258
|
-
const table = new
|
|
6925
|
+
const table = new aws19.dynamodb.Table(
|
|
6259
6926
|
group,
|
|
6260
6927
|
"table",
|
|
6261
6928
|
{
|
|
@@ -6299,7 +6966,7 @@ var tableFeature = defineFeature({
|
|
|
6299
6966
|
const result = createLambdaFunction(group, ctx, "table", id, props.stream.consumer);
|
|
6300
6967
|
result.setEnvironment("THROW_EXPECTED_ERRORS", "1");
|
|
6301
6968
|
const onFailure = getGlobalOnFailure(ctx);
|
|
6302
|
-
new
|
|
6969
|
+
new aws19.lambda.EventSourceMapping(
|
|
6303
6970
|
group,
|
|
6304
6971
|
id,
|
|
6305
6972
|
{
|
|
@@ -6309,7 +6976,7 @@ var tableFeature = defineFeature({
|
|
|
6309
6976
|
// maximumRecordAgeInSeconds: toSeconds(props.stream.maxRecordAge),
|
|
6310
6977
|
// bisectBatchOnFunctionError: true,
|
|
6311
6978
|
batchSize: props.stream.batchSize,
|
|
6312
|
-
maximumBatchingWindowInSeconds: props.stream.batchWindow ?
|
|
6979
|
+
maximumBatchingWindowInSeconds: props.stream.batchWindow ? toSeconds7(props.stream.batchWindow) : void 0,
|
|
6313
6980
|
maximumRetryAttempts: props.stream.retryAttempts,
|
|
6314
6981
|
parallelizationFactor: props.stream.concurrencyPerShard,
|
|
6315
6982
|
functionResponseTypes: ["ReportBatchItemFailures"],
|
|
@@ -6375,11 +7042,11 @@ var tableFeature = defineFeature({
|
|
|
6375
7042
|
});
|
|
6376
7043
|
|
|
6377
7044
|
// src/feature/task/index.ts
|
|
6378
|
-
import { Group as
|
|
6379
|
-
import { aws as
|
|
7045
|
+
import { Group as Group19 } from "@terraforge/core";
|
|
7046
|
+
import { aws as aws20 } from "@terraforge/aws";
|
|
6380
7047
|
import { camelCase as camelCase7 } from "change-case";
|
|
6381
7048
|
import { relative as relative7 } from "path";
|
|
6382
|
-
var
|
|
7049
|
+
var typeGenCode8 = `
|
|
6383
7050
|
import { Duration } from '@awsless/duration'
|
|
6384
7051
|
import { InvokeOptions } from '@awsless/lambda'
|
|
6385
7052
|
import type { Mock } from 'vitest'
|
|
@@ -6437,26 +7104,26 @@ var taskFeature = defineFeature({
|
|
|
6437
7104
|
resources2.addType(stack.name, resource);
|
|
6438
7105
|
mockResponses.addType(stack.name, mockResponse);
|
|
6439
7106
|
}
|
|
6440
|
-
types2.addCode(
|
|
7107
|
+
types2.addCode(typeGenCode8);
|
|
6441
7108
|
types2.addInterface("TaskResources", resources2);
|
|
6442
7109
|
types2.addInterface("TaskMock", mocks);
|
|
6443
7110
|
types2.addInterface("TaskMockResponse", mockResponses);
|
|
6444
7111
|
await ctx.write("task.d.ts", types2, true);
|
|
6445
7112
|
},
|
|
6446
7113
|
onApp(ctx) {
|
|
6447
|
-
const group = new
|
|
7114
|
+
const group = new Group19(ctx.base, "task", "main");
|
|
6448
7115
|
const scheduleGroupName = formatGlobalResourceName({
|
|
6449
7116
|
appName: ctx.app.name,
|
|
6450
7117
|
resourceType: "task",
|
|
6451
7118
|
resourceName: "group"
|
|
6452
7119
|
});
|
|
6453
|
-
new
|
|
7120
|
+
new aws20.scheduler.ScheduleGroup(group, "group", {
|
|
6454
7121
|
name: scheduleGroupName,
|
|
6455
7122
|
tags: {
|
|
6456
7123
|
app: ctx.app.name
|
|
6457
7124
|
}
|
|
6458
7125
|
});
|
|
6459
|
-
const role = new
|
|
7126
|
+
const role = new aws20.iam.Role(group, "schedule", {
|
|
6460
7127
|
name: formatGlobalResourceName({
|
|
6461
7128
|
appName: ctx.app.name,
|
|
6462
7129
|
resourceType: "task",
|
|
@@ -6503,7 +7170,7 @@ var taskFeature = defineFeature({
|
|
|
6503
7170
|
},
|
|
6504
7171
|
onStack(ctx) {
|
|
6505
7172
|
for (const [id, props] of Object.entries(ctx.stackConfig.tasks ?? {})) {
|
|
6506
|
-
const group = new
|
|
7173
|
+
const group = new Group19(ctx.stack, "task", id);
|
|
6507
7174
|
createAsyncLambdaFunction(group, ctx, "task", id, props);
|
|
6508
7175
|
}
|
|
6509
7176
|
}
|
|
@@ -6528,9 +7195,9 @@ var testFeature = defineFeature({
|
|
|
6528
7195
|
});
|
|
6529
7196
|
|
|
6530
7197
|
// src/feature/topic/index.ts
|
|
6531
|
-
import { Group as
|
|
6532
|
-
import { aws as
|
|
6533
|
-
var
|
|
7198
|
+
import { Group as Group20 } from "@terraforge/core";
|
|
7199
|
+
import { aws as aws21 } from "@terraforge/aws";
|
|
7200
|
+
var typeGenCode9 = `
|
|
6534
7201
|
import type { PublishOptions } from '@awsless/sns'
|
|
6535
7202
|
|
|
6536
7203
|
type Publish<Name extends string> = {
|
|
@@ -6558,7 +7225,7 @@ var topicFeature = defineFeature({
|
|
|
6558
7225
|
resources2.addType(topic, `Publish<'${name}'>`);
|
|
6559
7226
|
mocks.addType(topic, `MockBuilder`);
|
|
6560
7227
|
}
|
|
6561
|
-
gen.addCode(
|
|
7228
|
+
gen.addCode(typeGenCode9);
|
|
6562
7229
|
gen.addInterface("TopicResources", resources2);
|
|
6563
7230
|
gen.addInterface("TopicMock", mocks);
|
|
6564
7231
|
gen.addInterface("TopicMockResponse", mockResponses);
|
|
@@ -6576,13 +7243,13 @@ var topicFeature = defineFeature({
|
|
|
6576
7243
|
},
|
|
6577
7244
|
onApp(ctx) {
|
|
6578
7245
|
for (const id of ctx.appConfig.defaults.topics ?? []) {
|
|
6579
|
-
const group = new
|
|
7246
|
+
const group = new Group20(ctx.base, "topic", id);
|
|
6580
7247
|
const name = formatGlobalResourceName({
|
|
6581
7248
|
appName: ctx.appConfig.name,
|
|
6582
7249
|
resourceType: "topic",
|
|
6583
7250
|
resourceName: id
|
|
6584
7251
|
});
|
|
6585
|
-
const topic = new
|
|
7252
|
+
const topic = new aws21.sns.Topic(group, "topic", {
|
|
6586
7253
|
name
|
|
6587
7254
|
});
|
|
6588
7255
|
ctx.shared.add("topic", `arn`, id, topic.arn);
|
|
@@ -6600,15 +7267,15 @@ var topicFeature = defineFeature({
|
|
|
6600
7267
|
},
|
|
6601
7268
|
onStack(ctx) {
|
|
6602
7269
|
for (const [id, props] of Object.entries(ctx.stackConfig.subscribers ?? {})) {
|
|
6603
|
-
const group = new
|
|
7270
|
+
const group = new Group20(ctx.stack, "topic", id);
|
|
6604
7271
|
const topicArn = ctx.shared.entry("topic", "arn", id);
|
|
6605
7272
|
const { lambda } = createAsyncLambdaFunction(group, ctx, `topic`, id, props);
|
|
6606
|
-
new
|
|
7273
|
+
new aws21.sns.TopicSubscription(group, id, {
|
|
6607
7274
|
topicArn,
|
|
6608
7275
|
protocol: "lambda",
|
|
6609
7276
|
endpoint: lambda.arn
|
|
6610
7277
|
});
|
|
6611
|
-
new
|
|
7278
|
+
new aws21.lambda.Permission(group, id, {
|
|
6612
7279
|
action: "lambda:InvokeFunction",
|
|
6613
7280
|
principal: "sns.amazonaws.com",
|
|
6614
7281
|
functionName: lambda.functionName,
|
|
@@ -6619,13 +7286,13 @@ var topicFeature = defineFeature({
|
|
|
6619
7286
|
});
|
|
6620
7287
|
|
|
6621
7288
|
// src/feature/vpc/index.ts
|
|
6622
|
-
import { Group as
|
|
6623
|
-
import { aws as
|
|
7289
|
+
import { Group as Group21 } from "@terraforge/core";
|
|
7290
|
+
import { aws as aws22 } from "@terraforge/aws";
|
|
6624
7291
|
var vpcFeature = defineFeature({
|
|
6625
7292
|
name: "vpc",
|
|
6626
7293
|
onApp(ctx) {
|
|
6627
|
-
const group = new
|
|
6628
|
-
const vpc = new
|
|
7294
|
+
const group = new Group21(ctx.base, "vpc", "main");
|
|
7295
|
+
const vpc = new aws22.Vpc(group, "vpc", {
|
|
6629
7296
|
tags: {
|
|
6630
7297
|
Name: ctx.app.name
|
|
6631
7298
|
},
|
|
@@ -6635,39 +7302,39 @@ var vpcFeature = defineFeature({
|
|
|
6635
7302
|
ipv6CidrBlockNetworkBorderGroup: ctx.appConfig.region,
|
|
6636
7303
|
assignGeneratedIpv6CidrBlock: true
|
|
6637
7304
|
});
|
|
6638
|
-
const privateRouteTable = new
|
|
7305
|
+
const privateRouteTable = new aws22.route.Table(group, "private", {
|
|
6639
7306
|
vpcId: vpc.id,
|
|
6640
7307
|
tags: {
|
|
6641
7308
|
Name: "private"
|
|
6642
7309
|
}
|
|
6643
7310
|
});
|
|
6644
|
-
const publicRouteTable = new
|
|
7311
|
+
const publicRouteTable = new aws22.route.Table(group, "public", {
|
|
6645
7312
|
vpcId: vpc.id,
|
|
6646
7313
|
tags: {
|
|
6647
7314
|
Name: "public"
|
|
6648
7315
|
}
|
|
6649
7316
|
});
|
|
6650
|
-
const gateway = new
|
|
7317
|
+
const gateway = new aws22.internet.Gateway(group, "gateway", {
|
|
6651
7318
|
tags: {
|
|
6652
7319
|
Name: ctx.app.name
|
|
6653
7320
|
}
|
|
6654
7321
|
});
|
|
6655
|
-
const egressOnlyInternetGateway = new
|
|
7322
|
+
const egressOnlyInternetGateway = new aws22.egress.OnlyInternetGateway(group, "gateway", {
|
|
6656
7323
|
vpcId: vpc.id,
|
|
6657
7324
|
tags: {
|
|
6658
7325
|
Name: ctx.app.name
|
|
6659
7326
|
}
|
|
6660
7327
|
});
|
|
6661
|
-
const attachment = new
|
|
7328
|
+
const attachment = new aws22.internet.GatewayAttachment(group, "attachment", {
|
|
6662
7329
|
vpcId: vpc.id,
|
|
6663
7330
|
internetGatewayId: gateway.id
|
|
6664
7331
|
});
|
|
6665
|
-
new
|
|
7332
|
+
new aws22.Route(group, "ipv4", {
|
|
6666
7333
|
routeTableId: publicRouteTable.id,
|
|
6667
7334
|
destinationCidrBlock: "0.0.0.0/0",
|
|
6668
7335
|
gatewayId: gateway.id
|
|
6669
7336
|
});
|
|
6670
|
-
new
|
|
7337
|
+
new aws22.Route(group, "ipv6", {
|
|
6671
7338
|
routeTableId: privateRouteTable.id,
|
|
6672
7339
|
destinationIpv6CidrBlock: "::/0",
|
|
6673
7340
|
egressOnlyGatewayId: egressOnlyInternetGateway.id
|
|
@@ -6692,7 +7359,7 @@ var vpcFeature = defineFeature({
|
|
|
6692
7359
|
for (const i in zones) {
|
|
6693
7360
|
const index = Number(i) + 1;
|
|
6694
7361
|
const id = `${type}-${index}`;
|
|
6695
|
-
const subnet = new
|
|
7362
|
+
const subnet = new aws22.Subnet(group, id, {
|
|
6696
7363
|
tags: {
|
|
6697
7364
|
Name: `${ctx.app.name}--${type}-${index}`
|
|
6698
7365
|
},
|
|
@@ -6706,7 +7373,7 @@ var vpcFeature = defineFeature({
|
|
|
6706
7373
|
return `${cidrBlock}${ipv6Identifier++}::/64`;
|
|
6707
7374
|
})
|
|
6708
7375
|
});
|
|
6709
|
-
new
|
|
7376
|
+
new aws22.route.TableAssociation(group, id, {
|
|
6710
7377
|
routeTableId: table.id,
|
|
6711
7378
|
subnetId: subnet.id
|
|
6712
7379
|
});
|
|
@@ -6719,9 +7386,9 @@ var vpcFeature = defineFeature({
|
|
|
6719
7386
|
});
|
|
6720
7387
|
|
|
6721
7388
|
// src/feature/alert/index.ts
|
|
6722
|
-
import { Group as
|
|
6723
|
-
import { aws as
|
|
6724
|
-
var
|
|
7389
|
+
import { Group as Group22 } from "@terraforge/core";
|
|
7390
|
+
import { aws as aws23 } from "@terraforge/aws";
|
|
7391
|
+
var typeGenCode10 = `
|
|
6725
7392
|
import type { PublishOptions } from '@awsless/sns'
|
|
6726
7393
|
|
|
6727
7394
|
type Alert<Name extends string> = {
|
|
@@ -6749,7 +7416,7 @@ var alertFeature = defineFeature({
|
|
|
6749
7416
|
mockResponses.addType(alert, "Mock");
|
|
6750
7417
|
mocks.addType(alert, `MockBuilder`);
|
|
6751
7418
|
}
|
|
6752
|
-
gen.addCode(
|
|
7419
|
+
gen.addCode(typeGenCode10);
|
|
6753
7420
|
gen.addInterface("AlertResources", resources2);
|
|
6754
7421
|
gen.addInterface("AlertMock", mocks);
|
|
6755
7422
|
gen.addInterface("AlertMockResponse", mockResponses);
|
|
@@ -6757,17 +7424,17 @@ var alertFeature = defineFeature({
|
|
|
6757
7424
|
},
|
|
6758
7425
|
onApp(ctx) {
|
|
6759
7426
|
for (const [id, emails] of Object.entries(ctx.appConfig.defaults.alerts ?? {})) {
|
|
6760
|
-
const group = new
|
|
7427
|
+
const group = new Group22(ctx.base, "alert", id);
|
|
6761
7428
|
const name = formatGlobalResourceName({
|
|
6762
7429
|
appName: ctx.appConfig.name,
|
|
6763
7430
|
resourceType: "alert",
|
|
6764
7431
|
resourceName: id
|
|
6765
7432
|
});
|
|
6766
|
-
const topic = new
|
|
7433
|
+
const topic = new aws23.sns.Topic(group, "topic", {
|
|
6767
7434
|
name
|
|
6768
7435
|
});
|
|
6769
7436
|
for (const email of emails) {
|
|
6770
|
-
new
|
|
7437
|
+
new aws23.sns.TopicSubscription(group, email, {
|
|
6771
7438
|
topicArn: topic.arn,
|
|
6772
7439
|
protocol: "email",
|
|
6773
7440
|
endpoint: email
|
|
@@ -6788,13 +7455,13 @@ var alertFeature = defineFeature({
|
|
|
6788
7455
|
});
|
|
6789
7456
|
|
|
6790
7457
|
// src/feature/layer/index.ts
|
|
6791
|
-
import { Group as
|
|
6792
|
-
import { aws as
|
|
7458
|
+
import { Group as Group23 } from "@terraforge/core";
|
|
7459
|
+
import { aws as aws24 } from "@terraforge/aws";
|
|
6793
7460
|
var layerFeature = defineFeature({
|
|
6794
7461
|
name: "layer",
|
|
6795
7462
|
onBefore(ctx) {
|
|
6796
|
-
const group = new
|
|
6797
|
-
const bucket = new
|
|
7463
|
+
const group = new Group23(ctx.base, "layer", "asset");
|
|
7464
|
+
const bucket = new aws24.s3.Bucket(group, "bucket", {
|
|
6798
7465
|
bucket: formatGlobalResourceName({
|
|
6799
7466
|
appName: ctx.app.name,
|
|
6800
7467
|
resourceType: "layer",
|
|
@@ -6826,15 +7493,15 @@ var layerFeature = defineFeature({
|
|
|
6826
7493
|
}
|
|
6827
7494
|
for (const [id, _props] of layers) {
|
|
6828
7495
|
const props = _props;
|
|
6829
|
-
const group = new
|
|
6830
|
-
const zip = new
|
|
7496
|
+
const group = new Group23(ctx.base, "layer", id);
|
|
7497
|
+
const zip = new aws24.s3.BucketObject(group, "zip", {
|
|
6831
7498
|
bucket: ctx.shared.get("layer", "bucket-name"),
|
|
6832
7499
|
key: `/layer/${id}.zip`,
|
|
6833
7500
|
contentType: "application/zip",
|
|
6834
7501
|
source: props.file,
|
|
6835
7502
|
sourceHash: $hash(props.file)
|
|
6836
7503
|
});
|
|
6837
|
-
const layer = new
|
|
7504
|
+
const layer = new aws24.lambda.LayerVersion(
|
|
6838
7505
|
group,
|
|
6839
7506
|
"layer",
|
|
6840
7507
|
{
|
|
@@ -6869,14 +7536,14 @@ var layerFeature = defineFeature({
|
|
|
6869
7536
|
});
|
|
6870
7537
|
|
|
6871
7538
|
// src/feature/image/index.ts
|
|
6872
|
-
import { Group as
|
|
6873
|
-
import { aws as
|
|
6874
|
-
import { join as
|
|
6875
|
-
import { mebibytes as
|
|
6876
|
-
import { seconds as
|
|
6877
|
-
import { fileURLToPath as
|
|
7539
|
+
import { Group as Group24 } from "@terraforge/core";
|
|
7540
|
+
import { aws as aws25 } from "@terraforge/aws";
|
|
7541
|
+
import { join as join18, dirname as dirname9 } from "path";
|
|
7542
|
+
import { mebibytes as mebibytes7 } from "@awsless/size";
|
|
7543
|
+
import { seconds as seconds9, toDays as toDays9 } from "@awsless/duration";
|
|
7544
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
6878
7545
|
import { glob as glob4 } from "glob";
|
|
6879
|
-
var
|
|
7546
|
+
var __dirname5 = dirname9(fileURLToPath4(import.meta.url));
|
|
6880
7547
|
var imageFeature = defineFeature({
|
|
6881
7548
|
name: "image",
|
|
6882
7549
|
onApp(ctx) {
|
|
@@ -6886,21 +7553,21 @@ var imageFeature = defineFeature({
|
|
|
6886
7553
|
if (found.length === 0) {
|
|
6887
7554
|
return;
|
|
6888
7555
|
}
|
|
6889
|
-
const group = new
|
|
6890
|
-
const path =
|
|
7556
|
+
const group = new Group24(ctx.base, "image", "layer");
|
|
7557
|
+
const path = join18(__dirname5, "/layers/sharp-arm.zip");
|
|
6891
7558
|
const layerId = formatGlobalResourceName({
|
|
6892
7559
|
appName: ctx.appConfig.name,
|
|
6893
7560
|
resourceType: "layer",
|
|
6894
7561
|
resourceName: "sharp"
|
|
6895
7562
|
});
|
|
6896
|
-
const zipFile = new
|
|
7563
|
+
const zipFile = new aws25.s3.BucketObject(group, "layer", {
|
|
6897
7564
|
bucket: ctx.shared.get("layer", "bucket-name"),
|
|
6898
7565
|
key: `/layer/${layerId}.zip`,
|
|
6899
7566
|
contentType: "application/zip",
|
|
6900
7567
|
source: path,
|
|
6901
7568
|
sourceHash: $hash(path)
|
|
6902
7569
|
});
|
|
6903
|
-
const layer = new
|
|
7570
|
+
const layer = new aws25.lambda.LayerVersion(
|
|
6904
7571
|
group,
|
|
6905
7572
|
"layer",
|
|
6906
7573
|
{
|
|
@@ -6927,7 +7594,7 @@ var imageFeature = defineFeature({
|
|
|
6927
7594
|
},
|
|
6928
7595
|
onStack(ctx) {
|
|
6929
7596
|
for (const [id, props] of Object.entries(ctx.stackConfig.images ?? {})) {
|
|
6930
|
-
const group = new
|
|
7597
|
+
const group = new Group24(ctx.stack, "image", id);
|
|
6931
7598
|
const routerId = ctx.shared.entry("router", "id", props.router);
|
|
6932
7599
|
const addRoutes = ctx.shared.entry("router", "addRoutes", props.router);
|
|
6933
7600
|
const routeKey = props.path.endsWith("/") ? `${props.path}*` : `${props.path}/*`;
|
|
@@ -6937,7 +7604,7 @@ var imageFeature = defineFeature({
|
|
|
6937
7604
|
}
|
|
6938
7605
|
let s3Origin;
|
|
6939
7606
|
if (props.origin.static) {
|
|
6940
|
-
s3Origin = new
|
|
7607
|
+
s3Origin = new aws25.s3.Bucket(group, "origin", {
|
|
6941
7608
|
bucket: formatLocalResourceName({
|
|
6942
7609
|
appName: ctx.app.name,
|
|
6943
7610
|
stackName: ctx.stack.name,
|
|
@@ -6947,7 +7614,7 @@ var imageFeature = defineFeature({
|
|
|
6947
7614
|
forceDestroy: true
|
|
6948
7615
|
});
|
|
6949
7616
|
}
|
|
6950
|
-
const cacheBucket = new
|
|
7617
|
+
const cacheBucket = new aws25.s3.Bucket(group, "cache", {
|
|
6951
7618
|
bucket: formatLocalResourceName({
|
|
6952
7619
|
appName: ctx.app.name,
|
|
6953
7620
|
stackName: ctx.stack.name,
|
|
@@ -6964,7 +7631,7 @@ var imageFeature = defineFeature({
|
|
|
6964
7631
|
enabled: true,
|
|
6965
7632
|
id: "image-cache-duration",
|
|
6966
7633
|
expiration: {
|
|
6967
|
-
days:
|
|
7634
|
+
days: toDays9(props.cacheDuration)
|
|
6968
7635
|
}
|
|
6969
7636
|
}
|
|
6970
7637
|
]
|
|
@@ -6976,23 +7643,23 @@ var imageFeature = defineFeature({
|
|
|
6976
7643
|
resourceName: "sharp"
|
|
6977
7644
|
});
|
|
6978
7645
|
const serverLambda = createPrebuildLambdaFunction(group, ctx, "image", id, {
|
|
6979
|
-
bundleFile:
|
|
6980
|
-
bundleHash:
|
|
6981
|
-
memorySize:
|
|
6982
|
-
timeout:
|
|
7646
|
+
bundleFile: join18(__dirname5, "/prebuild/image/bundle.zip"),
|
|
7647
|
+
bundleHash: join18(__dirname5, "/prebuild/image/HASH"),
|
|
7648
|
+
memorySize: mebibytes7(512),
|
|
7649
|
+
timeout: seconds9(10),
|
|
6983
7650
|
handler: "index.default",
|
|
6984
7651
|
runtime: "nodejs24.x",
|
|
6985
7652
|
log: props.log,
|
|
6986
7653
|
layers: [sharpLayerId]
|
|
6987
7654
|
});
|
|
6988
|
-
const permission = new
|
|
7655
|
+
const permission = new aws25.lambda.Permission(group, "permission", {
|
|
6989
7656
|
principal: "cloudfront.amazonaws.com",
|
|
6990
7657
|
action: "lambda:InvokeFunctionUrl",
|
|
6991
7658
|
functionName: serverLambda.lambda.functionName,
|
|
6992
7659
|
functionUrlAuthType: "AWS_IAM",
|
|
6993
7660
|
sourceArn: `arn:aws:cloudfront::${ctx.accountId}:distribution/*`
|
|
6994
7661
|
});
|
|
6995
|
-
const serverLambdaUrl = new
|
|
7662
|
+
const serverLambdaUrl = new aws25.lambda.FunctionUrl(
|
|
6996
7663
|
group,
|
|
6997
7664
|
"url",
|
|
6998
7665
|
{
|
|
@@ -7049,11 +7716,11 @@ var imageFeature = defineFeature({
|
|
|
7049
7716
|
nodir: true
|
|
7050
7717
|
});
|
|
7051
7718
|
for (const file of files) {
|
|
7052
|
-
new
|
|
7719
|
+
new aws25.s3.BucketObject(group, `static-${file}`, {
|
|
7053
7720
|
bucket: s3Origin.bucket,
|
|
7054
7721
|
key: file,
|
|
7055
|
-
source:
|
|
7056
|
-
sourceHash: $hash(
|
|
7722
|
+
source: join18(props.origin.static, file),
|
|
7723
|
+
sourceHash: $hash(join18(props.origin.static, file))
|
|
7057
7724
|
});
|
|
7058
7725
|
}
|
|
7059
7726
|
}
|
|
@@ -7066,19 +7733,19 @@ var imageFeature = defineFeature({
|
|
|
7066
7733
|
});
|
|
7067
7734
|
|
|
7068
7735
|
// src/feature/icon/index.ts
|
|
7069
|
-
import { Group as
|
|
7070
|
-
import { aws as
|
|
7071
|
-
import { join as
|
|
7072
|
-
import { mebibytes as
|
|
7073
|
-
import { seconds as
|
|
7074
|
-
import { fileURLToPath as
|
|
7736
|
+
import { Group as Group25 } from "@terraforge/core";
|
|
7737
|
+
import { aws as aws26 } from "@terraforge/aws";
|
|
7738
|
+
import { join as join19, dirname as dirname10 } from "path";
|
|
7739
|
+
import { mebibytes as mebibytes8 } from "@awsless/size";
|
|
7740
|
+
import { seconds as seconds10, toDays as toDays10 } from "@awsless/duration";
|
|
7741
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
7075
7742
|
import { glob as glob5 } from "glob";
|
|
7076
|
-
var
|
|
7743
|
+
var __dirname6 = dirname10(fileURLToPath5(import.meta.url));
|
|
7077
7744
|
var iconFeature = defineFeature({
|
|
7078
7745
|
name: "icon",
|
|
7079
7746
|
onStack(ctx) {
|
|
7080
7747
|
for (const [id, props] of Object.entries(ctx.stackConfig.icons ?? {})) {
|
|
7081
|
-
const group = new
|
|
7748
|
+
const group = new Group25(ctx.stack, "icon", id);
|
|
7082
7749
|
const routerId = ctx.shared.entry("router", "id", props.router);
|
|
7083
7750
|
const addRoutes = ctx.shared.entry("router", "addRoutes", props.router);
|
|
7084
7751
|
const routeKey = props.path.endsWith("/") ? `${props.path}*` : `${props.path}/*`;
|
|
@@ -7088,7 +7755,7 @@ var iconFeature = defineFeature({
|
|
|
7088
7755
|
}
|
|
7089
7756
|
let s3Origin;
|
|
7090
7757
|
if (props.origin.static) {
|
|
7091
|
-
s3Origin = new
|
|
7758
|
+
s3Origin = new aws26.s3.Bucket(group, "origin", {
|
|
7092
7759
|
bucket: formatLocalResourceName({
|
|
7093
7760
|
appName: ctx.app.name,
|
|
7094
7761
|
stackName: ctx.stack.name,
|
|
@@ -7098,7 +7765,7 @@ var iconFeature = defineFeature({
|
|
|
7098
7765
|
forceDestroy: true
|
|
7099
7766
|
});
|
|
7100
7767
|
}
|
|
7101
|
-
const cacheBucket = new
|
|
7768
|
+
const cacheBucket = new aws26.s3.Bucket(group, "cache", {
|
|
7102
7769
|
bucket: formatLocalResourceName({
|
|
7103
7770
|
appName: ctx.app.name,
|
|
7104
7771
|
stackName: ctx.stack.name,
|
|
@@ -7115,29 +7782,29 @@ var iconFeature = defineFeature({
|
|
|
7115
7782
|
enabled: true,
|
|
7116
7783
|
id: "icon-cache-duration",
|
|
7117
7784
|
expiration: {
|
|
7118
|
-
days:
|
|
7785
|
+
days: toDays10(props.cacheDuration)
|
|
7119
7786
|
}
|
|
7120
7787
|
}
|
|
7121
7788
|
]
|
|
7122
7789
|
} : {}
|
|
7123
7790
|
});
|
|
7124
7791
|
const serverLambda = createPrebuildLambdaFunction(group, ctx, "icon", id, {
|
|
7125
|
-
bundleFile:
|
|
7126
|
-
bundleHash:
|
|
7127
|
-
memorySize:
|
|
7128
|
-
timeout:
|
|
7792
|
+
bundleFile: join19(__dirname6, "/prebuild/icon/bundle.zip"),
|
|
7793
|
+
bundleHash: join19(__dirname6, "/prebuild/icon/HASH"),
|
|
7794
|
+
memorySize: mebibytes8(512),
|
|
7795
|
+
timeout: seconds10(10),
|
|
7129
7796
|
handler: "index.default",
|
|
7130
7797
|
runtime: "nodejs24.x",
|
|
7131
7798
|
log: props.log
|
|
7132
7799
|
});
|
|
7133
|
-
const permission = new
|
|
7800
|
+
const permission = new aws26.lambda.Permission(group, "permission", {
|
|
7134
7801
|
principal: "cloudfront.amazonaws.com",
|
|
7135
7802
|
action: "lambda:InvokeFunctionUrl",
|
|
7136
7803
|
functionName: serverLambda.lambda.functionName,
|
|
7137
7804
|
functionUrlAuthType: "AWS_IAM",
|
|
7138
7805
|
sourceArn: `arn:aws:cloudfront::${ctx.accountId}:distribution/*`
|
|
7139
7806
|
});
|
|
7140
|
-
const serverLambdaUrl = new
|
|
7807
|
+
const serverLambdaUrl = new aws26.lambda.FunctionUrl(
|
|
7141
7808
|
group,
|
|
7142
7809
|
"url",
|
|
7143
7810
|
{
|
|
@@ -7197,11 +7864,11 @@ var iconFeature = defineFeature({
|
|
|
7197
7864
|
if (!file.endsWith(".svg")) {
|
|
7198
7865
|
throw new Error(`Icon file "${file}" in "${props.origin.static}" is not an SVG file.`);
|
|
7199
7866
|
}
|
|
7200
|
-
new
|
|
7867
|
+
new aws26.s3.BucketObject(group, `static-${file}`, {
|
|
7201
7868
|
bucket: s3Origin.bucket,
|
|
7202
7869
|
key: file,
|
|
7203
|
-
source:
|
|
7204
|
-
sourceHash: $hash(
|
|
7870
|
+
source: join19(props.origin.static, file),
|
|
7871
|
+
sourceHash: $hash(join19(props.origin.static, file))
|
|
7205
7872
|
});
|
|
7206
7873
|
}
|
|
7207
7874
|
}
|
|
@@ -7214,30 +7881,30 @@ var iconFeature = defineFeature({
|
|
|
7214
7881
|
});
|
|
7215
7882
|
|
|
7216
7883
|
// src/feature/job/index.ts
|
|
7217
|
-
import { Group as
|
|
7218
|
-
import { aws as
|
|
7884
|
+
import { Group as Group27, Output as Output8, resolveInputs as resolveInputs5, findInputDeps as findInputDeps5 } from "@terraforge/core";
|
|
7885
|
+
import { aws as aws28 } from "@terraforge/aws";
|
|
7219
7886
|
import { camelCase as camelCase8 } from "change-case";
|
|
7220
7887
|
import deepmerge5 from "deepmerge";
|
|
7221
7888
|
import { relative as relative8 } from "path";
|
|
7222
7889
|
|
|
7223
7890
|
// src/feature/job/util.ts
|
|
7224
|
-
import { createHash as
|
|
7225
|
-
import { toDays as
|
|
7226
|
-
import { stringify } from "@awsless/json";
|
|
7891
|
+
import { createHash as createHash6 } from "crypto";
|
|
7892
|
+
import { toDays as toDays11, toSeconds as toSeconds8 } from "@awsless/duration";
|
|
7893
|
+
import { stringify as stringify2 } from "@awsless/json";
|
|
7227
7894
|
import { toMebibytes as toMebibytes5 } from "@awsless/size";
|
|
7228
7895
|
import { generateFileHash as generateFileHash2 } from "@awsless/ts-file-cache";
|
|
7229
|
-
import { aws as
|
|
7230
|
-
import { Group as
|
|
7231
|
-
import { constantCase as constantCase12, pascalCase as
|
|
7896
|
+
import { aws as aws27 } from "@terraforge/aws";
|
|
7897
|
+
import { Group as Group26, Output as Output7, findInputDeps as findInputDeps4, resolveInputs as resolveInputs4 } from "@terraforge/core";
|
|
7898
|
+
import { constantCase as constantCase12, pascalCase as pascalCase4 } from "change-case";
|
|
7232
7899
|
import deepmerge4 from "deepmerge";
|
|
7233
7900
|
|
|
7234
7901
|
// src/feature/job/build/executable.ts
|
|
7235
|
-
import { createHash as
|
|
7236
|
-
import { readFile as
|
|
7237
|
-
import { join as
|
|
7902
|
+
import { createHash as createHash5 } from "crypto";
|
|
7903
|
+
import { readFile as readFile6, writeFile as writeFile3 } from "fs/promises";
|
|
7904
|
+
import { join as join20, resolve } from "path";
|
|
7238
7905
|
var buildJobExecutable = async (input, outputPath, architecture) => {
|
|
7239
|
-
const filePath =
|
|
7240
|
-
const wrapperPath =
|
|
7906
|
+
const filePath = join20(outputPath, "program");
|
|
7907
|
+
const wrapperPath = join20(outputPath, "wrapper.ts");
|
|
7241
7908
|
const handlerPath = resolve(input);
|
|
7242
7909
|
await writeFile3(
|
|
7243
7910
|
wrapperPath,
|
|
@@ -7292,16 +7959,16 @@ await handler(payload)
|
|
|
7292
7959
|
throw new ExpectedError(`Job executable build failed:
|
|
7293
7960
|
${result.logs?.map((log35) => log35.message).join("\n")}`);
|
|
7294
7961
|
}
|
|
7295
|
-
const file = await
|
|
7962
|
+
const file = await readFile6(filePath);
|
|
7296
7963
|
return {
|
|
7297
|
-
hash:
|
|
7964
|
+
hash: createHash5("sha1").update(file).update(target).digest("hex"),
|
|
7298
7965
|
file
|
|
7299
7966
|
};
|
|
7300
7967
|
};
|
|
7301
7968
|
|
|
7302
7969
|
// src/feature/job/util.ts
|
|
7303
7970
|
var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
7304
|
-
const group = new
|
|
7971
|
+
const group = new Group26(parentGroup, "job", ns);
|
|
7305
7972
|
const name = formatLocalResourceName({
|
|
7306
7973
|
appName: ctx.app.name,
|
|
7307
7974
|
stackName: ctx.stack.name,
|
|
@@ -7327,13 +7994,13 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7327
7994
|
};
|
|
7328
7995
|
});
|
|
7329
7996
|
});
|
|
7330
|
-
const code = new
|
|
7997
|
+
const code = new aws27.s3.BucketObject(group, "code", {
|
|
7331
7998
|
bucket: ctx.shared.get("job", "bucket-name"),
|
|
7332
7999
|
key: name,
|
|
7333
8000
|
source: relativePath(getBuildPath("job", name, "program")),
|
|
7334
8001
|
sourceHash: $file(getBuildPath("job", name, "HASH"))
|
|
7335
8002
|
});
|
|
7336
|
-
const executionRole = new
|
|
8003
|
+
const executionRole = new aws27.iam.Role(group, "execution-role", {
|
|
7337
8004
|
name: shortId(`${shortName}:execution-role`),
|
|
7338
8005
|
description: name,
|
|
7339
8006
|
assumeRolePolicy: JSON.stringify({
|
|
@@ -7350,7 +8017,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7350
8017
|
}),
|
|
7351
8018
|
managedPolicyArns: ["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]
|
|
7352
8019
|
});
|
|
7353
|
-
const role = new
|
|
8020
|
+
const role = new aws27.iam.Role(
|
|
7354
8021
|
group,
|
|
7355
8022
|
"task-role",
|
|
7356
8023
|
{
|
|
@@ -7376,7 +8043,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7376
8043
|
Version: "2012-10-17",
|
|
7377
8044
|
Statement: [
|
|
7378
8045
|
{
|
|
7379
|
-
Effect:
|
|
8046
|
+
Effect: pascalCase4("allow"),
|
|
7380
8047
|
Action: ["s3:GetObject", "s3:HeadObject"],
|
|
7381
8048
|
Resource: [`arn:aws:s3:::${bucket}/${key}`, `arn:aws:s3:::${bucket}/payloads/*`]
|
|
7382
8049
|
}
|
|
@@ -7392,16 +8059,16 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7392
8059
|
);
|
|
7393
8060
|
const statements = [];
|
|
7394
8061
|
const statementDeps = /* @__PURE__ */ new Set();
|
|
7395
|
-
const policy = new
|
|
8062
|
+
const policy = new aws27.iam.RolePolicy(group, "policy", {
|
|
7396
8063
|
role: role.name,
|
|
7397
8064
|
name: "task-policy",
|
|
7398
|
-
policy: new
|
|
7399
|
-
const list3 = await
|
|
8065
|
+
policy: new Output7(statementDeps, async (resolve2) => {
|
|
8066
|
+
const list3 = await resolveInputs4(statements);
|
|
7400
8067
|
resolve2(
|
|
7401
8068
|
JSON.stringify({
|
|
7402
8069
|
Version: "2012-10-17",
|
|
7403
8070
|
Statement: list3.map((statement) => ({
|
|
7404
|
-
Effect:
|
|
8071
|
+
Effect: pascalCase4(statement.effect ?? "allow"),
|
|
7405
8072
|
Action: statement.actions,
|
|
7406
8073
|
Resource: statement.resources
|
|
7407
8074
|
}))
|
|
@@ -7411,7 +8078,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7411
8078
|
});
|
|
7412
8079
|
const addPermission = (...permissions) => {
|
|
7413
8080
|
statements.push(...permissions);
|
|
7414
|
-
for (const dep of
|
|
8081
|
+
for (const dep of findInputDeps4(permissions)) {
|
|
7415
8082
|
statementDeps.add(dep);
|
|
7416
8083
|
}
|
|
7417
8084
|
};
|
|
@@ -7420,12 +8087,12 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7420
8087
|
});
|
|
7421
8088
|
let logGroup;
|
|
7422
8089
|
if (props.log.retention && props.log.retention.value > 0n) {
|
|
7423
|
-
logGroup = new
|
|
8090
|
+
logGroup = new aws27.cloudwatch.LogGroup(group, "log", {
|
|
7424
8091
|
name: `/aws/ecs/${name}`,
|
|
7425
|
-
retentionInDays:
|
|
8092
|
+
retentionInDays: toDays11(props.log.retention)
|
|
7426
8093
|
});
|
|
7427
8094
|
if (ctx.shared.has("on-error-log", "subscriber-arn")) {
|
|
7428
|
-
new
|
|
8095
|
+
new aws27.cloudwatch.LogSubscriptionFilter(group, "on-error-log", {
|
|
7429
8096
|
name: "error-log-subscription",
|
|
7430
8097
|
destinationArn: ctx.shared.get("on-error-log", "subscriber-arn"),
|
|
7431
8098
|
logGroupName: logGroup.name,
|
|
@@ -7443,7 +8110,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7443
8110
|
const taskDependsOn = [code];
|
|
7444
8111
|
const accessPoint = props.persistentStorage ? (() => {
|
|
7445
8112
|
const fileSystemId = ctx.shared.get("job", "persistent-storage-file-system-id");
|
|
7446
|
-
const accessPoint2 = new
|
|
8113
|
+
const accessPoint2 = new aws27.efs.AccessPoint(
|
|
7447
8114
|
group,
|
|
7448
8115
|
"access-point",
|
|
7449
8116
|
{
|
|
@@ -7468,7 +8135,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7468
8135
|
fileSystemId
|
|
7469
8136
|
};
|
|
7470
8137
|
})() : void 0;
|
|
7471
|
-
const task2 = new
|
|
8138
|
+
const task2 = new aws27.ecs.TaskDefinition(
|
|
7472
8139
|
group,
|
|
7473
8140
|
"task",
|
|
7474
8141
|
{
|
|
@@ -7498,9 +8165,9 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7498
8165
|
}
|
|
7499
8166
|
]
|
|
7500
8167
|
},
|
|
7501
|
-
containerDefinitions: new
|
|
7502
|
-
const data = await
|
|
7503
|
-
const { s3Bucket, s3Key } = await
|
|
8168
|
+
containerDefinitions: new Output7(variableDeps, async (resolve2) => {
|
|
8169
|
+
const data = await resolveInputs4(variables);
|
|
8170
|
+
const { s3Bucket, s3Key } = await resolveInputs4({
|
|
7504
8171
|
s3Bucket: code.bucket,
|
|
7505
8172
|
s3Key: code.key
|
|
7506
8173
|
});
|
|
@@ -7516,7 +8183,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7516
8183
|
[
|
|
7517
8184
|
...props.startupCommand?.length ? [props.startupCommand.join(" && ")] : [],
|
|
7518
8185
|
`if [ "$(cat /root/.code-hash 2>/dev/null)" != "$CODE_HASH" ]; then command -v aws >/dev/null 2>&1 || dnf install -y awscli && aws s3 cp s3://${s3Bucket}/${s3Key} /root/program.tmp && mv /root/program.tmp /root/program && chmod +x /root/program && echo "$CODE_HASH" > /root/.code-hash; fi`,
|
|
7519
|
-
`exec timeout --kill-after=10 ${
|
|
8186
|
+
`exec timeout --kill-after=10 ${toSeconds8(props.timeout)} /root/program`
|
|
7520
8187
|
].join(" && ")
|
|
7521
8188
|
],
|
|
7522
8189
|
environment: Object.entries(data).map(([name2, value]) => ({
|
|
@@ -7562,7 +8229,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7562
8229
|
);
|
|
7563
8230
|
ctx.onEnv((name2, value) => {
|
|
7564
8231
|
variables[name2] = value;
|
|
7565
|
-
for (const dep of
|
|
8232
|
+
for (const dep of findInputDeps4([value])) {
|
|
7566
8233
|
variableDeps.add(dep);
|
|
7567
8234
|
}
|
|
7568
8235
|
});
|
|
@@ -7571,7 +8238,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7571
8238
|
variables.AWS_ACCOUNT_ID = ctx.accountId;
|
|
7572
8239
|
variables.STACK = ctx.stackConfig.name;
|
|
7573
8240
|
variables.CODE_HASH = code.sourceHash;
|
|
7574
|
-
variables.JOB_CONFIG_HASH =
|
|
8241
|
+
variables.JOB_CONFIG_HASH = createHash6("sha1").update(stringify2(props)).digest("hex");
|
|
7575
8242
|
if (props.environment) {
|
|
7576
8243
|
for (const [key, value] of Object.entries(props.environment)) {
|
|
7577
8244
|
variables[key] = value;
|
|
@@ -7587,7 +8254,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7587
8254
|
};
|
|
7588
8255
|
|
|
7589
8256
|
// src/feature/job/index.ts
|
|
7590
|
-
var
|
|
8257
|
+
var typeGenCode11 = `
|
|
7591
8258
|
import type { Mock } from 'vitest'
|
|
7592
8259
|
|
|
7593
8260
|
type Func = (...args: any[]) => any
|
|
@@ -7643,15 +8310,15 @@ var jobFeature = defineFeature({
|
|
|
7643
8310
|
resources2.addType(stack.name, resource);
|
|
7644
8311
|
mockResponses.addType(stack.name, mockResponse);
|
|
7645
8312
|
}
|
|
7646
|
-
types2.addCode(
|
|
8313
|
+
types2.addCode(typeGenCode11);
|
|
7647
8314
|
types2.addInterface("JobResources", resources2);
|
|
7648
8315
|
types2.addInterface("JobMock", mocks);
|
|
7649
8316
|
types2.addInterface("JobMockResponse", mockResponses);
|
|
7650
8317
|
await ctx.write("job.d.ts", types2, true);
|
|
7651
8318
|
},
|
|
7652
8319
|
onBefore(ctx) {
|
|
7653
|
-
const group = new
|
|
7654
|
-
const bucket = new
|
|
8320
|
+
const group = new Group27(ctx.base, "job", "asset");
|
|
8321
|
+
const bucket = new aws28.s3.Bucket(group, "bucket", {
|
|
7655
8322
|
bucket: formatGlobalResourceName({
|
|
7656
8323
|
appName: ctx.app.name,
|
|
7657
8324
|
resourceType: "job",
|
|
@@ -7677,8 +8344,8 @@ var jobFeature = defineFeature({
|
|
|
7677
8344
|
if (found.length === 0) {
|
|
7678
8345
|
return;
|
|
7679
8346
|
}
|
|
7680
|
-
const group = new
|
|
7681
|
-
const cluster = new
|
|
8347
|
+
const group = new Group27(ctx.base, "job", "cluster");
|
|
8348
|
+
const cluster = new aws28.ecs.Cluster(
|
|
7682
8349
|
group,
|
|
7683
8350
|
"cluster",
|
|
7684
8351
|
{
|
|
@@ -7690,7 +8357,7 @@ var jobFeature = defineFeature({
|
|
|
7690
8357
|
);
|
|
7691
8358
|
ctx.shared.set("job", "cluster-name", cluster.name);
|
|
7692
8359
|
ctx.shared.set("job", "cluster-arn", cluster.arn);
|
|
7693
|
-
const securityGroup = new
|
|
8360
|
+
const securityGroup = new aws28.security.Group(group, "security-group", {
|
|
7694
8361
|
name: `${ctx.app.name}-job`,
|
|
7695
8362
|
description: "Shared security group for jobs",
|
|
7696
8363
|
vpcId: ctx.shared.get("vpc", "id"),
|
|
@@ -7699,7 +8366,7 @@ var jobFeature = defineFeature({
|
|
|
7699
8366
|
APP: ctx.appConfig.name
|
|
7700
8367
|
}
|
|
7701
8368
|
});
|
|
7702
|
-
new
|
|
8369
|
+
new aws28.vpc.SecurityGroupEgressRule(group, "egress-rule", {
|
|
7703
8370
|
securityGroupId: securityGroup.id,
|
|
7704
8371
|
description: "Allow all outbound traffic from jobs",
|
|
7705
8372
|
ipProtocol: "-1",
|
|
@@ -7716,8 +8383,8 @@ var jobFeature = defineFeature({
|
|
|
7716
8383
|
})
|
|
7717
8384
|
);
|
|
7718
8385
|
if (needsPersistentStorage) {
|
|
7719
|
-
const storageGroup = new
|
|
7720
|
-
new
|
|
8386
|
+
const storageGroup = new Group27(ctx.base, "job", "persistent-storage");
|
|
8387
|
+
new aws28.vpc.SecurityGroupIngressRule(storageGroup, "ingress-rule", {
|
|
7721
8388
|
securityGroupId: securityGroup.id,
|
|
7722
8389
|
referencedSecurityGroupId: securityGroup.id,
|
|
7723
8390
|
description: "Allow NFS traffic from jobs",
|
|
@@ -7728,7 +8395,7 @@ var jobFeature = defineFeature({
|
|
|
7728
8395
|
APP: ctx.appConfig.name
|
|
7729
8396
|
}
|
|
7730
8397
|
});
|
|
7731
|
-
const fileSystem = new
|
|
8398
|
+
const fileSystem = new aws28.efs.FileSystem(storageGroup, "file-system", {
|
|
7732
8399
|
encrypted: true,
|
|
7733
8400
|
performanceMode: "generalPurpose",
|
|
7734
8401
|
throughputMode: "elastic",
|
|
@@ -7738,7 +8405,7 @@ var jobFeature = defineFeature({
|
|
|
7738
8405
|
}
|
|
7739
8406
|
});
|
|
7740
8407
|
for (const [index, subnetId] of ctx.shared.get("vpc", "public-subnets").entries()) {
|
|
7741
|
-
new
|
|
8408
|
+
new aws28.efs.MountTarget(storageGroup, `mount-target-${index + 1}`, {
|
|
7742
8409
|
fileSystemId: fileSystem.id,
|
|
7743
8410
|
subnetId,
|
|
7744
8411
|
securityGroups: [securityGroup.id]
|
|
@@ -7753,15 +8420,15 @@ var jobFeature = defineFeature({
|
|
|
7753
8420
|
const subnets = ctx.shared.get("vpc", "public-subnets");
|
|
7754
8421
|
ctx.addEnv(
|
|
7755
8422
|
"JOB_SUBNETS",
|
|
7756
|
-
new
|
|
7757
|
-
const resolved = await
|
|
8423
|
+
new Output8(new Set(findInputDeps5(subnets)), async (resolve2) => {
|
|
8424
|
+
const resolved = await resolveInputs5(subnets);
|
|
7758
8425
|
resolve2(JSON.stringify(resolved));
|
|
7759
8426
|
})
|
|
7760
8427
|
);
|
|
7761
8428
|
ctx.addEnv("JOB_SECURITY_GROUP", ctx.shared.get("job", "security-group-id"));
|
|
7762
8429
|
ctx.addEnv("JOB_PAYLOAD_BUCKET", ctx.shared.get("job", "bucket-name"));
|
|
7763
8430
|
for (const [id, props] of jobs) {
|
|
7764
|
-
const group = new
|
|
8431
|
+
const group = new Group27(ctx.stack, "job", id);
|
|
7765
8432
|
createFargateJob(group, ctx, "job", id, props);
|
|
7766
8433
|
}
|
|
7767
8434
|
ctx.addStackPermission({
|
|
@@ -7794,77 +8461,25 @@ var jobFeature = defineFeature({
|
|
|
7794
8461
|
});
|
|
7795
8462
|
|
|
7796
8463
|
// src/feature/instance/index.ts
|
|
7797
|
-
import { days as
|
|
8464
|
+
import { days as days11, seconds as seconds11, toSeconds as toSeconds10 } from "@awsless/duration";
|
|
7798
8465
|
import { kibibytes as kibibytes2, toBytes as toBytes2 } from "@awsless/size";
|
|
7799
|
-
import { Group as
|
|
7800
|
-
import { aws as
|
|
8466
|
+
import { Group as Group29 } from "@terraforge/core";
|
|
8467
|
+
import { aws as aws30 } from "@terraforge/aws";
|
|
7801
8468
|
import { constantCase as constantCase14 } from "change-case";
|
|
7802
8469
|
|
|
7803
8470
|
// src/feature/instance/util.ts
|
|
7804
|
-
import { toDays as
|
|
7805
|
-
import { stringify as
|
|
8471
|
+
import { toDays as toDays12, toSeconds as toSeconds9 } from "@awsless/duration";
|
|
8472
|
+
import { stringify as stringify3 } from "@awsless/json";
|
|
7806
8473
|
import { toMebibytes as toMebibytes6 } from "@awsless/size";
|
|
7807
8474
|
import { generateFileHash as generateFileHash3 } from "@awsless/ts-file-cache";
|
|
7808
|
-
import { aws as
|
|
7809
|
-
import { Group as
|
|
7810
|
-
import { constantCase as constantCase13, pascalCase as
|
|
7811
|
-
import { createHash as
|
|
8475
|
+
import { aws as aws29 } from "@terraforge/aws";
|
|
8476
|
+
import { Group as Group28, Output as Output9, findInputDeps as findInputDeps6, resolveInputs as resolveInputs6 } from "@terraforge/core";
|
|
8477
|
+
import { constantCase as constantCase13, pascalCase as pascalCase5 } from "change-case";
|
|
8478
|
+
import { createHash as createHash7 } from "crypto";
|
|
7812
8479
|
import deepmerge6 from "deepmerge";
|
|
7813
|
-
import { join as
|
|
7814
|
-
|
|
7815
|
-
// src/feature/instance/build/executable.ts
|
|
7816
|
-
import { createHash as createHash5 } from "crypto";
|
|
7817
|
-
import { readFile as readFile5 } from "fs/promises";
|
|
7818
|
-
import { join as join18 } from "path";
|
|
7819
|
-
var buildExecutable = async (input, outputPath, architecture) => {
|
|
7820
|
-
const filePath = join18(outputPath, "program");
|
|
7821
|
-
const target = architecture === "x86_64" ? "bun-linux-x64" : "bun-linux-arm64";
|
|
7822
|
-
let result;
|
|
7823
|
-
try {
|
|
7824
|
-
result = await Bun.build({
|
|
7825
|
-
entrypoints: [input],
|
|
7826
|
-
compile: {
|
|
7827
|
-
target,
|
|
7828
|
-
outfile: filePath
|
|
7829
|
-
},
|
|
7830
|
-
target: "bun",
|
|
7831
|
-
loader: {
|
|
7832
|
-
".md": "text",
|
|
7833
|
-
".txt": "text",
|
|
7834
|
-
".html": "text",
|
|
7835
|
-
".css": "text",
|
|
7836
|
-
".yaml": "text",
|
|
7837
|
-
".yml": "text",
|
|
7838
|
-
".xml": "text",
|
|
7839
|
-
".csv": "text",
|
|
7840
|
-
".svg": "text",
|
|
7841
|
-
".png": "file",
|
|
7842
|
-
".jpg": "file",
|
|
7843
|
-
".jpeg": "file",
|
|
7844
|
-
".gif": "file",
|
|
7845
|
-
".webp": "file",
|
|
7846
|
-
".wasm": "file"
|
|
7847
|
-
}
|
|
7848
|
-
});
|
|
7849
|
-
} catch (error) {
|
|
7850
|
-
throw new ExpectedError(
|
|
7851
|
-
`Executable build failed: ${error instanceof Error ? error.message : JSON.stringify(error)}`
|
|
7852
|
-
);
|
|
7853
|
-
}
|
|
7854
|
-
if (!result.success) {
|
|
7855
|
-
throw new ExpectedError(`Executable build failed:
|
|
7856
|
-
${result.logs?.map((log35) => log35.message).join("\n")}`);
|
|
7857
|
-
}
|
|
7858
|
-
const file = await readFile5(filePath);
|
|
7859
|
-
return {
|
|
7860
|
-
hash: createHash5("sha1").update(file).update("x86_64").digest("hex"),
|
|
7861
|
-
file
|
|
7862
|
-
};
|
|
7863
|
-
};
|
|
7864
|
-
|
|
7865
|
-
// src/feature/instance/util.ts
|
|
8480
|
+
import { join as join21 } from "path";
|
|
7866
8481
|
var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
7867
|
-
const group = new
|
|
8482
|
+
const group = new Group28(parentGroup, "instance", ns);
|
|
7868
8483
|
const name = formatLocalResourceName({
|
|
7869
8484
|
appName: ctx.app.name,
|
|
7870
8485
|
stackName: ctx.stack.name,
|
|
@@ -7890,13 +8505,13 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
7890
8505
|
};
|
|
7891
8506
|
});
|
|
7892
8507
|
});
|
|
7893
|
-
const code = new
|
|
8508
|
+
const code = new aws29.s3.BucketObject(group, "code", {
|
|
7894
8509
|
bucket: ctx.shared.get("instance", "bucket-name"),
|
|
7895
8510
|
key: name,
|
|
7896
8511
|
source: relativePath(getBuildPath("instance", name, "program")),
|
|
7897
8512
|
sourceHash: $file(getBuildPath("instance", name, "HASH"))
|
|
7898
8513
|
});
|
|
7899
|
-
const executionRole = new
|
|
8514
|
+
const executionRole = new aws29.iam.Role(group, "execution-role", {
|
|
7900
8515
|
name: shortId(`${shortName}:execution-role`),
|
|
7901
8516
|
description: name,
|
|
7902
8517
|
assumeRolePolicy: JSON.stringify({
|
|
@@ -7913,7 +8528,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
7913
8528
|
}),
|
|
7914
8529
|
managedPolicyArns: ["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]
|
|
7915
8530
|
});
|
|
7916
|
-
const role = new
|
|
8531
|
+
const role = new aws29.iam.Role(
|
|
7917
8532
|
group,
|
|
7918
8533
|
"task-role",
|
|
7919
8534
|
{
|
|
@@ -7939,7 +8554,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
7939
8554
|
Version: "2012-10-17",
|
|
7940
8555
|
Statement: [
|
|
7941
8556
|
{
|
|
7942
|
-
Effect:
|
|
8557
|
+
Effect: pascalCase5("allow"),
|
|
7943
8558
|
Action: ["s3:getObject", "s3:HeadObject"],
|
|
7944
8559
|
Resource: `arn:aws:s3:::${bucket}/${key}`
|
|
7945
8560
|
}
|
|
@@ -7955,16 +8570,16 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
7955
8570
|
);
|
|
7956
8571
|
const statements = [];
|
|
7957
8572
|
const statementDeps = /* @__PURE__ */ new Set();
|
|
7958
|
-
const policy = new
|
|
8573
|
+
const policy = new aws29.iam.RolePolicy(group, "policy", {
|
|
7959
8574
|
role: role.name,
|
|
7960
8575
|
name: "task-policy",
|
|
7961
|
-
policy: new
|
|
7962
|
-
const list3 = await
|
|
8576
|
+
policy: new Output9(statementDeps, async (resolve2) => {
|
|
8577
|
+
const list3 = await resolveInputs6(statements);
|
|
7963
8578
|
resolve2(
|
|
7964
8579
|
JSON.stringify({
|
|
7965
8580
|
Version: "2012-10-17",
|
|
7966
8581
|
Statement: list3.map((statement) => ({
|
|
7967
|
-
Effect:
|
|
8582
|
+
Effect: pascalCase5(statement.effect ?? "allow"),
|
|
7968
8583
|
Action: statement.actions,
|
|
7969
8584
|
Resource: statement.resources
|
|
7970
8585
|
}))
|
|
@@ -7974,7 +8589,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
7974
8589
|
});
|
|
7975
8590
|
const addPermission = (...permissions) => {
|
|
7976
8591
|
statements.push(...permissions);
|
|
7977
|
-
for (const dep of
|
|
8592
|
+
for (const dep of findInputDeps6(permissions)) {
|
|
7978
8593
|
statementDeps.add(dep);
|
|
7979
8594
|
}
|
|
7980
8595
|
};
|
|
@@ -7983,13 +8598,13 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
7983
8598
|
});
|
|
7984
8599
|
let logGroup;
|
|
7985
8600
|
if (props.log.retention && props.log.retention.value > 0n) {
|
|
7986
|
-
logGroup = new
|
|
8601
|
+
logGroup = new aws29.cloudwatch.LogGroup(group, "log", {
|
|
7987
8602
|
name: `/aws/ecs/${name}`,
|
|
7988
8603
|
// name: `/aws/lambda/${name}`,
|
|
7989
|
-
retentionInDays:
|
|
8604
|
+
retentionInDays: toDays12(props.log.retention)
|
|
7990
8605
|
});
|
|
7991
8606
|
if (ctx.shared.has("on-error-log", "subscriber-arn")) {
|
|
7992
|
-
new
|
|
8607
|
+
new aws29.cloudwatch.LogSubscriptionFilter(group, "on-error-log", {
|
|
7993
8608
|
name: "error-log-subscription",
|
|
7994
8609
|
destinationArn: ctx.shared.get("on-error-log", "subscriber-arn"),
|
|
7995
8610
|
logGroupName: logGroup.name,
|
|
@@ -8004,7 +8619,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8004
8619
|
};
|
|
8005
8620
|
const variables = {};
|
|
8006
8621
|
const variableDeps = /* @__PURE__ */ new Set();
|
|
8007
|
-
const task2 = new
|
|
8622
|
+
const task2 = new aws29.ecs.TaskDefinition(
|
|
8008
8623
|
group,
|
|
8009
8624
|
"task",
|
|
8010
8625
|
{
|
|
@@ -8020,9 +8635,9 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8020
8635
|
operatingSystemFamily: "LINUX"
|
|
8021
8636
|
},
|
|
8022
8637
|
trackLatest: true,
|
|
8023
|
-
containerDefinitions: new
|
|
8024
|
-
const data = await
|
|
8025
|
-
const { s3Bucket, s3Key } = await
|
|
8638
|
+
containerDefinitions: new Output9(variableDeps, async (resolve2) => {
|
|
8639
|
+
const data = await resolveInputs6(variables);
|
|
8640
|
+
const { s3Bucket, s3Key } = await resolveInputs6({
|
|
8026
8641
|
s3Bucket: code.bucket,
|
|
8027
8642
|
s3Key: code.key
|
|
8028
8643
|
});
|
|
@@ -8077,12 +8692,12 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8077
8692
|
healthCheck: props.healthCheck ? {
|
|
8078
8693
|
command: [
|
|
8079
8694
|
"CMD-SHELL",
|
|
8080
|
-
`curl -f http://${
|
|
8695
|
+
`curl -f http://${join21("localhost", props.healthCheck.path)} || exit 1`
|
|
8081
8696
|
],
|
|
8082
|
-
interval:
|
|
8697
|
+
interval: toSeconds9(props.healthCheck.interval),
|
|
8083
8698
|
retries: props.healthCheck.retries,
|
|
8084
|
-
startPeriod:
|
|
8085
|
-
timeout:
|
|
8699
|
+
startPeriod: toSeconds9(props.healthCheck.startPeriod),
|
|
8700
|
+
timeout: toSeconds9(props.healthCheck.timeout)
|
|
8086
8701
|
} : void 0
|
|
8087
8702
|
}
|
|
8088
8703
|
])
|
|
@@ -8102,14 +8717,14 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8102
8717
|
dependsOn: [code]
|
|
8103
8718
|
}
|
|
8104
8719
|
);
|
|
8105
|
-
const securityGroup = new
|
|
8720
|
+
const securityGroup = new aws29.security.Group(group, "security-group", {
|
|
8106
8721
|
name,
|
|
8107
8722
|
description: "Security group for the instance",
|
|
8108
8723
|
vpcId: ctx.shared.get("vpc", "id"),
|
|
8109
8724
|
revokeRulesOnDelete: true,
|
|
8110
8725
|
tags
|
|
8111
8726
|
});
|
|
8112
|
-
new
|
|
8727
|
+
new aws29.vpc.SecurityGroupEgressRule(group, "egress-rule", {
|
|
8113
8728
|
securityGroupId: securityGroup.id,
|
|
8114
8729
|
description: `Allow all outbound traffic from the ${name} instance`,
|
|
8115
8730
|
ipProtocol: "-1",
|
|
@@ -8118,7 +8733,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8118
8733
|
});
|
|
8119
8734
|
const clusterName = ctx.shared.get("instance", "cluster-name");
|
|
8120
8735
|
const clusterArn = ctx.shared.get("instance", "cluster-arn");
|
|
8121
|
-
const service = new
|
|
8736
|
+
const service = new aws29.ecs.Service(
|
|
8122
8737
|
group,
|
|
8123
8738
|
"service",
|
|
8124
8739
|
{
|
|
@@ -8154,7 +8769,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8154
8769
|
replaceOnChanges: ["cluster"]
|
|
8155
8770
|
}
|
|
8156
8771
|
);
|
|
8157
|
-
new
|
|
8772
|
+
new aws29.appautoscaling.Target(
|
|
8158
8773
|
group,
|
|
8159
8774
|
"autoscaling-target",
|
|
8160
8775
|
{
|
|
@@ -8173,7 +8788,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8173
8788
|
);
|
|
8174
8789
|
ctx.onEnv((name2, value) => {
|
|
8175
8790
|
variables[name2] = value;
|
|
8176
|
-
for (const dep of
|
|
8791
|
+
for (const dep of findInputDeps6([value])) {
|
|
8177
8792
|
variableDeps.add(dep);
|
|
8178
8793
|
}
|
|
8179
8794
|
});
|
|
@@ -8182,7 +8797,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8182
8797
|
variables.AWS_ACCOUNT_ID = ctx.accountId;
|
|
8183
8798
|
variables.STACK = ctx.stackConfig.name;
|
|
8184
8799
|
variables.CODE_HASH = code.sourceHash;
|
|
8185
|
-
variables.INSTANCE_CONFIG_HASH =
|
|
8800
|
+
variables.INSTANCE_CONFIG_HASH = createHash7("sha1").update(stringify3(props)).digest("hex");
|
|
8186
8801
|
if (props.environment) {
|
|
8187
8802
|
for (const [key, value] of Object.entries(props.environment)) {
|
|
8188
8803
|
variables[key] = value;
|
|
@@ -8198,7 +8813,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8198
8813
|
};
|
|
8199
8814
|
|
|
8200
8815
|
// src/feature/instance/index.ts
|
|
8201
|
-
var
|
|
8816
|
+
var typeGenCode12 = `
|
|
8202
8817
|
import { SendMessageOptions } from '@awsless/sqs'
|
|
8203
8818
|
import type { Mock } from 'vitest'
|
|
8204
8819
|
|
|
@@ -8237,15 +8852,15 @@ var instanceFeature = defineFeature({
|
|
|
8237
8852
|
mocks.addType(stack.name, mock);
|
|
8238
8853
|
mockResponses.addType(stack.name, mockResponse);
|
|
8239
8854
|
}
|
|
8240
|
-
gen.addCode(
|
|
8855
|
+
gen.addCode(typeGenCode12);
|
|
8241
8856
|
gen.addInterface("InstanceResources", resources2);
|
|
8242
8857
|
gen.addInterface("InstanceMock", mocks);
|
|
8243
8858
|
gen.addInterface("InstanceMockResponse", mockResponses);
|
|
8244
8859
|
await ctx.write("instance.d.ts", gen, true);
|
|
8245
8860
|
},
|
|
8246
8861
|
onBefore(ctx) {
|
|
8247
|
-
const group = new
|
|
8248
|
-
const bucket = new
|
|
8862
|
+
const group = new Group29(ctx.base, "instance", "asset");
|
|
8863
|
+
const bucket = new aws30.s3.Bucket(group, "bucket", {
|
|
8249
8864
|
bucket: formatGlobalResourceName({
|
|
8250
8865
|
appName: ctx.app.name,
|
|
8251
8866
|
resourceType: "instance",
|
|
@@ -8263,8 +8878,8 @@ var instanceFeature = defineFeature({
|
|
|
8263
8878
|
if (found.length === 0) {
|
|
8264
8879
|
return;
|
|
8265
8880
|
}
|
|
8266
|
-
const group = new
|
|
8267
|
-
const cluster = new
|
|
8881
|
+
const group = new Group29(ctx.base, "instance", "cluster");
|
|
8882
|
+
const cluster = new aws30.ecs.Cluster(
|
|
8268
8883
|
group,
|
|
8269
8884
|
"cluster",
|
|
8270
8885
|
{
|
|
@@ -8279,14 +8894,14 @@ var instanceFeature = defineFeature({
|
|
|
8279
8894
|
},
|
|
8280
8895
|
onStack(ctx) {
|
|
8281
8896
|
for (const [id, props] of Object.entries(ctx.stackConfig.instances ?? {})) {
|
|
8282
|
-
const group = new
|
|
8897
|
+
const group = new Group29(ctx.stack, "instance", id);
|
|
8283
8898
|
const task2 = createFargateTask(group, ctx, "instance", id, props);
|
|
8284
|
-
const queue2 = new
|
|
8899
|
+
const queue2 = new aws30.sqs.Queue(group, "queue", {
|
|
8285
8900
|
name: task2.name,
|
|
8286
|
-
visibilityTimeoutSeconds:
|
|
8287
|
-
messageRetentionSeconds:
|
|
8901
|
+
visibilityTimeoutSeconds: toSeconds10(seconds11(30)),
|
|
8902
|
+
messageRetentionSeconds: toSeconds10(days11(4)),
|
|
8288
8903
|
maxMessageSize: toBytes2(kibibytes2(256)),
|
|
8289
|
-
receiveWaitTimeSeconds:
|
|
8904
|
+
receiveWaitTimeSeconds: toSeconds10(seconds11(20))
|
|
8290
8905
|
});
|
|
8291
8906
|
task2.addPermission({
|
|
8292
8907
|
actions: [
|
|
@@ -8308,11 +8923,11 @@ var instanceFeature = defineFeature({
|
|
|
8308
8923
|
});
|
|
8309
8924
|
|
|
8310
8925
|
// src/feature/metric/index.ts
|
|
8311
|
-
import { Group as
|
|
8312
|
-
import { aws as
|
|
8926
|
+
import { Group as Group30 } from "@terraforge/core";
|
|
8927
|
+
import { aws as aws31 } from "@terraforge/aws";
|
|
8313
8928
|
import { kebabCase as kebabCase8, constantCase as constantCase15 } from "change-case";
|
|
8314
|
-
import { toSeconds as
|
|
8315
|
-
var
|
|
8929
|
+
import { toSeconds as toSeconds11 } from "@awsless/duration";
|
|
8930
|
+
var typeGenCode13 = `
|
|
8316
8931
|
import { type PutDataProps, putData, batchPutData } from '@awsless/cloudwatch'
|
|
8317
8932
|
import { type Duration } from '@awsless/duration'
|
|
8318
8933
|
import { type Size } from '@awsless/size'
|
|
@@ -8360,7 +8975,7 @@ var metricFeature = defineFeature({
|
|
|
8360
8975
|
resources2.addType(stack.name, stackResources);
|
|
8361
8976
|
}
|
|
8362
8977
|
resources2.addType("batch", "Batch");
|
|
8363
|
-
gen.addCode(
|
|
8978
|
+
gen.addCode(typeGenCode13);
|
|
8364
8979
|
gen.addInterface("MetricResources", resources2);
|
|
8365
8980
|
await ctx.write("metric.d.ts", gen, true);
|
|
8366
8981
|
},
|
|
@@ -8377,16 +8992,16 @@ var metricFeature = defineFeature({
|
|
|
8377
8992
|
}
|
|
8378
8993
|
});
|
|
8379
8994
|
for (const [id, props] of Object.entries(ctx.stackConfig.metrics ?? {})) {
|
|
8380
|
-
const group = new
|
|
8995
|
+
const group = new Group30(ctx.stack, "metric", id);
|
|
8381
8996
|
ctx.addEnv(`METRIC_${constantCase15(id)}`, props.type);
|
|
8382
8997
|
for (const alarmId in props.alarms ?? []) {
|
|
8383
|
-
const alarmGroup = new
|
|
8998
|
+
const alarmGroup = new Group30(group, "alarm", alarmId);
|
|
8384
8999
|
const alarmName = kebabCase8(`${id}-${alarmId}`);
|
|
8385
9000
|
const alarmProps = props.alarms[alarmId];
|
|
8386
9001
|
let alarmAction;
|
|
8387
9002
|
let alarmLambda;
|
|
8388
9003
|
if (Array.isArray(alarmProps.trigger)) {
|
|
8389
|
-
const topic = new
|
|
9004
|
+
const topic = new aws31.sns.Topic(alarmGroup, "alarm-trigger", {
|
|
8390
9005
|
name: formatLocalResourceName({
|
|
8391
9006
|
appName: ctx.app.name,
|
|
8392
9007
|
stackName: ctx.stack.name,
|
|
@@ -8396,7 +9011,7 @@ var metricFeature = defineFeature({
|
|
|
8396
9011
|
});
|
|
8397
9012
|
alarmAction = topic.arn;
|
|
8398
9013
|
for (const email of alarmProps.trigger) {
|
|
8399
|
-
new
|
|
9014
|
+
new aws31.sns.TopicSubscription(alarmGroup, email, {
|
|
8400
9015
|
topicArn: topic.arn,
|
|
8401
9016
|
protocol: "email",
|
|
8402
9017
|
endpoint: email
|
|
@@ -8407,7 +9022,7 @@ var metricFeature = defineFeature({
|
|
|
8407
9022
|
alarmLambda = lambda;
|
|
8408
9023
|
alarmAction = lambda.arn;
|
|
8409
9024
|
}
|
|
8410
|
-
const alarm = new
|
|
9025
|
+
const alarm = new aws31.cloudwatch.MetricAlarm(alarmGroup, "alarm", {
|
|
8411
9026
|
namespace,
|
|
8412
9027
|
metricName: kebabCase8(id),
|
|
8413
9028
|
alarmName: formatLocalResourceName({
|
|
@@ -8419,13 +9034,13 @@ var metricFeature = defineFeature({
|
|
|
8419
9034
|
alarmDescription: alarmProps.description,
|
|
8420
9035
|
statistic: alarmProps.where.stat,
|
|
8421
9036
|
threshold: alarmProps.where.value,
|
|
8422
|
-
period:
|
|
9037
|
+
period: toSeconds11(alarmProps.period),
|
|
8423
9038
|
evaluationPeriods: alarmProps.minDataPoints,
|
|
8424
9039
|
comparisonOperator: alarmProps.where.op,
|
|
8425
9040
|
alarmActions: [alarmAction]
|
|
8426
9041
|
});
|
|
8427
9042
|
if (alarmLambda) {
|
|
8428
|
-
new
|
|
9043
|
+
new aws31.lambda.Permission(alarmGroup, "permission", {
|
|
8429
9044
|
action: "lambda:InvokeFunction",
|
|
8430
9045
|
principal: "lambda.alarms.cloudwatch.amazonaws.com",
|
|
8431
9046
|
functionName: alarmLambda.functionName,
|
|
@@ -8438,9 +9053,9 @@ var metricFeature = defineFeature({
|
|
|
8438
9053
|
});
|
|
8439
9054
|
|
|
8440
9055
|
// src/feature/router/index.ts
|
|
8441
|
-
import { days as
|
|
8442
|
-
import { Future, Group as
|
|
8443
|
-
import { aws as
|
|
9056
|
+
import { days as days12, seconds as seconds12, toSeconds as toSeconds12, years } from "@awsless/duration";
|
|
9057
|
+
import { Future, Group as Group31 } from "@terraforge/core";
|
|
9058
|
+
import { aws as aws32 } from "@terraforge/aws";
|
|
8444
9059
|
import { camelCase as camelCase9, constantCase as constantCase16 } from "change-case";
|
|
8445
9060
|
|
|
8446
9061
|
// src/feature/router/router-code.ts
|
|
@@ -8689,18 +9304,18 @@ async function handler(event) {
|
|
|
8689
9304
|
`;
|
|
8690
9305
|
|
|
8691
9306
|
// src/feature/router/index.ts
|
|
8692
|
-
import { createHash as
|
|
9307
|
+
import { createHash as createHash8 } from "crypto";
|
|
8693
9308
|
var routerFeature = defineFeature({
|
|
8694
9309
|
name: "router",
|
|
8695
9310
|
onApp(ctx) {
|
|
8696
9311
|
for (const [id, props] of Object.entries(ctx.appConfig.defaults.router ?? {})) {
|
|
8697
|
-
const group = new
|
|
9312
|
+
const group = new Group31(ctx.base, "router", id);
|
|
8698
9313
|
const name = formatGlobalResourceName({
|
|
8699
9314
|
appName: ctx.app.name,
|
|
8700
9315
|
resourceType: "router",
|
|
8701
9316
|
resourceName: id
|
|
8702
9317
|
});
|
|
8703
|
-
const routeStore = new
|
|
9318
|
+
const routeStore = new aws32.cloudfront.KeyValueStore(group, "routes", {
|
|
8704
9319
|
name,
|
|
8705
9320
|
comment: "Store for routes"
|
|
8706
9321
|
});
|
|
@@ -8730,11 +9345,11 @@ var routerFeature = defineFeature({
|
|
|
8730
9345
|
);
|
|
8731
9346
|
importedRoutes.push(importKeys);
|
|
8732
9347
|
});
|
|
8733
|
-
const cache = new
|
|
9348
|
+
const cache = new aws32.cloudfront.CachePolicy(group, "cache", {
|
|
8734
9349
|
name,
|
|
8735
|
-
minTtl:
|
|
8736
|
-
maxTtl:
|
|
8737
|
-
defaultTtl:
|
|
9350
|
+
minTtl: toSeconds12(seconds12(0)),
|
|
9351
|
+
maxTtl: toSeconds12(days12(365)),
|
|
9352
|
+
defaultTtl: toSeconds12(days12(0)),
|
|
8738
9353
|
parametersInCacheKeyAndForwardedToOrigin: {
|
|
8739
9354
|
enableAcceptEncodingBrotli: true,
|
|
8740
9355
|
enableAcceptEncodingGzip: true,
|
|
@@ -8762,7 +9377,7 @@ var routerFeature = defineFeature({
|
|
|
8762
9377
|
}
|
|
8763
9378
|
}
|
|
8764
9379
|
});
|
|
8765
|
-
const originRequest = new
|
|
9380
|
+
const originRequest = new aws32.cloudfront.OriginRequestPolicy(group, "request", {
|
|
8766
9381
|
name,
|
|
8767
9382
|
headersConfig: {
|
|
8768
9383
|
headerBehavior: camelCase9("all-except"),
|
|
@@ -8780,11 +9395,11 @@ var routerFeature = defineFeature({
|
|
|
8780
9395
|
queryStringBehavior: "all"
|
|
8781
9396
|
}
|
|
8782
9397
|
});
|
|
8783
|
-
const responseHeaders = new
|
|
9398
|
+
const responseHeaders = new aws32.cloudfront.ResponseHeadersPolicy(group, "response", {
|
|
8784
9399
|
name,
|
|
8785
9400
|
corsConfig: {
|
|
8786
9401
|
originOverride: props.cors?.override ?? true,
|
|
8787
|
-
accessControlMaxAgeSec:
|
|
9402
|
+
accessControlMaxAgeSec: toSeconds12(props.cors?.maxAge ?? years(1)),
|
|
8788
9403
|
accessControlAllowHeaders: { items: props.cors?.headers ?? ["*"] },
|
|
8789
9404
|
accessControlAllowMethods: { items: props.cors?.methods ?? ["ALL"] },
|
|
8790
9405
|
accessControlAllowOrigins: { items: props.cors?.origins ?? ["*"] },
|
|
@@ -8809,7 +9424,7 @@ var routerFeature = defineFeature({
|
|
|
8809
9424
|
strictTransportSecurity: {
|
|
8810
9425
|
override: true,
|
|
8811
9426
|
preload: true,
|
|
8812
|
-
accessControlMaxAgeSec:
|
|
9427
|
+
accessControlMaxAgeSec: toSeconds12(years(1)),
|
|
8813
9428
|
includeSubdomains: true
|
|
8814
9429
|
},
|
|
8815
9430
|
xssProtection: {
|
|
@@ -8819,7 +9434,7 @@ var routerFeature = defineFeature({
|
|
|
8819
9434
|
}
|
|
8820
9435
|
}
|
|
8821
9436
|
});
|
|
8822
|
-
const viewerRequest = new
|
|
9437
|
+
const viewerRequest = new aws32.cloudfront.Function(group, "viewer-request", {
|
|
8823
9438
|
name,
|
|
8824
9439
|
runtime: `cloudfront-js-2.0`,
|
|
8825
9440
|
comment: `Viewer Request - ${name}`,
|
|
@@ -8841,7 +9456,7 @@ var routerFeature = defineFeature({
|
|
|
8841
9456
|
rateBasedStatement: {
|
|
8842
9457
|
limit: wafSettingsConfig.rateLimiter.limit,
|
|
8843
9458
|
aggregateKeyType: "IP",
|
|
8844
|
-
evaluationWindowSec:
|
|
9459
|
+
evaluationWindowSec: toSeconds12(wafSettingsConfig.rateLimiter.window)
|
|
8845
9460
|
}
|
|
8846
9461
|
},
|
|
8847
9462
|
action: {
|
|
@@ -8921,7 +9536,7 @@ var routerFeature = defineFeature({
|
|
|
8921
9536
|
}
|
|
8922
9537
|
let waf;
|
|
8923
9538
|
if (wafRules.length && wafSettingsConfig) {
|
|
8924
|
-
waf = new
|
|
9539
|
+
waf = new aws32.wafv2.WebAcl(group, "waf", {
|
|
8925
9540
|
name: `${name}-wafv2`,
|
|
8926
9541
|
scope: "CLOUDFRONT",
|
|
8927
9542
|
defaultAction: {
|
|
@@ -8931,12 +9546,12 @@ var routerFeature = defineFeature({
|
|
|
8931
9546
|
rule: wafRules,
|
|
8932
9547
|
captchaConfig: {
|
|
8933
9548
|
immunityTimeProperty: {
|
|
8934
|
-
immunityTime:
|
|
9549
|
+
immunityTime: toSeconds12(wafSettingsConfig.captchaImmunityTime)
|
|
8935
9550
|
}
|
|
8936
9551
|
},
|
|
8937
9552
|
challengeConfig: {
|
|
8938
9553
|
immunityTimeProperty: {
|
|
8939
|
-
immunityTime:
|
|
9554
|
+
immunityTime: toSeconds12(wafSettingsConfig.challengeImmunityTime)
|
|
8940
9555
|
}
|
|
8941
9556
|
},
|
|
8942
9557
|
visibilityConfig: {
|
|
@@ -8946,7 +9561,7 @@ var routerFeature = defineFeature({
|
|
|
8946
9561
|
}
|
|
8947
9562
|
});
|
|
8948
9563
|
}
|
|
8949
|
-
const distribution = new
|
|
9564
|
+
const distribution = new aws32.cloudfront.MultitenantDistribution(group, "distribution", {
|
|
8950
9565
|
tags: {
|
|
8951
9566
|
name
|
|
8952
9567
|
},
|
|
@@ -8992,7 +9607,7 @@ var routerFeature = defineFeature({
|
|
|
8992
9607
|
}
|
|
8993
9608
|
return {
|
|
8994
9609
|
errorCode: Number(errorCode),
|
|
8995
|
-
errorCachingMinTtl: item.minTTL ?
|
|
9610
|
+
errorCachingMinTtl: item.minTTL ? toSeconds12(item.minTTL) : void 0,
|
|
8996
9611
|
responseCode: item.statusCode?.toString() ?? errorCode,
|
|
8997
9612
|
responsePagePath: item.path
|
|
8998
9613
|
};
|
|
@@ -9043,7 +9658,7 @@ var routerFeature = defineFeature({
|
|
|
9043
9658
|
version: new Future((resolve2) => {
|
|
9044
9659
|
$combine(...versions).then((versions2) => {
|
|
9045
9660
|
const combined = versions2.filter((v) => !!v).sort().join(",");
|
|
9046
|
-
const version =
|
|
9661
|
+
const version = createHash8("sha1").update(combined).digest("hex");
|
|
9047
9662
|
resolve2(version);
|
|
9048
9663
|
});
|
|
9049
9664
|
})
|
|
@@ -9058,10 +9673,10 @@ var routerFeature = defineFeature({
|
|
|
9058
9673
|
const domainName = formatFullDomainName(ctx.appConfig, props.domain, props.subDomain);
|
|
9059
9674
|
const certificateArn = ctx.shared.entry("domain", `global-certificate-arn`, props.domain);
|
|
9060
9675
|
const zoneId = ctx.shared.entry("domain", "zone-id", props.domain);
|
|
9061
|
-
const connectionGroup = new
|
|
9676
|
+
const connectionGroup = new aws32.cloudfront.ConnectionGroup(group, "connection-group", {
|
|
9062
9677
|
name
|
|
9063
9678
|
});
|
|
9064
|
-
new
|
|
9679
|
+
new aws32.cloudfront.DistributionTenant(group, `tenant`, {
|
|
9065
9680
|
name,
|
|
9066
9681
|
enabled: true,
|
|
9067
9682
|
distributionId: distribution.id,
|
|
@@ -9069,7 +9684,7 @@ var routerFeature = defineFeature({
|
|
|
9069
9684
|
domain: [{ domain: domainName }],
|
|
9070
9685
|
customizations: [{ certificate: [{ arn: certificateArn }] }]
|
|
9071
9686
|
});
|
|
9072
|
-
new
|
|
9687
|
+
new aws32.route53.Record(group, `record`, {
|
|
9073
9688
|
zoneId,
|
|
9074
9689
|
type: "A",
|
|
9075
9690
|
name: domainName,
|
|
@@ -10192,21 +10807,21 @@ import wildstring4 from "wildstring";
|
|
|
10192
10807
|
|
|
10193
10808
|
// src/cli/ui/complex/run-tests.ts
|
|
10194
10809
|
import { log as log18 } from "@awsless/clui";
|
|
10195
|
-
import { mkdir as mkdir4, readFile as
|
|
10196
|
-
import { join as
|
|
10810
|
+
import { mkdir as mkdir4, readFile as readFile7, writeFile as writeFile4 } from "fs/promises";
|
|
10811
|
+
import { join as join23 } from "path";
|
|
10197
10812
|
import wildstring3 from "wildstring";
|
|
10198
|
-
import { parse as parse4, stringify as
|
|
10813
|
+
import { parse as parse4, stringify as stringify4 } from "@awsless/json";
|
|
10199
10814
|
import { generateFolderHash, loadWorkspace as loadWorkspace2 } from "@awsless/ts-file-cache";
|
|
10200
10815
|
|
|
10201
10816
|
// src/test/start.ts
|
|
10202
|
-
import { dirname as
|
|
10203
|
-
import { fileURLToPath as
|
|
10817
|
+
import { dirname as dirname11, join as join22 } from "path";
|
|
10818
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
10204
10819
|
import { configDefaults } from "vitest/config";
|
|
10205
10820
|
import { startVitest } from "vitest/node";
|
|
10206
10821
|
var NullReporter = class {
|
|
10207
10822
|
};
|
|
10208
10823
|
var startTest = async (props) => {
|
|
10209
|
-
const
|
|
10824
|
+
const __dirname7 = dirname11(fileURLToPath6(import.meta.url));
|
|
10210
10825
|
const startTime = process.hrtime.bigint();
|
|
10211
10826
|
process.noDeprecation = true;
|
|
10212
10827
|
const vitest = await startVitest(
|
|
@@ -10237,7 +10852,7 @@ var startTest = async (props) => {
|
|
|
10237
10852
|
// },
|
|
10238
10853
|
setupFiles: [
|
|
10239
10854
|
//
|
|
10240
|
-
|
|
10855
|
+
join22(__dirname7, "test-global-setup.js")
|
|
10241
10856
|
]
|
|
10242
10857
|
// globalSetup: [
|
|
10243
10858
|
// //
|
|
@@ -10431,12 +11046,12 @@ var logTestErrors = (event) => {
|
|
|
10431
11046
|
};
|
|
10432
11047
|
var runTest = async (stack, dir, filters, workspace, opts) => {
|
|
10433
11048
|
await mkdir4(directories.test, { recursive: true });
|
|
10434
|
-
const file =
|
|
11049
|
+
const file = join23(directories.test, `${stack}.json`);
|
|
10435
11050
|
const fingerprint = await generateFolderHash(workspace, dir);
|
|
10436
11051
|
if (!process.env.NO_CACHE) {
|
|
10437
11052
|
const exists = await fileExist(file);
|
|
10438
11053
|
if (exists) {
|
|
10439
|
-
const raw = await
|
|
11054
|
+
const raw = await readFile7(file, { encoding: "utf8" });
|
|
10440
11055
|
const data = parse4(raw);
|
|
10441
11056
|
if (data.fingerprint === fingerprint) {
|
|
10442
11057
|
log18.step(
|
|
@@ -10481,7 +11096,7 @@ var runTest = async (stack, dir, filters, workspace, opts) => {
|
|
|
10481
11096
|
logTestErrors(result);
|
|
10482
11097
|
await writeFile4(
|
|
10483
11098
|
file,
|
|
10484
|
-
|
|
11099
|
+
stringify4({
|
|
10485
11100
|
...result,
|
|
10486
11101
|
fingerprint
|
|
10487
11102
|
})
|
|
@@ -11116,7 +11731,7 @@ import { log as log25 } from "@awsless/clui";
|
|
|
11116
11731
|
|
|
11117
11732
|
// src/type-gen/generate.ts
|
|
11118
11733
|
import { mkdir as mkdir5, writeFile as writeFile5 } from "fs/promises";
|
|
11119
|
-
import { dirname as
|
|
11734
|
+
import { dirname as dirname12, join as join24, relative as relative9 } from "path";
|
|
11120
11735
|
var generateTypes = async (props) => {
|
|
11121
11736
|
const files = [];
|
|
11122
11737
|
await Promise.all(
|
|
@@ -11125,12 +11740,12 @@ var generateTypes = async (props) => {
|
|
|
11125
11740
|
...props,
|
|
11126
11741
|
async write(file, data, include = false) {
|
|
11127
11742
|
const code = data?.toString("utf8");
|
|
11128
|
-
const path =
|
|
11743
|
+
const path = join24(directories.types, file);
|
|
11129
11744
|
if (code) {
|
|
11130
11745
|
if (include) {
|
|
11131
11746
|
files.push(relative9(directories.root, path));
|
|
11132
11747
|
}
|
|
11133
|
-
await mkdir5(
|
|
11748
|
+
await mkdir5(dirname12(path), { recursive: true });
|
|
11134
11749
|
await writeFile5(path, code);
|
|
11135
11750
|
}
|
|
11136
11751
|
}
|
|
@@ -11139,7 +11754,7 @@ var generateTypes = async (props) => {
|
|
|
11139
11754
|
);
|
|
11140
11755
|
if (files.length) {
|
|
11141
11756
|
const code = files.map((file) => `/// <reference path='${file}' />`).join("\n");
|
|
11142
|
-
await writeFile5(
|
|
11757
|
+
await writeFile5(join24(directories.root, `awsless.d.ts`), code);
|
|
11143
11758
|
}
|
|
11144
11759
|
};
|
|
11145
11760
|
|
|
@@ -11565,7 +12180,7 @@ var domain = (program2) => {
|
|
|
11565
12180
|
// src/cli/command/logs.ts
|
|
11566
12181
|
import { CloudWatchLogsClient, StartLiveTailCommand } from "@aws-sdk/client-cloudwatch-logs";
|
|
11567
12182
|
import { log as log30 } from "@awsless/clui";
|
|
11568
|
-
import { aws as
|
|
12183
|
+
import { aws as aws33 } from "@terraforge/aws";
|
|
11569
12184
|
import chalk6 from "chalk";
|
|
11570
12185
|
import chunk2 from "chunk";
|
|
11571
12186
|
import { formatDate } from "date-fns";
|
|
@@ -11588,7 +12203,7 @@ var logs = (program2) => {
|
|
|
11588
12203
|
for (const stack of app.stacks) {
|
|
11589
12204
|
if (filters.find((f) => wildstring7.match(f, stack.name))) {
|
|
11590
12205
|
for (const resource of stack.resources) {
|
|
11591
|
-
if (resource instanceof
|
|
12206
|
+
if (resource instanceof aws33.cloudwatch.LogGroup) {
|
|
11592
12207
|
logGroupArns.push(await resource.arn);
|
|
11593
12208
|
}
|
|
11594
12209
|
}
|