ninepm 0.68.0 → 0.72.0
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 +74 -10
- package/dist/cli-types.d.ts +2 -0
- package/dist/dns-host.d.ts +7 -0
- package/dist/dns-host.js +27 -0
- package/dist/index.d.ts +194 -6
- package/dist/index.js +730 -30
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -62,6 +62,28 @@ Deploy a static directory:
|
|
|
62
62
|
9pm deploy . --name my-app --slug my-app
|
|
63
63
|
```
|
|
64
64
|
|
|
65
|
+
### How long an app's address stays the same
|
|
66
|
+
|
|
67
|
+
Check this before printing a link or QR code. The live URL is `<slug>-<suffix>.9pm.ai`, and the suffix comes from the app's internal id, not from the slug:
|
|
68
|
+
|
|
69
|
+
- Redeploying under the same slug keeps the address.
|
|
70
|
+
- Deleting the app and creating it again under the same slug gives it a **new** address, because the new app gets a new id. Anything printed with the old one stops working.
|
|
71
|
+
- There is no rename: a different address means a different app.
|
|
72
|
+
- A custom domain you own, added on the dashboard's Domains page, gives the app an address of your own. Not every plan includes custom domains.
|
|
73
|
+
|
|
74
|
+
### Pages that do not exist
|
|
75
|
+
|
|
76
|
+
A static site or `--entry` worker app answers a path that has no file in one of two ways. Every deploy prints which, as a `Missing pages:` line.
|
|
77
|
+
|
|
78
|
+
- `--no-spa` (the default for new apps): the path returns status 404, with the deploy's own `404.html` when it has one. `/` still serves `index.html`, and extensionless links work: `/menu` serves `menu.html`, or redirects to `/menu/` when only `menu/index.html` exists, and `/menu/` serves `menu/index.html`. Right for a multi-page site, where a removed or mistyped page should say "not found" rather than show the homepage.
|
|
79
|
+
- `--spa`: every path with no file serves `index.html`, so a single-page app that routes in the browser loads on a deep link or a refresh. That includes dotted paths such as `/users/jane.smith` and missing files such as `/missing.json`, which get the app's shell rather than a 404.
|
|
80
|
+
|
|
81
|
+
```sh
|
|
82
|
+
9pm deploy ./dist --name my-spa --spa
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The app remembers the choice: a deploy without either flag keeps it, and a deploy that fails to publish leaves the previous choice in place. Apps created before this choice existed keep serving `index.html` for every unmatched path until a deploy passes one of the flags. A worker app's own `Response`, a 404 included, is always returned as it is. The flags do not apply to `--bundle` or container apps.
|
|
86
|
+
|
|
65
87
|
Deploy a built framework output directory:
|
|
66
88
|
|
|
67
89
|
```sh
|
|
@@ -137,16 +159,20 @@ Delete an app, its managed database, managed container app, and retained image:
|
|
|
137
159
|
9pm delete my-app --confirm my-app
|
|
138
160
|
```
|
|
139
161
|
|
|
162
|
+
The app's address goes with it: creating an app again under the same slug gives it a new address, so printed links and QR codes stop working. `9pm delete` prints this warning before it deletes anything.
|
|
163
|
+
|
|
140
164
|
## Access Modes
|
|
141
165
|
|
|
142
166
|
Apps are public by default.
|
|
143
167
|
|
|
168
|
+
Changing an app's access mode needs `--switch-mode`. Without it the command changes nothing and prints what the change would do (who loses access, what happens to the app's custom domains) and the command to re-run. Service-token mode locks every person out and removes the app's custom domains; leaving it sets them up again with new DNS records to publish. Creating another service token on an app already in service-token mode needs no flag.
|
|
169
|
+
|
|
144
170
|
One-time PIN with email/domain allowlist:
|
|
145
171
|
|
|
146
172
|
```sh
|
|
147
173
|
9pm access allow email my-app dev@example.com
|
|
148
174
|
9pm access allow domain my-app example.com
|
|
149
|
-
9pm access otp my-app
|
|
175
|
+
9pm access otp my-app --switch-mode
|
|
150
176
|
9pm access revoke email my-app dev@example.com
|
|
151
177
|
9pm access revoke domain my-app example.com
|
|
152
178
|
```
|
|
@@ -154,19 +180,19 @@ One-time PIN with email/domain allowlist:
|
|
|
154
180
|
Identity provider access:
|
|
155
181
|
|
|
156
182
|
```sh
|
|
157
|
-
9pm access idp my-app --provider google
|
|
183
|
+
9pm access idp my-app --provider google --switch-mode
|
|
158
184
|
```
|
|
159
185
|
|
|
160
186
|
Machine access:
|
|
161
187
|
|
|
162
188
|
```sh
|
|
163
|
-
9pm access service create my-app --name backend
|
|
189
|
+
9pm access service create my-app --name backend --switch-mode
|
|
164
190
|
```
|
|
165
191
|
|
|
166
192
|
Return to public:
|
|
167
193
|
|
|
168
194
|
```sh
|
|
169
|
-
9pm access public my-app
|
|
195
|
+
9pm access public my-app --switch-mode
|
|
170
196
|
```
|
|
171
197
|
|
|
172
198
|
Create an app-scoped runtime token for server-side allowlist management:
|
|
@@ -178,11 +204,40 @@ Create an app-scoped runtime token for server-side allowlist management:
|
|
|
178
204
|
Use `9pm_app_...` runtime tokens only from server-side code. They can list, add, and remove email/domain grants for one app. They cannot deploy, create databases, create API keys, or manage another app.
|
|
179
205
|
Service token secrets returned by `access service create` are also server-side secrets.
|
|
180
206
|
|
|
207
|
+
## Custom Domains
|
|
208
|
+
|
|
209
|
+
Connect a domain you own to an app:
|
|
210
|
+
|
|
211
|
+
```sh
|
|
212
|
+
9pm domains add my-app www.example.com
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
This prints the DNS records to publish at your DNS provider, with names relative to your
|
|
216
|
+
domain (`www`, `_acme-challenge.www`) and what DNS shows for each right now. When a TXT value
|
|
217
|
+
is missing, add it as its own TXT record; other TXT values on that name can stay. The root of
|
|
218
|
+
your domain (`@`) cannot hold a CNAME, so a root domain is shown as an `ALIAS` record: add it as
|
|
219
|
+
ALIAS or ANAME (or a CNAME your provider flattens). A correct ALIAS answers with addresses, which
|
|
220
|
+
cannot be compared from outside, so that row follows the platform's own routing check. Then:
|
|
221
|
+
|
|
222
|
+
```sh
|
|
223
|
+
9pm domains wait my-app www.example.com
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
`wait` exits `0` once the domain is live, `10` if it timed out while a record is missing or could
|
|
227
|
+
not be checked, `11` if it timed out with every record checked and found (the platform is still
|
|
228
|
+
finishing; wait again), `20` if the domain failed or expired, and `1` on a usage, sign-in or API
|
|
229
|
+
error. `9pm domains status <app> <hostname> --json` prints `{hostname, app, state, routing, tls,
|
|
230
|
+
provider, nameservers, records, error, expiresAt, checkedAt}`, where `state` is `live`,
|
|
231
|
+
`waiting_for_dns`, `dns_unverified` (routing is active but the records could not be checked),
|
|
232
|
+
`issuing_certificate`, `failed` or `expired`. Each record's `ok` is `null` when the check cannot
|
|
233
|
+
say, and its `check` says why (`not_checked`, or `apex_addresses`). `list`, `status` and `wait`
|
|
234
|
+
only read; `add`, `check`, `restart` and `remove` need permission to configure the app.
|
|
235
|
+
|
|
181
236
|
## Commands
|
|
182
237
|
|
|
183
238
|
```sh
|
|
184
239
|
9pm --version
|
|
185
|
-
9pm deploy [directory] --name <name> [--slug <slug>] [--with-db]
|
|
240
|
+
9pm deploy [directory] --name <name> [--slug <slug>] [--spa | --no-spa] [--with-db]
|
|
186
241
|
9pm deploy [directory] --check [--runtime worker --entry <path> (--assets <dir> | --no-assets)]
|
|
187
242
|
9pm deploy [directory] --runtime container --port 8080 [--health-path /health] [--region auto] [--with-db]
|
|
188
243
|
9pm signup
|
|
@@ -197,17 +252,24 @@ Service token secrets returned by `access service create` are also server-side s
|
|
|
197
252
|
9pm files get <file-id> [--output <path>] [--project <site>]
|
|
198
253
|
9pm files share <file-id> [--expires 24h] [--public] [--project <site>]
|
|
199
254
|
9pm files delete <file-id> [--project <site>]
|
|
200
|
-
9pm deploy [directory] --runtime worker --entry <path> (--assets <dir> | --no-assets) [--with-db]
|
|
255
|
+
9pm deploy [directory] --runtime worker --entry <path> (--assets <dir> | --no-assets) [--spa | --no-spa] [--with-db]
|
|
201
256
|
9pm delete <site> --confirm <slug>
|
|
257
|
+
9pm domains list [<app>] [--owner <organisation>] [--json]
|
|
258
|
+
9pm domains add <app> <hostname> [--json]
|
|
259
|
+
9pm domains status <app> <hostname> [--json]
|
|
260
|
+
9pm domains check <app> <hostname> [--json]
|
|
261
|
+
9pm domains wait <app> <hostname> [--timeout 30m] [--interval 20s] [--json]
|
|
262
|
+
9pm domains restart <app> <hostname>
|
|
263
|
+
9pm domains remove <app> <hostname> --confirm <hostname>
|
|
202
264
|
9pm access show <site>
|
|
203
|
-
9pm access public <site>
|
|
204
|
-
9pm access otp <site>
|
|
205
|
-
9pm access idp <site> [--provider google|github|entra]
|
|
265
|
+
9pm access public <site> [--switch-mode]
|
|
266
|
+
9pm access otp <site> [--switch-mode]
|
|
267
|
+
9pm access idp <site> [--provider google|github|entra] [--switch-mode]
|
|
206
268
|
9pm access allow email <site> <email>
|
|
207
269
|
9pm access allow domain <site> <domain>
|
|
208
270
|
9pm access revoke email <site> <email>
|
|
209
271
|
9pm access revoke domain <site> <domain>
|
|
210
|
-
9pm access service create <site> [--name <name>] [--duration 8760h]
|
|
272
|
+
9pm access service create <site> [--name <name>] [--duration 8760h] [--switch-mode]
|
|
211
273
|
9pm access service revoke <site> <service-token-id>
|
|
212
274
|
9pm access token create <site> [--name <name>]
|
|
213
275
|
9pm access token revoke <site> <token-id>
|
|
@@ -229,6 +291,8 @@ Options:
|
|
|
229
291
|
- `--entry <path>` selects the Worker runtime server entry file
|
|
230
292
|
- `--assets <dir>` makes only that directory of a worker deploy public (remembered for later deploys)
|
|
231
293
|
- `--no-assets` makes no file of a worker deploy public (remembered for later deploys)
|
|
294
|
+
- `--spa` serves `index.html` for every path that has no file, for single-page apps (remembered for later deploys)
|
|
295
|
+
- `--no-spa` returns 404 for a path that has no file, with the deploy's `404.html` when present; the default for new apps (remembered for later deploys)
|
|
232
296
|
- `--port <port>` selects the HTTP port exposed by a container app
|
|
233
297
|
- `--health-path <path>` optionally lets 9pm.ai check container health before marking it healthy
|
|
234
298
|
- `--region <region>` optionally selects provider-neutral container placement
|
package/dist/cli-types.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type AppRuntime = "static" | "worker" | "container";
|
|
|
8
8
|
export type ContainerRegion = "auto" | "us-east" | "us-west" | "europe" | "asia" | "south-america" | "middle-east" | "oceania" | "africa";
|
|
9
9
|
export type ManagedFileScope = "user" | "project";
|
|
10
10
|
export type ManagedFileShareMode = "public" | "login_required";
|
|
11
|
+
export type MissingPagesMode = "legacy" | "spa" | "404";
|
|
11
12
|
export interface Project {
|
|
12
13
|
id: string;
|
|
13
14
|
name: string;
|
|
@@ -16,6 +17,7 @@ export interface Project {
|
|
|
16
17
|
createdAt: string;
|
|
17
18
|
updatedAt: string;
|
|
18
19
|
workerPublicAssets?: string | null;
|
|
20
|
+
missingPages?: MissingPagesMode;
|
|
19
21
|
}
|
|
20
22
|
export interface AppUserFilesUsage {
|
|
21
23
|
usedBytes: number;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** A best guess at the zone a custom hostname lives in: `www.tmrwtitans.com` -> `tmrwtitans.com`. */
|
|
2
|
+
export declare function guessZoneApex(hostname: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* The record name the way most registrars' Host field wants it, relative to the zone:
|
|
5
|
+
* `www.tmrwtitans.com` -> `www`, the apex itself -> `@`. A name outside the zone stays whole.
|
|
6
|
+
*/
|
|
7
|
+
export declare function relativeRecordName(recordHost: string, apex: string): string;
|
package/dist/dns-host.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// AUTO-GENERATED by scripts/generate-cli-package.mjs from the in-repo CLI source -- do not edit.
|
|
2
|
+
// Edit src/cli or src/shared instead; this is regenerated on typecheck/test/build/pack.
|
|
3
|
+
// Record names for a custom domain's DNS instructions, written the way a registrar's Host
|
|
4
|
+
// field wants them. Read by the dashboard's DNS table and by `9pm domains`, and copied into
|
|
5
|
+
// the CLI tarball by scripts/generate-cli-package.mjs, so it must import nothing.
|
|
6
|
+
// Second-level labels that sit under a two-letter country code as part of the public suffix
|
|
7
|
+
// (example.co.uk, example.com.au). Not a public suffix list: it covers the common shapes, and
|
|
8
|
+
// the full name is always shown beside the short one for the cases it misses.
|
|
9
|
+
const SECOND_LEVEL = new Set(["co", "com", "net", "org", "gov", "ac", "edu", "ne", "or", "go"]);
|
|
10
|
+
/** A best guess at the zone a custom hostname lives in: `www.tmrwtitans.com` -> `tmrwtitans.com`. */
|
|
11
|
+
export function guessZoneApex(hostname) {
|
|
12
|
+
const labels = hostname.toLowerCase().replace(/\.$/, "").split(".");
|
|
13
|
+
if (labels.length >= 3 && SECOND_LEVEL.has(labels[labels.length - 2]) && labels[labels.length - 1].length === 2) {
|
|
14
|
+
return labels.slice(-3).join(".");
|
|
15
|
+
}
|
|
16
|
+
return labels.slice(-2).join(".");
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The record name the way most registrars' Host field wants it, relative to the zone:
|
|
20
|
+
* `www.tmrwtitans.com` -> `www`, the apex itself -> `@`. A name outside the zone stays whole.
|
|
21
|
+
*/
|
|
22
|
+
export function relativeRecordName(recordHost, apex) {
|
|
23
|
+
const host = recordHost.toLowerCase().replace(/\.$/, "");
|
|
24
|
+
if (host === apex)
|
|
25
|
+
return "@";
|
|
26
|
+
return host.endsWith(`.${apex}`) ? host.slice(0, -(apex.length + 1)) : host;
|
|
27
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export interface DeployOptions {
|
|
|
18
18
|
runtime?: AppRuntime;
|
|
19
19
|
entry?: string;
|
|
20
20
|
publicAssets?: string;
|
|
21
|
+
missingPages?: "spa" | "404";
|
|
21
22
|
port?: number;
|
|
22
23
|
healthPath?: string;
|
|
23
24
|
region?: ContainerRegion;
|
|
@@ -124,7 +125,7 @@ export interface CreatedServiceToken {
|
|
|
124
125
|
clientSecret: string;
|
|
125
126
|
}
|
|
126
127
|
export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
127
|
-
export declare const CLI_VERSION = "0.
|
|
128
|
+
export declare const CLI_VERSION = "0.72.0";
|
|
128
129
|
type CredentialBackend = "macos-keychain" | "windows-dpapi" | "linux-secret-service" | "file-plaintext" | "none";
|
|
129
130
|
export interface StoredCredentialEntry {
|
|
130
131
|
token: string;
|
|
@@ -225,7 +226,8 @@ export declare class DeployError extends Error {
|
|
|
225
226
|
* prevent (#1061).
|
|
226
227
|
*/
|
|
227
228
|
export declare class DeliberateRefusalError extends Error {
|
|
228
|
-
|
|
229
|
+
readonly code: string | undefined;
|
|
230
|
+
constructor(message: string, code?: string);
|
|
229
231
|
}
|
|
230
232
|
export declare function isDeliberateRefusal(error: unknown): boolean;
|
|
231
233
|
export declare function deployDirectory(initialOptions: DeployOptions): Promise<DeployResult>;
|
|
@@ -271,12 +273,16 @@ export type LogoutSummary = {
|
|
|
271
273
|
};
|
|
272
274
|
export declare function summarizeRevocations(attempts: RevocationAttempt[]): LogoutSummary;
|
|
273
275
|
export declare function getSiteAccess(options: SiteAccessOptions): Promise<AccessState>;
|
|
274
|
-
export declare
|
|
275
|
-
export
|
|
276
|
-
|
|
276
|
+
export declare const ACCESS_MODE_CHANGE_UNCONFIRMED = "access_mode_change_unconfirmed";
|
|
277
|
+
export interface AccessModeChangeOptions extends SiteAccessOptions {
|
|
278
|
+
switchMode?: boolean;
|
|
279
|
+
}
|
|
280
|
+
export declare function setSiteAccessPublic(options: AccessModeChangeOptions): Promise<AccessState["access"]>;
|
|
281
|
+
export declare function setSiteAccessOtp(options: AccessModeChangeOptions): Promise<AccessState["access"]>;
|
|
282
|
+
export declare function setSiteAccessIdp(options: AccessModeChangeOptions & {
|
|
277
283
|
providers?: AccessProviderKey[];
|
|
278
284
|
}): Promise<AccessState["access"]>;
|
|
279
|
-
export declare function createAccessServiceToken(options:
|
|
285
|
+
export declare function createAccessServiceToken(options: AccessModeChangeOptions & {
|
|
280
286
|
name?: string;
|
|
281
287
|
duration?: string;
|
|
282
288
|
}): Promise<CreatedServiceToken>;
|
|
@@ -343,6 +349,7 @@ export interface ListSitesResult {
|
|
|
343
349
|
export declare function listSites(options: ApiOptions & {
|
|
344
350
|
owner?: string;
|
|
345
351
|
}): Promise<ListSitesResult>;
|
|
352
|
+
export declare function deleteWarningLines(slug: string): string[];
|
|
346
353
|
export declare function deleteSite(options: DeleteSiteOptions): Promise<DeletedSiteResult>;
|
|
347
354
|
export interface DeviceAuthFeedbackOptions {
|
|
348
355
|
progressStream?: NodeJS.WriteStream;
|
|
@@ -611,6 +618,36 @@ type CliCommand = {
|
|
|
611
618
|
};
|
|
612
619
|
apiUrl: string;
|
|
613
620
|
token: string;
|
|
621
|
+
} | {
|
|
622
|
+
kind: "domains";
|
|
623
|
+
owner?: string;
|
|
624
|
+
action: {
|
|
625
|
+
kind: "list";
|
|
626
|
+
site?: string;
|
|
627
|
+
json: boolean;
|
|
628
|
+
} | {
|
|
629
|
+
kind: "add" | "status" | "check";
|
|
630
|
+
site: string;
|
|
631
|
+
hostname: string;
|
|
632
|
+
json: boolean;
|
|
633
|
+
} | {
|
|
634
|
+
kind: "wait";
|
|
635
|
+
site: string;
|
|
636
|
+
hostname: string;
|
|
637
|
+
json: boolean;
|
|
638
|
+
timeoutSeconds: number;
|
|
639
|
+
intervalSeconds: number;
|
|
640
|
+
} | {
|
|
641
|
+
kind: "restart";
|
|
642
|
+
site: string;
|
|
643
|
+
hostname: string;
|
|
644
|
+
} | {
|
|
645
|
+
kind: "remove";
|
|
646
|
+
site: string;
|
|
647
|
+
hostname: string;
|
|
648
|
+
};
|
|
649
|
+
apiUrl: string;
|
|
650
|
+
token: string;
|
|
614
651
|
} | {
|
|
615
652
|
kind: "deployments";
|
|
616
653
|
action: {
|
|
@@ -631,13 +668,16 @@ type CliCommand = {
|
|
|
631
668
|
} | {
|
|
632
669
|
kind: "public";
|
|
633
670
|
site: string;
|
|
671
|
+
switchMode?: true;
|
|
634
672
|
} | {
|
|
635
673
|
kind: "otp";
|
|
636
674
|
site: string;
|
|
675
|
+
switchMode?: true;
|
|
637
676
|
} | {
|
|
638
677
|
kind: "idp";
|
|
639
678
|
site: string;
|
|
640
679
|
providers?: AccessProviderKey[];
|
|
680
|
+
switchMode?: true;
|
|
641
681
|
} | {
|
|
642
682
|
kind: "allow";
|
|
643
683
|
site: string;
|
|
@@ -653,6 +693,7 @@ type CliCommand = {
|
|
|
653
693
|
site: string;
|
|
654
694
|
name?: string;
|
|
655
695
|
duration?: string;
|
|
696
|
+
switchMode?: true;
|
|
656
697
|
} | {
|
|
657
698
|
kind: "service-revoke";
|
|
658
699
|
site: string;
|
|
@@ -668,6 +709,7 @@ type CliCommand = {
|
|
|
668
709
|
tokenId: string;
|
|
669
710
|
};
|
|
670
711
|
apiUrl: string;
|
|
712
|
+
apiUrlFrom: ApiUrlSource;
|
|
671
713
|
token: string;
|
|
672
714
|
};
|
|
673
715
|
export declare function parseArgs(argv: string[]): CliCommand;
|
|
@@ -676,7 +718,142 @@ export declare function parseEnvFileEntries(content: string, kind: "secret" | "v
|
|
|
676
718
|
value: string;
|
|
677
719
|
kind: "secret" | "var";
|
|
678
720
|
}>;
|
|
721
|
+
export type ListedDeployment = Pick<Deployment, "id" | "version" | "status" | "createdAt"> & {
|
|
722
|
+
active: boolean;
|
|
723
|
+
};
|
|
724
|
+
export declare function deploymentStatusLabel(deployment: ListedDeployment): string;
|
|
725
|
+
export declare function formatDeploymentsList(deployments: ListedDeployment[]): string[];
|
|
726
|
+
export declare function deploymentsListJson<T extends ListedDeployment>(deployments: T[]): {
|
|
727
|
+
servingDeploymentId: string | null;
|
|
728
|
+
deployments: Array<T & {
|
|
729
|
+
serving: boolean;
|
|
730
|
+
}>;
|
|
731
|
+
};
|
|
732
|
+
export interface CliDnsInstruction {
|
|
733
|
+
type: string;
|
|
734
|
+
host: string;
|
|
735
|
+
value: string;
|
|
736
|
+
optional?: boolean;
|
|
737
|
+
}
|
|
738
|
+
export interface CliDomainDnsCheck {
|
|
739
|
+
provider: string | null;
|
|
740
|
+
nameservers: string[];
|
|
741
|
+
records: Array<{
|
|
742
|
+
type: string;
|
|
743
|
+
host: string;
|
|
744
|
+
expected: string;
|
|
745
|
+
current: string[];
|
|
746
|
+
matches: boolean;
|
|
747
|
+
}>;
|
|
748
|
+
}
|
|
749
|
+
export interface CliDomain {
|
|
750
|
+
hostname: string;
|
|
751
|
+
routingStatus: string;
|
|
752
|
+
tlsStatus: string;
|
|
753
|
+
dnsInstructions: CliDnsInstruction[];
|
|
754
|
+
provisioningError: string | null;
|
|
755
|
+
expireAfter?: string | null;
|
|
756
|
+
expiresAt?: string | null;
|
|
757
|
+
dnsCheck?: CliDomainDnsCheck;
|
|
758
|
+
app?: {
|
|
759
|
+
id: string;
|
|
760
|
+
slug: string;
|
|
761
|
+
name: string;
|
|
762
|
+
};
|
|
763
|
+
}
|
|
764
|
+
export type DomainState = "live" | "waiting_for_dns" | "dns_unverified" | "issuing_certificate" | "failed" | "expired";
|
|
765
|
+
export declare const CUSTOM_DOMAIN_EXPIRED_TEXT = "This domain was removed because its DNS verification was never completed. Add the domain again to retry.";
|
|
766
|
+
export interface DomainRecordStatus {
|
|
767
|
+
type: string;
|
|
768
|
+
name: string;
|
|
769
|
+
fqdn: string;
|
|
770
|
+
expected: string;
|
|
771
|
+
current: string[] | null;
|
|
772
|
+
ok: boolean | null;
|
|
773
|
+
check: DomainRecordCheck;
|
|
774
|
+
apex: boolean;
|
|
775
|
+
optional: boolean;
|
|
776
|
+
}
|
|
777
|
+
export type DomainRecordCheck = "found" | "missing" | "different" | "not_checked" | "apex_addresses";
|
|
778
|
+
export interface DomainStatusJson {
|
|
779
|
+
hostname: string;
|
|
780
|
+
app: string;
|
|
781
|
+
state: DomainState;
|
|
782
|
+
routing: string;
|
|
783
|
+
tls: string;
|
|
784
|
+
provider: string | null;
|
|
785
|
+
nameservers: string[];
|
|
786
|
+
records: DomainRecordStatus[];
|
|
787
|
+
error: string | null;
|
|
788
|
+
expiresAt: string | null;
|
|
789
|
+
checkedAt: string;
|
|
790
|
+
}
|
|
791
|
+
export declare const DOMAIN_WAIT_EXIT: {
|
|
792
|
+
readonly live: 0;
|
|
793
|
+
readonly ownerAction: 10;
|
|
794
|
+
readonly platform: 11;
|
|
795
|
+
readonly failed: 20;
|
|
796
|
+
};
|
|
797
|
+
export declare function domainRecordStatuses(domain: CliDomain): DomainRecordStatus[];
|
|
798
|
+
export declare function deriveDomainState(domain: CliDomain, records?: DomainRecordStatus[]): DomainState;
|
|
799
|
+
export declare function domainStatusJson(domain: CliDomain, app: string, checkedAt: string): DomainStatusJson;
|
|
800
|
+
export declare function domainStateLabel(state: DomainState): string;
|
|
801
|
+
export declare function formatDomainStatus(status: DomainStatusJson, options?: {
|
|
802
|
+
owner?: string;
|
|
803
|
+
}): string[];
|
|
804
|
+
export declare function domainWaitTimeoutMessage(status: DomainStatusJson): string;
|
|
805
|
+
export declare function formatDomainsList(statuses: DomainStatusJson[]): string[];
|
|
806
|
+
export declare class DomainsApiError extends Error {
|
|
807
|
+
readonly status: number;
|
|
808
|
+
readonly code: string | null;
|
|
809
|
+
constructor(message: string, status: number, code: string | null);
|
|
810
|
+
}
|
|
811
|
+
export declare function domainsApiError(status: number, text: string): DomainsApiError;
|
|
812
|
+
export interface DomainCommandOptions extends ApiOptions {
|
|
813
|
+
site: string;
|
|
814
|
+
owner?: string;
|
|
815
|
+
}
|
|
816
|
+
export declare function normalizeDomainArg(value: string): string;
|
|
817
|
+
export declare function listDomainStatuses(options: ApiOptions & {
|
|
818
|
+
site?: string;
|
|
819
|
+
owner?: string;
|
|
820
|
+
now?: () => Date;
|
|
821
|
+
}): Promise<DomainStatusJson[]>;
|
|
822
|
+
export declare function getDomainStatus(options: DomainCommandOptions & {
|
|
823
|
+
hostname: string;
|
|
824
|
+
now?: () => Date;
|
|
825
|
+
}): Promise<DomainStatusJson>;
|
|
826
|
+
export declare function addDomain(options: DomainCommandOptions & {
|
|
827
|
+
hostname: string;
|
|
828
|
+
}): Promise<CliDomain | null>;
|
|
829
|
+
export declare function recheckDomain(options: DomainCommandOptions & {
|
|
830
|
+
hostname: string;
|
|
831
|
+
}): Promise<void>;
|
|
832
|
+
export declare function restartDomain(options: DomainCommandOptions & {
|
|
833
|
+
hostname: string;
|
|
834
|
+
}): Promise<{
|
|
835
|
+
domain: CliDomain;
|
|
836
|
+
replacedInstructions: CliDnsInstruction[];
|
|
837
|
+
}>;
|
|
838
|
+
export declare function removeDomain(options: DomainCommandOptions & {
|
|
839
|
+
hostname: string;
|
|
840
|
+
}): Promise<CliDomain | null>;
|
|
841
|
+
export interface DomainWaitResult {
|
|
842
|
+
status: DomainStatusJson;
|
|
843
|
+
exitCode: number;
|
|
844
|
+
timedOut: boolean;
|
|
845
|
+
}
|
|
846
|
+
export declare function waitForDomain(options: DomainCommandOptions & {
|
|
847
|
+
hostname: string;
|
|
848
|
+
timeoutMs: number;
|
|
849
|
+
intervalMs: number;
|
|
850
|
+
nowMs?: () => number;
|
|
851
|
+
sleepFn?: (ms: number) => Promise<void>;
|
|
852
|
+
onStatus?: (status: DomainStatusJson) => void;
|
|
853
|
+
onRetry?: (error: unknown) => void;
|
|
854
|
+
}): Promise<DomainWaitResult>;
|
|
679
855
|
export declare function healthWithReason(status: string | null | undefined, reason: string | null | undefined): string;
|
|
856
|
+
export type ApiUrlSource = "flag" | "env" | "default";
|
|
680
857
|
export declare function workerPublicFiles(paths: readonly string[], serverEntry: string, selection: string | null): Array<{
|
|
681
858
|
path: string;
|
|
682
859
|
url: string;
|
|
@@ -711,4 +888,15 @@ export declare function hasNoGraphicalDisplay(platform: string, env: Record<stri
|
|
|
711
888
|
export declare function formatAppUserFilesUsageLine(slug: string, usage: AppUserFilesUsage): string;
|
|
712
889
|
export declare class UsageError extends Error {
|
|
713
890
|
}
|
|
891
|
+
export declare function missingPagesLine(deployment: Deployment): string | null;
|
|
892
|
+
type AccessModeChangeAction = Extract<Extract<CliCommand, {
|
|
893
|
+
kind: "access";
|
|
894
|
+
}>["action"], {
|
|
895
|
+
kind: "public" | "otp" | "idp" | "service-create";
|
|
896
|
+
}>;
|
|
897
|
+
export interface AccessApiTarget {
|
|
898
|
+
apiUrl: string;
|
|
899
|
+
apiUrlFrom: ApiUrlSource;
|
|
900
|
+
}
|
|
901
|
+
export declare function accessSwitchModeCommand(action: AccessModeChangeAction, target?: AccessApiTarget): string;
|
|
714
902
|
export {};
|