@stacksjs/ts-cloud 0.7.116 → 0.7.118

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 (57) hide show
  1. package/dist/bin/cli.js +487 -485
  2. package/dist/bin/dashboard-server.js +240 -238
  3. package/dist/{chunk-ck9gzxr0.js → chunk-kk68jrm3.js} +47 -12
  4. package/dist/{chunk-f52r4fsk.js → chunk-s9m4vfcr.js} +1 -1
  5. package/dist/deploy/index.js +4 -2
  6. package/dist/deploy/site-target.d.ts +2 -0
  7. package/dist/drivers/index.js +1 -1
  8. package/dist/index.js +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 +4 -4
  22. package/dist/ui/operations/maintenance.html +4 -4
  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 +4 -4
  27. package/dist/ui/operations/releases.html +4 -4
  28. package/dist/ui/operations/spend.html +4 -4
  29. package/dist/ui/operations/workloads.html +4 -4
  30. package/dist/ui/server/actions.html +4 -4
  31. package/dist/ui/server/activity.html +2 -2
  32. package/dist/ui/server/capacity.html +4 -4
  33. package/dist/ui/server/database.html +4 -4
  34. package/dist/ui/server/deployments.html +4 -4
  35. package/dist/ui/server/diagnostics.html +2 -2
  36. package/dist/ui/server/firewall.html +4 -4
  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 +4 -4
  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 +3 -3
  43. package/dist/ui/server/ssh-keys.html +3 -3
  44. package/dist/ui/server/team.html +4 -4
  45. package/dist/ui/server/terminal.html +2 -2
  46. package/dist/ui/serverless/alarms.html +4 -4
  47. package/dist/ui/serverless/cost.html +2 -2
  48. package/dist/ui/serverless/data.html +4 -4
  49. package/dist/ui/serverless/firewall.html +2 -2
  50. package/dist/ui/serverless/functions.html +4 -4
  51. package/dist/ui/serverless/logs.html +4 -4
  52. package/dist/ui/serverless/metrics.html +2 -2
  53. package/dist/ui/serverless/queues.html +4 -4
  54. package/dist/ui/serverless/secrets.html +4 -4
  55. package/dist/ui/serverless/traces.html +4 -4
  56. package/dist/ui/serverless.html +4 -4
  57. package/package.json +3 -3
@@ -1480,6 +1480,9 @@ function shipsARelease(site) {
1480
1480
  const kind = resolveSiteKind(site);
1481
1481
  return kind !== "bucket" && kind !== "redirect" && kind !== "proxy";
1482
1482
  }
1483
+ function shipsToBucket(site) {
1484
+ return resolveSiteKind(site) === "bucket";
1485
+ }
1483
1486
  function deployShipsFiles(config, onlySite) {
1484
1487
  if (resolveDeploymentMode(config) === "serverless")
1485
1488
  return true;
@@ -2667,8 +2670,8 @@ class AwsDriver {
2667
2670
 
2668
2671
  // src/drivers/hetzner/driver.ts
2669
2672
  import { execFileSync, execSync } from "node:child_process";
2670
- import { randomUUID } from "node:crypto";
2671
- import { existsSync, readFileSync as readFileSync2 } from "node:fs";
2673
+ import { createHash, randomUUID } from "node:crypto";
2674
+ import { createReadStream, existsSync, readFileSync as readFileSync2 } from "node:fs";
2672
2675
 
2673
2676
  // src/drivers/shared/fleet.ts
2674
2677
  function resolveFleetTopology(compute = {}) {
@@ -3209,6 +3212,15 @@ async function writeDriverState(stackName, state) {
3209
3212
  // src/drivers/hetzner/driver.ts
3210
3213
  var SSH_MAX_BUFFER = 1024 * 1024 * 256;
3211
3214
  var SSH_ERROR_OUTPUT_LIMIT = 8000;
3215
+ function shellQuote(value) {
3216
+ return `'${value.replace(/'/g, `'"'"'`)}'`;
3217
+ }
3218
+ async function sha256File(path) {
3219
+ const hash = createHash("sha256");
3220
+ for await (const chunk of createReadStream(path))
3221
+ hash.update(chunk);
3222
+ return hash.digest("hex");
3223
+ }
3212
3224
  function sshErrorOutput(value) {
3213
3225
  const output = Buffer.isBuffer(value) ? value.toString("utf8") : typeof value === "string" ? value : "";
3214
3226
  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 +3850,34 @@ class HetznerDriver {
3838
3850
  const stagingStem = options.remoteKey.replace(/^releases\//, "").replace(/\.tar\.gz$/, "").replace(/\//g, "-");
3839
3851
  const stagingName = `${stagingStem}-${randomUUID()}.tar.gz`;
3840
3852
  const remotePath = `/var/ts-cloud/staging/${stagingName}`;
3853
+ const digest = await sha256File(options.localPath);
3854
+ const artifactDir = "/var/ts-cloud/artifacts";
3855
+ const cachedPath = `${artifactDir}/${digest}.tar.gz`;
3841
3856
  for (const target of targets) {
3842
3857
  if (!target.publicIp) {
3843
3858
  throw new Error(`Target ${target.id} has no public IP for SCP upload`);
3844
3859
  }
3845
- this.scpToHost(target.publicIp, options.localPath, remotePath);
3860
+ const stageCached = [
3861
+ "set -euo pipefail",
3862
+ `mkdir -p ${shellQuote(artifactDir)} /var/ts-cloud/staging`,
3863
+ `test -s ${shellQuote(cachedPath)}`,
3864
+ `cp -- ${shellQuote(cachedPath)} ${shellQuote(remotePath)}`
3865
+ ].join(`
3866
+ `);
3867
+ try {
3868
+ this.sshExec(target.publicIp, stageCached);
3869
+ continue;
3870
+ } catch {}
3871
+ const uploadPath = `${artifactDir}/.${digest}-${randomUUID()}.tmp`;
3872
+ this.scpToHost(target.publicIp, options.localPath, uploadPath);
3873
+ this.sshExec(target.publicIp, [
3874
+ "set -euo pipefail",
3875
+ `chmod 600 ${shellQuote(uploadPath)}`,
3876
+ `mv -f -- ${shellQuote(uploadPath)} ${shellQuote(cachedPath)}`,
3877
+ `cp -- ${shellQuote(cachedPath)} ${shellQuote(remotePath)}`,
3878
+ `find ${shellQuote(artifactDir)} -type f -name '*.tar.gz' -mtime +7 -delete 2>/dev/null || true`
3879
+ ].join(`
3880
+ `));
3846
3881
  }
3847
3882
  return { artifactRef: remotePath };
3848
3883
  }
@@ -6179,21 +6214,21 @@ function buildGitCheckoutScript(options) {
6179
6214
  const lines = [`rm -rf ${releaseDir}`, `mkdir -p ${releaseDir}`];
6180
6215
  if (repository.strategy === "tag") {
6181
6216
  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`);
6217
+ lines.push(`git clone -q --depth 1 --branch ${shellQuote2(repository.tag)} ${shellQuote2(url)} ${releaseDir}`);
6218
+ lines.push(`printf '%s' ${shellQuote2(repository.tag)} > ${releaseDir}/.ts-cloud-tag`);
6184
6219
  } else {
6185
6220
  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`);
6221
+ 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
6222
  }
6188
6223
  } 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`);
6224
+ 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
6225
  } else {
6191
- lines.push(`git clone -q --depth 1 --branch ${shellQuote(branch)} ${shellQuote(url)} ${releaseDir}`);
6226
+ lines.push(`git clone -q --depth 1 --branch ${shellQuote2(branch)} ${shellQuote2(url)} ${releaseDir}`);
6192
6227
  }
6193
6228
  lines.push(`git -C ${releaseDir} rev-parse HEAD > ${releaseDir}/.ts-cloud-sha`);
6194
6229
  return lines;
6195
6230
  }
6196
- function shellQuote(value) {
6231
+ function shellQuote2(value) {
6197
6232
  const escaped = value.split("'").join("'\\''");
6198
6233
  return `'${escaped}'`;
6199
6234
  }
@@ -6382,7 +6417,7 @@ var noopLogger2 = {
6382
6417
  step: () => {},
6383
6418
  success: () => {}
6384
6419
  };
6385
- function shellQuote2(value) {
6420
+ function shellQuote3(value) {
6386
6421
  return `'${value.replace(/'/g, `'"'"'`)}'`;
6387
6422
  }
6388
6423
  async function deploySiteRelease(driver, options, logger = noopLogger2) {
@@ -6914,7 +6949,7 @@ async function renewRpxCertificates(options) {
6914
6949
  return true;
6915
6950
  }
6916
6951
  logger.step("Issuing rpx TLS certificates after DNS reconciliation...");
6917
- const certChecks = certDomains.map((domain) => `test -s ${shellQuote2(`${rpxConfig.productionCerts.certsDir}/${domain}.crt`)}`).join(" && ");
6952
+ const certChecks = certDomains.map((domain) => `test -s ${shellQuote3(`${rpxConfig.productionCerts.certsDir}/${domain}.crt`)}`).join(" && ");
6918
6953
  const result = await driver.runRemoteDeploy({
6919
6954
  targets,
6920
6955
  commands: [
@@ -7023,4 +7058,4 @@ function buildCloudFrontOriginConfig(options) {
7023
7058
  CustomErrorResponses: { Quantity: 0 }
7024
7059
  };
7025
7060
  }
7026
- export { collectServerDnsDomains, removeStaleServerAddressRecords, normalizePublicIpv6, IPV6_EXCLUDED_HOST_LABELS, hostAcceptsIpv6, reconcileAddressRecords, verifyAddressRecord, PANTRY_PROJECT_DIR, buildPantryBootstrapScript, buildVitessProvisionScript, pgAdminCommand, BACKUP_RUNNER_PATH, buildBackupRestoreScript, siteInstallBase, isPhpSite, resolveProxyUpstreams, hasProxyUpstream, resolveSiteDeployTarget, resolveSiteKind, validateDeploymentConfig, shipsARelease, deployShipsFiles, DEFAULT_RPX_CERTS_DIR, normalizeRoutePath, deriveRouteId, buildRpxConfig, buildRpxLbConfig, renderRpxLauncher, RPX_DIR, RPX_LAUNCHER_PATH, RPX_SERVICE_NAME, buildRpxProvisionScript, buildRpxFragmentRefreshScript, buildUbuntuBootstrapScript, AwsDriver, resolveHetznerLocation, HetznerClient, resolveHetznerApiToken2 as resolveHetznerApiToken, normalizeSshPublicKey, wrapCloudInitUserData, HetznerDriver, LocalBoxDriver, isBoxMode, createCloudDriver, CloudDriverFactory, cloudDrivers, planHetznerServerResize, isHetznerCapacityError, executeHetznerServerResize, buildSshArgs, sshExec, sshExecOrThrow, scpUpload, waitForSsh, waitForCloudInit, collectHetznerResizeManifest, prepareHetznerResize, verifyHetznerResize, resolveHetznerHostOptimizationPlan, buildHetznerHostOptimizationScript, applyHetznerHostOptimization, collectHetznerHostOptimizationReport, verifyHetznerHostOptimization, resizeCheckpointPath, resizeLockPath, readResizeCheckpoint, writeResizeCheckpoint, acquireResizeLock, ensureSshKey, ensureFirewall, ensureServer, serverPublicIpv4, UBUNTU_2404_AMI_PARAM, buildBoxUserData, HetznerBoxProvisioner, AwsBoxProvisioner, createBoxProvisioner, releasePaths, buildRollbackScript, resolveExecStart, buildSiteDeployScript, buildStaticSiteDeployScript, releaseTarballTmpPath, buildAwsArtifactFetch, buildLocalArtifactFetch, buildHostCleanupScript, MANAGEMENT_DASHBOARD_SITE, dashboardCredentialsFile, resolveDashboardAuth, resolveUiSource, ensureManagementDashboard, buildManagementDashboardArtifact, resolveSiteFramework, deploySiteRelease, deployAllComputeSites, reloadRpxGateway, renewRpxCertificates, MANAGED_CACHE_POLICY_OPTIMIZED, MANAGED_CACHE_POLICY_DISABLED, MANAGED_ORIGIN_REQUEST_POLICY_ALL_VIEWER, buildCloudFrontOriginConfig };
7061
+ export { collectServerDnsDomains, removeStaleServerAddressRecords, normalizePublicIpv6, IPV6_EXCLUDED_HOST_LABELS, hostAcceptsIpv6, reconcileAddressRecords, verifyAddressRecord, PANTRY_PROJECT_DIR, buildPantryBootstrapScript, buildVitessProvisionScript, pgAdminCommand, BACKUP_RUNNER_PATH, buildBackupRestoreScript, siteInstallBase, isPhpSite, resolveProxyUpstreams, hasProxyUpstream, resolveSiteDeployTarget, resolveSiteKind, validateDeploymentConfig, shipsARelease, shipsToBucket, deployShipsFiles, DEFAULT_RPX_CERTS_DIR, normalizeRoutePath, deriveRouteId, buildRpxConfig, buildRpxLbConfig, renderRpxLauncher, RPX_DIR, RPX_LAUNCHER_PATH, RPX_SERVICE_NAME, buildRpxProvisionScript, buildRpxFragmentRefreshScript, buildUbuntuBootstrapScript, AwsDriver, resolveHetznerLocation, HetznerClient, resolveHetznerApiToken2 as resolveHetznerApiToken, normalizeSshPublicKey, wrapCloudInitUserData, HetznerDriver, LocalBoxDriver, isBoxMode, createCloudDriver, CloudDriverFactory, cloudDrivers, planHetznerServerResize, isHetznerCapacityError, executeHetznerServerResize, buildSshArgs, sshExec, sshExecOrThrow, scpUpload, waitForSsh, waitForCloudInit, collectHetznerResizeManifest, prepareHetznerResize, verifyHetznerResize, resolveHetznerHostOptimizationPlan, buildHetznerHostOptimizationScript, applyHetznerHostOptimization, collectHetznerHostOptimizationReport, verifyHetznerHostOptimization, resizeCheckpointPath, resizeLockPath, readResizeCheckpoint, writeResizeCheckpoint, acquireResizeLock, ensureSshKey, ensureFirewall, ensureServer, serverPublicIpv4, UBUNTU_2404_AMI_PARAM, buildBoxUserData, HetznerBoxProvisioner, AwsBoxProvisioner, createBoxProvisioner, releasePaths, buildRollbackScript, resolveExecStart, buildSiteDeployScript, buildStaticSiteDeployScript, releaseTarballTmpPath, buildAwsArtifactFetch, buildLocalArtifactFetch, buildHostCleanupScript, MANAGEMENT_DASHBOARD_SITE, dashboardCredentialsFile, resolveDashboardAuth, resolveUiSource, ensureManagementDashboard, buildManagementDashboardArtifact, resolveSiteFramework, deploySiteRelease, deployAllComputeSites, reloadRpxGateway, renewRpxCertificates, MANAGED_CACHE_POLICY_OPTIMIZED, MANAGED_CACHE_POLICY_DISABLED, MANAGED_ORIGIN_REQUEST_POLICY_ALL_VIEWER, buildCloudFrontOriginConfig };
@@ -50,7 +50,7 @@ import {
50
50
  resolveSiteKind,
51
51
  resolveUiSource,
52
52
  siteInstallBase
53
- } from "./chunk-ck9gzxr0.js";
53
+ } from "./chunk-kk68jrm3.js";
54
54
  import {
55
55
  SSMClient
56
56
  } from "./chunk-7m60qnc8.js";
@@ -36,7 +36,7 @@ import {
36
36
  synchronizeDashboardUsers,
37
37
  trackDashboardOperation,
38
38
  verifyStaticApiOrigin
39
- } from "../chunk-f52r4fsk.js";
39
+ } from "../chunk-s9m4vfcr.js";
40
40
  import {
41
41
  deleteStaticSite,
42
42
  deployStaticSite,
@@ -78,10 +78,11 @@ import {
78
78
  resolveSiteKind,
79
79
  resolveUiSource,
80
80
  shipsARelease,
81
+ shipsToBucket,
81
82
  siteInstallBase,
82
83
  validateDeploymentConfig,
83
84
  verifyAddressRecord
84
- } from "../chunk-ck9gzxr0.js";
85
+ } from "../chunk-kk68jrm3.js";
85
86
  import"../chunk-7m60qnc8.js";
86
87
  import"../chunk-4cjrg98a.js";
87
88
  import"../chunk-rds0sy87.js";
@@ -100,6 +101,7 @@ export {
100
101
  synchronizeDashboardUsers,
101
102
  startLocalDashboardServer,
102
103
  siteInstallBase,
104
+ shipsToBucket,
103
105
  shipsARelease,
104
106
  setMaintenance,
105
107
  sanitizeCloudConfig,
@@ -97,6 +97,8 @@ export declare function validateDeploymentConfig(config: CloudConfig): Deploymen
97
97
  * regenerated from the full `sites` model, not from this list.
98
98
  */
99
99
  export declare function shipsARelease(site: SiteConfig): boolean;
100
+ /** Does the static object-storage pipeline own this site? */
101
+ export declare function shipsToBucket(site: SiteConfig): boolean;
100
102
  /**
101
103
  * Does this deploy put any file from the working tree onto a server or into a
102
104
  * bucket?
@@ -68,7 +68,7 @@ import {
68
68
  waitForSsh,
69
69
  wrapCloudInitUserData,
70
70
  writeResizeCheckpoint
71
- } from "../chunk-ck9gzxr0.js";
71
+ } from "../chunk-kk68jrm3.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-s9m4vfcr.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-kk68jrm3.js";
345
345
  import {
346
346
  EC2Client,
347
347
  SSMClient