@stacksjs/ts-cloud 0.5.3 → 0.5.5
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/cli.js +357 -357
- package/dist/index.js +58 -15
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -26262,7 +26262,7 @@ function composeServerlessAppTemplate(opts) {
|
|
|
26262
26262
|
...app.assetDomain ? {
|
|
26263
26263
|
Aliases: [app.assetDomain],
|
|
26264
26264
|
ViewerCertificate: {
|
|
26265
|
-
AcmCertificateArn: app.assetCertificateArn,
|
|
26265
|
+
AcmCertificateArn: app.assetCertificateArn ?? Fn2.ref("AssetsCertificate"),
|
|
26266
26266
|
SslSupportMethod: "sni-only",
|
|
26267
26267
|
MinimumProtocolVersion: "TLSv1.2_2021"
|
|
26268
26268
|
}
|
|
@@ -26271,8 +26271,20 @@ function composeServerlessAppTemplate(opts) {
|
|
|
26271
26271
|
}
|
|
26272
26272
|
};
|
|
26273
26273
|
if (app.assetDomain) {
|
|
26274
|
-
if (!app.assetCertificateArn)
|
|
26275
|
-
|
|
26274
|
+
if (!app.assetCertificateArn) {
|
|
26275
|
+
if (!app.hostedZoneId)
|
|
26276
|
+
throw new Error("serverless app: `assetDomain` requires either `assetCertificateArn` (a us-east-1 ACM cert) or `hostedZoneId` (to auto-issue + validate one). CloudFront only accepts certs from us-east-1.");
|
|
26277
|
+
if (region !== "us-east-1")
|
|
26278
|
+
throw new Error(`serverless app: auto-issuing an asset-domain cert needs a us-east-1 app (CloudFront certs must be us-east-1); this app is in ${region}. Supply a pre-issued us-east-1 \`assetCertificateArn\` instead.`);
|
|
26279
|
+
resources.AssetsCertificate = {
|
|
26280
|
+
Type: "AWS::CertificateManager::Certificate",
|
|
26281
|
+
Properties: {
|
|
26282
|
+
DomainName: app.assetDomain,
|
|
26283
|
+
ValidationMethod: "DNS",
|
|
26284
|
+
DomainValidationOptions: [{ DomainName: app.assetDomain, HostedZoneId: app.hostedZoneId }]
|
|
26285
|
+
}
|
|
26286
|
+
};
|
|
26287
|
+
}
|
|
26276
26288
|
if (app.hostedZoneId) {
|
|
26277
26289
|
resources.AssetsDomainRecord = {
|
|
26278
26290
|
Type: "AWS::Route53::RecordSet",
|
|
@@ -26359,9 +26371,12 @@ function composeServerlessAppTemplate(opts) {
|
|
|
26359
26371
|
};
|
|
26360
26372
|
}
|
|
26361
26373
|
if (hasVpc && needsDataVpc) {
|
|
26374
|
+
if (!app.vpc?.id)
|
|
26375
|
+
throw new Error("serverless app: data services (elasticache / aurora-serverless / rdsProxy / efs) need app.vpc.id (the VPC id) so the managed security group is created in the right VPC.");
|
|
26362
26376
|
resources.DataSecurityGroup = {
|
|
26363
26377
|
Type: "AWS::EC2::SecurityGroup",
|
|
26364
26378
|
Properties: {
|
|
26379
|
+
VpcId: app.vpc.id,
|
|
26365
26380
|
GroupDescription: `${slug}-${environment} serverless data access`,
|
|
26366
26381
|
SecurityGroupIngress: [{ IpProtocol: "-1", CidrIp: "10.0.0.0/8" }]
|
|
26367
26382
|
}
|
|
@@ -26442,6 +26457,7 @@ function composeServerlessAppTemplate(opts) {
|
|
|
26442
26457
|
Engine: "aurora-mysql",
|
|
26443
26458
|
EngineMode: "provisioned",
|
|
26444
26459
|
DBClusterIdentifier: `${slug}-${environment}-db`,
|
|
26460
|
+
DatabaseName: "app",
|
|
26445
26461
|
MasterUsername: Fn2.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:username}}"),
|
|
26446
26462
|
MasterUserPassword: Fn2.sub("{{resolve:secretsmanager:${DbSecret}:SecretString:password}}"),
|
|
26447
26463
|
ServerlessV2ScalingConfiguration: { MinCapacity: 0.5, MaxCapacity: 4 },
|
|
@@ -26488,6 +26504,15 @@ function composeServerlessAppTemplate(opts) {
|
|
|
26488
26504
|
RequireTLS: false
|
|
26489
26505
|
}
|
|
26490
26506
|
};
|
|
26507
|
+
resources.DbProxyTargetGroup = {
|
|
26508
|
+
Type: "AWS::RDS::DBProxyTargetGroup",
|
|
26509
|
+
DependsOn: ["DbInstance"],
|
|
26510
|
+
Properties: {
|
|
26511
|
+
DBProxyName: Fn2.ref("DbProxy"),
|
|
26512
|
+
TargetGroupName: "default",
|
|
26513
|
+
DBClusterIdentifiers: [Fn2.ref("DbCluster")]
|
|
26514
|
+
}
|
|
26515
|
+
};
|
|
26491
26516
|
outputs.DbProxyEndpoint = { Description: "RDS Proxy endpoint", Value: Fn2.getAtt("DbProxy", "Endpoint") };
|
|
26492
26517
|
}
|
|
26493
26518
|
outputs.HttpFunctionName = { Description: "HTTP function name", Value: Fn2.ref("HttpFunction") };
|
|
@@ -57435,7 +57460,7 @@ var exports_serverless_image = {};
|
|
|
57435
57460
|
__export(exports_serverless_image, {
|
|
57436
57461
|
buildAndPushServerlessImage: () => buildAndPushServerlessImage
|
|
57437
57462
|
});
|
|
57438
|
-
import { execFileSync as execFileSync3
|
|
57463
|
+
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
57439
57464
|
import { mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync4, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
|
|
57440
57465
|
import { tmpdir as tmpdir4 } from "node:os";
|
|
57441
57466
|
import { dirname as dirname7, join as join15 } from "node:path";
|
|
@@ -57497,12 +57522,17 @@ async function buildAndPushServerlessImage(opts) {
|
|
|
57497
57522
|
throw new Error(`could not resolve ECR repository URI for ${repository}`);
|
|
57498
57523
|
const imageUri = `${repoUri}:${tag}`;
|
|
57499
57524
|
step2("docker build");
|
|
57500
|
-
execFileSync3("docker", ["build", "--platform", platform, "-t", imageUri, stage], { stdio: "inherit" });
|
|
57501
|
-
step2("ecr
|
|
57502
|
-
const
|
|
57503
|
-
|
|
57504
|
-
|
|
57505
|
-
|
|
57525
|
+
execFileSync3("docker", ["build", "--platform", platform, "--provenance=false", "--sbom=false", "-t", imageUri, stage], { stdio: "inherit" });
|
|
57526
|
+
step2("ecr auth + push");
|
|
57527
|
+
const auth = await ecr2.getAuthorizationToken();
|
|
57528
|
+
const data = auth.authorizationData?.[0];
|
|
57529
|
+
if (!data?.authorizationToken || !data.proxyEndpoint)
|
|
57530
|
+
throw new Error("failed to get an ECR authorization token");
|
|
57531
|
+
const registry = data.proxyEndpoint.replace(/^https?:\/\//, "");
|
|
57532
|
+
const dockerConfig = join15(stage, ".docker");
|
|
57533
|
+
mkdirSync7(dockerConfig, { recursive: true });
|
|
57534
|
+
writeFileSync10(join15(dockerConfig, "config.json"), JSON.stringify({ auths: { [registry]: { auth: data.authorizationToken } } }));
|
|
57535
|
+
execFileSync3("docker", ["push", imageUri], { stdio: "inherit", env: { ...process.env, DOCKER_CONFIG: dockerConfig } });
|
|
57506
57536
|
info(`Image: ${imageUri}`);
|
|
57507
57537
|
return { imageUri, tag, handlers };
|
|
57508
57538
|
} finally {
|
|
@@ -83385,6 +83415,19 @@ async function deployServerlessApp(config6, environment, opts = {}) {
|
|
|
83385
83415
|
}
|
|
83386
83416
|
step("Resolving secrets");
|
|
83387
83417
|
const secrets = await resolveSecrets(app, region);
|
|
83418
|
+
if (app.database?.connection === "aurora-serverless") {
|
|
83419
|
+
try {
|
|
83420
|
+
const sm = new SecretsManagerClient(region);
|
|
83421
|
+
const v = await sm.getSecretValue({ SecretId: `${slug}/${environment}/db` });
|
|
83422
|
+
const creds = JSON.parse(v.SecretString ?? "{}");
|
|
83423
|
+
if (creds.username)
|
|
83424
|
+
secrets.DB_USERNAME = creds.username;
|
|
83425
|
+
if (creds.password)
|
|
83426
|
+
secrets.DB_PASSWORD = creds.password;
|
|
83427
|
+
} catch (err) {
|
|
83428
|
+
warn(`Could not resolve Aurora DB credentials: ${err.message}`);
|
|
83429
|
+
}
|
|
83430
|
+
}
|
|
83388
83431
|
if (!await s32.bucketExists(artifactBucket)) {
|
|
83389
83432
|
await s32.createBucket(artifactBucket);
|
|
83390
83433
|
}
|
|
@@ -83584,7 +83627,7 @@ function planServices(services) {
|
|
|
83584
83627
|
const packages = [];
|
|
83585
83628
|
const names = [];
|
|
83586
83629
|
if (enabled(services.mysql)) {
|
|
83587
|
-
packages.push("mysql.com");
|
|
83630
|
+
packages.push(typeof services.mysql === "object" && services.mysql.version ? `mysql.com@${services.mysql.version}` : "mysql.com@8.0.43");
|
|
83588
83631
|
names.push("mysql");
|
|
83589
83632
|
} else if (enabled(services.mariadb)) {
|
|
83590
83633
|
packages.push(PANTRY_PACKAGES.mariadb);
|
|
@@ -84785,7 +84828,7 @@ await init_dist2();
|
|
|
84785
84828
|
import { existsSync as existsSync18, readFileSync as readFileSync15 } from "node:fs";
|
|
84786
84829
|
import { homedir as homedir7 } from "node:os";
|
|
84787
84830
|
import { join as join18 } from "node:path";
|
|
84788
|
-
import { execSync as
|
|
84831
|
+
import { execSync as execSync3 } from "node:child_process";
|
|
84789
84832
|
|
|
84790
84833
|
// src/drivers/hetzner/client.ts
|
|
84791
84834
|
var DEFAULT_API_URL = "https://api.hetzner.cloud/v1";
|
|
@@ -85721,7 +85764,7 @@ class HetznerDriver {
|
|
|
85721
85764
|
let lastErr;
|
|
85722
85765
|
while (Date.now() - start < sshTimeoutMs) {
|
|
85723
85766
|
try {
|
|
85724
|
-
|
|
85767
|
+
execSync3(`ssh ${this.sshBaseArgs(host, ["-o", "ConnectTimeout=5"]).map((a) => `"${a.replace(/"/g, "\\\"")}"`).join(" ")} true`, {
|
|
85725
85768
|
stdio: "pipe",
|
|
85726
85769
|
maxBuffer: SSH_MAX_BUFFER
|
|
85727
85770
|
});
|
|
@@ -85781,7 +85824,7 @@ ${out}`);
|
|
|
85781
85824
|
];
|
|
85782
85825
|
}
|
|
85783
85826
|
scpToHost(host, localPath, remotePath) {
|
|
85784
|
-
|
|
85827
|
+
execSync3([
|
|
85785
85828
|
"scp",
|
|
85786
85829
|
"-i",
|
|
85787
85830
|
this.sshPrivateKeyPath,
|
|
@@ -85794,7 +85837,7 @@ ${out}`);
|
|
|
85794
85837
|
}
|
|
85795
85838
|
sshExec(host, script) {
|
|
85796
85839
|
const escaped = script.replace(/'/g, `'\\''`);
|
|
85797
|
-
return
|
|
85840
|
+
return execSync3(`ssh ${this.sshBaseArgs(host).map((a) => `"${a.replace(/"/g, "\\\"")}"`).join(" ")} '${escaped}'`, {
|
|
85798
85841
|
encoding: "utf8",
|
|
85799
85842
|
stdio: ["pipe", "pipe", "pipe"],
|
|
85800
85843
|
maxBuffer: SSH_MAX_BUFFER
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/ts-cloud",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.5",
|
|
5
5
|
"description": "A lightweight, performant infrastructure-as-code library and CLI for deploying both server-based (EC2) and serverless applications.",
|
|
6
6
|
"author": "Chris Breuer <chris@stacksjs.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -89,8 +89,8 @@
|
|
|
89
89
|
"test": "bun test"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@ts-cloud/aws-types": "0.5.
|
|
93
|
-
"@ts-cloud/core": "0.5.
|
|
92
|
+
"@ts-cloud/aws-types": "0.5.5",
|
|
93
|
+
"@ts-cloud/core": "0.5.5",
|
|
94
94
|
"@stacksjs/ts-xml": "^0.1.0"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|