@stacksjs/ts-cloud 0.5.16 → 0.5.18

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.
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Deploy lifecycle hooks (`config.hooks`): `beforeBuild` / `afterBuild` /
3
+ * `beforeDeploy` / `afterDeploy`. Each hook is either a shell command (string,
4
+ * run on the deploying machine) or an async function called with the config.
5
+ * Mirrors Forge/Envoyer-style deploy hooks, but they run locally around the
6
+ * `cloud deploy` lifecycle (server-side steps belong in `site.deployScript`).
7
+ */
8
+ import type { CloudConfig } from '@ts-cloud/core';
9
+ export type LifecycleHook = string | ((config: CloudConfig) => void | Promise<void>) | undefined;
10
+ export type HookName = 'beforeBuild' | 'afterBuild' | 'beforeDeploy' | 'afterDeploy';
11
+ export interface HookLogger {
12
+ step?: (message: string) => void;
13
+ error?: (message: string) => void;
14
+ }
15
+ /**
16
+ * Run a single lifecycle hook. A string is executed as a shell command (inherits
17
+ * stdio, runs in `cwd`); a function is awaited. Throws if a string hook exits
18
+ * non-zero so the caller can abort the deploy. No-op when the hook is unset.
19
+ */
20
+ export declare function runHook(hook: LifecycleHook, config: CloudConfig, name: HookName, logger?: HookLogger, cwd?: string): Promise<void>;
21
+ /**
22
+ * Run a named hook from `config.hooks`, returning false if a string hook fails
23
+ * (so the deploy command can stop). Logs the failure via `logger.error`.
24
+ */
25
+ export declare function runConfigHook(config: CloudConfig, name: HookName, logger?: HookLogger, cwd?: string): Promise<boolean>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Quick Deploy (Forge's push-to-deploy): generate a CI pipeline for the app's
3
+ * git provider that runs `cloud deploy` on push to the deploy branch. ts-cloud
4
+ * deploys from the operator's machine/CI (git-clone-on-server), so the modern
5
+ * equivalent of Forge's deploy webhook is a provider-native pipeline rather than
6
+ * an inbound webhook — keyed off `site.repository.provider`.
7
+ */
8
+ import type { CloudConfig } from '@ts-cloud/core';
9
+ export interface QuickDeployFile {
10
+ /** Repo-relative path to write the pipeline to. */
11
+ path: string;
12
+ /** File contents. */
13
+ content: string;
14
+ /** Resolved git provider. */
15
+ provider: 'github' | 'gitlab' | 'bitbucket';
16
+ /** Branch the pipeline triggers on. */
17
+ branch: string;
18
+ }
19
+ /**
20
+ * Build the CI pipeline file for the config's git provider, or `null` when no
21
+ * site has a github/gitlab/bitbucket repository (the `custom` provider and
22
+ * webhook-less setups have no native pipeline to generate). `environment`
23
+ * selects which `cloud deploy <env>` runs.
24
+ */
25
+ export declare function buildQuickDeployCi(config: CloudConfig, environment?: string): QuickDeployFile | null;
@@ -108,7 +108,7 @@ export declare class HetznerDriver implements CloudDriver {
108
108
  * `/dev/null`): the box is identified + trusted via the Hetzner API, and
109
109
  * providers recycle public IPs, so a stale `known_hosts` entry from a prior
110
110
  * (now-deleted) server would otherwise abort the deploy with
111
- * "REMOTE HOST IDENTIFICATION HAS CHANGED".
111
+ * `REMOTE HOST IDENTIFICATION HAS CHANGED`.
112
112
  */
113
113
  private static readonly SSH_HOST_KEY_OPTS;
114
114
  private sshBaseArgs;
@@ -26,3 +26,15 @@ export interface BackupProvisionOptions {
26
26
  * disabled. Assumes the box can install Bun (to run `ts-backups`).
27
27
  */
28
28
  export declare function buildBackupProvisionScript(options: BackupProvisionOptions): string[];
29
+ export interface BackupRestoreOptions {
30
+ /** Specific dump file on the box (absolute path). Default: newest matching dump. */
31
+ from?: string;
32
+ }
33
+ /**
34
+ * Build the commands that restore a database from a ts-backups dump on the box.
35
+ * With no `from`, the newest dump under {@link BACKUP_OUTPUT_DIR} matching the
36
+ * database name is used. Handles plain `.sql` and gzipped `.sql.gz`. MySQL/
37
+ * MariaDB restore over the root unix socket; Postgres via `psql -U postgres`.
38
+ * Returns `[]` when the database has no name.
39
+ */
40
+ export declare function buildBackupRestoreScript(database: DatabaseConfig | undefined, options?: BackupRestoreOptions): string[];
@@ -7,7 +7,7 @@
7
7
  * with the shared generators, and runs it on every box — mirroring how
8
8
  * {@link import('./compute-deploy').deploySiteRelease} drives a deploy.
9
9
  */
10
- import type { CloudDriver, EnvironmentType, RemoteDeployInstanceResult } from '@ts-cloud/core';
10
+ import type { CloudDriver, DatabaseConfig, EnvironmentType, RemoteDeployInstanceResult } from '@ts-cloud/core';
11
11
  export interface ComputeOpsLogger {
12
12
  info(message: string): void;
13
13
  warn(message: string): void;
@@ -57,3 +57,12 @@ export declare function runComputeRecipe(ctx: ComputeOpsContext, options: {
57
57
  script: string[];
58
58
  user?: string;
59
59
  }): Promise<ComputeOpsResult>;
60
+ /**
61
+ * Restore a database from a ts-backups dump on the box (Forge's backup restore).
62
+ * Runs the restore on the project's servers; with no `from`, the newest matching
63
+ * dump is used. Returns per-server output.
64
+ */
65
+ export declare function restoreDatabaseBackup(ctx: ComputeOpsContext, options: {
66
+ database: DatabaseConfig | undefined;
67
+ from?: string;
68
+ }): Promise<ComputeOpsResult>;
@@ -40,6 +40,14 @@ export interface LaravelDeployOptions {
40
40
  * Composer `auth.json` and/or `.npmrc`. Quoted heredocs keep tokens literal.
41
41
  */
42
42
  export declare function buildCredentialFiles(releaseDir: string, creds?: SiteCredentialsConfig): string[];
43
+ /**
44
+ * Post-deploy health check (Forge-style): once the release is live, hit the
45
+ * site through nginx on localhost (with the site's `Host` header) and fail the
46
+ * deploy if it doesn't return 2xx/3xx within a few retries. A redirect (e.g.
47
+ * the certbot HTTP→HTTPS 301) counts as healthy — nginx is up and routing.
48
+ * Returns `[]` when no `healthCheck.path` (or domain) is configured.
49
+ */
50
+ export declare function buildHealthCheckScript(site: SiteConfig): string[];
43
51
  /**
44
52
  * Build the full remote shell script for a PHP/Laravel git deploy, expanding the
45
53
  * release macros. Requires `site.repository` to be set.
@@ -1,15 +1,23 @@
1
1
  /**
2
- * Lightweight server monitoring, mirroring Forge's basic server metrics.
2
+ * Lightweight server monitoring + resource alerts, mirroring Forge's server
3
+ * metrics and notifications.
3
4
  *
4
- * Dependency-free: a small shell collector reads load average, memory, and
5
- * disk usage and writes a JSON snapshot to `/var/lib/ts-cloud/metrics.json`
6
- * every minute via a systemd timer. The ts-cloud UI (and any operator tooling)
7
- * can read that file for at-a-glance server health.
5
+ * Dependency-free: a small shell collector reads load average, memory, swap,
6
+ * disk, uptime, network throughput, and per-service TCP health, then writes a
7
+ * JSON snapshot to {@link METRICS_PATH} every minute via a systemd timer. The
8
+ * ts-cloud UI (and any operator tooling) reads that file for at-a-glance health.
9
+ *
10
+ * When alert thresholds are configured (CPU load per core, memory %, disk %),
11
+ * the collector calls the on-box `ts-cloud-notify` helper on each OK→alert
12
+ * transition (and once more on recovery), so channels aren't spammed every
13
+ * minute the box stays hot.
8
14
  */
15
+ import type { ComputeMonitoringConfig } from '@ts-cloud/core';
9
16
  /** Where the metrics snapshot is written. */
10
17
  export declare const METRICS_PATH = "/var/lib/ts-cloud/metrics.json";
11
18
  /**
12
19
  * Build the commands that install the metrics collector + systemd timer.
13
- * Idempotent. Returns `[]` when disabled.
20
+ * Accepts `true`/`false` or a {@link ComputeMonitoringConfig} (with alert
21
+ * thresholds). Idempotent. Returns `[]` when disabled.
14
22
  */
15
- export declare function buildMonitoringScript(enabled?: boolean): string[];
23
+ export declare function buildMonitoringScript(monitoring?: boolean | ComputeMonitoringConfig): string[];
@@ -41,6 +41,12 @@ export interface NginxVhostOptions {
41
41
  webDirectory?: string;
42
42
  /** PHP version selecting the php-fpm socket. @default '8.3' */
43
43
  phpVersion?: string;
44
+ /**
45
+ * Override the `fastcgi_pass` target (e.g. an isolated site's dedicated
46
+ * php-fpm pool — see {@link import('./php-fpm-pool').phpFpmPoolListen}).
47
+ * Defaults to the shared php-fpm listen address for {@link phpVersion}.
48
+ */
49
+ fastcgiPass?: string;
44
50
  /** `from path` → `to URL` 301 redirects. */
45
51
  redirects?: Record<string, string>;
46
52
  /**
@@ -71,6 +77,19 @@ export interface NginxVhostOptions {
71
77
  serverSnippet?: string[];
72
78
  /** `client_max_body_size` override for this vhost (e.g. `'256M'`). */
73
79
  clientMaxBodySize?: string;
80
+ /** Emit an HSTS header. `true` = 1yr + includeSubDomains; object customizes. */
81
+ hsts?: boolean | {
82
+ maxAge?: number;
83
+ includeSubDomains?: boolean;
84
+ preload?: boolean;
85
+ };
86
+ /** `ssl_protocols` for the custom-cert :443 block. */
87
+ tlsProtocols?: string[];
88
+ /** Per-site IP allow/deny (Forge "Security Rules"). */
89
+ security?: {
90
+ allow?: string[];
91
+ deny?: string[];
92
+ };
74
93
  }
75
94
  /** Path of the htpasswd file for a site. */
76
95
  export declare function htpasswdPath(siteName: string): string;
@@ -0,0 +1,34 @@
1
+ /** Directory pantry's php-fpm master scans for extra pool configs (`include`). */
2
+ export declare const PHP_FPM_POOL_DIR = "/var/lib/pantry/php-fpm/pool.d";
3
+ /** Dedicated Linux user (and group) the site's php-fpm pool runs as. */
4
+ export declare function siteUser(siteName: string): string;
5
+ /**
6
+ * Deterministic per-site php-fpm listen port in `[9100, 9499]`. Stable for a
7
+ * given site name (stateless generation), so redeploys reuse the same port.
8
+ */
9
+ export declare function phpFpmPoolPort(siteName: string): number;
10
+ /** The `fastcgi_pass` target for an isolated site's dedicated pool. */
11
+ export declare function phpFpmPoolListen(siteName: string): string;
12
+ export interface PhpFpmPoolOptions {
13
+ /** Site key — names the pool, user, and config file. */
14
+ siteName: string;
15
+ /** Site root (`/var/www/<site>`) — owned by the site user and the open_basedir jail. */
16
+ appBase: string;
17
+ /** Max worker processes for the pool. @default 10 */
18
+ maxChildren?: number;
19
+ }
20
+ /**
21
+ * Render the php-fpm pool config for an isolated site: a named pool running as
22
+ * the site's dedicated user, listening on its per-site port, jailed to its own
23
+ * directory tree (`open_basedir`) plus `/tmp`.
24
+ */
25
+ export declare function buildPhpFpmPoolConf(options: PhpFpmPoolOptions): string;
26
+ /**
27
+ * Build the shell commands that set up an isolated site's php-fpm pool: create
28
+ * the dedicated system user/group, give www-data (nginx) group access so it can
29
+ * still read static files, take ownership of the site tree, write the pool conf
30
+ * into pantry's pool include dir, and restart php-fpm so the pool comes up.
31
+ *
32
+ * Idempotent — re-runnable on every deploy.
33
+ */
34
+ export declare function buildPhpFpmPoolScript(options: PhpFpmPoolOptions): string[];