@awsless/cli 0.0.2 → 0.0.4
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/bin.js
CHANGED
|
@@ -3894,9 +3894,9 @@ var createLambdaFunction = (parentGroup, ctx, ns, id, local) => {
|
|
|
3894
3894
|
const policy = new aws4.iam.RolePolicy(group, "policy", {
|
|
3895
3895
|
role: role.name,
|
|
3896
3896
|
name: "lambda-policy",
|
|
3897
|
-
policy: new Output3(statementDeps, async (
|
|
3897
|
+
policy: new Output3(statementDeps, async (resolve) => {
|
|
3898
3898
|
const list3 = await resolveInputs(statements);
|
|
3899
|
-
|
|
3899
|
+
resolve(
|
|
3900
3900
|
JSON.stringify({
|
|
3901
3901
|
Version: "2012-10-17",
|
|
3902
3902
|
Statement: list3.map((statement) => ({
|
|
@@ -4645,9 +4645,9 @@ var createPrebuildLambdaFunction = (group, ctx, ns, id, props) => {
|
|
|
4645
4645
|
const policy = new aws8.iam.RolePolicy(group, "policy", {
|
|
4646
4646
|
role: role.name,
|
|
4647
4647
|
name: "lambda-policy",
|
|
4648
|
-
policy: new Output4(statementDeps, async (
|
|
4648
|
+
policy: new Output4(statementDeps, async (resolve) => {
|
|
4649
4649
|
const list3 = await resolveInputs2(statements);
|
|
4650
|
-
|
|
4650
|
+
resolve(
|
|
4651
4651
|
JSON.stringify({
|
|
4652
4652
|
Version: "2012-10-17",
|
|
4653
4653
|
Statement: list3.map((statement) => ({
|
|
@@ -7233,14 +7233,11 @@ var iconFeature = defineFeature({
|
|
|
7233
7233
|
}
|
|
7234
7234
|
});
|
|
7235
7235
|
|
|
7236
|
-
// src/feature/
|
|
7237
|
-
import { Group as Group26
|
|
7236
|
+
// src/feature/instance/index.ts
|
|
7237
|
+
import { Group as Group26 } from "@terraforge/core";
|
|
7238
7238
|
import { aws as aws27 } from "@terraforge/aws";
|
|
7239
|
-
import { camelCase as camelCase8 } from "change-case";
|
|
7240
|
-
import { relative as relative8 } from "path";
|
|
7241
7239
|
|
|
7242
|
-
// src/feature/
|
|
7243
|
-
import { createHash as createHash4 } from "crypto";
|
|
7240
|
+
// src/feature/instance/util.ts
|
|
7244
7241
|
import { toDays as toDays9, toSeconds as toSeconds9 } from "@awsless/duration";
|
|
7245
7242
|
import { stringify } from "@awsless/json";
|
|
7246
7243
|
import { toMebibytes as toMebibytes5 } from "@awsless/size";
|
|
@@ -7248,37 +7245,21 @@ import { generateFileHash as generateFileHash2 } from "@awsless/ts-file-cache";
|
|
|
7248
7245
|
import { aws as aws26 } from "@terraforge/aws";
|
|
7249
7246
|
import { Group as Group25, Output as Output6, findInputDeps as findInputDeps3, resolveInputs as resolveInputs3 } from "@terraforge/core";
|
|
7250
7247
|
import { constantCase as constantCase12, pascalCase as pascalCase3 } from "change-case";
|
|
7248
|
+
import { createHash as createHash4 } from "crypto";
|
|
7251
7249
|
import deepmerge4 from "deepmerge";
|
|
7250
|
+
import { join as join18 } from "path";
|
|
7252
7251
|
|
|
7253
|
-
// src/feature/
|
|
7252
|
+
// src/feature/instance/build/executable.ts
|
|
7254
7253
|
import { createHash as createHash3 } from "crypto";
|
|
7255
|
-
import { readFile as readFile4
|
|
7256
|
-
import { join as join17
|
|
7257
|
-
var
|
|
7254
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
7255
|
+
import { join as join17 } from "path";
|
|
7256
|
+
var buildExecutable = async (input, outputPath, architecture) => {
|
|
7258
7257
|
const filePath = join17(outputPath, "program");
|
|
7259
|
-
const wrapperPath = join17(outputPath, "wrapper.ts");
|
|
7260
|
-
const handlerPath = resolve(input);
|
|
7261
|
-
await writeFile3(
|
|
7262
|
-
wrapperPath,
|
|
7263
|
-
`import { parse } from '@awsless/json'
|
|
7264
|
-
import { getObject } from '@awsless/s3'
|
|
7265
|
-
import handler from '${handlerPath}'
|
|
7266
|
-
|
|
7267
|
-
let payload = process.env.PAYLOAD ? parse(process.env.PAYLOAD) : undefined
|
|
7268
|
-
if (typeof payload === 'string' && payload.startsWith('s3://')) {
|
|
7269
|
-
const url = new URL(payload)
|
|
7270
|
-
const response = await getObject({ bucket: url.hostname, key: url.pathname.slice(1) })
|
|
7271
|
-
if (!response) throw new Error('Failed to fetch payload from S3: ' + payload)
|
|
7272
|
-
payload = parse(await response.body.transformToString())
|
|
7273
|
-
}
|
|
7274
|
-
await handler(payload)
|
|
7275
|
-
`
|
|
7276
|
-
);
|
|
7277
7258
|
const target = architecture === "x86_64" ? "bun-linux-x64" : "bun-linux-arm64";
|
|
7278
7259
|
let result;
|
|
7279
7260
|
try {
|
|
7280
7261
|
result = await Bun.build({
|
|
7281
|
-
entrypoints: [
|
|
7262
|
+
entrypoints: [input],
|
|
7282
7263
|
compile: {
|
|
7283
7264
|
target,
|
|
7284
7265
|
outfile: filePath
|
|
@@ -7287,23 +7268,23 @@ await handler(payload)
|
|
|
7287
7268
|
});
|
|
7288
7269
|
} catch (error) {
|
|
7289
7270
|
throw new ExpectedError(
|
|
7290
|
-
`
|
|
7271
|
+
`Executable build failed: ${error instanceof Error ? error.message : JSON.stringify(error)}`
|
|
7291
7272
|
);
|
|
7292
7273
|
}
|
|
7293
7274
|
if (!result.success) {
|
|
7294
|
-
throw new ExpectedError(`
|
|
7275
|
+
throw new ExpectedError(`Executable build failed:
|
|
7295
7276
|
${result.logs?.map((log35) => log35.message).join("\n")}`);
|
|
7296
7277
|
}
|
|
7297
7278
|
const file = await readFile4(filePath);
|
|
7298
7279
|
return {
|
|
7299
|
-
hash: createHash3("sha1").update(file).update(
|
|
7280
|
+
hash: createHash3("sha1").update(file).update("x86_64").digest("hex"),
|
|
7300
7281
|
file
|
|
7301
7282
|
};
|
|
7302
7283
|
};
|
|
7303
7284
|
|
|
7304
|
-
// src/feature/
|
|
7305
|
-
var
|
|
7306
|
-
const group = new Group25(parentGroup, "
|
|
7285
|
+
// src/feature/instance/util.ts
|
|
7286
|
+
var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
7287
|
+
const group = new Group25(parentGroup, "instance", ns);
|
|
7307
7288
|
const name = formatLocalResourceName({
|
|
7308
7289
|
appName: ctx.app.name,
|
|
7309
7290
|
stackName: ctx.stack.name,
|
|
@@ -7311,13 +7292,13 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7311
7292
|
resourceName: id
|
|
7312
7293
|
});
|
|
7313
7294
|
const shortName = shortId(`${ctx.app.name}:${ctx.stack.name}:${ns}:${id}:${ctx.appId}`);
|
|
7314
|
-
const props = deepmerge4(ctx.appConfig.defaults.
|
|
7315
|
-
const image2 = props.image || "public.ecr.aws/
|
|
7316
|
-
ctx.registerBuild("
|
|
7317
|
-
const fingerprint =
|
|
7295
|
+
const props = deepmerge4(ctx.appConfig.defaults.instance, local);
|
|
7296
|
+
const image2 = props.image || (props.architecture === "arm64" ? "public.ecr.aws/aws-cli/aws-cli:arm64" : "public.ecr.aws/aws-cli/aws-cli:amd64");
|
|
7297
|
+
ctx.registerBuild("instance", name, async (build3, { workspace }) => {
|
|
7298
|
+
const fingerprint = await generateFileHash2(workspace, local.code.file);
|
|
7318
7299
|
return build3(fingerprint, async (write) => {
|
|
7319
|
-
const temp = await createTempFolder(`
|
|
7320
|
-
const executable = await
|
|
7300
|
+
const temp = await createTempFolder(`instance--${name}`);
|
|
7301
|
+
const executable = await buildExecutable(local.code.file, temp.path, props.architecture);
|
|
7321
7302
|
await Promise.all([
|
|
7322
7303
|
//
|
|
7323
7304
|
write("HASH", executable.hash),
|
|
@@ -7330,10 +7311,10 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7330
7311
|
});
|
|
7331
7312
|
});
|
|
7332
7313
|
const code = new aws26.s3.BucketObject(group, "code", {
|
|
7333
|
-
bucket: ctx.shared.get("
|
|
7314
|
+
bucket: ctx.shared.get("instance", "bucket-name"),
|
|
7334
7315
|
key: name,
|
|
7335
|
-
source: relativePath(getBuildPath("
|
|
7336
|
-
sourceHash: $file(getBuildPath("
|
|
7316
|
+
source: relativePath(getBuildPath("instance", name, "program")),
|
|
7317
|
+
sourceHash: $file(getBuildPath("instance", name, "HASH"))
|
|
7337
7318
|
});
|
|
7338
7319
|
const executionRole = new aws26.iam.Role(group, "execution-role", {
|
|
7339
7320
|
name: shortId(`${shortName}:execution-role`),
|
|
@@ -7379,8 +7360,8 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7379
7360
|
Statement: [
|
|
7380
7361
|
{
|
|
7381
7362
|
Effect: pascalCase3("allow"),
|
|
7382
|
-
Action: ["s3:
|
|
7383
|
-
Resource:
|
|
7363
|
+
Action: ["s3:getObject", "s3:HeadObject"],
|
|
7364
|
+
Resource: `arn:aws:s3:::${bucket}/${key}`
|
|
7384
7365
|
}
|
|
7385
7366
|
]
|
|
7386
7367
|
});
|
|
@@ -7397,9 +7378,9 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7397
7378
|
const policy = new aws26.iam.RolePolicy(group, "policy", {
|
|
7398
7379
|
role: role.name,
|
|
7399
7380
|
name: "task-policy",
|
|
7400
|
-
policy: new Output6(statementDeps, async (
|
|
7381
|
+
policy: new Output6(statementDeps, async (resolve) => {
|
|
7401
7382
|
const list3 = await resolveInputs3(statements);
|
|
7402
|
-
|
|
7383
|
+
resolve(
|
|
7403
7384
|
JSON.stringify({
|
|
7404
7385
|
Version: "2012-10-17",
|
|
7405
7386
|
Statement: list3.map((statement) => ({
|
|
@@ -7424,6 +7405,7 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7424
7405
|
if (props.log.retention && props.log.retention.value > 0n) {
|
|
7425
7406
|
logGroup = new aws26.cloudwatch.LogGroup(group, "log", {
|
|
7426
7407
|
name: `/aws/ecs/${name}`,
|
|
7408
|
+
// name: `/aws/lambda/${name}`,
|
|
7427
7409
|
retentionInDays: toDays9(props.log.retention)
|
|
7428
7410
|
});
|
|
7429
7411
|
if (ctx.shared.has("on-error-log", "subscriber-arn")) {
|
|
@@ -7442,63 +7424,6 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7442
7424
|
};
|
|
7443
7425
|
const variables = {};
|
|
7444
7426
|
const variableDeps = /* @__PURE__ */ new Set();
|
|
7445
|
-
const taskDependsOn = [code];
|
|
7446
|
-
const accessPoint = props.persistentStorage ? (() => {
|
|
7447
|
-
const persistentStorageSecurityGroup = new aws26.security.Group(
|
|
7448
|
-
group,
|
|
7449
|
-
"persistent-storage-security-group",
|
|
7450
|
-
{
|
|
7451
|
-
name: shortId(`${shortName}:storage-sg`),
|
|
7452
|
-
description: name,
|
|
7453
|
-
vpcId: ctx.shared.get("vpc", "id"),
|
|
7454
|
-
revokeRulesOnDelete: true,
|
|
7455
|
-
tags
|
|
7456
|
-
}
|
|
7457
|
-
);
|
|
7458
|
-
new aws26.vpc.SecurityGroupIngressRule(group, "persistent-storage-ingress-rule", {
|
|
7459
|
-
securityGroupId: persistentStorageSecurityGroup.id,
|
|
7460
|
-
referencedSecurityGroupId: ctx.shared.get("job", "security-group-id"),
|
|
7461
|
-
description: "Allow NFS traffic from this job",
|
|
7462
|
-
ipProtocol: "tcp",
|
|
7463
|
-
fromPort: 2049,
|
|
7464
|
-
toPort: 2049,
|
|
7465
|
-
tags
|
|
7466
|
-
});
|
|
7467
|
-
const fileSystem = new aws26.efs.FileSystem(group, "persistent-storage-file-system", {
|
|
7468
|
-
encrypted: true,
|
|
7469
|
-
performanceMode: "generalPurpose",
|
|
7470
|
-
throughputMode: "elastic",
|
|
7471
|
-
tags: {
|
|
7472
|
-
...tags,
|
|
7473
|
-
Name: `${name}-storage`
|
|
7474
|
-
}
|
|
7475
|
-
});
|
|
7476
|
-
for (const [index, subnetId] of ctx.shared.get("vpc", "public-subnets").entries()) {
|
|
7477
|
-
const mountTarget = new aws26.efs.MountTarget(group, `mount-target-${index + 1}`, {
|
|
7478
|
-
fileSystemId: fileSystem.id,
|
|
7479
|
-
subnetId,
|
|
7480
|
-
securityGroups: [persistentStorageSecurityGroup.id]
|
|
7481
|
-
});
|
|
7482
|
-
taskDependsOn.push(mountTarget);
|
|
7483
|
-
}
|
|
7484
|
-
const accessPoint2 = new aws26.efs.AccessPoint(group, "access-point", {
|
|
7485
|
-
fileSystemId: fileSystem.id,
|
|
7486
|
-
rootDirectory: {
|
|
7487
|
-
path: `/jobs/${name}`,
|
|
7488
|
-
creationInfo: {
|
|
7489
|
-
ownerUid: 0,
|
|
7490
|
-
ownerGid: 0,
|
|
7491
|
-
permissions: "755"
|
|
7492
|
-
}
|
|
7493
|
-
},
|
|
7494
|
-
tags
|
|
7495
|
-
});
|
|
7496
|
-
taskDependsOn.push(fileSystem, accessPoint2);
|
|
7497
|
-
return {
|
|
7498
|
-
accessPoint: accessPoint2,
|
|
7499
|
-
fileSystem
|
|
7500
|
-
};
|
|
7501
|
-
})() : void 0;
|
|
7502
7427
|
const task2 = new aws26.ecs.TaskDefinition(
|
|
7503
7428
|
group,
|
|
7504
7429
|
"task",
|
|
@@ -7515,495 +7440,13 @@ var createFargateJob = (parentGroup, ctx, ns, id, local) => {
|
|
|
7515
7440
|
operatingSystemFamily: "LINUX"
|
|
7516
7441
|
},
|
|
7517
7442
|
trackLatest: true,
|
|
7518
|
-
|
|
7519
|
-
volume: [
|
|
7520
|
-
{
|
|
7521
|
-
name: "persistent-storage",
|
|
7522
|
-
efsVolumeConfiguration: {
|
|
7523
|
-
fileSystemId: accessPoint.fileSystem.id,
|
|
7524
|
-
transitEncryption: "ENABLED",
|
|
7525
|
-
authorizationConfig: {
|
|
7526
|
-
accessPointId: accessPoint.accessPoint.id
|
|
7527
|
-
}
|
|
7528
|
-
}
|
|
7529
|
-
}
|
|
7530
|
-
]
|
|
7531
|
-
},
|
|
7532
|
-
containerDefinitions: new Output6(variableDeps, async (resolve2) => {
|
|
7443
|
+
containerDefinitions: new Output6(variableDeps, async (resolve) => {
|
|
7533
7444
|
const data = await resolveInputs3(variables);
|
|
7534
7445
|
const { s3Bucket, s3Key } = await resolveInputs3({
|
|
7535
7446
|
s3Bucket: code.bucket,
|
|
7536
7447
|
s3Key: code.key
|
|
7537
7448
|
});
|
|
7538
|
-
|
|
7539
|
-
JSON.stringify([
|
|
7540
|
-
{
|
|
7541
|
-
name: `container-${id}`,
|
|
7542
|
-
essential: true,
|
|
7543
|
-
image: image2,
|
|
7544
|
-
workingDirectory: "/usr/app",
|
|
7545
|
-
entryPoint: ["sh", "-c"],
|
|
7546
|
-
command: [
|
|
7547
|
-
[
|
|
7548
|
-
...props.startupCommand?.length ? (() => {
|
|
7549
|
-
const setupHash = createHash4("sha1").update(props.startupCommand.join(" && ")).digest("hex").slice(0, 8);
|
|
7550
|
-
return [`if [ ! -f /root/.setup-done-${setupHash} ]; then ${props.startupCommand.join(" && ")} && touch /root/.setup-done-${setupHash}; fi`];
|
|
7551
|
-
})() : [],
|
|
7552
|
-
`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`,
|
|
7553
|
-
`exec timeout --kill-after=10 ${toSeconds9(props.timeout)} /root/program`
|
|
7554
|
-
].join(" && ")
|
|
7555
|
-
],
|
|
7556
|
-
environment: Object.entries(data).map(([name2, value]) => ({
|
|
7557
|
-
name: name2,
|
|
7558
|
-
value
|
|
7559
|
-
})),
|
|
7560
|
-
...accessPoint && {
|
|
7561
|
-
mountPoints: [
|
|
7562
|
-
{
|
|
7563
|
-
sourceVolume: "persistent-storage",
|
|
7564
|
-
containerPath: "/root"
|
|
7565
|
-
}
|
|
7566
|
-
]
|
|
7567
|
-
},
|
|
7568
|
-
...logGroup && {
|
|
7569
|
-
logConfiguration: {
|
|
7570
|
-
logDriver: "awslogs",
|
|
7571
|
-
options: {
|
|
7572
|
-
"awslogs-group": `/aws/ecs/${name}`,
|
|
7573
|
-
"awslogs-region": ctx.appConfig.region,
|
|
7574
|
-
"awslogs-stream-prefix": "ecs",
|
|
7575
|
-
mode: "non-blocking"
|
|
7576
|
-
}
|
|
7577
|
-
}
|
|
7578
|
-
}
|
|
7579
|
-
}
|
|
7580
|
-
])
|
|
7581
|
-
);
|
|
7582
|
-
}),
|
|
7583
|
-
tags
|
|
7584
|
-
},
|
|
7585
|
-
{
|
|
7586
|
-
replaceOnChanges: [
|
|
7587
|
-
"containerDefinitions",
|
|
7588
|
-
"cpu",
|
|
7589
|
-
"memory",
|
|
7590
|
-
"runtimePlatform",
|
|
7591
|
-
"executionRoleArn",
|
|
7592
|
-
"taskRoleArn"
|
|
7593
|
-
],
|
|
7594
|
-
dependsOn: taskDependsOn
|
|
7595
|
-
}
|
|
7596
|
-
);
|
|
7597
|
-
ctx.onEnv((name2, value) => {
|
|
7598
|
-
variables[name2] = value;
|
|
7599
|
-
for (const dep of findInputDeps3([value])) {
|
|
7600
|
-
variableDeps.add(dep);
|
|
7601
|
-
}
|
|
7602
|
-
});
|
|
7603
|
-
variables.APP = ctx.appConfig.name;
|
|
7604
|
-
variables.APP_ID = ctx.appId;
|
|
7605
|
-
variables.AWS_ACCOUNT_ID = ctx.accountId;
|
|
7606
|
-
variables.STACK = ctx.stackConfig.name;
|
|
7607
|
-
variables.CODE_HASH = code.sourceHash;
|
|
7608
|
-
variables.JOB_CONFIG_HASH = createHash4("sha1").update(stringify(props)).digest("hex");
|
|
7609
|
-
if (props.environment) {
|
|
7610
|
-
for (const [key, value] of Object.entries(props.environment)) {
|
|
7611
|
-
variables[key] = value;
|
|
7612
|
-
}
|
|
7613
|
-
}
|
|
7614
|
-
if (ctx.appConfig.defaults.job.permissions) {
|
|
7615
|
-
statements.push(...ctx.appConfig.defaults.job.permissions);
|
|
7616
|
-
}
|
|
7617
|
-
if ("permissions" in local && local.permissions) {
|
|
7618
|
-
statements.push(...local.permissions);
|
|
7619
|
-
}
|
|
7620
|
-
return { name, task: task2, policy, code, group };
|
|
7621
|
-
};
|
|
7622
|
-
|
|
7623
|
-
// src/feature/job/index.ts
|
|
7624
|
-
var typeGenCode10 = `
|
|
7625
|
-
import type { Mock } from 'vitest'
|
|
7626
|
-
|
|
7627
|
-
type Func = (...args: any[]) => any
|
|
7628
|
-
|
|
7629
|
-
type Invoke<N extends string, F extends Func> = Parameters<F> extends []
|
|
7630
|
-
? InvokeWithoutPayload<N, F>
|
|
7631
|
-
: unknown extends Parameters<F>[0]
|
|
7632
|
-
? InvokeWithoutPayload<N, F>
|
|
7633
|
-
: InvokeWithPayload<N, F>
|
|
7634
|
-
|
|
7635
|
-
type InvokeWithPayload<Name extends string, F extends Func> = {
|
|
7636
|
-
readonly name: Name
|
|
7637
|
-
(payload: Parameters<F>[0]): Promise<{ taskArn: string | undefined }>
|
|
7638
|
-
}
|
|
7639
|
-
|
|
7640
|
-
type InvokeWithoutPayload<Name extends string, F extends Func> = {
|
|
7641
|
-
readonly name: Name
|
|
7642
|
-
(payload?: Parameters<F>[0]): Promise<{ taskArn: string | undefined }>
|
|
7643
|
-
}
|
|
7644
|
-
|
|
7645
|
-
type MockHandle<F extends Func> = (payload: Parameters<F>[0]) => void | Promise<void>
|
|
7646
|
-
type MockBuilder<F extends Func> = (handle?: MockHandle<F>) => void
|
|
7647
|
-
type MockObject<F extends Func> = Mock<Parameters<F>, ReturnType<F>>
|
|
7648
|
-
`;
|
|
7649
|
-
var jobFeature = defineFeature({
|
|
7650
|
-
name: "job",
|
|
7651
|
-
async onTypeGen(ctx) {
|
|
7652
|
-
const types2 = new TypeFile("awsless");
|
|
7653
|
-
const resources2 = new TypeObject(1);
|
|
7654
|
-
const mocks = new TypeObject(1);
|
|
7655
|
-
const mockResponses = new TypeObject(1);
|
|
7656
|
-
for (const stack of ctx.stackConfigs) {
|
|
7657
|
-
const resource = new TypeObject(2);
|
|
7658
|
-
const mock = new TypeObject(2);
|
|
7659
|
-
const mockResponse = new TypeObject(2);
|
|
7660
|
-
for (const [name, props] of Object.entries(stack.jobs || {})) {
|
|
7661
|
-
const varName = camelCase8(`${stack.name}-${name}`);
|
|
7662
|
-
const funcName = formatLocalResourceName({
|
|
7663
|
-
appName: ctx.appConfig.name,
|
|
7664
|
-
stackName: stack.name,
|
|
7665
|
-
resourceType: "job",
|
|
7666
|
-
resourceName: name
|
|
7667
|
-
});
|
|
7668
|
-
if ("file" in props.code) {
|
|
7669
|
-
const relFile = relative8(directories.types, props.code.file);
|
|
7670
|
-
types2.addImport(varName, relFile);
|
|
7671
|
-
resource.addType(name, `Invoke<'${funcName}', typeof ${varName}>`);
|
|
7672
|
-
mock.addType(name, `MockBuilder<typeof ${varName}>`);
|
|
7673
|
-
mockResponse.addType(name, `MockObject<typeof ${varName}>`);
|
|
7674
|
-
}
|
|
7675
|
-
}
|
|
7676
|
-
mocks.addType(stack.name, mock);
|
|
7677
|
-
resources2.addType(stack.name, resource);
|
|
7678
|
-
mockResponses.addType(stack.name, mockResponse);
|
|
7679
|
-
}
|
|
7680
|
-
types2.addCode(typeGenCode10);
|
|
7681
|
-
types2.addInterface("JobResources", resources2);
|
|
7682
|
-
types2.addInterface("JobMock", mocks);
|
|
7683
|
-
types2.addInterface("JobMockResponse", mockResponses);
|
|
7684
|
-
await ctx.write("job.d.ts", types2, true);
|
|
7685
|
-
},
|
|
7686
|
-
onBefore(ctx) {
|
|
7687
|
-
const group = new Group26(ctx.base, "job", "asset");
|
|
7688
|
-
const bucket = new aws27.s3.Bucket(group, "bucket", {
|
|
7689
|
-
bucket: formatGlobalResourceName({
|
|
7690
|
-
appName: ctx.app.name,
|
|
7691
|
-
resourceType: "job",
|
|
7692
|
-
resourceName: "assets",
|
|
7693
|
-
postfix: ctx.appId
|
|
7694
|
-
}),
|
|
7695
|
-
forceDestroy: true,
|
|
7696
|
-
lifecycleRule: [
|
|
7697
|
-
{
|
|
7698
|
-
id: "expire-payloads",
|
|
7699
|
-
enabled: true,
|
|
7700
|
-
prefix: "payloads/",
|
|
7701
|
-
expiration: { days: 1 }
|
|
7702
|
-
}
|
|
7703
|
-
]
|
|
7704
|
-
});
|
|
7705
|
-
ctx.shared.set("job", "bucket-name", bucket.bucket);
|
|
7706
|
-
},
|
|
7707
|
-
onApp(ctx) {
|
|
7708
|
-
const found = ctx.stackConfigs.filter((stack) => {
|
|
7709
|
-
return Object.keys(stack.jobs ?? {}).length > 0;
|
|
7710
|
-
});
|
|
7711
|
-
if (found.length === 0) {
|
|
7712
|
-
return;
|
|
7713
|
-
}
|
|
7714
|
-
const group = new Group26(ctx.base, "job", "cluster");
|
|
7715
|
-
const cluster = new aws27.ecs.Cluster(
|
|
7716
|
-
group,
|
|
7717
|
-
"cluster",
|
|
7718
|
-
{
|
|
7719
|
-
name: `${ctx.app.name}-job`
|
|
7720
|
-
},
|
|
7721
|
-
{
|
|
7722
|
-
replaceOnChanges: ["name"]
|
|
7723
|
-
}
|
|
7724
|
-
);
|
|
7725
|
-
ctx.shared.set("job", "cluster-name", cluster.name);
|
|
7726
|
-
ctx.shared.set("job", "cluster-arn", cluster.arn);
|
|
7727
|
-
const securityGroup = new aws27.security.Group(group, "security-group", {
|
|
7728
|
-
name: `${ctx.app.name}-job`,
|
|
7729
|
-
description: "Shared security group for jobs",
|
|
7730
|
-
vpcId: ctx.shared.get("vpc", "id"),
|
|
7731
|
-
revokeRulesOnDelete: true,
|
|
7732
|
-
tags: {
|
|
7733
|
-
APP: ctx.appConfig.name
|
|
7734
|
-
}
|
|
7735
|
-
});
|
|
7736
|
-
new aws27.vpc.SecurityGroupEgressRule(group, "egress-rule", {
|
|
7737
|
-
securityGroupId: securityGroup.id,
|
|
7738
|
-
description: "Allow all outbound traffic from jobs",
|
|
7739
|
-
ipProtocol: "-1",
|
|
7740
|
-
cidrIpv4: "0.0.0.0/0",
|
|
7741
|
-
tags: {
|
|
7742
|
-
APP: ctx.appConfig.name
|
|
7743
|
-
}
|
|
7744
|
-
});
|
|
7745
|
-
ctx.shared.set("job", "security-group-id", securityGroup.id);
|
|
7746
|
-
},
|
|
7747
|
-
onStack(ctx) {
|
|
7748
|
-
const subnets = ctx.shared.get("vpc", "public-subnets");
|
|
7749
|
-
ctx.addEnv(
|
|
7750
|
-
"JOB_SUBNETS",
|
|
7751
|
-
new Output7(new Set(findInputDeps4(subnets)), async (resolve2) => {
|
|
7752
|
-
const resolved = await resolveInputs4(subnets);
|
|
7753
|
-
resolve2(JSON.stringify(resolved));
|
|
7754
|
-
})
|
|
7755
|
-
);
|
|
7756
|
-
ctx.addEnv("JOB_SECURITY_GROUP", ctx.shared.get("job", "security-group-id"));
|
|
7757
|
-
ctx.addEnv("JOB_PAYLOAD_BUCKET", ctx.shared.get("job", "bucket-name"));
|
|
7758
|
-
const jobs = Object.entries(ctx.stackConfig.jobs ?? {});
|
|
7759
|
-
if (jobs.length === 0) return;
|
|
7760
|
-
for (const [id, props] of jobs) {
|
|
7761
|
-
const group = new Group26(ctx.stack, "job", id);
|
|
7762
|
-
createFargateJob(group, ctx, "job", id, props);
|
|
7763
|
-
}
|
|
7764
|
-
ctx.addStackPermission({
|
|
7765
|
-
actions: ["ecs:RunTask"],
|
|
7766
|
-
resources: [
|
|
7767
|
-
`arn:aws:ecs:${ctx.appConfig.region}:*:task-definition/${ctx.app.name}--${ctx.stackConfig.name}--*`
|
|
7768
|
-
]
|
|
7769
|
-
});
|
|
7770
|
-
ctx.addStackPermission({
|
|
7771
|
-
actions: ["iam:PassRole"],
|
|
7772
|
-
resources: ["*"],
|
|
7773
|
-
conditions: {
|
|
7774
|
-
StringEquals: {
|
|
7775
|
-
"iam:PassedToService": "ecs-tasks.amazonaws.com"
|
|
7776
|
-
}
|
|
7777
|
-
}
|
|
7778
|
-
});
|
|
7779
|
-
ctx.addStackPermission({
|
|
7780
|
-
actions: ["s3:PutObject"],
|
|
7781
|
-
resources: [
|
|
7782
|
-
`arn:aws:s3:::${formatGlobalResourceName({
|
|
7783
|
-
appName: ctx.app.name,
|
|
7784
|
-
resourceType: "job",
|
|
7785
|
-
resourceName: "assets",
|
|
7786
|
-
postfix: ctx.appId
|
|
7787
|
-
})}/payloads/*`
|
|
7788
|
-
]
|
|
7789
|
-
});
|
|
7790
|
-
}
|
|
7791
|
-
});
|
|
7792
|
-
|
|
7793
|
-
// src/feature/instance/index.ts
|
|
7794
|
-
import { Group as Group28 } from "@terraforge/core";
|
|
7795
|
-
import { aws as aws29 } from "@terraforge/aws";
|
|
7796
|
-
|
|
7797
|
-
// src/feature/instance/util.ts
|
|
7798
|
-
import { toDays as toDays10, toSeconds as toSeconds10 } from "@awsless/duration";
|
|
7799
|
-
import { stringify as stringify2 } from "@awsless/json";
|
|
7800
|
-
import { toMebibytes as toMebibytes6 } from "@awsless/size";
|
|
7801
|
-
import { generateFileHash as generateFileHash3 } from "@awsless/ts-file-cache";
|
|
7802
|
-
import { aws as aws28 } from "@terraforge/aws";
|
|
7803
|
-
import { Group as Group27, Output as Output8, findInputDeps as findInputDeps5, resolveInputs as resolveInputs5 } from "@terraforge/core";
|
|
7804
|
-
import { constantCase as constantCase13, pascalCase as pascalCase4 } from "change-case";
|
|
7805
|
-
import { createHash as createHash6 } from "crypto";
|
|
7806
|
-
import deepmerge5 from "deepmerge";
|
|
7807
|
-
import { join as join19 } from "path";
|
|
7808
|
-
|
|
7809
|
-
// src/feature/instance/build/executable.ts
|
|
7810
|
-
import { createHash as createHash5 } from "crypto";
|
|
7811
|
-
import { readFile as readFile5 } from "fs/promises";
|
|
7812
|
-
import { join as join18 } from "path";
|
|
7813
|
-
var buildExecutable = async (input, outputPath, architecture) => {
|
|
7814
|
-
const filePath = join18(outputPath, "program");
|
|
7815
|
-
const target = architecture === "x86_64" ? "bun-linux-x64" : "bun-linux-arm64";
|
|
7816
|
-
let result;
|
|
7817
|
-
try {
|
|
7818
|
-
result = await Bun.build({
|
|
7819
|
-
entrypoints: [input],
|
|
7820
|
-
compile: {
|
|
7821
|
-
target,
|
|
7822
|
-
outfile: filePath
|
|
7823
|
-
},
|
|
7824
|
-
target: "bun"
|
|
7825
|
-
});
|
|
7826
|
-
} catch (error) {
|
|
7827
|
-
throw new ExpectedError(
|
|
7828
|
-
`Executable build failed: ${error instanceof Error ? error.message : JSON.stringify(error)}`
|
|
7829
|
-
);
|
|
7830
|
-
}
|
|
7831
|
-
if (!result.success) {
|
|
7832
|
-
throw new ExpectedError(`Executable build failed:
|
|
7833
|
-
${result.logs?.map((log35) => log35.message).join("\n")}`);
|
|
7834
|
-
}
|
|
7835
|
-
const file = await readFile5(filePath);
|
|
7836
|
-
return {
|
|
7837
|
-
hash: createHash5("sha1").update(file).update("x86_64").digest("hex"),
|
|
7838
|
-
file
|
|
7839
|
-
};
|
|
7840
|
-
};
|
|
7841
|
-
|
|
7842
|
-
// src/feature/instance/util.ts
|
|
7843
|
-
var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
7844
|
-
const group = new Group27(parentGroup, "instance", ns);
|
|
7845
|
-
const name = formatLocalResourceName({
|
|
7846
|
-
appName: ctx.app.name,
|
|
7847
|
-
stackName: ctx.stack.name,
|
|
7848
|
-
resourceType: ns,
|
|
7849
|
-
resourceName: id
|
|
7850
|
-
});
|
|
7851
|
-
const shortName = shortId(`${ctx.app.name}:${ctx.stack.name}:${ns}:${id}:${ctx.appId}`);
|
|
7852
|
-
const props = deepmerge5(ctx.appConfig.defaults.instance, local);
|
|
7853
|
-
const image2 = props.image || (props.architecture === "arm64" ? "public.ecr.aws/aws-cli/aws-cli:arm64" : "public.ecr.aws/aws-cli/aws-cli:amd64");
|
|
7854
|
-
ctx.registerBuild("instance", name, async (build3, { workspace }) => {
|
|
7855
|
-
const fingerprint = await generateFileHash3(workspace, local.code.file);
|
|
7856
|
-
return build3(fingerprint, async (write) => {
|
|
7857
|
-
const temp = await createTempFolder(`instance--${name}`);
|
|
7858
|
-
const executable = await buildExecutable(local.code.file, temp.path, props.architecture);
|
|
7859
|
-
await Promise.all([
|
|
7860
|
-
//
|
|
7861
|
-
write("HASH", executable.hash),
|
|
7862
|
-
write("program", executable.file),
|
|
7863
|
-
temp.delete()
|
|
7864
|
-
]);
|
|
7865
|
-
return {
|
|
7866
|
-
size: formatByteSize(executable.file.byteLength)
|
|
7867
|
-
};
|
|
7868
|
-
});
|
|
7869
|
-
});
|
|
7870
|
-
const code = new aws28.s3.BucketObject(group, "code", {
|
|
7871
|
-
bucket: ctx.shared.get("instance", "bucket-name"),
|
|
7872
|
-
key: name,
|
|
7873
|
-
source: relativePath(getBuildPath("instance", name, "program")),
|
|
7874
|
-
sourceHash: $file(getBuildPath("instance", name, "HASH"))
|
|
7875
|
-
});
|
|
7876
|
-
const executionRole = new aws28.iam.Role(group, "execution-role", {
|
|
7877
|
-
name: shortId(`${shortName}:execution-role`),
|
|
7878
|
-
description: name,
|
|
7879
|
-
assumeRolePolicy: JSON.stringify({
|
|
7880
|
-
Version: "2012-10-17",
|
|
7881
|
-
Statement: [
|
|
7882
|
-
{
|
|
7883
|
-
Effect: "Allow",
|
|
7884
|
-
Action: "sts:AssumeRole",
|
|
7885
|
-
Principal: {
|
|
7886
|
-
Service: ["ecs-tasks.amazonaws.com"]
|
|
7887
|
-
}
|
|
7888
|
-
}
|
|
7889
|
-
]
|
|
7890
|
-
}),
|
|
7891
|
-
managedPolicyArns: ["arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy"]
|
|
7892
|
-
});
|
|
7893
|
-
const role = new aws28.iam.Role(
|
|
7894
|
-
group,
|
|
7895
|
-
"task-role",
|
|
7896
|
-
{
|
|
7897
|
-
name: shortId(`${shortName}:task-role`),
|
|
7898
|
-
description: name,
|
|
7899
|
-
assumeRolePolicy: JSON.stringify({
|
|
7900
|
-
Version: "2012-10-17",
|
|
7901
|
-
Statement: [
|
|
7902
|
-
{
|
|
7903
|
-
Effect: "Allow",
|
|
7904
|
-
Action: "sts:AssumeRole",
|
|
7905
|
-
Principal: {
|
|
7906
|
-
Service: ["ecs-tasks.amazonaws.com"]
|
|
7907
|
-
}
|
|
7908
|
-
}
|
|
7909
|
-
]
|
|
7910
|
-
}),
|
|
7911
|
-
inlinePolicy: [
|
|
7912
|
-
{
|
|
7913
|
-
name: "s3-code-access",
|
|
7914
|
-
policy: $resolve([code.bucket, code.key], (bucket, key) => {
|
|
7915
|
-
return JSON.stringify({
|
|
7916
|
-
Version: "2012-10-17",
|
|
7917
|
-
Statement: [
|
|
7918
|
-
{
|
|
7919
|
-
Effect: pascalCase4("allow"),
|
|
7920
|
-
Action: ["s3:getObject", "s3:HeadObject"],
|
|
7921
|
-
Resource: `arn:aws:s3:::${bucket}/${key}`
|
|
7922
|
-
}
|
|
7923
|
-
]
|
|
7924
|
-
});
|
|
7925
|
-
})
|
|
7926
|
-
}
|
|
7927
|
-
]
|
|
7928
|
-
},
|
|
7929
|
-
{
|
|
7930
|
-
dependsOn: [code]
|
|
7931
|
-
}
|
|
7932
|
-
);
|
|
7933
|
-
const statements = [];
|
|
7934
|
-
const statementDeps = /* @__PURE__ */ new Set();
|
|
7935
|
-
const policy = new aws28.iam.RolePolicy(group, "policy", {
|
|
7936
|
-
role: role.name,
|
|
7937
|
-
name: "task-policy",
|
|
7938
|
-
policy: new Output8(statementDeps, async (resolve2) => {
|
|
7939
|
-
const list3 = await resolveInputs5(statements);
|
|
7940
|
-
resolve2(
|
|
7941
|
-
JSON.stringify({
|
|
7942
|
-
Version: "2012-10-17",
|
|
7943
|
-
Statement: list3.map((statement) => ({
|
|
7944
|
-
Effect: pascalCase4(statement.effect ?? "allow"),
|
|
7945
|
-
Action: statement.actions,
|
|
7946
|
-
Resource: statement.resources
|
|
7947
|
-
}))
|
|
7948
|
-
})
|
|
7949
|
-
);
|
|
7950
|
-
})
|
|
7951
|
-
});
|
|
7952
|
-
const addPermission = (...permissions) => {
|
|
7953
|
-
statements.push(...permissions);
|
|
7954
|
-
for (const dep of findInputDeps5(permissions)) {
|
|
7955
|
-
statementDeps.add(dep);
|
|
7956
|
-
}
|
|
7957
|
-
};
|
|
7958
|
-
ctx.onPermission((statement) => {
|
|
7959
|
-
addPermission(statement);
|
|
7960
|
-
});
|
|
7961
|
-
let logGroup;
|
|
7962
|
-
if (props.log.retention && props.log.retention.value > 0n) {
|
|
7963
|
-
logGroup = new aws28.cloudwatch.LogGroup(group, "log", {
|
|
7964
|
-
name: `/aws/ecs/${name}`,
|
|
7965
|
-
// name: `/aws/lambda/${name}`,
|
|
7966
|
-
retentionInDays: toDays10(props.log.retention)
|
|
7967
|
-
});
|
|
7968
|
-
if (ctx.shared.has("on-error-log", "subscriber-arn")) {
|
|
7969
|
-
new aws28.cloudwatch.LogSubscriptionFilter(group, "on-error-log", {
|
|
7970
|
-
name: "error-log-subscription",
|
|
7971
|
-
destinationArn: ctx.shared.get("on-error-log", "subscriber-arn"),
|
|
7972
|
-
logGroupName: logGroup.name,
|
|
7973
|
-
filterPattern
|
|
7974
|
-
});
|
|
7975
|
-
}
|
|
7976
|
-
}
|
|
7977
|
-
const tags = {
|
|
7978
|
-
APP: ctx.appConfig.name,
|
|
7979
|
-
APP_ID: ctx.appId,
|
|
7980
|
-
STACK: ctx.stackConfig.name
|
|
7981
|
-
};
|
|
7982
|
-
const variables = {};
|
|
7983
|
-
const variableDeps = /* @__PURE__ */ new Set();
|
|
7984
|
-
const task2 = new aws28.ecs.TaskDefinition(
|
|
7985
|
-
group,
|
|
7986
|
-
"task",
|
|
7987
|
-
{
|
|
7988
|
-
family: name,
|
|
7989
|
-
networkMode: "awsvpc",
|
|
7990
|
-
cpu: props.cpu,
|
|
7991
|
-
memory: toMebibytes6(props.memorySize).toString(),
|
|
7992
|
-
requiresCompatibilities: ["FARGATE"],
|
|
7993
|
-
executionRoleArn: executionRole.arn,
|
|
7994
|
-
taskRoleArn: role.arn,
|
|
7995
|
-
runtimePlatform: {
|
|
7996
|
-
cpuArchitecture: constantCase13(props.architecture),
|
|
7997
|
-
operatingSystemFamily: "LINUX"
|
|
7998
|
-
},
|
|
7999
|
-
trackLatest: true,
|
|
8000
|
-
containerDefinitions: new Output8(variableDeps, async (resolve2) => {
|
|
8001
|
-
const data = await resolveInputs5(variables);
|
|
8002
|
-
const { s3Bucket, s3Key } = await resolveInputs5({
|
|
8003
|
-
s3Bucket: code.bucket,
|
|
8004
|
-
s3Key: code.key
|
|
8005
|
-
});
|
|
8006
|
-
resolve2(
|
|
7449
|
+
resolve(
|
|
8007
7450
|
JSON.stringify([
|
|
8008
7451
|
{
|
|
8009
7452
|
name: `container-${id}`,
|
|
@@ -8054,12 +7497,12 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8054
7497
|
healthCheck: props.healthCheck ? {
|
|
8055
7498
|
command: [
|
|
8056
7499
|
"CMD-SHELL",
|
|
8057
|
-
`curl -f http://${
|
|
7500
|
+
`curl -f http://${join18("localhost", props.healthCheck.path)} || exit 1`
|
|
8058
7501
|
],
|
|
8059
|
-
interval:
|
|
7502
|
+
interval: toSeconds9(props.healthCheck.interval),
|
|
8060
7503
|
retries: props.healthCheck.retries,
|
|
8061
|
-
startPeriod:
|
|
8062
|
-
timeout:
|
|
7504
|
+
startPeriod: toSeconds9(props.healthCheck.startPeriod),
|
|
7505
|
+
timeout: toSeconds9(props.healthCheck.timeout)
|
|
8063
7506
|
} : void 0
|
|
8064
7507
|
}
|
|
8065
7508
|
])
|
|
@@ -8079,14 +7522,14 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8079
7522
|
dependsOn: [code]
|
|
8080
7523
|
}
|
|
8081
7524
|
);
|
|
8082
|
-
const securityGroup = new
|
|
7525
|
+
const securityGroup = new aws26.security.Group(group, "security-group", {
|
|
8083
7526
|
name,
|
|
8084
7527
|
description: "Security group for the instance",
|
|
8085
7528
|
vpcId: ctx.shared.get("vpc", "id"),
|
|
8086
7529
|
revokeRulesOnDelete: true,
|
|
8087
7530
|
tags
|
|
8088
7531
|
});
|
|
8089
|
-
new
|
|
7532
|
+
new aws26.vpc.SecurityGroupEgressRule(group, "egress-rule", {
|
|
8090
7533
|
securityGroupId: securityGroup.id,
|
|
8091
7534
|
description: `Allow all outbound traffic from the ${name} instance`,
|
|
8092
7535
|
ipProtocol: "-1",
|
|
@@ -8095,7 +7538,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8095
7538
|
});
|
|
8096
7539
|
const clusterName = ctx.shared.get("instance", "cluster-name");
|
|
8097
7540
|
const clusterArn = ctx.shared.get("instance", "cluster-arn");
|
|
8098
|
-
const service = new
|
|
7541
|
+
const service = new aws26.ecs.Service(
|
|
8099
7542
|
group,
|
|
8100
7543
|
"service",
|
|
8101
7544
|
{
|
|
@@ -8131,7 +7574,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8131
7574
|
replaceOnChanges: ["cluster"]
|
|
8132
7575
|
}
|
|
8133
7576
|
);
|
|
8134
|
-
new
|
|
7577
|
+
new aws26.appautoscaling.Target(
|
|
8135
7578
|
group,
|
|
8136
7579
|
"autoscaling-target",
|
|
8137
7580
|
{
|
|
@@ -8150,7 +7593,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8150
7593
|
);
|
|
8151
7594
|
ctx.onEnv((name2, value) => {
|
|
8152
7595
|
variables[name2] = value;
|
|
8153
|
-
for (const dep of
|
|
7596
|
+
for (const dep of findInputDeps3([value])) {
|
|
8154
7597
|
variableDeps.add(dep);
|
|
8155
7598
|
}
|
|
8156
7599
|
});
|
|
@@ -8159,7 +7602,7 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8159
7602
|
variables.AWS_ACCOUNT_ID = ctx.accountId;
|
|
8160
7603
|
variables.STACK = ctx.stackConfig.name;
|
|
8161
7604
|
variables.CODE_HASH = code.sourceHash;
|
|
8162
|
-
variables.INSTANCE_CONFIG_HASH =
|
|
7605
|
+
variables.INSTANCE_CONFIG_HASH = createHash4("sha1").update(stringify(props)).digest("hex");
|
|
8163
7606
|
if (props.environment) {
|
|
8164
7607
|
for (const [key, value] of Object.entries(props.environment)) {
|
|
8165
7608
|
variables[key] = value;
|
|
@@ -8178,8 +7621,8 @@ var createFargateTask = (parentGroup, ctx, ns, id, local) => {
|
|
|
8178
7621
|
var instanceFeature = defineFeature({
|
|
8179
7622
|
name: "instance",
|
|
8180
7623
|
onBefore(ctx) {
|
|
8181
|
-
const group = new
|
|
8182
|
-
const bucket = new
|
|
7624
|
+
const group = new Group26(ctx.base, "instance", "asset");
|
|
7625
|
+
const bucket = new aws27.s3.Bucket(group, "bucket", {
|
|
8183
7626
|
bucket: formatGlobalResourceName({
|
|
8184
7627
|
appName: ctx.app.name,
|
|
8185
7628
|
resourceType: "instance",
|
|
@@ -8197,8 +7640,8 @@ var instanceFeature = defineFeature({
|
|
|
8197
7640
|
if (found.length === 0) {
|
|
8198
7641
|
return;
|
|
8199
7642
|
}
|
|
8200
|
-
const group = new
|
|
8201
|
-
const cluster = new
|
|
7643
|
+
const group = new Group26(ctx.base, "instance", "cluster");
|
|
7644
|
+
const cluster = new aws27.ecs.Cluster(
|
|
8202
7645
|
group,
|
|
8203
7646
|
"cluster",
|
|
8204
7647
|
{
|
|
@@ -8213,18 +7656,18 @@ var instanceFeature = defineFeature({
|
|
|
8213
7656
|
},
|
|
8214
7657
|
onStack(ctx) {
|
|
8215
7658
|
for (const [id, props] of Object.entries(ctx.stackConfig.instances ?? {})) {
|
|
8216
|
-
const group = new
|
|
7659
|
+
const group = new Group26(ctx.stack, "instance", id);
|
|
8217
7660
|
createFargateTask(group, ctx, "instance", id, props);
|
|
8218
7661
|
}
|
|
8219
7662
|
}
|
|
8220
7663
|
});
|
|
8221
7664
|
|
|
8222
7665
|
// src/feature/metric/index.ts
|
|
8223
|
-
import { Group as
|
|
8224
|
-
import { aws as
|
|
8225
|
-
import { kebabCase as kebabCase8, constantCase as
|
|
8226
|
-
import { toSeconds as
|
|
8227
|
-
var
|
|
7666
|
+
import { Group as Group27 } from "@terraforge/core";
|
|
7667
|
+
import { aws as aws28 } from "@terraforge/aws";
|
|
7668
|
+
import { kebabCase as kebabCase8, constantCase as constantCase13 } from "change-case";
|
|
7669
|
+
import { toSeconds as toSeconds10 } from "@awsless/duration";
|
|
7670
|
+
var typeGenCode10 = `
|
|
8228
7671
|
import { type PutDataProps, putData, batchPutData } from '@awsless/cloudwatch'
|
|
8229
7672
|
import { type Duration } from '@awsless/duration'
|
|
8230
7673
|
import { type Size } from '@awsless/size'
|
|
@@ -8272,7 +7715,7 @@ var metricFeature = defineFeature({
|
|
|
8272
7715
|
resources2.addType(stack.name, stackResources);
|
|
8273
7716
|
}
|
|
8274
7717
|
resources2.addType("batch", "Batch");
|
|
8275
|
-
gen.addCode(
|
|
7718
|
+
gen.addCode(typeGenCode10);
|
|
8276
7719
|
gen.addInterface("MetricResources", resources2);
|
|
8277
7720
|
await ctx.write("metric.d.ts", gen, true);
|
|
8278
7721
|
},
|
|
@@ -8289,16 +7732,16 @@ var metricFeature = defineFeature({
|
|
|
8289
7732
|
}
|
|
8290
7733
|
});
|
|
8291
7734
|
for (const [id, props] of Object.entries(ctx.stackConfig.metrics ?? {})) {
|
|
8292
|
-
const group = new
|
|
8293
|
-
ctx.addEnv(`METRIC_${
|
|
7735
|
+
const group = new Group27(ctx.stack, "metric", id);
|
|
7736
|
+
ctx.addEnv(`METRIC_${constantCase13(id)}`, props.type);
|
|
8294
7737
|
for (const alarmId in props.alarms ?? []) {
|
|
8295
|
-
const alarmGroup = new
|
|
7738
|
+
const alarmGroup = new Group27(group, "alarm", alarmId);
|
|
8296
7739
|
const alarmName = kebabCase8(`${id}-${alarmId}`);
|
|
8297
7740
|
const alarmProps = props.alarms[alarmId];
|
|
8298
7741
|
let alarmAction;
|
|
8299
7742
|
let alarmLambda;
|
|
8300
7743
|
if (Array.isArray(alarmProps.trigger)) {
|
|
8301
|
-
const topic = new
|
|
7744
|
+
const topic = new aws28.sns.Topic(alarmGroup, "alarm-trigger", {
|
|
8302
7745
|
name: formatLocalResourceName({
|
|
8303
7746
|
appName: ctx.app.name,
|
|
8304
7747
|
stackName: ctx.stack.name,
|
|
@@ -8308,7 +7751,7 @@ var metricFeature = defineFeature({
|
|
|
8308
7751
|
});
|
|
8309
7752
|
alarmAction = topic.arn;
|
|
8310
7753
|
for (const email of alarmProps.trigger) {
|
|
8311
|
-
new
|
|
7754
|
+
new aws28.sns.TopicSubscription(alarmGroup, email, {
|
|
8312
7755
|
topicArn: topic.arn,
|
|
8313
7756
|
protocol: "email",
|
|
8314
7757
|
endpoint: email
|
|
@@ -8319,7 +7762,7 @@ var metricFeature = defineFeature({
|
|
|
8319
7762
|
alarmLambda = lambda;
|
|
8320
7763
|
alarmAction = lambda.arn;
|
|
8321
7764
|
}
|
|
8322
|
-
const alarm = new
|
|
7765
|
+
const alarm = new aws28.cloudwatch.MetricAlarm(alarmGroup, "alarm", {
|
|
8323
7766
|
namespace,
|
|
8324
7767
|
metricName: kebabCase8(id),
|
|
8325
7768
|
alarmName: formatLocalResourceName({
|
|
@@ -8331,13 +7774,13 @@ var metricFeature = defineFeature({
|
|
|
8331
7774
|
alarmDescription: alarmProps.description,
|
|
8332
7775
|
statistic: alarmProps.where.stat,
|
|
8333
7776
|
threshold: alarmProps.where.value,
|
|
8334
|
-
period:
|
|
7777
|
+
period: toSeconds10(alarmProps.period),
|
|
8335
7778
|
evaluationPeriods: alarmProps.minDataPoints,
|
|
8336
7779
|
comparisonOperator: alarmProps.where.op,
|
|
8337
7780
|
alarmActions: [alarmAction]
|
|
8338
7781
|
});
|
|
8339
7782
|
if (alarmLambda) {
|
|
8340
|
-
new
|
|
7783
|
+
new aws28.lambda.Permission(alarmGroup, "permission", {
|
|
8341
7784
|
action: "lambda:InvokeFunction",
|
|
8342
7785
|
principal: "lambda.alarms.cloudwatch.amazonaws.com",
|
|
8343
7786
|
functionName: alarmLambda.functionName,
|
|
@@ -8350,10 +7793,10 @@ var metricFeature = defineFeature({
|
|
|
8350
7793
|
});
|
|
8351
7794
|
|
|
8352
7795
|
// src/feature/router/index.ts
|
|
8353
|
-
import { days as days9, seconds as seconds10, toSeconds as
|
|
8354
|
-
import { Future, Group as
|
|
8355
|
-
import { aws as
|
|
8356
|
-
import { camelCase as
|
|
7796
|
+
import { days as days9, seconds as seconds10, toSeconds as toSeconds11, years } from "@awsless/duration";
|
|
7797
|
+
import { Future, Group as Group28 } from "@terraforge/core";
|
|
7798
|
+
import { aws as aws29 } from "@terraforge/aws";
|
|
7799
|
+
import { camelCase as camelCase8, constantCase as constantCase14 } from "change-case";
|
|
8357
7800
|
|
|
8358
7801
|
// src/feature/router/router-code.ts
|
|
8359
7802
|
var getViewerRequestFunctionCode = (props) => {
|
|
@@ -8538,7 +7981,7 @@ function setLambdaOrigin(route) {
|
|
|
8538
7981
|
}));
|
|
8539
7982
|
}
|
|
8540
7983
|
|
|
8541
|
-
function
|
|
7984
|
+
function setUrlOrigin(route) {
|
|
8542
7985
|
cf.updateRequestOrigin(getRequestOriginConfig(route));
|
|
8543
7986
|
}
|
|
8544
7987
|
|
|
@@ -8589,18 +8032,18 @@ async function handler(event) {
|
|
|
8589
8032
|
`;
|
|
8590
8033
|
|
|
8591
8034
|
// src/feature/router/index.ts
|
|
8592
|
-
import { createHash as
|
|
8035
|
+
import { createHash as createHash5 } from "crypto";
|
|
8593
8036
|
var routerFeature = defineFeature({
|
|
8594
8037
|
name: "router",
|
|
8595
8038
|
onApp(ctx) {
|
|
8596
8039
|
for (const [id, props] of Object.entries(ctx.appConfig.defaults.router ?? {})) {
|
|
8597
|
-
const group = new
|
|
8040
|
+
const group = new Group28(ctx.base, "router", id);
|
|
8598
8041
|
const name = formatGlobalResourceName({
|
|
8599
8042
|
appName: ctx.app.name,
|
|
8600
8043
|
resourceType: "router",
|
|
8601
8044
|
resourceName: id
|
|
8602
8045
|
});
|
|
8603
|
-
const routeStore = new
|
|
8046
|
+
const routeStore = new aws29.cloudfront.KeyValueStore(group, "routes", {
|
|
8604
8047
|
name,
|
|
8605
8048
|
comment: "Store for routes"
|
|
8606
8049
|
});
|
|
@@ -8630,11 +8073,11 @@ var routerFeature = defineFeature({
|
|
|
8630
8073
|
);
|
|
8631
8074
|
importedRoutes.push(importKeys);
|
|
8632
8075
|
});
|
|
8633
|
-
const cache = new
|
|
8076
|
+
const cache = new aws29.cloudfront.CachePolicy(group, "cache", {
|
|
8634
8077
|
name,
|
|
8635
|
-
minTtl:
|
|
8636
|
-
maxTtl:
|
|
8637
|
-
defaultTtl:
|
|
8078
|
+
minTtl: toSeconds11(seconds10(0)),
|
|
8079
|
+
maxTtl: toSeconds11(days9(365)),
|
|
8080
|
+
defaultTtl: toSeconds11(days9(0)),
|
|
8638
8081
|
parametersInCacheKeyAndForwardedToOrigin: {
|
|
8639
8082
|
enableAcceptEncodingBrotli: true,
|
|
8640
8083
|
enableAcceptEncodingGzip: true,
|
|
@@ -8662,10 +8105,10 @@ var routerFeature = defineFeature({
|
|
|
8662
8105
|
}
|
|
8663
8106
|
}
|
|
8664
8107
|
});
|
|
8665
|
-
const originRequest = new
|
|
8108
|
+
const originRequest = new aws29.cloudfront.OriginRequestPolicy(group, "request", {
|
|
8666
8109
|
name,
|
|
8667
8110
|
headersConfig: {
|
|
8668
|
-
headerBehavior:
|
|
8111
|
+
headerBehavior: camelCase8("all-except"),
|
|
8669
8112
|
headers: {
|
|
8670
8113
|
items: [
|
|
8671
8114
|
"host"
|
|
@@ -8680,11 +8123,11 @@ var routerFeature = defineFeature({
|
|
|
8680
8123
|
queryStringBehavior: "all"
|
|
8681
8124
|
}
|
|
8682
8125
|
});
|
|
8683
|
-
const responseHeaders = new
|
|
8126
|
+
const responseHeaders = new aws29.cloudfront.ResponseHeadersPolicy(group, "response", {
|
|
8684
8127
|
name,
|
|
8685
8128
|
corsConfig: {
|
|
8686
8129
|
originOverride: props.cors?.override ?? true,
|
|
8687
|
-
accessControlMaxAgeSec:
|
|
8130
|
+
accessControlMaxAgeSec: toSeconds11(props.cors?.maxAge ?? years(1)),
|
|
8688
8131
|
accessControlAllowHeaders: { items: props.cors?.headers ?? ["*"] },
|
|
8689
8132
|
accessControlAllowMethods: { items: props.cors?.methods ?? ["ALL"] },
|
|
8690
8133
|
accessControlAllowOrigins: { items: props.cors?.origins ?? ["*"] },
|
|
@@ -8709,7 +8152,7 @@ var routerFeature = defineFeature({
|
|
|
8709
8152
|
strictTransportSecurity: {
|
|
8710
8153
|
override: true,
|
|
8711
8154
|
preload: true,
|
|
8712
|
-
accessControlMaxAgeSec:
|
|
8155
|
+
accessControlMaxAgeSec: toSeconds11(years(1)),
|
|
8713
8156
|
includeSubdomains: true
|
|
8714
8157
|
},
|
|
8715
8158
|
xssProtection: {
|
|
@@ -8719,7 +8162,7 @@ var routerFeature = defineFeature({
|
|
|
8719
8162
|
}
|
|
8720
8163
|
}
|
|
8721
8164
|
});
|
|
8722
|
-
const viewerRequest = new
|
|
8165
|
+
const viewerRequest = new aws29.cloudfront.Function(group, "viewer-request", {
|
|
8723
8166
|
name,
|
|
8724
8167
|
runtime: `cloudfront-js-2.0`,
|
|
8725
8168
|
comment: `Viewer Request - ${name}`,
|
|
@@ -8741,7 +8184,7 @@ var routerFeature = defineFeature({
|
|
|
8741
8184
|
rateBasedStatement: {
|
|
8742
8185
|
limit: wafSettingsConfig.rateLimiter.limit,
|
|
8743
8186
|
aggregateKeyType: "IP",
|
|
8744
|
-
evaluationWindowSec:
|
|
8187
|
+
evaluationWindowSec: toSeconds11(wafSettingsConfig.rateLimiter.window)
|
|
8745
8188
|
}
|
|
8746
8189
|
},
|
|
8747
8190
|
action: {
|
|
@@ -8821,7 +8264,7 @@ var routerFeature = defineFeature({
|
|
|
8821
8264
|
}
|
|
8822
8265
|
let waf;
|
|
8823
8266
|
if (wafRules.length && wafSettingsConfig) {
|
|
8824
|
-
waf = new
|
|
8267
|
+
waf = new aws29.wafv2.WebAcl(group, "waf", {
|
|
8825
8268
|
name: `${name}-wafv2`,
|
|
8826
8269
|
scope: "CLOUDFRONT",
|
|
8827
8270
|
defaultAction: {
|
|
@@ -8831,12 +8274,12 @@ var routerFeature = defineFeature({
|
|
|
8831
8274
|
rule: wafRules,
|
|
8832
8275
|
captchaConfig: {
|
|
8833
8276
|
immunityTimeProperty: {
|
|
8834
|
-
immunityTime:
|
|
8277
|
+
immunityTime: toSeconds11(wafSettingsConfig.captchaImmunityTime)
|
|
8835
8278
|
}
|
|
8836
8279
|
},
|
|
8837
8280
|
challengeConfig: {
|
|
8838
8281
|
immunityTimeProperty: {
|
|
8839
|
-
immunityTime:
|
|
8282
|
+
immunityTime: toSeconds11(wafSettingsConfig.challengeImmunityTime)
|
|
8840
8283
|
}
|
|
8841
8284
|
},
|
|
8842
8285
|
visibilityConfig: {
|
|
@@ -8846,7 +8289,7 @@ var routerFeature = defineFeature({
|
|
|
8846
8289
|
}
|
|
8847
8290
|
});
|
|
8848
8291
|
}
|
|
8849
|
-
const distribution = new
|
|
8292
|
+
const distribution = new aws29.cloudfront.MultitenantDistribution(group, "distribution", {
|
|
8850
8293
|
tags: {
|
|
8851
8294
|
name
|
|
8852
8295
|
},
|
|
@@ -8892,7 +8335,7 @@ var routerFeature = defineFeature({
|
|
|
8892
8335
|
}
|
|
8893
8336
|
return {
|
|
8894
8337
|
errorCode: Number(errorCode),
|
|
8895
|
-
errorCachingMinTtl: item.minTTL ?
|
|
8338
|
+
errorCachingMinTtl: item.minTTL ? toSeconds11(item.minTTL) : void 0,
|
|
8896
8339
|
responseCode: item.statusCode?.toString() ?? errorCode,
|
|
8897
8340
|
responsePagePath: item.path
|
|
8898
8341
|
};
|
|
@@ -8940,11 +8383,11 @@ var routerFeature = defineFeature({
|
|
|
8940
8383
|
{
|
|
8941
8384
|
distributionId: distribution.id,
|
|
8942
8385
|
paths,
|
|
8943
|
-
version: new Future((
|
|
8386
|
+
version: new Future((resolve) => {
|
|
8944
8387
|
$combine(...versions).then((versions2) => {
|
|
8945
8388
|
const combined = versions2.filter((v) => !!v).sort().join(",");
|
|
8946
|
-
const version =
|
|
8947
|
-
|
|
8389
|
+
const version = createHash5("sha1").update(combined).digest("hex");
|
|
8390
|
+
resolve(version);
|
|
8948
8391
|
});
|
|
8949
8392
|
})
|
|
8950
8393
|
},
|
|
@@ -8958,10 +8401,10 @@ var routerFeature = defineFeature({
|
|
|
8958
8401
|
const domainName = formatFullDomainName(ctx.appConfig, props.domain, props.subDomain);
|
|
8959
8402
|
const certificateArn = ctx.shared.entry("domain", `global-certificate-arn`, props.domain);
|
|
8960
8403
|
const zoneId = ctx.shared.entry("domain", "zone-id", props.domain);
|
|
8961
|
-
const connectionGroup = new
|
|
8404
|
+
const connectionGroup = new aws29.cloudfront.ConnectionGroup(group, "connection-group", {
|
|
8962
8405
|
name
|
|
8963
8406
|
});
|
|
8964
|
-
new
|
|
8407
|
+
new aws29.cloudfront.DistributionTenant(group, `tenant`, {
|
|
8965
8408
|
name,
|
|
8966
8409
|
enabled: true,
|
|
8967
8410
|
distributionId: distribution.id,
|
|
@@ -8969,7 +8412,7 @@ var routerFeature = defineFeature({
|
|
|
8969
8412
|
domain: [{ domain: domainName }],
|
|
8970
8413
|
customizations: [{ certificate: [{ arn: certificateArn }] }]
|
|
8971
8414
|
});
|
|
8972
|
-
new
|
|
8415
|
+
new aws29.route53.Record(group, `record`, {
|
|
8973
8416
|
zoneId,
|
|
8974
8417
|
type: "A",
|
|
8975
8418
|
name: domainName,
|
|
@@ -8979,7 +8422,7 @@ var routerFeature = defineFeature({
|
|
|
8979
8422
|
evaluateTargetHealth: false
|
|
8980
8423
|
}
|
|
8981
8424
|
});
|
|
8982
|
-
ctx.bind(`ROUTER_${
|
|
8425
|
+
ctx.bind(`ROUTER_${constantCase14(id)}_ENDPOINT`, domainName);
|
|
8983
8426
|
}
|
|
8984
8427
|
}
|
|
8985
8428
|
}
|
|
@@ -9002,7 +8445,7 @@ var features = [
|
|
|
9002
8445
|
// 5
|
|
9003
8446
|
functionFeature,
|
|
9004
8447
|
instanceFeature,
|
|
9005
|
-
jobFeature,
|
|
8448
|
+
// jobFeature,
|
|
9006
8449
|
// graphqlFeature,
|
|
9007
8450
|
configFeature,
|
|
9008
8451
|
searchFeature,
|
|
@@ -10091,14 +9534,14 @@ import wildstring4 from "wildstring";
|
|
|
10091
9534
|
|
|
10092
9535
|
// src/cli/ui/complex/run-tests.ts
|
|
10093
9536
|
import { log as log18 } from "@awsless/clui";
|
|
10094
|
-
import { mkdir as mkdir4, readFile as
|
|
10095
|
-
import { join as
|
|
9537
|
+
import { mkdir as mkdir4, readFile as readFile5, writeFile as writeFile3 } from "fs/promises";
|
|
9538
|
+
import { join as join20 } from "path";
|
|
10096
9539
|
import wildstring3 from "wildstring";
|
|
10097
|
-
import { parse as parse4, stringify as
|
|
9540
|
+
import { parse as parse4, stringify as stringify2 } from "@awsless/json";
|
|
10098
9541
|
import { generateFolderHash, loadWorkspace as loadWorkspace2 } from "@awsless/ts-file-cache";
|
|
10099
9542
|
|
|
10100
9543
|
// src/test/start.ts
|
|
10101
|
-
import { dirname as dirname9, join as
|
|
9544
|
+
import { dirname as dirname9, join as join19 } from "path";
|
|
10102
9545
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
10103
9546
|
import { configDefaults } from "vitest/config";
|
|
10104
9547
|
import { startVitest } from "vitest/node";
|
|
@@ -10136,7 +9579,7 @@ var startTest = async (props) => {
|
|
|
10136
9579
|
// },
|
|
10137
9580
|
setupFiles: [
|
|
10138
9581
|
//
|
|
10139
|
-
|
|
9582
|
+
join19(__dirname5, "test-global-setup.js")
|
|
10140
9583
|
]
|
|
10141
9584
|
// globalSetup: [
|
|
10142
9585
|
// //
|
|
@@ -10330,12 +9773,12 @@ var logTestErrors = (event) => {
|
|
|
10330
9773
|
};
|
|
10331
9774
|
var runTest = async (stack, dir, filters, workspace, opts) => {
|
|
10332
9775
|
await mkdir4(directories.test, { recursive: true });
|
|
10333
|
-
const file =
|
|
9776
|
+
const file = join20(directories.test, `${stack}.json`);
|
|
10334
9777
|
const fingerprint = await generateFolderHash(workspace, dir);
|
|
10335
9778
|
if (!process.env.NO_CACHE) {
|
|
10336
9779
|
const exists = await fileExist(file);
|
|
10337
9780
|
if (exists) {
|
|
10338
|
-
const raw = await
|
|
9781
|
+
const raw = await readFile5(file, { encoding: "utf8" });
|
|
10339
9782
|
const data = parse4(raw);
|
|
10340
9783
|
if (data.fingerprint === fingerprint) {
|
|
10341
9784
|
log18.step(
|
|
@@ -10378,9 +9821,9 @@ var runTest = async (stack, dir, filters, workspace, opts) => {
|
|
|
10378
9821
|
logTestLogs(result);
|
|
10379
9822
|
}
|
|
10380
9823
|
logTestErrors(result);
|
|
10381
|
-
await
|
|
9824
|
+
await writeFile3(
|
|
10382
9825
|
file,
|
|
10383
|
-
|
|
9826
|
+
stringify2({
|
|
10384
9827
|
...result,
|
|
10385
9828
|
fingerprint
|
|
10386
9829
|
})
|
|
@@ -10918,7 +10361,7 @@ var auth = (program2) => {
|
|
|
10918
10361
|
// src/cli/command/bind.ts
|
|
10919
10362
|
import { log as log24 } from "@awsless/clui";
|
|
10920
10363
|
import chalk4 from "chalk";
|
|
10921
|
-
import { constantCase as
|
|
10364
|
+
import { constantCase as constantCase15 } from "change-case";
|
|
10922
10365
|
var bind = (program2) => {
|
|
10923
10366
|
program2.command("bind").argument("[command...]", "The command to execute").option("--config <string...>", "List of config values that will be accessable", (v) => v.split(",")).description(`Bind your site environment variables to a command`).action(async (commands11 = [], opts) => {
|
|
10924
10367
|
await layout("bind", async ({ appConfig, stackConfigs }) => {
|
|
@@ -10945,10 +10388,10 @@ var bind = (program2) => {
|
|
|
10945
10388
|
const configList = opts.config ?? [];
|
|
10946
10389
|
const configs = {};
|
|
10947
10390
|
for (const name of configList) {
|
|
10948
|
-
configs[`CONFIG_${
|
|
10391
|
+
configs[`CONFIG_${constantCase15(name)}`] = name;
|
|
10949
10392
|
}
|
|
10950
10393
|
if (configList.length ?? 0 > 0) {
|
|
10951
|
-
log24.note("Bind Config", configList.map((v) => color.label(
|
|
10394
|
+
log24.note("Bind Config", configList.map((v) => color.label(constantCase15(v))).join("\n"));
|
|
10952
10395
|
}
|
|
10953
10396
|
if (commands11.length === 0) {
|
|
10954
10397
|
return "No command to execute.";
|
|
@@ -10987,7 +10430,7 @@ var bind = (program2) => {
|
|
|
10987
10430
|
|
|
10988
10431
|
// src/config/load/watch.ts
|
|
10989
10432
|
import { watch } from "chokidar";
|
|
10990
|
-
var watchConfig = async (options,
|
|
10433
|
+
var watchConfig = async (options, resolve, reject) => {
|
|
10991
10434
|
await loadAppConfig(options);
|
|
10992
10435
|
debug("Start watching...");
|
|
10993
10436
|
const ext = "{json,jsonc,json5}";
|
|
@@ -11002,7 +10445,7 @@ var watchConfig = async (options, resolve2, reject) => {
|
|
|
11002
10445
|
const appConfig = await loadAppConfig(options);
|
|
11003
10446
|
const stackConfigs = await loadStackConfigs(options);
|
|
11004
10447
|
validateFeatures({ appConfig, stackConfigs });
|
|
11005
|
-
|
|
10448
|
+
resolve({ appConfig, stackConfigs });
|
|
11006
10449
|
} catch (error) {
|
|
11007
10450
|
reject(error);
|
|
11008
10451
|
}
|
|
@@ -11014,8 +10457,8 @@ var watchConfig = async (options, resolve2, reject) => {
|
|
|
11014
10457
|
import { log as log25 } from "@awsless/clui";
|
|
11015
10458
|
|
|
11016
10459
|
// src/type-gen/generate.ts
|
|
11017
|
-
import { mkdir as mkdir5, writeFile as
|
|
11018
|
-
import { dirname as dirname10, join as
|
|
10460
|
+
import { mkdir as mkdir5, writeFile as writeFile4 } from "fs/promises";
|
|
10461
|
+
import { dirname as dirname10, join as join21, relative as relative8 } from "path";
|
|
11019
10462
|
var generateTypes = async (props) => {
|
|
11020
10463
|
const files = [];
|
|
11021
10464
|
await Promise.all(
|
|
@@ -11024,13 +10467,13 @@ var generateTypes = async (props) => {
|
|
|
11024
10467
|
...props,
|
|
11025
10468
|
async write(file, data, include = false) {
|
|
11026
10469
|
const code = data?.toString("utf8");
|
|
11027
|
-
const path =
|
|
10470
|
+
const path = join21(directories.types, file);
|
|
11028
10471
|
if (code) {
|
|
11029
10472
|
if (include) {
|
|
11030
|
-
files.push(
|
|
10473
|
+
files.push(relative8(directories.root, path));
|
|
11031
10474
|
}
|
|
11032
10475
|
await mkdir5(dirname10(path), { recursive: true });
|
|
11033
|
-
await
|
|
10476
|
+
await writeFile4(path, code);
|
|
11034
10477
|
}
|
|
11035
10478
|
}
|
|
11036
10479
|
});
|
|
@@ -11038,7 +10481,7 @@ var generateTypes = async (props) => {
|
|
|
11038
10481
|
);
|
|
11039
10482
|
if (files.length) {
|
|
11040
10483
|
const code = files.map((file) => `/// <reference path='${file}' />`).join("\n");
|
|
11041
|
-
await
|
|
10484
|
+
await writeFile4(join21(directories.root, `awsless.d.ts`), code);
|
|
11042
10485
|
}
|
|
11043
10486
|
};
|
|
11044
10487
|
|
|
@@ -11062,9 +10505,9 @@ var dev = (program2) => {
|
|
|
11062
10505
|
logError(error);
|
|
11063
10506
|
}
|
|
11064
10507
|
);
|
|
11065
|
-
await new Promise((
|
|
11066
|
-
process.once("exit",
|
|
11067
|
-
process.once("SIGINT",
|
|
10508
|
+
await new Promise((resolve) => {
|
|
10509
|
+
process.once("exit", resolve);
|
|
10510
|
+
process.once("SIGINT", resolve);
|
|
11068
10511
|
});
|
|
11069
10512
|
});
|
|
11070
10513
|
});
|
|
@@ -11464,7 +10907,7 @@ var domain = (program2) => {
|
|
|
11464
10907
|
// src/cli/command/logs.ts
|
|
11465
10908
|
import { CloudWatchLogsClient, StartLiveTailCommand } from "@aws-sdk/client-cloudwatch-logs";
|
|
11466
10909
|
import { log as log30 } from "@awsless/clui";
|
|
11467
|
-
import { aws as
|
|
10910
|
+
import { aws as aws30 } from "@terraforge/aws";
|
|
11468
10911
|
import chalk6 from "chalk";
|
|
11469
10912
|
import chunk2 from "chunk";
|
|
11470
10913
|
import { formatDate } from "date-fns";
|
|
@@ -11487,7 +10930,7 @@ var logs = (program2) => {
|
|
|
11487
10930
|
for (const stack of app.stacks) {
|
|
11488
10931
|
if (filters.find((f) => wildstring7.match(f, stack.name))) {
|
|
11489
10932
|
for (const resource of stack.resources) {
|
|
11490
|
-
if (resource instanceof
|
|
10933
|
+
if (resource instanceof aws30.cloudwatch.LogGroup) {
|
|
11491
10934
|
logGroupArns.push(await resource.arn);
|
|
11492
10935
|
}
|
|
11493
10936
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@awsless/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -86,24 +86,24 @@
|
|
|
86
86
|
"zip-a-folder": "^3.1.6",
|
|
87
87
|
"zod": "^3.24.2",
|
|
88
88
|
"zod-to-json-schema": "^3.24.3",
|
|
89
|
+
"@awsless/big-float": "^0.1.6",
|
|
89
90
|
"@awsless/cloudwatch": "^0.0.1",
|
|
90
|
-
"@awsless/clui": "^0.0.8",
|
|
91
|
-
"@awsless/dynamodb": "^0.3.20",
|
|
92
91
|
"@awsless/duration": "^0.0.4",
|
|
93
|
-
"@awsless/
|
|
92
|
+
"@awsless/clui": "^0.0.8",
|
|
94
93
|
"@awsless/iot": "^0.0.5",
|
|
95
94
|
"@awsless/json": "^0.0.11",
|
|
96
95
|
"@awsless/lambda": "^0.0.42",
|
|
97
|
-
"@awsless/redis": "^0.0.16",
|
|
98
96
|
"@awsless/s3": "^0.0.21",
|
|
99
|
-
"@awsless/scheduler": "^0.0.4",
|
|
100
97
|
"@awsless/size": "^0.0.2",
|
|
101
|
-
"@awsless/
|
|
102
|
-
"@awsless/
|
|
98
|
+
"@awsless/dynamodb": "^0.3.20",
|
|
99
|
+
"@awsless/redis": "^0.0.16",
|
|
103
100
|
"@awsless/sns": "^0.0.10",
|
|
104
|
-
"@awsless/
|
|
105
|
-
"awsless": "^0.0.
|
|
106
|
-
"@awsless/
|
|
101
|
+
"@awsless/sqs": "^0.0.21",
|
|
102
|
+
"@awsless/ts-file-cache": "^0.0.12",
|
|
103
|
+
"@awsless/scheduler": "^0.0.4",
|
|
104
|
+
"@awsless/weak-cache": "^0.0.1",
|
|
105
|
+
"awsless": "^0.0.3",
|
|
106
|
+
"@awsless/validate": "^0.1.7"
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
109
|
"@hono/node-server": "1.19.9",
|
|
@@ -124,7 +124,6 @@
|
|
|
124
124
|
"build-layers": "mkdir -p dist/layers && cp -r layers/* dist/layers",
|
|
125
125
|
"jack": "pnpm tsup ./example/jack/jack.ts --format esm --external bun; bun ./dist/jack.js",
|
|
126
126
|
"kennedy": "pnpm tsup ./example/kennedy/kennedy.ts --format esm --external bun; bun ./dist/kennedy.js",
|
|
127
|
-
"tanmay": "pnpm tsup ./example/tanmay/tanmay.ts --format esm --external bun; bun ./dist/tanmay.js",
|
|
128
127
|
"prepublish": "if pnpm test; then pnpm build; pnpm build-json-schema; pnpm build-test-setup; pnpm build-prebuild; pnpm build-layers; else exit; fi"
|
|
129
128
|
}
|
|
130
129
|
}
|