@stacksjs/ts-cloud 0.7.90 → 0.7.91

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 (55) hide show
  1. package/dist/bin/cli.js +308 -308
  2. package/dist/bin/dashboard-server.js +245 -245
  3. package/dist/{chunk-gcehnzty.js → chunk-3scf213a.js} +37 -8
  4. package/dist/{chunk-hcdewpt6.js → chunk-j1kkmmrz.js} +1 -1
  5. package/dist/deploy/index.js +2 -2
  6. package/dist/drivers/hetzner/driver.d.ts +7 -0
  7. package/dist/drivers/index.js +1 -1
  8. package/dist/index.js +2 -2
  9. package/dist/ui/access-denied.html +2 -2
  10. package/dist/ui/account/automation.html +3 -3
  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/integrations.html +2 -2
  18. package/dist/ui/operations/alerts.html +4 -4
  19. package/dist/ui/operations/configuration.html +4 -4
  20. package/dist/ui/operations/jobs.html +4 -4
  21. package/dist/ui/operations/maintenance.html +3 -3
  22. package/dist/ui/operations/observability.html +4 -4
  23. package/dist/ui/operations/previews.html +4 -4
  24. package/dist/ui/operations/queue.html +4 -4
  25. package/dist/ui/operations/regions.html +4 -4
  26. package/dist/ui/operations/releases.html +3 -3
  27. package/dist/ui/operations/workloads.html +4 -4
  28. package/dist/ui/security.html +2 -2
  29. package/dist/ui/server/actions.html +3 -3
  30. package/dist/ui/server/activity.html +2 -2
  31. package/dist/ui/server/capacity.html +4 -4
  32. package/dist/ui/server/database.html +4 -4
  33. package/dist/ui/server/deployments.html +4 -4
  34. package/dist/ui/server/diagnostics.html +2 -2
  35. package/dist/ui/server/firewall.html +3 -3
  36. package/dist/ui/server/fleet.html +4 -4
  37. package/dist/ui/server/logs.html +3 -3
  38. package/dist/ui/server/metrics.html +4 -4
  39. package/dist/ui/server/services.html +2 -2
  40. package/dist/ui/server/sites.html +4 -4
  41. package/dist/ui/server/ssh-keys.html +4 -4
  42. package/dist/ui/server/team.html +4 -4
  43. package/dist/ui/serverless/alarms.html +4 -4
  44. package/dist/ui/serverless/assets.html +2 -2
  45. package/dist/ui/serverless/cost.html +2 -2
  46. package/dist/ui/serverless/data.html +4 -4
  47. package/dist/ui/serverless/firewall.html +2 -2
  48. package/dist/ui/serverless/functions.html +4 -4
  49. package/dist/ui/serverless/logs.html +4 -4
  50. package/dist/ui/serverless/metrics.html +2 -2
  51. package/dist/ui/serverless/queues.html +4 -4
  52. package/dist/ui/serverless/secrets.html +4 -4
  53. package/dist/ui/serverless/traces.html +3 -3
  54. package/dist/ui/serverless.html +4 -4
  55. package/package.json +3 -3
@@ -2649,11 +2649,17 @@ class HetznerDriver {
2649
2649
  sshPublicKeyPath;
2650
2650
  sshUser;
2651
2651
  location;
2652
+ stateOnly;
2652
2653
  waitForBoot;
2653
2654
  bootWait;
2654
2655
  constructor(options = {}) {
2656
+ const apiToken = resolveHetznerApiToken(options.apiToken);
2657
+ this.stateOnly = !options.client && !apiToken && options.allowStateOnly === true;
2658
+ if (!options.client && !apiToken && !this.stateOnly) {
2659
+ throw new Error("Hetzner API token required. Set hetzner.apiToken in cloud.config.ts or HCLOUD_TOKEN / HETZNER_API_TOKEN.");
2660
+ }
2655
2661
  this.client = options.client ?? new HetznerClient({
2656
- apiToken: resolveHetznerApiToken2(options.apiToken)
2662
+ apiToken: apiToken ?? ""
2657
2663
  });
2658
2664
  const settings = resolveHetznerSettings(undefined, {
2659
2665
  sshPrivateKeyPath: options.sshPrivateKeyPath,
@@ -3259,7 +3265,6 @@ class HetznerDriver {
3259
3265
  return { artifactRef: remotePath };
3260
3266
  }
3261
3267
  async findComputeTargets(options) {
3262
- const servers = await this.client.listServers();
3263
3268
  const role = options.role || "app";
3264
3269
  const toTarget = (server) => ({
3265
3270
  id: String(server.id),
@@ -3274,25 +3279,48 @@ class HetznerDriver {
3274
3279
  const pinnedIds = [
3275
3280
  ...new Set(role === "app" ? [state?.serverId, ...state?.appServerIds ?? []] : role === "lb" ? [state?.lbServerId] : [state?.servicesServerId])
3276
3281
  ].filter((id) => typeof id === "number");
3282
+ if (this.stateOnly) {
3283
+ if (pinnedIds.length > 0 && state?.publicIp) {
3284
+ return pinnedIds.map((id) => ({
3285
+ id: String(id),
3286
+ name: id === state.serverId ? state.serverName : undefined,
3287
+ publicIp: state.publicIp,
3288
+ publicIpv6: state.publicIpv6,
3289
+ status: "running"
3290
+ }));
3291
+ }
3292
+ if (role !== "app")
3293
+ return [];
3294
+ throw new Error(`Hetzner API token required because '${options.stackName ?? `${options.slug}-${options.environment}`}' has no complete local compute state pin.`);
3295
+ }
3296
+ const servers2 = await this.client.listServers();
3277
3297
  if (pinnedIds.length > 0) {
3278
3298
  const pinned = [];
3279
3299
  for (const id of pinnedIds) {
3280
- const server = servers.find((candidate) => candidate.id === id) ?? await this.tryGetServer(id);
3300
+ const server = servers2.find((candidate) => candidate.id === id) ?? await this.tryGetServer(id);
3281
3301
  if (server && server.status !== "off")
3282
3302
  pinned.push(server);
3283
3303
  }
3284
3304
  if (pinned.length > 0)
3285
3305
  return pinned.map(toTarget);
3286
3306
  }
3307
+ const exact2 = servers2.filter((server) => matchesTsCloudLabels(server.labels, options.slug, options.environment, role));
3308
+ if (exact2.length > 0)
3309
+ return exact2.map(toTarget);
3310
+ if (role === "app") {
3311
+ const candidates = servers2.filter((server) => server.status !== "off" && server.labels?.[`${TS_CLOUD_LABEL_PREFIX}/managed-by`] === "ts-cloud" && server.labels?.[`${TS_CLOUD_LABEL_PREFIX}/environment`] === options.environment && server.labels?.[`${TS_CLOUD_LABEL_PREFIX}/role`] === "app");
3312
+ if (candidates.length === 1)
3313
+ return candidates.map(toTarget);
3314
+ }
3315
+ return [];
3316
+ }
3317
+ if (this.stateOnly) {
3318
+ throw new Error(`Hetzner API token required to discover '${role}' compute targets.`);
3287
3319
  }
3320
+ const servers = await this.client.listServers();
3288
3321
  const exact = servers.filter((server) => matchesTsCloudLabels(server.labels, options.slug, options.environment, role));
3289
3322
  if (exact.length > 0)
3290
3323
  return exact.map(toTarget);
3291
- if (role === "app") {
3292
- const candidates = servers.filter((server) => server.status !== "off" && server.labels?.[`${TS_CLOUD_LABEL_PREFIX}/managed-by`] === "ts-cloud" && server.labels?.[`${TS_CLOUD_LABEL_PREFIX}/environment`] === options.environment && server.labels?.[`${TS_CLOUD_LABEL_PREFIX}/role`] === "app");
3293
- if (candidates.length === 1)
3294
- return candidates.map(toTarget);
3295
- }
3296
3324
  return [];
3297
3325
  }
3298
3326
  async attachToComputeInfrastructure(ownerSlug, config, environment) {
@@ -3604,6 +3632,7 @@ function createCloudDriver(options) {
3604
3632
  case "hetzner":
3605
3633
  return new HetznerDriver({
3606
3634
  apiToken: options.config.hetzner?.apiToken,
3635
+ allowStateOnly: Boolean(options.config.cloud?.attachTo),
3607
3636
  sshPrivateKeyPath: options.config.hetzner?.sshPrivateKeyPath,
3608
3637
  sshPublicKeyPath: options.config.hetzner?.sshPublicKeyPath,
3609
3638
  sshUser: options.config.hetzner?.sshUser,
@@ -45,7 +45,7 @@ import {
45
45
  resolveSiteKind,
46
46
  resolveUiSource,
47
47
  siteInstallBase
48
- } from "./chunk-gcehnzty.js";
48
+ } from "./chunk-3scf213a.js";
49
49
  import {
50
50
  artifactKey,
51
51
  buildCloudFormationTemplate,
@@ -30,7 +30,7 @@ import {
30
30
  synchronizeDashboardUsers,
31
31
  trackDashboardOperation,
32
32
  verifyStaticApiOrigin
33
- } from "../chunk-hcdewpt6.js";
33
+ } from "../chunk-j1kkmmrz.js";
34
34
  import {
35
35
  deleteStaticSite,
36
36
  deployStaticSite,
@@ -70,7 +70,7 @@ import {
70
70
  siteInstallBase,
71
71
  validateDeploymentConfig,
72
72
  verifyAddressRecord
73
- } from "../chunk-gcehnzty.js";
73
+ } from "../chunk-3scf213a.js";
74
74
  import"../chunk-hmehkeqx.js";
75
75
  import"../chunk-7m60qnc8.js";
76
76
  import"../chunk-4cjrg98a.js";
@@ -3,6 +3,12 @@ import { HetznerClient } from './client';
3
3
  export declare function formatSshFailure(error: unknown): string;
4
4
  export interface HetznerDriverOptions {
5
5
  apiToken?: string;
6
+ /**
7
+ * Permit SSH-only deploy operations to use an existing local state pin when
8
+ * no provider token is available. Intended for tenants attached to compute
9
+ * owned and provisioned by another project.
10
+ */
11
+ allowStateOnly?: boolean;
6
12
  sshPrivateKeyPath?: string;
7
13
  sshPublicKeyPath?: string;
8
14
  sshUser?: string;
@@ -38,6 +44,7 @@ export declare class HetznerDriver implements CloudDriver {
38
44
  private sshPublicKeyPath;
39
45
  private sshUser;
40
46
  private location;
47
+ private stateOnly;
41
48
  private waitForBoot;
42
49
  private bootWait;
43
50
  constructor(options?: HetznerDriverOptions);
@@ -68,7 +68,7 @@ import {
68
68
  waitForSsh,
69
69
  wrapCloudInitUserData,
70
70
  writeResizeCheckpoint
71
- } from "../chunk-gcehnzty.js";
71
+ } from "../chunk-3scf213a.js";
72
72
  import"../chunk-hmehkeqx.js";
73
73
  import"../chunk-7m60qnc8.js";
74
74
  import"../chunk-4cjrg98a.js";
package/dist/index.js CHANGED
@@ -283,7 +283,7 @@ import {
283
283
  volumeCapabilities,
284
284
  webhookEndpoint,
285
285
  zeroCapacity
286
- } from "./chunk-hcdewpt6.js";
286
+ } from "./chunk-j1kkmmrz.js";
287
287
  import {
288
288
  deleteStaticSite,
289
289
  deployStaticSite,
@@ -403,7 +403,7 @@ import {
403
403
  waitForCloudInit,
404
404
  waitForSsh,
405
405
  wrapCloudInitUserData
406
- } from "./chunk-gcehnzty.js";
406
+ } from "./chunk-3scf213a.js";
407
407
  import {
408
408
  ABTestManager,
409
409
  AI,