@stacksjs/ts-cloud 0.3.1 → 0.4.1
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 +418 -416
- package/dist/drivers/shared/package-manager.d.ts +1 -1
- package/dist/index.js +260 -101
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -39,17 +39,22 @@ import { cpSync, mkdtempSync, rmSync, writeFileSync as writeFileSync32 } from "n
|
|
|
39
39
|
import { tmpdir } from "node:os";
|
|
40
40
|
import { dirname as dirname22, isAbsolute as isAbsolute3, join as join62, resolve as resolve13 } from "node:path";
|
|
41
41
|
import { fileURLToPath } from "node:url";
|
|
42
|
-
import { readFileSync as readFileSync4 } from "node:fs";
|
|
43
|
-
import { dirname as dirname32, join as join72 } from "node:path";
|
|
44
|
-
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
45
42
|
import { execFileSync } from "node:child_process";
|
|
46
|
-
import {
|
|
43
|
+
import { mkdtempSync as mkdtempSync2, readFileSync as readFileSync4, rmSync as rmSync2 } from "node:fs";
|
|
47
44
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
48
|
-
import {
|
|
45
|
+
import { dirname as dirname32, join as join72 } from "node:path";
|
|
46
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
47
|
+
import { readFileSync as readFileSync5 } from "node:fs";
|
|
48
|
+
import { dirname as dirname42, join as join8 } from "node:path";
|
|
49
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
50
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
51
|
+
import { existsSync as existsSync52, mkdtempSync as mkdtempSync3, readdirSync as readdirSync52, readFileSync as readFileSync6, rmSync as rmSync3, statSync as statSync32, writeFileSync as writeFileSync52 } from "node:fs";
|
|
52
|
+
import { tmpdir as tmpdir3 } from "node:os";
|
|
53
|
+
import { join as join9, relative as relative22 } from "node:path";
|
|
49
54
|
import { execSync as execSync2 } from "node:child_process";
|
|
50
55
|
import { createHash as createHash5 } from "node:crypto";
|
|
51
|
-
import { readdirSync as readdirSync62, readFileSync as
|
|
52
|
-
import { join as
|
|
56
|
+
import { readdirSync as readdirSync62, readFileSync as readFileSync7, statSync as statSync4 } from "node:fs";
|
|
57
|
+
import { join as join10, relative as relative32, resolve as resolve22 } from "node:path";
|
|
53
58
|
function __exportSetter3(name, newValue) {
|
|
54
59
|
this[name] = __returnValue3.bind(null, newValue);
|
|
55
60
|
}
|
|
@@ -25711,7 +25716,7 @@ async function packageServerlessApp(opts) {
|
|
|
25711
25716
|
opts.onStep?.("bundling application");
|
|
25712
25717
|
const result = await Bun.build({
|
|
25713
25718
|
entrypoints: [bootstrapPath],
|
|
25714
|
-
target: "node",
|
|
25719
|
+
target: app.kind === "bun" ? "bun" : "node",
|
|
25715
25720
|
format: "esm",
|
|
25716
25721
|
minify: false,
|
|
25717
25722
|
sourcemap: "none"
|
|
@@ -25742,6 +25747,54 @@ ${logs}`);
|
|
|
25742
25747
|
rmSync(stage, { recursive: true, force: true });
|
|
25743
25748
|
}
|
|
25744
25749
|
}
|
|
25750
|
+
function normalizeNodeVersion(v) {
|
|
25751
|
+
if (!v)
|
|
25752
|
+
return "22";
|
|
25753
|
+
const m = String(v).match(/(\d+)/);
|
|
25754
|
+
return m ? m[1] : "22";
|
|
25755
|
+
}
|
|
25756
|
+
function resolveServerlessRuntime(app) {
|
|
25757
|
+
const kind = app.kind ?? "node";
|
|
25758
|
+
if (kind === "php") {
|
|
25759
|
+
return {
|
|
25760
|
+
lambdaRuntime: "provided.al2023",
|
|
25761
|
+
kind: "php",
|
|
25762
|
+
version: app.phpVersion ?? "8.3",
|
|
25763
|
+
usesLayer: true,
|
|
25764
|
+
layerKind: "php",
|
|
25765
|
+
layerEnvVar: "TSCLOUD_PHP_LAYER_ARN"
|
|
25766
|
+
};
|
|
25767
|
+
}
|
|
25768
|
+
if (kind === "bun") {
|
|
25769
|
+
return {
|
|
25770
|
+
lambdaRuntime: "provided.al2023",
|
|
25771
|
+
kind: "bun",
|
|
25772
|
+
version: app.runtimeVersion ?? "latest",
|
|
25773
|
+
usesLayer: true,
|
|
25774
|
+
layerKind: "bun",
|
|
25775
|
+
layerEnvVar: "TSCLOUD_BUN_LAYER_ARN"
|
|
25776
|
+
};
|
|
25777
|
+
}
|
|
25778
|
+
const version2 = normalizeNodeVersion(app.runtimeVersion);
|
|
25779
|
+
const explicitProvided = app.runtime === "provided.al2023";
|
|
25780
|
+
const managed = !explicitProvided && MANAGED_NODE_VERSIONS.includes(version2);
|
|
25781
|
+
if (managed) {
|
|
25782
|
+
return {
|
|
25783
|
+
lambdaRuntime: app.runtime && app.runtime.startsWith("nodejs") ? app.runtime : `nodejs${version2}.x`,
|
|
25784
|
+
kind: "node",
|
|
25785
|
+
version: version2,
|
|
25786
|
+
usesLayer: false
|
|
25787
|
+
};
|
|
25788
|
+
}
|
|
25789
|
+
return {
|
|
25790
|
+
lambdaRuntime: "provided.al2023",
|
|
25791
|
+
kind: "node",
|
|
25792
|
+
version: version2,
|
|
25793
|
+
usesLayer: true,
|
|
25794
|
+
layerKind: "node",
|
|
25795
|
+
layerEnvVar: "TSCLOUD_NODE_LAYER_ARN"
|
|
25796
|
+
};
|
|
25797
|
+
}
|
|
25745
25798
|
function resolveQueueNames(app, slug, env) {
|
|
25746
25799
|
if (app.queues === false)
|
|
25747
25800
|
return [];
|
|
@@ -25755,7 +25808,7 @@ function resolveQueueNames(app, slug, env) {
|
|
|
25755
25808
|
function composeServerlessAppTemplate(opts) {
|
|
25756
25809
|
const { app, environment, handlers } = opts;
|
|
25757
25810
|
const slug = opts.config.project.slug;
|
|
25758
|
-
const runtime = app.
|
|
25811
|
+
const runtime = resolveServerlessRuntime(app).lambdaRuntime;
|
|
25759
25812
|
const architecture = app.architecture ?? "x86_64";
|
|
25760
25813
|
const region = opts.config.project.region;
|
|
25761
25814
|
const functionNames = {
|
|
@@ -26360,6 +26413,78 @@ COPY app/ \${LAMBDA_TASK_ROOT}/
|
|
|
26360
26413
|
CMD [ "index.http" ]
|
|
26361
26414
|
`;
|
|
26362
26415
|
}
|
|
26416
|
+
function assetsDir() {
|
|
26417
|
+
return dirname32(fileURLToPath2(import.meta.url));
|
|
26418
|
+
}
|
|
26419
|
+
function sharedRuntimeLoop() {
|
|
26420
|
+
return readFileSync4(join72(assetsDir(), "runtime.mjs"), "utf-8");
|
|
26421
|
+
}
|
|
26422
|
+
function bootstrap(kind) {
|
|
26423
|
+
return readFileSync4(join72(assetsDir(), `${kind}-bootstrap`), "utf-8");
|
|
26424
|
+
}
|
|
26425
|
+
function buildNodeRuntimeLayerZip(options) {
|
|
26426
|
+
const architecture = options.architecture ?? "x86_64";
|
|
26427
|
+
const nodeArch = architecture === "arm64" ? "arm64" : "x64";
|
|
26428
|
+
const version2 = options.version.replace(/^v/, "");
|
|
26429
|
+
const step = options.onStep ?? (() => {});
|
|
26430
|
+
const stage = mkdtempSync2(join72(tmpdir2(), "tscloud-node-layer-"));
|
|
26431
|
+
try {
|
|
26432
|
+
const exact = version2.includes(".") ? version2 : resolveLatestNode(version2);
|
|
26433
|
+
const dir = `node-v${exact}-linux-${nodeArch}`;
|
|
26434
|
+
const url = `https://nodejs.org/dist/v${exact}/${dir}.tar.xz`;
|
|
26435
|
+
step(`downloading Node ${exact} (${architecture})`);
|
|
26436
|
+
const tar = join72(stage, "node.tar.xz");
|
|
26437
|
+
fetchToFile(url, tar);
|
|
26438
|
+
step("extracting node binary");
|
|
26439
|
+
execFileSync("tar", ["-xf", tar, "-C", stage, `${dir}/bin/node`], { stdio: "inherit" });
|
|
26440
|
+
const nodeBin = readFileSync4(join72(stage, dir, "bin", "node"));
|
|
26441
|
+
step("packaging layer");
|
|
26442
|
+
const entries = [
|
|
26443
|
+
{ name: "bootstrap", data: bootstrap("node"), mode: 493 },
|
|
26444
|
+
{ name: "runtime.mjs", data: sharedRuntimeLoop(), mode: 420 },
|
|
26445
|
+
{ name: "bin/node", data: nodeBin, mode: 493 }
|
|
26446
|
+
];
|
|
26447
|
+
return { zip: createZip(entries), architecture, version: exact, fileCount: entries.length };
|
|
26448
|
+
} finally {
|
|
26449
|
+
rmSync2(stage, { recursive: true, force: true });
|
|
26450
|
+
}
|
|
26451
|
+
}
|
|
26452
|
+
function buildBunRuntimeLayerZip(options) {
|
|
26453
|
+
const architecture = options.architecture ?? "x86_64";
|
|
26454
|
+
const bunArch = architecture === "arm64" ? "bun-linux-aarch64" : "bun-linux-x64";
|
|
26455
|
+
const version2 = options.version === "latest" ? "" : options.version.replace(/^v/, "");
|
|
26456
|
+
const step = options.onStep ?? (() => {});
|
|
26457
|
+
const stage = mkdtempSync2(join72(tmpdir2(), "tscloud-bun-layer-"));
|
|
26458
|
+
try {
|
|
26459
|
+
const url = version2 ? `https://github.com/oven-sh/bun/releases/download/bun-v${version2}/${bunArch}.zip` : `https://github.com/oven-sh/bun/releases/latest/download/${bunArch}.zip`;
|
|
26460
|
+
step(`downloading Bun ${version2 || "latest"} (${architecture})`);
|
|
26461
|
+
const zipPath = join72(stage, "bun.zip");
|
|
26462
|
+
fetchToFile(url, zipPath);
|
|
26463
|
+
step("extracting bun binary");
|
|
26464
|
+
execFileSync("unzip", ["-o", "-q", zipPath, "-d", stage], { stdio: "inherit" });
|
|
26465
|
+
const bunBin = readFileSync4(join72(stage, bunArch, "bun"));
|
|
26466
|
+
step("packaging layer");
|
|
26467
|
+
const entries = [
|
|
26468
|
+
{ name: "bootstrap", data: bootstrap("bun"), mode: 493 },
|
|
26469
|
+
{ name: "runtime.mjs", data: sharedRuntimeLoop(), mode: 420 },
|
|
26470
|
+
{ name: "bin/bun", data: bunBin, mode: 493 }
|
|
26471
|
+
];
|
|
26472
|
+
return { zip: createZip(entries), architecture, version: version2 || "latest", fileCount: entries.length };
|
|
26473
|
+
} finally {
|
|
26474
|
+
rmSync2(stage, { recursive: true, force: true });
|
|
26475
|
+
}
|
|
26476
|
+
}
|
|
26477
|
+
function fetchToFile(url, dest) {
|
|
26478
|
+
execFileSync("curl", ["-fsSL", "-o", dest, url], { stdio: ["ignore", "ignore", "inherit"] });
|
|
26479
|
+
}
|
|
26480
|
+
function resolveLatestNode(major) {
|
|
26481
|
+
const indexJson = execFileSync("curl", ["-fsSL", "https://nodejs.org/dist/index.json"], { encoding: "utf-8" });
|
|
26482
|
+
const releases = JSON.parse(indexJson);
|
|
26483
|
+
const match = releases.find((r) => r.version.startsWith(`v${major}.`));
|
|
26484
|
+
if (!match)
|
|
26485
|
+
throw new Error(`No Node release found for major version ${major}`);
|
|
26486
|
+
return match.version.replace(/^v/, "");
|
|
26487
|
+
}
|
|
26363
26488
|
function resolveApp(mod) {
|
|
26364
26489
|
const m = mod;
|
|
26365
26490
|
const def = m?.default ?? m;
|
|
@@ -26508,12 +26633,12 @@ php_admin_flag[log_errors] = on
|
|
|
26508
26633
|
clear_env = no
|
|
26509
26634
|
`;
|
|
26510
26635
|
}
|
|
26511
|
-
function
|
|
26512
|
-
return
|
|
26636
|
+
function assetsDir2() {
|
|
26637
|
+
return join8(dirname42(fileURLToPath3(import.meta.url)), "runtime-assets");
|
|
26513
26638
|
}
|
|
26514
26639
|
function phpRuntimeLayerAssets() {
|
|
26515
|
-
const dir =
|
|
26516
|
-
const read = (f) =>
|
|
26640
|
+
const dir = assetsDir2();
|
|
26641
|
+
const read = (f) => readFileSync5(join8(dir, f), "utf-8");
|
|
26517
26642
|
return [
|
|
26518
26643
|
{ path: "bootstrap", contents: read("bootstrap"), mode: 493 },
|
|
26519
26644
|
{ path: "tscloud/runtime.php", contents: read("runtime.php"), mode: 420 },
|
|
@@ -26543,7 +26668,7 @@ function laravelServerlessEnvDefaults(opts = {}) {
|
|
|
26543
26668
|
}
|
|
26544
26669
|
function* walk(dir) {
|
|
26545
26670
|
for (const entry of readdirSync52(dir)) {
|
|
26546
|
-
const full =
|
|
26671
|
+
const full = join9(dir, entry);
|
|
26547
26672
|
if (statSync32(full).isDirectory())
|
|
26548
26673
|
yield* walk(full);
|
|
26549
26674
|
else
|
|
@@ -26554,19 +26679,19 @@ function buildPhpRuntimeLayerZip(options = {}) {
|
|
|
26554
26679
|
const architecture = options.architecture ?? "x86_64";
|
|
26555
26680
|
const platform = options.platform ?? (architecture === "arm64" ? "linux/arm64" : "linux/amd64");
|
|
26556
26681
|
const step = options.onStep ?? (() => {});
|
|
26557
|
-
const stage =
|
|
26682
|
+
const stage = mkdtempSync3(join9(tmpdir3(), "tscloud-php-layer-"));
|
|
26558
26683
|
const imageTag = "tscloud-php-layer:build";
|
|
26559
26684
|
try {
|
|
26560
|
-
|
|
26685
|
+
writeFileSync52(join9(stage, "Dockerfile"), generatePhpLayerDockerfile(options));
|
|
26561
26686
|
step("Building PHP runtime image (docker)");
|
|
26562
|
-
|
|
26687
|
+
execFileSync2("docker", ["build", "--platform", platform, "-t", imageTag, stage], { stdio: "inherit" });
|
|
26563
26688
|
step("Extracting /opt from image");
|
|
26564
|
-
const cid =
|
|
26565
|
-
const optDir =
|
|
26689
|
+
const cid = execFileSync2("docker", ["create", "--platform", platform, imageTag], { encoding: "utf-8" }).trim();
|
|
26690
|
+
const optDir = join9(stage, "opt");
|
|
26566
26691
|
try {
|
|
26567
|
-
|
|
26692
|
+
execFileSync2("docker", ["cp", `${cid}:/opt/.`, optDir], { stdio: "inherit" });
|
|
26568
26693
|
} finally {
|
|
26569
|
-
|
|
26694
|
+
execFileSync2("docker", ["rm", cid], { stdio: "ignore" });
|
|
26570
26695
|
}
|
|
26571
26696
|
if (!existsSync52(optDir))
|
|
26572
26697
|
throw new Error("layer build produced no /opt directory");
|
|
@@ -26574,7 +26699,7 @@ function buildPhpRuntimeLayerZip(options = {}) {
|
|
|
26574
26699
|
for (const file of walk(optDir)) {
|
|
26575
26700
|
const rel = relative22(optDir, file).replace(/\\/g, "/");
|
|
26576
26701
|
const mode = statSync32(file).mode & 73 ? 493 : 420;
|
|
26577
|
-
entries.push({ name: rel, data:
|
|
26702
|
+
entries.push({ name: rel, data: readFileSync6(file), mode });
|
|
26578
26703
|
}
|
|
26579
26704
|
step("Injecting runtime assets");
|
|
26580
26705
|
const assetPaths = new Set(phpRuntimeLayerAssets().map((a) => a.path));
|
|
@@ -26586,7 +26711,7 @@ function buildPhpRuntimeLayerZip(options = {}) {
|
|
|
26586
26711
|
const zip2 = createZip(filtered);
|
|
26587
26712
|
return { zip: zip2, architecture, fileCount: filtered.length };
|
|
26588
26713
|
} finally {
|
|
26589
|
-
|
|
26714
|
+
rmSync3(stage, { recursive: true, force: true });
|
|
26590
26715
|
}
|
|
26591
26716
|
}
|
|
26592
26717
|
function isExcluded(rel, excludes) {
|
|
@@ -26594,7 +26719,7 @@ function isExcluded(rel, excludes) {
|
|
|
26594
26719
|
}
|
|
26595
26720
|
function* walk2(dir, root, excludes) {
|
|
26596
26721
|
for (const entry of readdirSync62(dir)) {
|
|
26597
|
-
const full =
|
|
26722
|
+
const full = join10(dir, entry);
|
|
26598
26723
|
const rel = relative32(root, full).replace(/\\/g, "/");
|
|
26599
26724
|
if (isExcluded(rel, excludes))
|
|
26600
26725
|
continue;
|
|
@@ -26621,7 +26746,7 @@ function collectPhpAppEntries(projectRoot, exclude = []) {
|
|
|
26621
26746
|
for (const file of walk2(root, root, excludes)) {
|
|
26622
26747
|
const rel = relative32(root, file).replace(/\\/g, "/");
|
|
26623
26748
|
const executable = (statSync4(file).mode & 73) !== 0;
|
|
26624
|
-
entries.push({ name: rel, data:
|
|
26749
|
+
entries.push({ name: rel, data: readFileSync7(file), mode: executable ? 493 : 420 });
|
|
26625
26750
|
}
|
|
26626
26751
|
return entries;
|
|
26627
26752
|
}
|
|
@@ -28068,7 +28193,7 @@ catch (error) {
|
|
|
28068
28193
|
|
|
28069
28194
|
return { statusCode: 200, body: 'OK' };
|
|
28070
28195
|
};
|
|
28071
|
-
`, inbound_default, exports_advanced2, IVRBuilder, exports_advanced3, MmsSupport, SmsChatbot, fifoQueueManager, dlqMonitoringManager, batchProcessingManager, queueManagementManager, CRC_TABLE, PHP_LAYER_EXTENSIONS, TEXT_CONTENT, LARAVEL_SERVERLESS_BUILD_STEPS, PHP_DEFAULT_EXCLUDES, staticSiteManager, storageAdvancedManager, healthCheckManager, networkSecurityManager, resourceManagementManager;
|
|
28196
|
+
`, inbound_default, exports_advanced2, IVRBuilder, exports_advanced3, MmsSupport, SmsChatbot, fifoQueueManager, dlqMonitoringManager, batchProcessingManager, queueManagementManager, CRC_TABLE, MANAGED_NODE_VERSIONS, PHP_LAYER_EXTENSIONS, TEXT_CONTENT, LARAVEL_SERVERLESS_BUILD_STEPS, PHP_DEFAULT_EXCLUDES, staticSiteManager, storageAdvancedManager, healthCheckManager, networkSecurityManager, resourceManagementManager;
|
|
28072
28197
|
var init_dist2 = __esm(async () => {
|
|
28073
28198
|
__defProp3 = Object.defineProperty;
|
|
28074
28199
|
__require3 = /* @__PURE__ */ createRequire2(import.meta.url);
|
|
@@ -41791,7 +41916,8 @@ Details:`;
|
|
|
41791
41916
|
type: "object",
|
|
41792
41917
|
description: "Serverless application manifest (Laravel-Vapor-equivalent). Defining this opts the environment into the serverless app deploy pipeline (http/queue/cli Lambda functions, assets, build/deploy hooks).",
|
|
41793
41918
|
properties: {
|
|
41794
|
-
runtime: { type: "string", description: "Lambda runtime (
|
|
41919
|
+
runtime: { type: "string", description: "Lambda runtime override (usually derived from kind + runtimeVersion)" },
|
|
41920
|
+
runtimeVersion: { type: "string", description: "Node major (18/20/22 managed, 24+ custom layer) or Bun release for node/bun apps" },
|
|
41795
41921
|
kind: { type: "string", enum: ["node", "bun", "php"], description: "Application kind (drives packaging + runtime)" },
|
|
41796
41922
|
entry: { type: "string", description: "Entry file exporting the request handler" },
|
|
41797
41923
|
memory: { type: "number", description: "HTTP function memory in MB" },
|
|
@@ -45604,6 +45730,7 @@ async function sendFallbackSms(to, message) {
|
|
|
45604
45730
|
}
|
|
45605
45731
|
return table2;
|
|
45606
45732
|
})();
|
|
45733
|
+
MANAGED_NODE_VERSIONS = ["18", "20", "22"];
|
|
45607
45734
|
PHP_LAYER_EXTENSIONS = [
|
|
45608
45735
|
"cli",
|
|
45609
45736
|
"fpm",
|
|
@@ -46829,9 +46956,9 @@ __export(exports_client, {
|
|
|
46829
46956
|
AWSClient: () => AWSClient
|
|
46830
46957
|
});
|
|
46831
46958
|
import * as crypto2 from "node:crypto";
|
|
46832
|
-
import { existsSync as existsSync14, readFileSync as
|
|
46959
|
+
import { existsSync as existsSync14, readFileSync as readFileSync8 } from "node:fs";
|
|
46833
46960
|
import { homedir as homedir6 } from "node:os";
|
|
46834
|
-
import { join as
|
|
46961
|
+
import { join as join11 } from "node:path";
|
|
46835
46962
|
function resolveS3Endpoint(options) {
|
|
46836
46963
|
const base = options.endpoint || `s3.${options.region}.amazonaws.com`;
|
|
46837
46964
|
if (!options.bucket) {
|
|
@@ -46889,12 +47016,12 @@ class AWSClient {
|
|
|
46889
47016
|
}
|
|
46890
47017
|
loadCredentialsFromFile() {
|
|
46891
47018
|
const profile = process.env.AWS_PROFILE || "default";
|
|
46892
|
-
const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE ||
|
|
47019
|
+
const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE || join11(homedir6(), ".aws", "credentials");
|
|
46893
47020
|
if (!existsSync14(credentialsPath)) {
|
|
46894
47021
|
return null;
|
|
46895
47022
|
}
|
|
46896
47023
|
try {
|
|
46897
|
-
const content =
|
|
47024
|
+
const content = readFileSync8(credentialsPath, "utf-8");
|
|
46898
47025
|
const credentials = this.parseCredentialsFile(content, profile);
|
|
46899
47026
|
if (credentials.accessKeyId && credentials.secretAccessKey) {
|
|
46900
47027
|
return credentials;
|
|
@@ -47388,7 +47515,7 @@ function detectCredentialSource() {
|
|
|
47388
47515
|
};
|
|
47389
47516
|
}
|
|
47390
47517
|
const profile = process.env.AWS_PROFILE || "default";
|
|
47391
|
-
const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE ||
|
|
47518
|
+
const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE || join11(homedir6(), ".aws", "credentials");
|
|
47392
47519
|
if (existsSync14(credentialsPath)) {
|
|
47393
47520
|
return {
|
|
47394
47521
|
source: "file",
|
|
@@ -47430,13 +47557,13 @@ function resolveCredentials2(profile) {
|
|
|
47430
47557
|
return loadProfileFromFile(process.env.AWS_PROFILE || "default") ?? { accessKeyId: "", secretAccessKey: "" };
|
|
47431
47558
|
}
|
|
47432
47559
|
function loadProfileFromFile(profile) {
|
|
47433
|
-
const { existsSync: existsSync15, readFileSync:
|
|
47560
|
+
const { existsSync: existsSync15, readFileSync: readFileSync9 } = __require("node:fs");
|
|
47434
47561
|
const { homedir: homedir5 } = __require("node:os");
|
|
47435
|
-
const { join:
|
|
47436
|
-
const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE ||
|
|
47562
|
+
const { join: join12 } = __require("node:path");
|
|
47563
|
+
const credentialsPath = process.env.AWS_SHARED_CREDENTIALS_FILE || join12(homedir5(), ".aws", "credentials");
|
|
47437
47564
|
if (!existsSync15(credentialsPath))
|
|
47438
47565
|
return null;
|
|
47439
|
-
const content =
|
|
47566
|
+
const content = readFileSync9(credentialsPath, "utf-8");
|
|
47440
47567
|
let currentProfile = null;
|
|
47441
47568
|
let accessKeyId;
|
|
47442
47569
|
let secretAccessKey;
|
|
@@ -47482,8 +47609,8 @@ function loadProfileFromFile(profile) {
|
|
|
47482
47609
|
// src/aws/s3.ts
|
|
47483
47610
|
import * as crypto3 from "node:crypto";
|
|
47484
47611
|
import { readdir as readdir4 } from "node:fs/promises";
|
|
47485
|
-
import { join as
|
|
47486
|
-
import { readFileSync as
|
|
47612
|
+
import { join as join13 } from "node:path";
|
|
47613
|
+
import { readFileSync as readFileSync10 } from "node:fs";
|
|
47487
47614
|
function toFetchBody(data) {
|
|
47488
47615
|
const { buffer, byteOffset, byteLength } = data;
|
|
47489
47616
|
if (buffer instanceof ArrayBuffer) {
|
|
@@ -47885,7 +48012,7 @@ class S3Client2 {
|
|
|
47885
48012
|
}
|
|
47886
48013
|
}
|
|
47887
48014
|
async copy(options) {
|
|
47888
|
-
const fileContent =
|
|
48015
|
+
const fileContent = readFileSync10(options.source);
|
|
47889
48016
|
await this.putObject({
|
|
47890
48017
|
bucket: options.bucket,
|
|
47891
48018
|
key: options.key,
|
|
@@ -47908,7 +48035,7 @@ class S3Client2 {
|
|
|
47908
48035
|
const relativePath = file.substring(options.source.length + 1);
|
|
47909
48036
|
const s3Key = options.prefix ? `${options.prefix}/${relativePath}` : relativePath;
|
|
47910
48037
|
if (!options.dryRun) {
|
|
47911
|
-
const fileContent =
|
|
48038
|
+
const fileContent = readFileSync10(file);
|
|
47912
48039
|
await this.putObject({
|
|
47913
48040
|
bucket: options.bucket,
|
|
47914
48041
|
key: s3Key,
|
|
@@ -47939,7 +48066,7 @@ class S3Client2 {
|
|
|
47939
48066
|
const files = [];
|
|
47940
48067
|
const entries = await readdir4(dir, { withFileTypes: true });
|
|
47941
48068
|
for (const entry of entries) {
|
|
47942
|
-
const fullPath =
|
|
48069
|
+
const fullPath = join13(dir, entry.name);
|
|
47943
48070
|
if (entry.isDirectory()) {
|
|
47944
48071
|
const subFiles = await this.listFilesRecursive(fullPath);
|
|
47945
48072
|
files.push(...subFiles);
|
|
@@ -56895,13 +57022,13 @@ async function uploadStaticFiles(options) {
|
|
|
56895
57022
|
const { sourceDir, bucket, region, cacheControl = "max-age=31536000, public", onProgress } = options;
|
|
56896
57023
|
const s32 = new S3Client2(region);
|
|
56897
57024
|
const { readdir: readdir5 } = await import("node:fs/promises");
|
|
56898
|
-
const { join:
|
|
57025
|
+
const { join: join12, relative: relative5 } = await import("node:path");
|
|
56899
57026
|
const { createHash: createHash7 } = await import("node:crypto");
|
|
56900
57027
|
async function listFiles(dir) {
|
|
56901
57028
|
const files2 = [];
|
|
56902
57029
|
const entries = await readdir5(dir, { withFileTypes: true });
|
|
56903
57030
|
for (const entry of entries) {
|
|
56904
|
-
const fullPath =
|
|
57031
|
+
const fullPath = join12(dir, entry.name);
|
|
56905
57032
|
if (entry.isDirectory()) {
|
|
56906
57033
|
files2.push(...await listFiles(fullPath));
|
|
56907
57034
|
} else {
|
|
@@ -57122,13 +57249,13 @@ var exports_serverless_image = {};
|
|
|
57122
57249
|
__export(exports_serverless_image, {
|
|
57123
57250
|
buildAndPushServerlessImage: () => buildAndPushServerlessImage
|
|
57124
57251
|
});
|
|
57125
|
-
import { execFileSync as
|
|
57126
|
-
import { mkdirSync as mkdirSync7, mkdtempSync as
|
|
57127
|
-
import { tmpdir as
|
|
57128
|
-
import { dirname as dirname7, join as
|
|
57252
|
+
import { execFileSync as execFileSync3, execSync as execSync3 } from "node:child_process";
|
|
57253
|
+
import { mkdirSync as mkdirSync7, mkdtempSync as mkdtempSync4, rmSync as rmSync4, writeFileSync as writeFileSync10 } from "node:fs";
|
|
57254
|
+
import { tmpdir as tmpdir4 } from "node:os";
|
|
57255
|
+
import { dirname as dirname7, join as join15 } from "node:path";
|
|
57129
57256
|
function writeEntries(baseDir, entries) {
|
|
57130
57257
|
for (const e of entries) {
|
|
57131
|
-
const dest =
|
|
57258
|
+
const dest = join15(baseDir, e.name);
|
|
57132
57259
|
mkdirSync7(dirname7(dest), { recursive: true });
|
|
57133
57260
|
writeFileSync10(dest, e.data, e.mode ? { mode: e.mode } : undefined);
|
|
57134
57261
|
}
|
|
@@ -57139,9 +57266,9 @@ async function buildAndPushServerlessImage(opts) {
|
|
|
57139
57266
|
const platform = arch === "arm64" ? "linux/arm64" : "linux/amd64";
|
|
57140
57267
|
const isPhp = app.kind === "php";
|
|
57141
57268
|
const step2 = opts.onStep ?? (() => {});
|
|
57142
|
-
const stage =
|
|
57269
|
+
const stage = mkdtempSync4(join15(tmpdir4(), "tscloud-img-"));
|
|
57143
57270
|
try {
|
|
57144
|
-
const appDir =
|
|
57271
|
+
const appDir = join15(stage, "app");
|
|
57145
57272
|
mkdirSync7(appDir, { recursive: true });
|
|
57146
57273
|
let handlers;
|
|
57147
57274
|
let contentHash;
|
|
@@ -57150,19 +57277,19 @@ async function buildAndPushServerlessImage(opts) {
|
|
|
57150
57277
|
step2("staging application tree");
|
|
57151
57278
|
const entries = collectPhpAppEntries(projectRoot);
|
|
57152
57279
|
writeEntries(appDir, entries);
|
|
57153
|
-
writeEntries(
|
|
57280
|
+
writeEntries(join15(stage, "runtime"), phpRuntimeLayerAssets().map((a) => ({ name: a.path, data: a.contents, mode: a.mode })));
|
|
57154
57281
|
const handler8 = app.handlers?.http ?? "public/index.php";
|
|
57155
57282
|
handlers = { http: handler8, queue: app.handlers?.queue ?? handler8, cli: app.handlers?.cli ?? handler8 };
|
|
57156
57283
|
contentHash = sha256(entries.map((e) => `${e.name}:${e.data.length}`).join("|"));
|
|
57157
57284
|
} else {
|
|
57158
57285
|
step2("bundling application");
|
|
57159
57286
|
const artifact = await packageServerlessApp({ projectRoot, app, skipBuild: opts.skipBuild, onStep: step2 });
|
|
57160
|
-
writeFileSync10(
|
|
57287
|
+
writeFileSync10(join15(appDir, "index.mjs"), artifact.bundle);
|
|
57161
57288
|
handlers = artifact.handlers;
|
|
57162
57289
|
contentHash = artifact.sha256;
|
|
57163
57290
|
}
|
|
57164
57291
|
const tag = contentHash.slice(0, 16);
|
|
57165
|
-
writeFileSync10(
|
|
57292
|
+
writeFileSync10(join15(stage, "Dockerfile"), generateAppImageDockerfile({
|
|
57166
57293
|
kind: app.kind ?? "node",
|
|
57167
57294
|
phpVersion: app.phpVersion,
|
|
57168
57295
|
architecture: arch
|
|
@@ -57184,16 +57311,16 @@ async function buildAndPushServerlessImage(opts) {
|
|
|
57184
57311
|
throw new Error(`could not resolve ECR repository URI for ${repository}`);
|
|
57185
57312
|
const imageUri = `${repoUri}:${tag}`;
|
|
57186
57313
|
step2("docker build");
|
|
57187
|
-
|
|
57314
|
+
execFileSync3("docker", ["build", "--platform", platform, "-t", imageUri, stage], { stdio: "inherit" });
|
|
57188
57315
|
step2("ecr login");
|
|
57189
57316
|
const loginCmd = await ecr2.getDockerLoginCommand();
|
|
57190
57317
|
execSync3(loginCmd, { stdio: "inherit" });
|
|
57191
57318
|
step2("docker push");
|
|
57192
|
-
|
|
57319
|
+
execFileSync3("docker", ["push", imageUri], { stdio: "inherit" });
|
|
57193
57320
|
info(`Image: ${imageUri}`);
|
|
57194
57321
|
return { imageUri, tag, handlers };
|
|
57195
57322
|
} finally {
|
|
57196
|
-
|
|
57323
|
+
rmSync4(stage, { recursive: true, force: true });
|
|
57197
57324
|
}
|
|
57198
57325
|
}
|
|
57199
57326
|
var init_serverless_image = __esm(async () => {
|
|
@@ -78421,7 +78548,7 @@ class ApplicationAutoScalingClient {
|
|
|
78421
78548
|
init_s3();
|
|
78422
78549
|
import * as net from "node:net";
|
|
78423
78550
|
import * as tls from "node:tls";
|
|
78424
|
-
import { readFileSync as
|
|
78551
|
+
import { readFileSync as readFileSync11 } from "node:fs";
|
|
78425
78552
|
import * as crypto4 from "node:crypto";
|
|
78426
78553
|
|
|
78427
78554
|
class ImapServer {
|
|
@@ -78456,8 +78583,8 @@ class ImapServer {
|
|
|
78456
78583
|
});
|
|
78457
78584
|
if (this.config.tls?.key && this.config.tls?.cert) {
|
|
78458
78585
|
const tlsOptions = {
|
|
78459
|
-
key:
|
|
78460
|
-
cert:
|
|
78586
|
+
key: readFileSync11(this.config.tls.key),
|
|
78587
|
+
cert: readFileSync11(this.config.tls.cert)
|
|
78461
78588
|
};
|
|
78462
78589
|
this.tlsServer = tls.createServer(tlsOptions, (socket) => {
|
|
78463
78590
|
this.handleConnection(socket);
|
|
@@ -79261,8 +79388,8 @@ class ImapServer {
|
|
|
79261
79388
|
}
|
|
79262
79389
|
this.send(session, `${tag} OK Begin TLS negotiation`);
|
|
79263
79390
|
const tlsOptions = {
|
|
79264
|
-
key:
|
|
79265
|
-
cert:
|
|
79391
|
+
key: readFileSync11(this.config.tls.key),
|
|
79392
|
+
cert: readFileSync11(this.config.tls.cert),
|
|
79266
79393
|
isServer: true
|
|
79267
79394
|
};
|
|
79268
79395
|
const tlsSocket = new tls.TLSSocket(session.socket, tlsOptions);
|
|
@@ -79855,7 +79982,7 @@ init_ses();
|
|
|
79855
79982
|
init_s3();
|
|
79856
79983
|
import * as net2 from "node:net";
|
|
79857
79984
|
import * as tls2 from "node:tls";
|
|
79858
|
-
import { readFileSync as
|
|
79985
|
+
import { readFileSync as readFileSync12 } from "node:fs";
|
|
79859
79986
|
import * as crypto5 from "node:crypto";
|
|
79860
79987
|
|
|
79861
79988
|
class SmtpServer {
|
|
@@ -79886,8 +80013,8 @@ class SmtpServer {
|
|
|
79886
80013
|
});
|
|
79887
80014
|
if (this.config.tls?.key && this.config.tls?.cert) {
|
|
79888
80015
|
const tlsOptions = {
|
|
79889
|
-
key:
|
|
79890
|
-
cert:
|
|
80016
|
+
key: readFileSync12(this.config.tls.key),
|
|
80017
|
+
cert: readFileSync12(this.config.tls.cert)
|
|
79891
80018
|
};
|
|
79892
80019
|
this.tlsServer = tls2.createServer(tlsOptions, (socket) => {
|
|
79893
80020
|
this.handleConnection(socket, true);
|
|
@@ -80021,8 +80148,8 @@ class SmtpServer {
|
|
|
80021
80148
|
}
|
|
80022
80149
|
this.send(session, "220 Ready to start TLS");
|
|
80023
80150
|
const tlsOptions = {
|
|
80024
|
-
key:
|
|
80025
|
-
cert:
|
|
80151
|
+
key: readFileSync12(this.config.tls.key),
|
|
80152
|
+
cert: readFileSync12(this.config.tls.cert),
|
|
80026
80153
|
isServer: true
|
|
80027
80154
|
};
|
|
80028
80155
|
const tlsSocket = new tls2.TLSSocket(session.socket, tlsOptions);
|
|
@@ -82721,11 +82848,11 @@ init_static_site_external_dns();
|
|
|
82721
82848
|
init_static_site_external_dns();
|
|
82722
82849
|
import process19 from "node:process";
|
|
82723
82850
|
import { existsSync as existsSync16 } from "node:fs";
|
|
82724
|
-
import { join as
|
|
82851
|
+
import { join as join14 } from "node:path";
|
|
82725
82852
|
async function deploySite(config6) {
|
|
82726
82853
|
const start = Date.now();
|
|
82727
82854
|
const sourceDir = config6.sourceDir ?? "dist";
|
|
82728
|
-
if (!existsSync16(
|
|
82855
|
+
if (!existsSync16(join14(sourceDir, "index.html"))) {
|
|
82729
82856
|
return fail(start, `${sourceDir}/ has no index.html — build first.`);
|
|
82730
82857
|
}
|
|
82731
82858
|
if (!process19.env.AWS_ACCESS_KEY_ID || !process19.env.AWS_SECRET_ACCESS_KEY) {
|
|
@@ -82796,8 +82923,8 @@ function fail(start, message) {
|
|
|
82796
82923
|
// src/deploy/serverless-app.ts
|
|
82797
82924
|
init_cloudformation();
|
|
82798
82925
|
await init_dist2();
|
|
82799
|
-
import { existsSync as existsSync17, readdirSync as readdirSync8, readFileSync as
|
|
82800
|
-
import { join as
|
|
82926
|
+
import { existsSync as existsSync17, readdirSync as readdirSync8, readFileSync as readFileSync13, statSync as statSync5 } from "node:fs";
|
|
82927
|
+
import { join as join16, relative as relative6 } from "node:path";
|
|
82801
82928
|
init_s3();
|
|
82802
82929
|
init_cli();
|
|
82803
82930
|
function resolveContext(config6, environment) {
|
|
@@ -82925,7 +83052,7 @@ function contentType(file) {
|
|
|
82925
83052
|
}
|
|
82926
83053
|
function* walk3(dir) {
|
|
82927
83054
|
for (const entry of readdirSync8(dir)) {
|
|
82928
|
-
const full =
|
|
83055
|
+
const full = join16(dir, entry);
|
|
82929
83056
|
if (statSync5(full).isDirectory())
|
|
82930
83057
|
yield* walk3(full);
|
|
82931
83058
|
else
|
|
@@ -82939,7 +83066,7 @@ async function uploadAssets(s32, bucket, dir, prefix) {
|
|
|
82939
83066
|
await s32.putObject({
|
|
82940
83067
|
bucket,
|
|
82941
83068
|
key,
|
|
82942
|
-
body:
|
|
83069
|
+
body: readFileSync13(file),
|
|
82943
83070
|
contentType: contentType(file),
|
|
82944
83071
|
cacheControl: "public, max-age=31536000, immutable"
|
|
82945
83072
|
});
|
|
@@ -82966,11 +83093,15 @@ async function deployServerlessApp(config6, environment, opts = {}) {
|
|
|
82966
83093
|
const lambda2 = new LambdaClient(region);
|
|
82967
83094
|
const isPhp = app.kind === "php";
|
|
82968
83095
|
const imageMode = app.packaging === "image";
|
|
83096
|
+
const resolved = resolveServerlessRuntime(app);
|
|
82969
83097
|
let handlers;
|
|
82970
83098
|
let codeSource;
|
|
82971
83099
|
let artifactSha;
|
|
82972
83100
|
let runtimeLayers;
|
|
82973
83101
|
const parameters = [];
|
|
83102
|
+
if (imageMode && resolved.usesLayer && resolved.layerKind !== "php") {
|
|
83103
|
+
throw new Error(`packaging: 'image' currently supports PHP and managed Node runtimes. ` + `${resolved.kind}${resolved.kind === "node" ? ` ${resolved.version}` : ""} uses a custom runtime — ` + `use the default zip packaging (the runtime layer is built + attached automatically).`);
|
|
83104
|
+
}
|
|
82974
83105
|
if (imageMode) {
|
|
82975
83106
|
step("Building + pushing container image");
|
|
82976
83107
|
const { buildAndPushServerlessImage: buildAndPushServerlessImage2 } = await init_serverless_image().then(() => exports_serverless_image);
|
|
@@ -82993,10 +83124,12 @@ async function deployServerlessApp(config6, environment, opts = {}) {
|
|
|
82993
83124
|
info(`Artifact: ${artifact.sha256.slice(0, 12)} (${(artifact.zip.length / 1024).toFixed(0)} KB)`);
|
|
82994
83125
|
handlers = artifact.handlers;
|
|
82995
83126
|
artifactSha = artifact.sha256;
|
|
82996
|
-
if (
|
|
82997
|
-
|
|
83127
|
+
if (resolved.usesLayer) {
|
|
83128
|
+
const envArn = resolved.layerEnvVar ? process.env[resolved.layerEnvVar] : undefined;
|
|
83129
|
+
runtimeLayers = app.layers ?? (envArn ? [envArn] : undefined);
|
|
82998
83130
|
if (!runtimeLayers?.length) {
|
|
82999
|
-
|
|
83131
|
+
const buildCmd = resolved.layerKind === "php" ? "serverless:build-php-layer" : resolved.layerKind === "bun" ? "serverless:build-bun-layer" : "serverless:build-node-layer";
|
|
83132
|
+
throw new Error(`${resolved.kind} apps on provided.al2023 need a runtime layer. Set environments.<env>.app.layers or the ${resolved.layerEnvVar} env var (build one with \`cloud ${buildCmd}\`)${resolved.kind === "node" ? ", or use a managed Node version (18/20/22)" : ""}.`);
|
|
83000
83133
|
}
|
|
83001
83134
|
}
|
|
83002
83135
|
if (!await s32.bucketExists(artifactBucket)) {
|
|
@@ -83036,15 +83169,15 @@ async function deployServerlessApp(config6, environment, opts = {}) {
|
|
|
83036
83169
|
const outputs = await cfn.getStackOutputs(stackName).catch(() => ({}));
|
|
83037
83170
|
let assetUrl;
|
|
83038
83171
|
if (app.assets) {
|
|
83039
|
-
const
|
|
83040
|
-
if (existsSync17(
|
|
83172
|
+
const assetsDir3 = join16(projectRoot, app.assets);
|
|
83173
|
+
if (existsSync17(assetsDir3)) {
|
|
83041
83174
|
const cdn = outputs.AssetsCdnDomain;
|
|
83042
83175
|
assetUrl = cdn ? `https://${cdn}/${artifactSha}` : undefined;
|
|
83043
83176
|
step(`Syncing assets from ${app.assets}`);
|
|
83044
|
-
const n = await uploadAssets(s32, ctx.assetsBucket,
|
|
83177
|
+
const n = await uploadAssets(s32, ctx.assetsBucket, assetsDir3, artifactSha);
|
|
83045
83178
|
info(`Uploaded ${n} asset(s)${assetUrl ? ` → ${assetUrl}` : ""}`);
|
|
83046
83179
|
} else {
|
|
83047
|
-
warn(`Assets directory not found: ${
|
|
83180
|
+
warn(`Assets directory not found: ${assetsDir3}`);
|
|
83048
83181
|
}
|
|
83049
83182
|
}
|
|
83050
83183
|
step("Resolving secrets");
|
|
@@ -83185,10 +83318,26 @@ await init_dist2();
|
|
|
83185
83318
|
// src/drivers/aws/driver.ts
|
|
83186
83319
|
init_cloudformation();
|
|
83187
83320
|
await init_dist2();
|
|
83188
|
-
import { readFileSync as
|
|
83321
|
+
import { readFileSync as readFileSync14 } from "node:fs";
|
|
83189
83322
|
init_s3();
|
|
83190
83323
|
|
|
83191
83324
|
// src/drivers/shared/package-manager.ts
|
|
83325
|
+
var PANTRY_PACKAGES = {
|
|
83326
|
+
php: "php.net",
|
|
83327
|
+
nginx: "nginx.org",
|
|
83328
|
+
composer: "getcomposer.org",
|
|
83329
|
+
mysql: "mysql.com",
|
|
83330
|
+
mariadb: "mariadb.com/server",
|
|
83331
|
+
postgres: "postgresql.org",
|
|
83332
|
+
redis: "redis.io",
|
|
83333
|
+
memcached: "memcached.org",
|
|
83334
|
+
meilisearch: "meilisearch.com",
|
|
83335
|
+
git: "git-scm.com",
|
|
83336
|
+
certbot: "certbot.eff.org",
|
|
83337
|
+
bun: "bun.sh",
|
|
83338
|
+
node: "nodejs.org",
|
|
83339
|
+
deno: "deno.land"
|
|
83340
|
+
};
|
|
83192
83341
|
var PANTRY_INSTALL_DIR = "/usr/local/bin";
|
|
83193
83342
|
var PANTRY_PROJECT_DIR = "/opt/pantry";
|
|
83194
83343
|
function sh(value) {
|
|
@@ -83228,10 +83377,6 @@ function buildPantryServiceScript(services) {
|
|
|
83228
83377
|
function enabled(spec) {
|
|
83229
83378
|
return spec === true || typeof spec === "object" && spec != null;
|
|
83230
83379
|
}
|
|
83231
|
-
function sq(value) {
|
|
83232
|
-
const escaped = value.split("'").join("'\\''");
|
|
83233
|
-
return `'${escaped}'`;
|
|
83234
|
-
}
|
|
83235
83380
|
function planServices(services) {
|
|
83236
83381
|
const packages = [];
|
|
83237
83382
|
const names = [];
|
|
@@ -83239,7 +83384,7 @@ function planServices(services) {
|
|
|
83239
83384
|
packages.push("mysql.com");
|
|
83240
83385
|
names.push("mysql");
|
|
83241
83386
|
} else if (enabled(services.mariadb)) {
|
|
83242
|
-
packages.push(
|
|
83387
|
+
packages.push(PANTRY_PACKAGES.mariadb);
|
|
83243
83388
|
names.push("mariadb");
|
|
83244
83389
|
}
|
|
83245
83390
|
if (enabled(services.postgres)) {
|
|
@@ -83281,17 +83426,26 @@ function buildDatabaseSetupScript(database, services = {}) {
|
|
|
83281
83426
|
const useMariadb = enabled(services.mariadb) || database.engine === "mariadb";
|
|
83282
83427
|
const useMysql = enabled(services.mysql) || database.engine === "mysql";
|
|
83283
83428
|
if (usePostgres && !useMysql && !useMariadb) {
|
|
83284
|
-
const
|
|
83429
|
+
const pgIdent = (v) => `"${v.replace(/"/g, '""')}"`;
|
|
83430
|
+
const pgLit = (v) => `'${v.replace(/'/g, "''")}'`;
|
|
83285
83431
|
return [
|
|
83286
83432
|
pantryEnvActivation(),
|
|
83287
|
-
|
|
83288
|
-
|
|
83433
|
+
"for i in $(seq 1 30); do pg_isready -h 127.0.0.1 -p 5432 -q && break; sleep 2; done",
|
|
83434
|
+
"psql -h 127.0.0.1 -p 5432 -U postgres <<'TS_CLOUD_PG_EOF'",
|
|
83435
|
+
"DO $$ BEGIN",
|
|
83436
|
+
` IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = ${pgLit(user)}) THEN`,
|
|
83437
|
+
` CREATE ROLE ${pgIdent(user)} LOGIN PASSWORD ${pgLit(pass)};`,
|
|
83438
|
+
" END IF;",
|
|
83439
|
+
"END $$;",
|
|
83440
|
+
`SELECT 'CREATE DATABASE ${pgIdent(name)} OWNER ${pgIdent(user)}' ` + `WHERE NOT EXISTS (SELECT FROM pg_database WHERE datname = ${pgLit(name)})\\gexec`,
|
|
83441
|
+
"TS_CLOUD_PG_EOF"
|
|
83289
83442
|
];
|
|
83290
83443
|
}
|
|
83291
83444
|
const ident = (v) => v.replace(/`/g, "``");
|
|
83292
83445
|
const lit = (v) => v.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
|
|
83293
83446
|
return [
|
|
83294
83447
|
pantryEnvActivation(),
|
|
83448
|
+
"for i in $(seq 1 30); do mysqladmin -h 127.0.0.1 -P 3306 -u root ping 2>/dev/null | grep -q alive && break; sleep 2; done",
|
|
83295
83449
|
"mysql -h 127.0.0.1 -P 3306 -u root <<'TS_CLOUD_SQL_EOF'",
|
|
83296
83450
|
`CREATE DATABASE IF NOT EXISTS \`${ident(name)}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;`,
|
|
83297
83451
|
`CREATE USER IF NOT EXISTS '${lit(user)}'@'%' IDENTIFIED BY '${lit(pass)}';`,
|
|
@@ -83438,9 +83592,9 @@ function buildNginxVhostScript(options) {
|
|
|
83438
83592
|
const out = [];
|
|
83439
83593
|
if (options.auth) {
|
|
83440
83594
|
const file = htpasswdPath(options.siteName);
|
|
83441
|
-
const
|
|
83442
|
-
const pw =
|
|
83443
|
-
const user =
|
|
83595
|
+
const sq = (v) => v.split("'").join("'\\''");
|
|
83596
|
+
const pw = sq(options.auth.password);
|
|
83597
|
+
const user = sq(options.auth.username);
|
|
83444
83598
|
out.push(`TS_CLOUD_HTPASS=$(openssl passwd -apr1 '${pw}')`, `printf '%s:%s\\n' '${user}' "$TS_CLOUD_HTPASS" > ${file}`, `chmod 640 ${file}`, `chown root:www-data ${file} 2>/dev/null || true`);
|
|
83445
83599
|
}
|
|
83446
83600
|
out.push(`cat > ${available} <<'TS_CLOUD_NGINX_EOF'`, vhost.replace(/\n$/, ""), "TS_CLOUD_NGINX_EOF", `ln -sf ${available} ${enabled2}`, "rm -f /etc/nginx/sites-enabled/default", `${NGINX_WRAPPER} -t`, "systemctl reload ts-cloud-nginx 2>/dev/null || systemctl restart ts-cloud-nginx 2>/dev/null || true");
|
|
@@ -84204,7 +84358,7 @@ class AwsDriver {
|
|
|
84204
84358
|
await s32.putObject({
|
|
84205
84359
|
bucket,
|
|
84206
84360
|
key: options.remoteKey,
|
|
84207
|
-
body:
|
|
84361
|
+
body: readFileSync14(options.localPath),
|
|
84208
84362
|
contentType: "application/gzip"
|
|
84209
84363
|
});
|
|
84210
84364
|
return { artifactRef: `s3://${bucket}/${options.remoteKey}` };
|
|
@@ -84311,9 +84465,9 @@ class AwsDriver {
|
|
|
84311
84465
|
|
|
84312
84466
|
// src/drivers/hetzner/driver.ts
|
|
84313
84467
|
await init_dist2();
|
|
84314
|
-
import { existsSync as existsSync18, readFileSync as
|
|
84468
|
+
import { existsSync as existsSync18, readFileSync as readFileSync15 } from "node:fs";
|
|
84315
84469
|
import { homedir as homedir7 } from "node:os";
|
|
84316
|
-
import { join as
|
|
84470
|
+
import { join as join18 } from "node:path";
|
|
84317
84471
|
import { execSync as execSync5 } from "node:child_process";
|
|
84318
84472
|
|
|
84319
84473
|
// src/drivers/hetzner/client.ts
|
|
@@ -84743,10 +84897,10 @@ function matchesTsCloudLabels(labels, slug, environment, role = "app") {
|
|
|
84743
84897
|
|
|
84744
84898
|
// src/drivers/hetzner/state.ts
|
|
84745
84899
|
import { mkdir as mkdir4, readFile, writeFile as writeFile4 } from "node:fs/promises";
|
|
84746
|
-
import { join as
|
|
84900
|
+
import { join as join17 } from "node:path";
|
|
84747
84901
|
var STATE_DIR = ".ts-cloud/state";
|
|
84748
84902
|
function driverStatePath(stackName) {
|
|
84749
|
-
return
|
|
84903
|
+
return join17(process.cwd(), STATE_DIR, `${stackName}.json`);
|
|
84750
84904
|
}
|
|
84751
84905
|
async function readDriverState(stackName) {
|
|
84752
84906
|
try {
|
|
@@ -84758,7 +84912,7 @@ async function readDriverState(stackName) {
|
|
|
84758
84912
|
}
|
|
84759
84913
|
async function writeDriverState(stackName, state) {
|
|
84760
84914
|
const path = driverStatePath(stackName);
|
|
84761
|
-
await mkdir4(
|
|
84915
|
+
await mkdir4(join17(process.cwd(), STATE_DIR), { recursive: true });
|
|
84762
84916
|
await writeFile4(path, `${JSON.stringify(state, null, 2)}
|
|
84763
84917
|
`, "utf8");
|
|
84764
84918
|
}
|
|
@@ -84766,7 +84920,7 @@ async function writeDriverState(stackName, state) {
|
|
|
84766
84920
|
// src/drivers/hetzner/driver.ts
|
|
84767
84921
|
var SSH_MAX_BUFFER = 1024 * 1024 * 256;
|
|
84768
84922
|
function expandHome(path) {
|
|
84769
|
-
return path.startsWith("~/") ?
|
|
84923
|
+
return path.startsWith("~/") ? join18(homedir7(), path.slice(2)) : path;
|
|
84770
84924
|
}
|
|
84771
84925
|
|
|
84772
84926
|
class HetznerDriver {
|
|
@@ -84838,7 +84992,7 @@ class HetznerDriver {
|
|
|
84838
84992
|
}) : undefined;
|
|
84839
84993
|
const provision = buildComputeProvisionScripts(config6);
|
|
84840
84994
|
const baked = compute.bakedImage === true;
|
|
84841
|
-
const
|
|
84995
|
+
const bootstrap2 = buildUbuntuBootstrapScript({
|
|
84842
84996
|
runtime: provision.runtime,
|
|
84843
84997
|
runtimeVersion: provision.runtimeVersion,
|
|
84844
84998
|
systemPackages: compute.systemPackages,
|
|
@@ -84848,7 +85002,7 @@ class HetznerDriver {
|
|
|
84848
85002
|
rpxProvision,
|
|
84849
85003
|
baked
|
|
84850
85004
|
});
|
|
84851
|
-
const userData = wrapCloudInitUserData(
|
|
85005
|
+
const userData = wrapCloudInitUserData(bootstrap2);
|
|
84852
85006
|
const serverType = resolveHetznerServerType(compute.size);
|
|
84853
85007
|
const image = compute.image || config6.hetzner?.image || "ubuntu-24.04";
|
|
84854
85008
|
const firewallName = `${slug}-${environment}-app-fw`;
|
|
@@ -85197,7 +85351,7 @@ class HetznerDriver {
|
|
|
85197
85351
|
if (!existsSync18(this.sshPublicKeyPath)) {
|
|
85198
85352
|
throw new Error(`SSH public key not found at ${this.sshPublicKeyPath}. ts-cloud deploys to Hetzner over SSH and needs a public key to authorize on the server. ` + `Generate one (\`ssh-keygen -t ed25519\`) or set hetzner.sshPrivateKeyPath / HCLOUD_SSH_PUBLIC_KEY.`);
|
|
85199
85353
|
}
|
|
85200
|
-
const publicKey =
|
|
85354
|
+
const publicKey = readFileSync15(this.sshPublicKeyPath, "utf8").trim();
|
|
85201
85355
|
const normalized = normalizeSshPublicKey(publicKey);
|
|
85202
85356
|
const existing = await this.client.listSshKeys();
|
|
85203
85357
|
const match = existing.find((key) => normalizeSshPublicKey(key.public_key) === normalized);
|
|
@@ -86077,6 +86231,7 @@ export {
|
|
|
86077
86231
|
stackDependencyManager,
|
|
86078
86232
|
signRequestAsync,
|
|
86079
86233
|
signRequest,
|
|
86234
|
+
sharedRuntimeLoop,
|
|
86080
86235
|
sha256,
|
|
86081
86236
|
setupDns01Challenge,
|
|
86082
86237
|
setMaintenance,
|
|
@@ -86103,6 +86258,7 @@ export {
|
|
|
86103
86258
|
resolveSiteKind,
|
|
86104
86259
|
resolveSiteDeployTarget,
|
|
86105
86260
|
resolveSiteBucketName,
|
|
86261
|
+
resolveServerlessRuntime,
|
|
86106
86262
|
resolveServerlessAssetBucketName,
|
|
86107
86263
|
resolveServerlessArtifactBucketName,
|
|
86108
86264
|
resolveServerlessAppStackName,
|
|
@@ -86333,8 +86489,10 @@ export {
|
|
|
86333
86489
|
buildSiteDeployScript,
|
|
86334
86490
|
buildPhpRuntimeLayerZip,
|
|
86335
86491
|
buildOptimizationManager,
|
|
86492
|
+
buildNodeRuntimeLayerZip,
|
|
86336
86493
|
buildFunctionEnv,
|
|
86337
86494
|
buildCloudFormationTemplate,
|
|
86495
|
+
buildBunRuntimeLayerZip,
|
|
86338
86496
|
buildAndPushServerlessImage,
|
|
86339
86497
|
bounceComplaintHandler,
|
|
86340
86498
|
blueGreenManager,
|
|
@@ -86439,6 +86597,7 @@ export {
|
|
|
86439
86597
|
MigrationManager,
|
|
86440
86598
|
MetricsManager,
|
|
86441
86599
|
Messaging,
|
|
86600
|
+
MANAGED_NODE_VERSIONS,
|
|
86442
86601
|
LogsManager,
|
|
86443
86602
|
LambdaVersionsManager,
|
|
86444
86603
|
LambdaVPCManager,
|