@stacksjs/ts-cloud 0.7.115 → 0.7.117

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.
Files changed (54) hide show
  1. package/dist/bin/cli.js +478 -476
  2. package/dist/bin/dashboard-server.js +240 -238
  3. package/dist/{chunk-f52r4fsk.js → chunk-adz3ffn0.js} +1 -1
  4. package/dist/{chunk-ck9gzxr0.js → chunk-rfm32pqg.js} +43 -11
  5. package/dist/deploy/index.js +2 -2
  6. package/dist/drivers/index.js +1 -1
  7. package/dist/index.js +2 -2
  8. package/dist/ui/access-denied.html +2 -2
  9. package/dist/ui/account/automation.html +3 -3
  10. package/dist/ui/account/security.html +2 -2
  11. package/dist/ui/applications/compose.html +4 -4
  12. package/dist/ui/applications/new.html +2 -2
  13. package/dist/ui/data/backups.html +4 -4
  14. package/dist/ui/data/services.html +4 -4
  15. package/dist/ui/data/volumes.html +4 -4
  16. package/dist/ui/index.html +3 -3
  17. package/dist/ui/infrastructure/topology.html +4 -4
  18. package/dist/ui/integrations.html +2 -2
  19. package/dist/ui/operations/alerts.html +4 -4
  20. package/dist/ui/operations/configuration.html +4 -4
  21. package/dist/ui/operations/jobs.html +3 -3
  22. package/dist/ui/operations/maintenance.html +3 -3
  23. package/dist/ui/operations/observability.html +4 -4
  24. package/dist/ui/operations/previews.html +4 -4
  25. package/dist/ui/operations/queue.html +4 -4
  26. package/dist/ui/operations/regions.html +3 -3
  27. package/dist/ui/operations/releases.html +3 -3
  28. package/dist/ui/operations/spend.html +4 -4
  29. package/dist/ui/operations/workloads.html +4 -4
  30. package/dist/ui/security.html +2 -2
  31. package/dist/ui/server/actions.html +4 -4
  32. package/dist/ui/server/activity.html +2 -2
  33. package/dist/ui/server/capacity.html +4 -4
  34. package/dist/ui/server/database.html +3 -3
  35. package/dist/ui/server/deployments.html +4 -4
  36. package/dist/ui/server/firewall.html +3 -3
  37. package/dist/ui/server/fleet.html +4 -4
  38. package/dist/ui/server/logs.html +3 -3
  39. package/dist/ui/server/metrics.html +3 -3
  40. package/dist/ui/server/security.html +2 -2
  41. package/dist/ui/server/services.html +2 -2
  42. package/dist/ui/server/sites.html +4 -4
  43. package/dist/ui/server/ssh-keys.html +4 -4
  44. package/dist/ui/server/team.html +4 -4
  45. package/dist/ui/serverless/alarms.html +4 -4
  46. package/dist/ui/serverless/assets.html +2 -2
  47. package/dist/ui/serverless/data.html +4 -4
  48. package/dist/ui/serverless/functions.html +4 -4
  49. package/dist/ui/serverless/logs.html +3 -3
  50. package/dist/ui/serverless/queues.html +3 -3
  51. package/dist/ui/serverless/secrets.html +4 -4
  52. package/dist/ui/serverless/traces.html +4 -4
  53. package/dist/ui/serverless.html +4 -4
  54. package/package.json +3 -3
@@ -50,7 +50,7 @@ import {
50
50
  resolveSiteKind,
51
51
  resolveUiSource,
52
52
  siteInstallBase
53
- } from "./chunk-ck9gzxr0.js";
53
+ } from "./chunk-rfm32pqg.js";
54
54
  import {
55
55
  SSMClient
56
56
  } from "./chunk-7m60qnc8.js";
@@ -2667,8 +2667,8 @@ class AwsDriver {
2667
2667
 
2668
2668
  // src/drivers/hetzner/driver.ts
2669
2669
  import { execFileSync, execSync } from "node:child_process";
2670
- import { randomUUID } from "node:crypto";
2671
- import { existsSync, readFileSync as readFileSync2 } from "node:fs";
2670
+ import { createHash, randomUUID } from "node:crypto";
2671
+ import { createReadStream, existsSync, readFileSync as readFileSync2 } from "node:fs";
2672
2672
 
2673
2673
  // src/drivers/shared/fleet.ts
2674
2674
  function resolveFleetTopology(compute = {}) {
@@ -3209,6 +3209,15 @@ async function writeDriverState(stackName, state) {
3209
3209
  // src/drivers/hetzner/driver.ts
3210
3210
  var SSH_MAX_BUFFER = 1024 * 1024 * 256;
3211
3211
  var SSH_ERROR_OUTPUT_LIMIT = 8000;
3212
+ function shellQuote(value) {
3213
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
3214
+ }
3215
+ async function sha256File(path) {
3216
+ const hash = createHash("sha256");
3217
+ for await (const chunk of createReadStream(path))
3218
+ hash.update(chunk);
3219
+ return hash.digest("hex");
3220
+ }
3212
3221
  function sshErrorOutput(value) {
3213
3222
  const output = Buffer.isBuffer(value) ? value.toString("utf8") : typeof value === "string" ? value : "";
3214
3223
  return output.replace(/(^|\n)(\s*(?:export\s+)?[A-Za-z_][A-Za-z0-9_]*=).*$/gm, "$1$2[redacted]").replace(/encrypted:[A-Za-z0-9+/=]+/g, "encrypted:[redacted]").trim().slice(-SSH_ERROR_OUTPUT_LIMIT);
@@ -3838,11 +3847,34 @@ class HetznerDriver {
3838
3847
  const stagingStem = options.remoteKey.replace(/^releases\//, "").replace(/\.tar\.gz$/, "").replace(/\//g, "-");
3839
3848
  const stagingName = `${stagingStem}-${randomUUID()}.tar.gz`;
3840
3849
  const remotePath = `/var/ts-cloud/staging/${stagingName}`;
3850
+ const digest = await sha256File(options.localPath);
3851
+ const artifactDir = "/var/ts-cloud/artifacts";
3852
+ const cachedPath = `${artifactDir}/${digest}.tar.gz`;
3841
3853
  for (const target of targets) {
3842
3854
  if (!target.publicIp) {
3843
3855
  throw new Error(`Target ${target.id} has no public IP for SCP upload`);
3844
3856
  }
3845
- this.scpToHost(target.publicIp, options.localPath, remotePath);
3857
+ const stageCached = [
3858
+ "set -euo pipefail",
3859
+ `mkdir -p ${shellQuote(artifactDir)} /var/ts-cloud/staging`,
3860
+ `test -s ${shellQuote(cachedPath)}`,
3861
+ `cp -- ${shellQuote(cachedPath)} ${shellQuote(remotePath)}`
3862
+ ].join(`
3863
+ `);
3864
+ try {
3865
+ this.sshExec(target.publicIp, stageCached);
3866
+ continue;
3867
+ } catch {}
3868
+ const uploadPath = `${artifactDir}/.${digest}-${randomUUID()}.tmp`;
3869
+ this.scpToHost(target.publicIp, options.localPath, uploadPath);
3870
+ this.sshExec(target.publicIp, [
3871
+ "set -euo pipefail",
3872
+ `chmod 600 ${shellQuote(uploadPath)}`,
3873
+ `mv -f -- ${shellQuote(uploadPath)} ${shellQuote(cachedPath)}`,
3874
+ `cp -- ${shellQuote(cachedPath)} ${shellQuote(remotePath)}`,
3875
+ `find ${shellQuote(artifactDir)} -type f -name '*.tar.gz' -mtime +7 -delete 2>/dev/null || true`
3876
+ ].join(`
3877
+ `));
3846
3878
  }
3847
3879
  return { artifactRef: remotePath };
3848
3880
  }
@@ -6179,21 +6211,21 @@ function buildGitCheckoutScript(options) {
6179
6211
  const lines = [`rm -rf ${releaseDir}`, `mkdir -p ${releaseDir}`];
6180
6212
  if (repository.strategy === "tag") {
6181
6213
  if (repository.tag) {
6182
- lines.push(`git clone -q --depth 1 --branch ${shellQuote(repository.tag)} ${shellQuote(url)} ${releaseDir}`);
6183
- lines.push(`printf '%s' ${shellQuote(repository.tag)} > ${releaseDir}/.ts-cloud-tag`);
6214
+ lines.push(`git clone -q --depth 1 --branch ${shellQuote2(repository.tag)} ${shellQuote2(url)} ${releaseDir}`);
6215
+ lines.push(`printf '%s' ${shellQuote2(repository.tag)} > ${releaseDir}/.ts-cloud-tag`);
6184
6216
  } else {
6185
6217
  const pattern = repository.tagPattern || DEFAULT_TAG_PATTERN;
6186
- lines.push(`TS_CLOUD_TAG="$(git ls-remote --tags --refs --sort=-v:refname ${shellQuote(url)} ${shellQuote(`refs/tags/${pattern}`)} | head -n1 | sed 's#.*refs/tags/##')"`, `test -n "$TS_CLOUD_TAG" || { echo "no tags matching" ${shellQuote(pattern)} "found in" ${shellQuote(url)} >&2; exit 1; }`, `git clone -q --depth 1 --branch "$TS_CLOUD_TAG" ${shellQuote(url)} ${releaseDir}`, `printf '%s' "$TS_CLOUD_TAG" > ${releaseDir}/.ts-cloud-tag`);
6218
+ lines.push(`TS_CLOUD_TAG="$(git ls-remote --tags --refs --sort=-v:refname ${shellQuote2(url)} ${shellQuote2(`refs/tags/${pattern}`)} | head -n1 | sed 's#.*refs/tags/##')"`, `test -n "$TS_CLOUD_TAG" || { echo "no tags matching" ${shellQuote2(pattern)} "found in" ${shellQuote2(url)} >&2; exit 1; }`, `git clone -q --depth 1 --branch "$TS_CLOUD_TAG" ${shellQuote2(url)} ${releaseDir}`, `printf '%s' "$TS_CLOUD_TAG" > ${releaseDir}/.ts-cloud-tag`);
6187
6219
  }
6188
6220
  } else if (commit) {
6189
- lines.push(`git -C ${releaseDir} init -q`, `git -C ${releaseDir} remote add origin ${shellQuote(url)}`, `git -C ${releaseDir} fetch -q --depth 1 origin ${shellQuote(commit)}`, `git -C ${releaseDir} checkout -q FETCH_HEAD`);
6221
+ lines.push(`git -C ${releaseDir} init -q`, `git -C ${releaseDir} remote add origin ${shellQuote2(url)}`, `git -C ${releaseDir} fetch -q --depth 1 origin ${shellQuote2(commit)}`, `git -C ${releaseDir} checkout -q FETCH_HEAD`);
6190
6222
  } else {
6191
- lines.push(`git clone -q --depth 1 --branch ${shellQuote(branch)} ${shellQuote(url)} ${releaseDir}`);
6223
+ lines.push(`git clone -q --depth 1 --branch ${shellQuote2(branch)} ${shellQuote2(url)} ${releaseDir}`);
6192
6224
  }
6193
6225
  lines.push(`git -C ${releaseDir} rev-parse HEAD > ${releaseDir}/.ts-cloud-sha`);
6194
6226
  return lines;
6195
6227
  }
6196
- function shellQuote(value) {
6228
+ function shellQuote2(value) {
6197
6229
  const escaped = value.split("'").join("'\\''");
6198
6230
  return `'${escaped}'`;
6199
6231
  }
@@ -6382,7 +6414,7 @@ var noopLogger2 = {
6382
6414
  step: () => {},
6383
6415
  success: () => {}
6384
6416
  };
6385
- function shellQuote2(value) {
6417
+ function shellQuote3(value) {
6386
6418
  return `'${value.replace(/'/g, `'"'"'`)}'`;
6387
6419
  }
6388
6420
  async function deploySiteRelease(driver, options, logger = noopLogger2) {
@@ -6914,7 +6946,7 @@ async function renewRpxCertificates(options) {
6914
6946
  return true;
6915
6947
  }
6916
6948
  logger.step("Issuing rpx TLS certificates after DNS reconciliation...");
6917
- const certChecks = certDomains.map((domain) => `test -s ${shellQuote2(`${rpxConfig.productionCerts.certsDir}/${domain}.crt`)}`).join(" && ");
6949
+ const certChecks = certDomains.map((domain) => `test -s ${shellQuote3(`${rpxConfig.productionCerts.certsDir}/${domain}.crt`)}`).join(" && ");
6918
6950
  const result = await driver.runRemoteDeploy({
6919
6951
  targets,
6920
6952
  commands: [
@@ -36,7 +36,7 @@ import {
36
36
  synchronizeDashboardUsers,
37
37
  trackDashboardOperation,
38
38
  verifyStaticApiOrigin
39
- } from "../chunk-f52r4fsk.js";
39
+ } from "../chunk-adz3ffn0.js";
40
40
  import {
41
41
  deleteStaticSite,
42
42
  deployStaticSite,
@@ -81,7 +81,7 @@ import {
81
81
  siteInstallBase,
82
82
  validateDeploymentConfig,
83
83
  verifyAddressRecord
84
- } from "../chunk-ck9gzxr0.js";
84
+ } from "../chunk-rfm32pqg.js";
85
85
  import"../chunk-7m60qnc8.js";
86
86
  import"../chunk-4cjrg98a.js";
87
87
  import"../chunk-rds0sy87.js";
@@ -68,7 +68,7 @@ import {
68
68
  waitForSsh,
69
69
  wrapCloudInitUserData,
70
70
  writeResizeCheckpoint
71
- } from "../chunk-ck9gzxr0.js";
71
+ } from "../chunk-rfm32pqg.js";
72
72
  import"../chunk-7m60qnc8.js";
73
73
  import"../chunk-4cjrg98a.js";
74
74
  import"../chunk-rds0sy87.js";
package/dist/index.js CHANGED
@@ -208,7 +208,7 @@ import {
208
208
  verifyUpdateSignature,
209
209
  webhookEndpoint,
210
210
  zeroCapacity
211
- } from "./chunk-f52r4fsk.js";
211
+ } from "./chunk-adz3ffn0.js";
212
212
  import {
213
213
  deleteStaticSite,
214
214
  deployStaticSite,
@@ -341,7 +341,7 @@ import {
341
341
  waitForCloudInit,
342
342
  waitForSsh,
343
343
  wrapCloudInitUserData
344
- } from "./chunk-ck9gzxr0.js";
344
+ } from "./chunk-rfm32pqg.js";
345
345
  import {
346
346
  EC2Client,
347
347
  SSMClient