@studiometa/forge-cli 0.5.1 → 0.5.3
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/README.md +105 -1
- package/dist/cli.js +1204 -44
- package/dist/cli.js.map +1 -1
- package/dist/commands/completion.d.ts.map +1 -1
- package/dist/commands/servers/command.d.ts.map +1 -1
- package/dist/commands/servers/handlers.d.ts +5 -0
- package/dist/commands/servers/handlers.d.ts.map +1 -1
- package/dist/commands/servers/help.d.ts.map +1 -1
- package/dist/commands/sites/apply/apply.d.ts +61 -0
- package/dist/commands/sites/apply/apply.d.ts.map +1 -0
- package/dist/commands/sites/apply/handler.d.ts +8 -0
- package/dist/commands/sites/apply/handler.d.ts.map +1 -0
- package/dist/commands/sites/apply/nginx.d.ts +31 -0
- package/dist/commands/sites/apply/nginx.d.ts.map +1 -0
- package/dist/commands/sites/apply/ownership.d.ts +88 -0
- package/dist/commands/sites/apply/ownership.d.ts.map +1 -0
- package/dist/commands/sites/apply/plan.d.ts +147 -0
- package/dist/commands/sites/apply/plan.d.ts.map +1 -0
- package/dist/commands/sites/apply/site-file.d.ts +94 -0
- package/dist/commands/sites/apply/site-file.d.ts.map +1 -0
- package/dist/commands/sites/apply/test-fixtures.d.ts +104 -0
- package/dist/commands/sites/apply/test-fixtures.d.ts.map +1 -0
- package/dist/commands/sites/command.d.ts.map +1 -1
- package/dist/commands/sites/help.d.ts.map +1 -1
- package/dist/commands/ssh-keys/sync.d.ts.map +1 -1
- package/dist/context.d.ts +15 -1
- package/dist/context.d.ts.map +1 -1
- package/dist/{error-handler-Adi84RcF.js → error-handler-s-BOJ1-h.js} +16 -4
- package/dist/error-handler-s-BOJ1-h.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/utils/args.d.ts.map +1 -1
- package/dist/utils/resolve.d.ts +19 -13
- package/dist/utils/resolve.d.ts.map +1 -1
- package/package.json +6 -4
- package/schemas/site.schema.json +149 -0
- package/dist/error-handler-Adi84RcF.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/commands/completion.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4zBH,wBAAgB,kBAAkB,IAAI,IAAI,CA2CzC;AAED,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,EAAE,CAAM,GACxD,IAAI,CAoEN"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/commands/servers/command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/commands/servers/command.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,oBAAoB,6GAW/B,CAAC"}
|
|
@@ -11,6 +11,11 @@ export declare function serversList(ctx: CommandContext): Promise<void>;
|
|
|
11
11
|
* Get a single server by ID or name.
|
|
12
12
|
*/
|
|
13
13
|
export declare function serversGet(args: string[], ctx: CommandContext): Promise<void>;
|
|
14
|
+
/**
|
|
15
|
+
* Print the public key of the `forge` user of a server (`~/.ssh/id_rsa.pub`), the key that
|
|
16
|
+
* Forge uses to clone repositories: add it to the git host before you create a site.
|
|
17
|
+
*/
|
|
18
|
+
export declare function serversPublicKey(args: string[], ctx: CommandContext): Promise<void>;
|
|
14
19
|
/**
|
|
15
20
|
* Create a server. Defaults to a Custom VPS app server on Ubuntu 26.04.
|
|
16
21
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../../src/commands/servers/handlers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"handlers.d.ts","sourceRoot":"","sources":["../../../src/commands/servers/handlers.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAMvD;;GAEG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBpE;AAED;;GAEG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAcnF;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBzF;AAID;;GAEG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DtE;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CActF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/commands/servers/help.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/commands/servers/help.ts"],"names":[],"mappings":"AAEA,wBAAgB,eAAe,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAgIzD"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read the state of Forge for a site file, and run a plan against Forge.
|
|
3
|
+
*/
|
|
4
|
+
import type { CliExecutorContext } from "../../../context.ts";
|
|
5
|
+
import { CliError } from "../../../errors.ts";
|
|
6
|
+
import { type Change, type Plan, type RemoteState, type Site } from "./plan.ts";
|
|
7
|
+
import type { SiteFile } from "./site-file.ts";
|
|
8
|
+
/** Error of `apply` that is not a validation error, e.g. a site that never gets installed. */
|
|
9
|
+
export declare class ApplyError extends CliError {
|
|
10
|
+
readonly code = "APPLY_ERROR";
|
|
11
|
+
readonly isRecoverable = false;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the server of the site file, always with an exact name (never a partial match).
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveApplyServer(server: string | number, ctx: CliExecutorContext): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* The site named `domain` on the server, compared without case. A partial match never counts.
|
|
19
|
+
*/
|
|
20
|
+
export declare function findSite(sites: Site[], domain: string): Site | null;
|
|
21
|
+
/**
|
|
22
|
+
* Read from Forge what the site file manages, and nothing else.
|
|
23
|
+
*/
|
|
24
|
+
export declare function readRemoteState(file: SiteFile, serverId: string, ctx: CliExecutorContext): Promise<RemoteState>;
|
|
25
|
+
/**
|
|
26
|
+
* Read the Nginx configuration of a site on Forge and render the Nginx file for the site.
|
|
27
|
+
*/
|
|
28
|
+
export declare function readNginx(template: string, serverId: string, site: Site, ctx: CliExecutorContext): Promise<{
|
|
29
|
+
remote: string;
|
|
30
|
+
rendered: string;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Exit with a validation error when the site does not exist and the site file cannot create it.
|
|
34
|
+
*/
|
|
35
|
+
export declare function assertCanCreateSite(file: SiteFile, state: RemoteState): void;
|
|
36
|
+
/** A random password for a database user: 32 characters, letters and digits only. */
|
|
37
|
+
export declare function generatePassword(): string;
|
|
38
|
+
/** Write a value for a .env file, quoted when it needs quotes. */
|
|
39
|
+
export declare function formatEnvValue(value: string): string;
|
|
40
|
+
/**
|
|
41
|
+
* Set .env variables: replace the line of a variable that exists, append the others.
|
|
42
|
+
*/
|
|
43
|
+
export declare function setEnvValues(content: string, values: Map<string, string>): string;
|
|
44
|
+
export interface ApplyOptions {
|
|
45
|
+
/** Wait between two reads of a new site; injectable for tests. */
|
|
46
|
+
sleep?: (ms: number) => Promise<void>;
|
|
47
|
+
/** Time between two reads of a new site, in ms. */
|
|
48
|
+
pollIntervalMs?: number;
|
|
49
|
+
/** Time to wait for a new site to be installed, in ms. */
|
|
50
|
+
timeoutMs?: number;
|
|
51
|
+
/** Called before each change. */
|
|
52
|
+
onChange?: (change: Change) => void;
|
|
53
|
+
/** Generate a password; injectable for tests. */
|
|
54
|
+
generatePassword?: () => string;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Apply a site file: create the site when it does not exist and wait until Forge installs it,
|
|
58
|
+
* then read the state again and run the other changes. Returns the plan that ran first.
|
|
59
|
+
*/
|
|
60
|
+
export declare function applySiteFile(file: SiteFile, serverId: string, ctx: CliExecutorContext, options?: ApplyOptions): Promise<Plan>;
|
|
61
|
+
//# sourceMappingURL=apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../../../src/commands/sites/apply/apply.ts"],"names":[],"mappings":"AAAA;;GAEG;AA4BH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAmB,MAAM,oBAAoB,CAAC;AAI/D,OAAO,EACL,KAAK,MAAM,EACX,KAAK,IAAI,EACT,KAAK,WAAW,EAChB,KAAK,IAAI,EAGV,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,8FAA8F;AAC9F,qBAAa,UAAW,SAAQ,QAAQ;IACtC,QAAQ,CAAC,IAAI,iBAAiB;IAC9B,QAAQ,CAAC,aAAa,SAAS;CAChC;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,MAAM,GAAG,MAAM,EACvB,GAAG,EAAE,kBAAkB,GACtB,OAAO,CAAC,MAAM,CAAC,CAKjB;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAEnE;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,kBAAkB,GACtB,OAAO,CAAC,WAAW,CAAC,CAsCtB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAC7B,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,kBAAkB,GACtB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAO/C;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,CAQ5E;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,IAAI,MAAM,CAUzC;AAED,kEAAkE;AAClE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIpD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAiBjF;AAED,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,mDAAmD;IACnD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,iDAAiD;IACjD,gBAAgB,CAAC,EAAE,MAAM,MAAM,CAAC;CACjC;AAmOD;;;GAGG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,QAAQ,EACd,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,kBAAkB,EACvB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAwCf"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { CommandContext } from "../../../context.ts";
|
|
2
|
+
import { type ApplyOptions } from "./apply.ts";
|
|
3
|
+
/**
|
|
4
|
+
* `forge sites apply --file site.json [--check]`: make a Forge site match a site file.
|
|
5
|
+
* With `--check`, print the plan and exit 1 when Forge differs, without any change.
|
|
6
|
+
*/
|
|
7
|
+
export declare function sitesApply(ctx: CommandContext, applyOptions?: ApplyOptions): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../src/commands/sites/apply/handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAG1D,OAAO,EACL,KAAK,YAAY,EAKlB,MAAM,YAAY,CAAC;AAIpB;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,GAAG,EAAE,cAAc,EACnB,YAAY,GAAE,YAAiB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAoDf"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Nginx file of a site file: an Nginx configuration with the template variables of Forge,
|
|
3
|
+
* e.g. `{{ PROXY_PASS }}`, rendered locally with the values of the site.
|
|
4
|
+
* See https://forge.laravel.com/docs/servers/nginx-templates
|
|
5
|
+
*/
|
|
6
|
+
import type { ServerAttributes } from "@studiometa/forge-api";
|
|
7
|
+
import { type Site } from "./plan.ts";
|
|
8
|
+
/** The variables of Forge Nginx templates. Forge accepts spaces inside the braces. */
|
|
9
|
+
export declare const NGINX_VARIABLES: readonly ["DIRECTORY", "DOMAINS", "PATH", "PORT", "PORT_V6", "PROXY_PASS", "ROOT_PATH", "SERVER_PUBLIC_IP", "SERVER_PRIVATE_IP", "SITE", "SITE_ID", "USER"];
|
|
10
|
+
export type NginxVariable = (typeof NGINX_VARIABLES)[number];
|
|
11
|
+
/** The names of the variables in a template, each once, in order. */
|
|
12
|
+
export declare function templateVariables(template: string): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Exit with a validation error when the template has a variable that Forge does not define.
|
|
15
|
+
*/
|
|
16
|
+
export declare function assertNginxTemplate(template: string, source: string): void;
|
|
17
|
+
/** True when rendering the template needs the attributes of the server. */
|
|
18
|
+
export declare function needsServer(template: string): boolean;
|
|
19
|
+
/** `PHP 8.3`, `php83` and `php8.3` all give `8.3`. */
|
|
20
|
+
export declare function phpSocketVersion(version: string): string;
|
|
21
|
+
export type NginxServer = Pick<ServerAttributes, "ip_address" | "private_ip_address">;
|
|
22
|
+
/**
|
|
23
|
+
* The value of each variable for a site, as Forge renders its templates.
|
|
24
|
+
* A server is needed only for the `SERVER_*` variables.
|
|
25
|
+
*/
|
|
26
|
+
export declare function nginxValues(site: Site, server?: NginxServer | null): Record<NginxVariable, string>;
|
|
27
|
+
/**
|
|
28
|
+
* Replace each variable of the template with its value for the site.
|
|
29
|
+
*/
|
|
30
|
+
export declare function renderNginx(template: string, site: Site, server?: NginxServer | null): string;
|
|
31
|
+
//# sourceMappingURL=nginx.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nginx.d.ts","sourceRoot":"","sources":["../../../../src/commands/sites/apply/nginx.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,OAAO,EAAE,KAAK,IAAI,EAAqB,MAAM,WAAW,CAAC;AAEzD,sFAAsF;AACtF,eAAO,MAAM,eAAe,YAC1B,WAAW,EACX,SAAS,EACT,MAAM,EACN,MAAM,EACN,SAAS,EACT,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,mBAAmB,EACnB,MAAM,EACN,SAAS,EACT,MAAM,CACE,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAO7D,qEAAqE;AACrE,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAE5D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAU1E;AAED,2EAA2E;AAC3E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAErD;AAED,sDAAsD;AACtD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAMxD;AAED,MAAM,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,oBAAoB,CAAC,CAAC;AAEtF;;;GAGG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,IAAI,EACV,MAAM,GAAE,WAAW,GAAG,IAAW,GAChC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAyB/B;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,IAAI,EACV,MAAM,GAAE,WAAW,GAAG,IAAW,GAChC,MAAM,CAKR"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path and command helpers of `forge sites apply`: normalize commands so that
|
|
3
|
+
* equivalent spellings compare equal, and find which site owns a daemon or a scheduled job.
|
|
4
|
+
*
|
|
5
|
+
* Ownership is strict on purpose: `apply` deletes the workers and scheduled jobs of a site
|
|
6
|
+
* that the site file does not declare, and a server often hosts many sites.
|
|
7
|
+
*/
|
|
8
|
+
/** A site, as far as ownership is concerned. */
|
|
9
|
+
export interface SiteRoots {
|
|
10
|
+
id: number;
|
|
11
|
+
/** Absolute paths that belong to the site, e.g. `/home/forge/example.com`. */
|
|
12
|
+
roots: string[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Normalize an absolute path: resolve `.` and `..`, collapse repeated slashes
|
|
16
|
+
* and drop the trailing slash.
|
|
17
|
+
*/
|
|
18
|
+
export declare function normalizePath(path: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Whether `path` is `root` or inside it, compared on whole path segments:
|
|
21
|
+
* `/home/forge/a.com` contains `/home/forge/a.com/current` but not `/home/forge/a.com-staging`.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isPathInside(path: string, root: string): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Resolve `path` against `base` when it is relative.
|
|
26
|
+
*/
|
|
27
|
+
export declare function resolvePath(base: string, path: string): string;
|
|
28
|
+
/**
|
|
29
|
+
* Whether a shell command uses `root` as a whole path: `root` must start the command or follow
|
|
30
|
+
* a space, a quote, `=` or a shell operator, and must end the command or be followed by `/`,
|
|
31
|
+
* a space, a quote or a shell operator. `/home/forge/a.com` is not found in
|
|
32
|
+
* `/home/forge/a.com-staging/artisan`, `/home/forge/a.com.old` or `/home/forge/*`.
|
|
33
|
+
*/
|
|
34
|
+
export declare function commandUsesPath(command: string, root: string): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Split a shell command into words, with the quoting rules of a POSIX shell:
|
|
37
|
+
* single quotes keep everything, double quotes and a backslash escape one character.
|
|
38
|
+
*/
|
|
39
|
+
export declare function splitCommand(command: string): string[];
|
|
40
|
+
/**
|
|
41
|
+
* Quote a word for a POSIX shell when it needs quotes.
|
|
42
|
+
*/
|
|
43
|
+
export declare function quoteWord(word: string): string;
|
|
44
|
+
/**
|
|
45
|
+
* Write a command in one canonical form, so that equivalent spellings compare equal:
|
|
46
|
+
* quotes only where needed, single spaces, and a relative `artisan` (or `./artisan`)
|
|
47
|
+
* replaced by its absolute path in `directory`.
|
|
48
|
+
*
|
|
49
|
+
* `php artisan queue:work 'database' --queue="default"` in `/home/forge/example.com/`
|
|
50
|
+
* gives `php /home/forge/example.com/artisan queue:work database --queue=default`.
|
|
51
|
+
*/
|
|
52
|
+
export declare function canonicalCommand(command: string, directory: string | null): string;
|
|
53
|
+
/**
|
|
54
|
+
* The site whose root holds `path`: the most specific root wins, so a site in
|
|
55
|
+
* `/home/forge/a.com/admin` is not owned by `/home/forge/a.com`. Returns null when no site holds it.
|
|
56
|
+
*/
|
|
57
|
+
export declare function siteOfPath(path: string, sites: SiteRoots[]): number | null;
|
|
58
|
+
/**
|
|
59
|
+
* The sites whose roots a command uses as a path.
|
|
60
|
+
*/
|
|
61
|
+
export declare function sitesOfCommand(command: string, sites: SiteRoots[]): number[];
|
|
62
|
+
/**
|
|
63
|
+
* Who owns a daemon or a scheduled job, from the point of view of one site:
|
|
64
|
+
* - `site`: it belongs to the site; `apply` can match it, and delete it when it is not declared
|
|
65
|
+
* - `ambiguous`: it may belong to the site; `apply` can match it but never deletes it
|
|
66
|
+
* - `other`: it belongs to another site, to the server, or to nobody known; `apply` ignores it
|
|
67
|
+
*/
|
|
68
|
+
export type Ownership = "site" | "ambiguous" | "other";
|
|
69
|
+
/**
|
|
70
|
+
* Ownership of a daemon (a Forge background process).
|
|
71
|
+
*
|
|
72
|
+
* - With a directory: the site that holds the directory (see {@link siteOfPath}).
|
|
73
|
+
* - Without a directory: `ambiguous` when the command uses the site root, `site` only when
|
|
74
|
+
* the command uses no other site root and Forge also associates the daemon with the site.
|
|
75
|
+
*/
|
|
76
|
+
export declare function daemonOwnership(daemon: {
|
|
77
|
+
directory: string | null;
|
|
78
|
+
command: string;
|
|
79
|
+
}, siteId: number, sites: SiteRoots[], associatedWithSite: boolean): Ownership;
|
|
80
|
+
/**
|
|
81
|
+
* Ownership of a scheduled job. Forge lists the jobs of a site on a site route: those
|
|
82
|
+
* belong to the site. A job of the server belongs to the site when its command uses the
|
|
83
|
+
* site root and no other site root; when it uses several site roots, it is `ambiguous`.
|
|
84
|
+
*/
|
|
85
|
+
export declare function scheduledJobOwnership(job: {
|
|
86
|
+
command: string;
|
|
87
|
+
}, siteId: number, sites: SiteRoots[], listedOnSite: boolean): Ownership;
|
|
88
|
+
//# sourceMappingURL=ownership.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ownership.d.ts","sourceRoot":"","sources":["../../../../src/commands/sites/apply/ownership.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,gDAAgD;AAChD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,8EAA8E;IAC9E,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGlD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAKhE;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAMD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOtE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAsCtD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAG9C;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAUlF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,IAAI,CAW1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,EAAE,CAI5E;AAED;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE;IAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACrD,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,SAAS,EAAE,EAClB,kBAAkB,EAAE,OAAO,GAC1B,SAAS,CAQX;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CACnC,GAAG,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EACxB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,SAAS,EAAE,EAClB,YAAY,EAAE,OAAO,GACpB,SAAS,CAKX"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare a site file with the state of Forge and list the changes that `apply` makes.
|
|
3
|
+
* Pure functions: no API call here.
|
|
4
|
+
*/
|
|
5
|
+
import type { BackgroundProcessAttributes, DatabaseAttributes, DatabaseUserAttributes, ScheduledJobAttributes, SiteAttributes } from "@studiometa/forge-api";
|
|
6
|
+
import type { SiteFile } from "./site-file.ts";
|
|
7
|
+
import { type SiteRoots } from "./ownership.ts";
|
|
8
|
+
export type Site = SiteAttributes & {
|
|
9
|
+
id: number;
|
|
10
|
+
};
|
|
11
|
+
export type Daemon = BackgroundProcessAttributes & {
|
|
12
|
+
id: number;
|
|
13
|
+
};
|
|
14
|
+
export type ScheduledJob = ScheduledJobAttributes & {
|
|
15
|
+
id: number;
|
|
16
|
+
};
|
|
17
|
+
export type Database = DatabaseAttributes & {
|
|
18
|
+
id: number;
|
|
19
|
+
};
|
|
20
|
+
export type DatabaseUser = DatabaseUserAttributes & {
|
|
21
|
+
id: number;
|
|
22
|
+
};
|
|
23
|
+
/** Shown in place of a generated password. */
|
|
24
|
+
export declare const GENERATED = "<generated>";
|
|
25
|
+
/** What `apply` reads from Forge. A list is undefined when the site file does not manage it. */
|
|
26
|
+
export interface RemoteState {
|
|
27
|
+
/** All sites of the server. */
|
|
28
|
+
sites: Site[];
|
|
29
|
+
/** The site of the file, or null when it does not exist yet. */
|
|
30
|
+
site: Site | null;
|
|
31
|
+
databases?: Database[];
|
|
32
|
+
databaseUsers?: DatabaseUser[];
|
|
33
|
+
/** Content of the site .env; null when the site does not exist. */
|
|
34
|
+
env?: string | null;
|
|
35
|
+
/** All daemons of the server. */
|
|
36
|
+
daemons?: Daemon[];
|
|
37
|
+
/** IDs of the daemons that Forge associates with the site. */
|
|
38
|
+
siteDaemonIds?: ReadonlySet<number>;
|
|
39
|
+
/** All scheduled jobs of the server, with the jobs of the site. */
|
|
40
|
+
jobs?: ScheduledJob[];
|
|
41
|
+
/** IDs of the scheduled jobs that Forge lists on the site. */
|
|
42
|
+
siteJobIds?: ReadonlySet<number>;
|
|
43
|
+
/** Nginx configuration on Forge and the Nginx file rendered for the site; null when the site does not exist. */
|
|
44
|
+
nginx?: {
|
|
45
|
+
remote: string;
|
|
46
|
+
rendered: string;
|
|
47
|
+
} | null;
|
|
48
|
+
}
|
|
49
|
+
export interface SiteSettings {
|
|
50
|
+
type?: string;
|
|
51
|
+
php_version?: string;
|
|
52
|
+
web_directory?: string;
|
|
53
|
+
source_control_provider?: string;
|
|
54
|
+
repository?: string;
|
|
55
|
+
branch?: string;
|
|
56
|
+
}
|
|
57
|
+
export type Change = {
|
|
58
|
+
action: "create-site";
|
|
59
|
+
name: string;
|
|
60
|
+
settings: SiteSettings;
|
|
61
|
+
} | {
|
|
62
|
+
action: "update-site";
|
|
63
|
+
changes: Array<{
|
|
64
|
+
field: string;
|
|
65
|
+
from: string | null;
|
|
66
|
+
to: string;
|
|
67
|
+
}>;
|
|
68
|
+
} | {
|
|
69
|
+
action: "add-alias";
|
|
70
|
+
name: string;
|
|
71
|
+
} | {
|
|
72
|
+
action: "create-database";
|
|
73
|
+
name: string;
|
|
74
|
+
} | {
|
|
75
|
+
action: "create-database-user";
|
|
76
|
+
name: string;
|
|
77
|
+
database: string;
|
|
78
|
+
} | {
|
|
79
|
+
action: "add-env";
|
|
80
|
+
keys: string[];
|
|
81
|
+
/** Keys that get the database name, user and password of a new database user. */
|
|
82
|
+
generated: string[];
|
|
83
|
+
/** The generated key that holds the password; its value never shows. */
|
|
84
|
+
password?: string;
|
|
85
|
+
} | {
|
|
86
|
+
action: "create-worker";
|
|
87
|
+
command: string;
|
|
88
|
+
directory: string;
|
|
89
|
+
processes: number;
|
|
90
|
+
} | {
|
|
91
|
+
action: "delete-worker";
|
|
92
|
+
id: number;
|
|
93
|
+
command: string;
|
|
94
|
+
directory: string | null;
|
|
95
|
+
processes: number;
|
|
96
|
+
} | {
|
|
97
|
+
action: "create-job";
|
|
98
|
+
command: string;
|
|
99
|
+
frequency: string;
|
|
100
|
+
cron?: string;
|
|
101
|
+
}
|
|
102
|
+
/** `diff` is null for a site that does not exist yet: the file is rendered once it exists. */
|
|
103
|
+
| {
|
|
104
|
+
action: "update-nginx";
|
|
105
|
+
diff: string | null;
|
|
106
|
+
} | {
|
|
107
|
+
action: "delete-job";
|
|
108
|
+
id: number;
|
|
109
|
+
command: string;
|
|
110
|
+
frequency: string;
|
|
111
|
+
cron: string;
|
|
112
|
+
onSite: boolean;
|
|
113
|
+
};
|
|
114
|
+
export interface Plan {
|
|
115
|
+
changes: Change[];
|
|
116
|
+
/** Differences that `apply` does not change, e.g. a different .env value. */
|
|
117
|
+
warnings: string[];
|
|
118
|
+
}
|
|
119
|
+
/** The path of the site folder, e.g. `/home/forge/example.com`. */
|
|
120
|
+
export declare function siteHome(site: Pick<Site, "user" | "name">): string;
|
|
121
|
+
/** The directory that workers run in and relative `artisan` resolves against. */
|
|
122
|
+
export declare function siteWorkDirectory(site: Pick<Site, "user" | "name" | "root_directory">): string;
|
|
123
|
+
/** The paths that belong to each site, for ownership. */
|
|
124
|
+
export declare function siteRoots(sites: Site[]): SiteRoots[];
|
|
125
|
+
/** `PHP 8.3`, `php83` and `php8.3` all give `php83`. */
|
|
126
|
+
export declare function normalizePhp(version: string | null | undefined): string | null;
|
|
127
|
+
/** The .env keys of a new database user, from `database.env` or the Laravel names. */
|
|
128
|
+
export declare function databaseEnvKeys(database: NonNullable<SiteFile["database"]>): {
|
|
129
|
+
name: string;
|
|
130
|
+
user: string;
|
|
131
|
+
password: string;
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Compare the site file with the state of Forge. Keys that the file does not have are not
|
|
135
|
+
* compared. The plan creates and updates what differs, and deletes only the workers and
|
|
136
|
+
* scheduled jobs that surely belong to the site and that the file does not declare.
|
|
137
|
+
*/
|
|
138
|
+
export declare function buildPlan(file: SiteFile, state: RemoteState): Plan;
|
|
139
|
+
/**
|
|
140
|
+
* One line per change, for human output. Values of .env keys never show.
|
|
141
|
+
*/
|
|
142
|
+
export declare function describeChange(change: Change): string;
|
|
143
|
+
/**
|
|
144
|
+
* The plan as text: one line per change, then the warnings.
|
|
145
|
+
*/
|
|
146
|
+
export declare function formatPlan(plan: Plan): string;
|
|
147
|
+
//# sourceMappingURL=plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../../src/commands/sites/apply/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The site file of `forge sites apply`: a JSON file that declares one Forge site.
|
|
3
|
+
* A key that is absent is not managed; only `server` and `domain` are required.
|
|
4
|
+
*/
|
|
5
|
+
import * as v from "valibot";
|
|
6
|
+
/** URL of the JSON Schema of the site file, published with the package. */
|
|
7
|
+
export declare const SITE_FILE_SCHEMA_URL = "https://unpkg.com/@studiometa/forge-cli/schemas/site.schema.json";
|
|
8
|
+
export declare const SITE_TYPES: readonly ["laravel", "symfony", "statamic", "wordpress", "phpmyadmin", "php", "nextjs", "nuxtjs", "static-html", "other", "custom"];
|
|
9
|
+
export declare const SOURCE_CONTROL_PROVIDERS: readonly ["github", "gitlab", "bitbucket", "gitlab-custom", "custom"];
|
|
10
|
+
export declare const SCHEDULE_FREQUENCIES: readonly ["minutely", "hourly", "nightly", "weekly", "monthly", "reboot", "custom"];
|
|
11
|
+
export declare const WorkerSchema: v.StrictObjectSchema<{
|
|
12
|
+
readonly command: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>;
|
|
13
|
+
readonly processes: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, 1>;
|
|
14
|
+
readonly directory: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>, undefined>;
|
|
15
|
+
}, undefined>;
|
|
16
|
+
export declare const ScheduledJobSchema: v.SchemaWithPipe<readonly [v.StrictObjectSchema<{
|
|
17
|
+
readonly command: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>;
|
|
18
|
+
readonly frequency: v.PicklistSchema<readonly ["minutely", "hourly", "nightly", "weekly", "monthly", "reboot", "custom"], undefined>;
|
|
19
|
+
readonly cron: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>, undefined>;
|
|
20
|
+
}, undefined>, v.CheckAction<{
|
|
21
|
+
command: string;
|
|
22
|
+
frequency: "custom" | "hourly" | "minutely" | "monthly" | "nightly" | "reboot" | "weekly";
|
|
23
|
+
cron?: string | undefined;
|
|
24
|
+
}, "cron is required with the custom frequency, and only with it">]>;
|
|
25
|
+
/** The .env keys that a new database user gets. Default: the Laravel names. */
|
|
26
|
+
export declare const DatabaseEnvSchema: v.SchemaWithPipe<readonly [v.StrictObjectSchema<{
|
|
27
|
+
readonly name: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "invalid .env variable name">]>, undefined>;
|
|
28
|
+
readonly user: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "invalid .env variable name">]>, undefined>;
|
|
29
|
+
readonly password: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "invalid .env variable name">]>, undefined>;
|
|
30
|
+
}, undefined>, v.CheckAction<{
|
|
31
|
+
name?: string | undefined;
|
|
32
|
+
user?: string | undefined;
|
|
33
|
+
password?: string | undefined;
|
|
34
|
+
}, "the .env keys of the database must be different">]>;
|
|
35
|
+
export declare const SiteFileSchema: v.StrictObjectSchema<{
|
|
36
|
+
readonly $schema: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
|
|
37
|
+
readonly server: v.UnionSchema<[v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>, v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>], undefined>;
|
|
38
|
+
readonly domain: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>;
|
|
39
|
+
readonly aliases: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>, undefined>, undefined>;
|
|
40
|
+
readonly type: v.OptionalSchema<v.PicklistSchema<readonly ["laravel", "symfony", "statamic", "wordpress", "phpmyadmin", "php", "nextjs", "nuxtjs", "static-html", "other", "custom"], undefined>, undefined>;
|
|
41
|
+
readonly php: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "php must look like php83">]>, undefined>;
|
|
42
|
+
readonly webDirectory: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>, undefined>;
|
|
43
|
+
readonly repository: v.OptionalSchema<v.StrictObjectSchema<{
|
|
44
|
+
readonly provider: v.PicklistSchema<readonly ["github", "gitlab", "bitbucket", "gitlab-custom", "custom"], undefined>;
|
|
45
|
+
readonly url: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>;
|
|
46
|
+
readonly branch: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>, undefined>;
|
|
47
|
+
}, undefined>, undefined>;
|
|
48
|
+
readonly database: v.OptionalSchema<v.StrictObjectSchema<{
|
|
49
|
+
readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>;
|
|
50
|
+
readonly user: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>;
|
|
51
|
+
readonly env: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StrictObjectSchema<{
|
|
52
|
+
readonly name: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "invalid .env variable name">]>, undefined>;
|
|
53
|
+
readonly user: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "invalid .env variable name">]>, undefined>;
|
|
54
|
+
readonly password: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "invalid .env variable name">]>, undefined>;
|
|
55
|
+
}, undefined>, v.CheckAction<{
|
|
56
|
+
name?: string | undefined;
|
|
57
|
+
user?: string | undefined;
|
|
58
|
+
password?: string | undefined;
|
|
59
|
+
}, "the .env keys of the database must be different">]>, undefined>;
|
|
60
|
+
}, undefined>, undefined>;
|
|
61
|
+
readonly env: v.OptionalSchema<v.RecordSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.RegexAction<string, "invalid .env variable name">]>, v.UnionSchema<[v.StringSchema<undefined>, v.NumberSchema<undefined>, v.BooleanSchema<undefined>], undefined>, undefined>, undefined>;
|
|
62
|
+
readonly nginx: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>, undefined>;
|
|
63
|
+
readonly workers: v.OptionalSchema<v.ArraySchema<v.StrictObjectSchema<{
|
|
64
|
+
readonly command: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>;
|
|
65
|
+
readonly processes: v.OptionalSchema<v.SchemaWithPipe<readonly [v.NumberSchema<undefined>, v.IntegerAction<number, undefined>, v.MinValueAction<number, 1, undefined>]>, 1>;
|
|
66
|
+
readonly directory: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>, undefined>;
|
|
67
|
+
}, undefined>, undefined>, undefined>;
|
|
68
|
+
readonly schedule: v.OptionalSchema<v.ArraySchema<v.SchemaWithPipe<readonly [v.StrictObjectSchema<{
|
|
69
|
+
readonly command: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>;
|
|
70
|
+
readonly frequency: v.PicklistSchema<readonly ["minutely", "hourly", "nightly", "weekly", "monthly", "reboot", "custom"], undefined>;
|
|
71
|
+
readonly cron: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.TrimAction, v.NonEmptyAction<string, undefined>]>, undefined>;
|
|
72
|
+
}, undefined>, v.CheckAction<{
|
|
73
|
+
command: string;
|
|
74
|
+
frequency: "custom" | "hourly" | "minutely" | "monthly" | "nightly" | "reboot" | "weekly";
|
|
75
|
+
cron?: string | undefined;
|
|
76
|
+
}, "cron is required with the custom frequency, and only with it">]>, undefined>, undefined>;
|
|
77
|
+
}, undefined>;
|
|
78
|
+
export type SiteFileData = v.InferOutput<typeof SiteFileSchema>;
|
|
79
|
+
/** A site file with the content of its Nginx file, when it declares one. */
|
|
80
|
+
export type SiteFile = SiteFileData & {
|
|
81
|
+
nginxTemplate?: string;
|
|
82
|
+
};
|
|
83
|
+
export type WorkerDeclaration = v.InferOutput<typeof WorkerSchema>;
|
|
84
|
+
export type ScheduledJobDeclaration = v.InferOutput<typeof ScheduledJobSchema>;
|
|
85
|
+
/**
|
|
86
|
+
* Validate parsed JSON as a site file. Throws a ValidationError that lists every issue.
|
|
87
|
+
*/
|
|
88
|
+
export declare function parseSiteFile(data: unknown, source?: string): SiteFileData;
|
|
89
|
+
/**
|
|
90
|
+
* Read and validate a site file from disk, with its Nginx file: a relative `nginx` path is
|
|
91
|
+
* read against the folder of the site file.
|
|
92
|
+
*/
|
|
93
|
+
export declare function readSiteFile(path: string): SiteFile;
|
|
94
|
+
//# sourceMappingURL=site-file.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"site-file.d.ts","sourceRoot":"","sources":["../../../../src/commands/sites/apply/site-file.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,CAAC,MAAM,SAAS,CAAC;AAK7B,2EAA2E;AAC3E,eAAO,MAAM,oBAAoB,qEACmC,CAAC;AAIrE,eAAO,MAAM,UAAU,YACrB,SAAS,EACT,SAAS,EACT,UAAU,EACV,WAAW,EACX,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,OAAO,EACP,QAAQ,CACA,CAAC;AAEX,eAAO,MAAM,wBAAwB,YACnC,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,eAAe,EACf,QAAQ,CACA,CAAC;AAEX,eAAO,MAAM,oBAAoB,YAC/B,UAAU,EACV,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,CACA,CAAC;AAEX,eAAO,MAAM,YAAY;;;;aAIvB,CAAC;AAEH,eAAO,MAAM,kBAAkB;;;;;;;;oEAU9B,CAAC;AAOF,+EAA+E;AAC/E,eAAO,MAAM,iBAAiB;;;;;;;;uDAY7B,CAAC;AAEF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAsBzB,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,cAAc,CAAC,CAAC;AAEhE,4EAA4E;AAC5E,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACjE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,YAAY,CAAC,CAAC;AACnE,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAE/E;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,SAAc,GAAG,YAAY,CAU/E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CA6BnD"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fixtures of Forge resources for the tests of `forge sites apply`.
|
|
3
|
+
*/
|
|
4
|
+
import type { CliExecutorContext } from "../../../context.ts";
|
|
5
|
+
import type { Daemon, ScheduledJob, Site } from "./plan.ts";
|
|
6
|
+
export declare function site(id: number, name: string, overrides?: Partial<Site>): Site;
|
|
7
|
+
export declare function daemon(id: number, command: string, directory: string | null, overrides?: Partial<Daemon>): Daemon;
|
|
8
|
+
export declare function job(id: number, command: string, overrides?: Partial<ScheduledJob>): ScheduledJob;
|
|
9
|
+
type Call = [method: string, url: string, body?: unknown];
|
|
10
|
+
/** Attributes of server 123, for the `SERVER_*` Nginx variables. */
|
|
11
|
+
export declare function webServer(): {
|
|
12
|
+
id: number;
|
|
13
|
+
credential_id: null;
|
|
14
|
+
name: string;
|
|
15
|
+
type: string;
|
|
16
|
+
ubuntu_version: string;
|
|
17
|
+
ssh_port: number;
|
|
18
|
+
provider: string;
|
|
19
|
+
identifier: null;
|
|
20
|
+
size: string;
|
|
21
|
+
region: string;
|
|
22
|
+
php_version: null;
|
|
23
|
+
php_cli_version: null;
|
|
24
|
+
opcache_status: null;
|
|
25
|
+
database_type: null;
|
|
26
|
+
db_status: null;
|
|
27
|
+
redis_status: null;
|
|
28
|
+
revoked: boolean;
|
|
29
|
+
created_at: string;
|
|
30
|
+
updated_at: string;
|
|
31
|
+
connection_status: null;
|
|
32
|
+
timezone: string;
|
|
33
|
+
local_public_key: null;
|
|
34
|
+
is_ready: boolean;
|
|
35
|
+
ip_address: string;
|
|
36
|
+
private_ip_address: string;
|
|
37
|
+
};
|
|
38
|
+
export interface FakeForge {
|
|
39
|
+
sites: Site[];
|
|
40
|
+
daemons: Daemon[];
|
|
41
|
+
siteDaemonIds: number[];
|
|
42
|
+
jobs: ScheduledJob[];
|
|
43
|
+
siteJobIds: number[];
|
|
44
|
+
databases: Array<{
|
|
45
|
+
id: number;
|
|
46
|
+
name: string;
|
|
47
|
+
}>;
|
|
48
|
+
users: Array<{
|
|
49
|
+
id: number;
|
|
50
|
+
name: string;
|
|
51
|
+
}>;
|
|
52
|
+
env: string;
|
|
53
|
+
/** Nginx configuration of every site. */
|
|
54
|
+
nginx: string;
|
|
55
|
+
/** Statuses a new site goes through, one per read. */
|
|
56
|
+
newSiteStatuses: string[];
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* A fake Forge API client, enough for `apply`. It records every call.
|
|
60
|
+
*/
|
|
61
|
+
export declare function fakeForge(initial?: Partial<FakeForge>): {
|
|
62
|
+
ctx: CliExecutorContext;
|
|
63
|
+
calls: Call[];
|
|
64
|
+
state: FakeForge;
|
|
65
|
+
client: {
|
|
66
|
+
get: import("vitest").Mock<(url: string) => Promise<{
|
|
67
|
+
data: {
|
|
68
|
+
id: string;
|
|
69
|
+
type: string;
|
|
70
|
+
attributes: {};
|
|
71
|
+
}[];
|
|
72
|
+
links: {};
|
|
73
|
+
meta: {
|
|
74
|
+
per_page: number;
|
|
75
|
+
next_cursor: null;
|
|
76
|
+
prev_cursor: null;
|
|
77
|
+
};
|
|
78
|
+
} | {
|
|
79
|
+
data: {
|
|
80
|
+
id: string;
|
|
81
|
+
type: string;
|
|
82
|
+
attributes: {};
|
|
83
|
+
};
|
|
84
|
+
}>>;
|
|
85
|
+
post: import("vitest").Mock<(raw: string, body: Record<string, unknown>) => Promise<{
|
|
86
|
+
data: {
|
|
87
|
+
id: string;
|
|
88
|
+
type: string;
|
|
89
|
+
attributes: {};
|
|
90
|
+
};
|
|
91
|
+
}>>;
|
|
92
|
+
put: import("vitest").Mock<(raw: string, body: Record<string, unknown>) => Promise<{
|
|
93
|
+
data: {
|
|
94
|
+
id: string;
|
|
95
|
+
type: string;
|
|
96
|
+
attributes: {};
|
|
97
|
+
};
|
|
98
|
+
} | null>>;
|
|
99
|
+
delete: import("vitest").Mock<(url: string) => Promise<void>>;
|
|
100
|
+
patch: import("vitest").Mock<import("@vitest/spy").Procedure>;
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
export {};
|
|
104
|
+
//# sourceMappingURL=test-fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-fixtures.d.ts","sourceRoot":"","sources":["../../../../src/commands/sites/apply/test-fixtures.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE5D,wBAAgB,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,OAAO,CAAC,IAAI,CAAM,GAAG,IAAI,CAmClF;AAED,wBAAgB,MAAM,CACpB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,SAAS,GAAE,OAAO,CAAC,MAAM,CAAM,GAC9B,MAAM,CAWR;AAED,wBAAgB,GAAG,CACjB,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,OAAO,CAAC,YAAY,CAAM,GACpC,YAAY,CAcd;AAED,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AAiD1D,oEAAoE;AACpE,wBAAgB,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;EAExB;AAOD,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,KAAK,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;IACd,sDAAsD;IACtD,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,OAAO,CAAC,SAAS,CAAM;;;;;yCAkB/B,MAAM;;;;;;;;gBApFrB,QAAQ;gBAAM,WAAW;gBAAQ,WAAW;;;;;;;;;0CA4I5B,MAAM,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;yCAsCtC,MAAM,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;;;;;;4CAalC,MAAM;;;EAYnC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/command.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/command.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,kBAAkB,6GAU7B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/help.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/help.ts"],"names":[],"mappings":"AAEA,wBAAgB,aAAa,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CA8FvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/commands/ssh-keys/sync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../../src/commands/ssh-keys/sync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAsB,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA8K3E;;GAEG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAgHpE"}
|