ninepm 0.81.0 → 0.85.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 +31 -3
- package/dist/index.d.ts +62 -2
- package/dist/index.js +477 -14
- package/dist/qr-code.d.ts +48 -0
- package/dist/qr-code.js +85 -0
- package/dist/vendor/qrcodegen.d.ts +93 -0
- package/dist/vendor/qrcodegen.js +879 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -163,6 +163,8 @@ Delete an app, its managed database, managed container app, and retained image:
|
|
|
163
163
|
|
|
164
164
|
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.
|
|
165
165
|
|
|
166
|
+
For a static or Worker app with no custom domain, `9pm delete` also prints `Its address stops serving the app within about a minute.` It prints nothing about timing for a container app or an app with a custom domain: how long those keep serving after a delete has not been measured, so check the address yourself.
|
|
167
|
+
|
|
166
168
|
## Access Modes
|
|
167
169
|
|
|
168
170
|
Apps are public by default.
|
|
@@ -267,9 +269,34 @@ another service's certificate check uses `_acme-challenge`) is not ours, so leav
|
|
|
267
269
|
that sends no such list it prints no deletion advice at all. When the removal is still finishing
|
|
268
270
|
upstream (the API answers `202` with `releasing: true`), it says so, names no record to delete, and
|
|
269
271
|
prints the `9pm domains list` command: once the domain is no longer listed, it has stopped serving
|
|
270
|
-
from 9pm.
|
|
271
|
-
|
|
272
|
-
|
|
272
|
+
from 9pm. Such a domain shows as `removing` in `list` and `status` (`"removing": true` in `--json`),
|
|
273
|
+
and `wait` on it exits `20`. Since 0.80.0.
|
|
274
|
+
|
|
275
|
+
Since 0.84.0, `9pm domains removed [--owner <organisation>]` lists the DNS records you may delete
|
|
276
|
+
after a removal that finished in the background: a `remove` that answered `releasing`, or a domain of
|
|
277
|
+
a deleted app, finished later by the platform. It is the same list `remove` prints when it finishes
|
|
278
|
+
itself, under the same rule (delete a record only while it still has the value shown), and the
|
|
279
|
+
printed hint after a still-finishing removal or `9pm delete` points at it, with `--owner` and
|
|
280
|
+
`--api-url` kept. A removal is listed for 30 days after it finishes, only to the account that owned
|
|
281
|
+
the domain, and not at all once the hostname has been added again anywhere: the server checks the
|
|
282
|
+
certificate provider for it when you run the command, and a domain it couldn't check is named without
|
|
283
|
+
its records, with the command to ask about it again. The server checks ten domains per page; the
|
|
284
|
+
command reads up to 20 pages and says so if more remain. `--hostname <hostname>` asks about one
|
|
285
|
+
domain only. `--json` prints the API's answer with its pages merged (`next` is null once every page
|
|
286
|
+
was read). Against a server without the route it says it can't list any, prints no record and exits `1`.
|
|
287
|
+
|
|
288
|
+
Since 0.83.0, `9pm domains cleanup <app> <hostname>` lists the setup TXT records 9pm issued for a
|
|
289
|
+
live domain and no longer needs, such as an earlier `_acme-challenge` value or the
|
|
290
|
+
`_cf-custom-hostname` ownership record (`--json` prints the API's answer). Each may be deleted only
|
|
291
|
+
while it still has the value shown; a different value at that name is not ours. The list is checked
|
|
292
|
+
against the certificate provider when you run the command: a value the provider still asks for is
|
|
293
|
+
never in it, a domain that is not live lists nothing, and if the provider cannot be read, or the
|
|
294
|
+
domain changes while it is being checked, the command fails and lists nothing; run it again. Only values the API issued are candidates, never anything read from public
|
|
295
|
+
DNS. `9pm domains status` on a live domain prints the command. `9pm domains remove` lists these values
|
|
296
|
+
with the rest of the domain's records, since once the domain is removed none of them is needed.
|
|
297
|
+
After `9pm domains restart`, the values it says no longer count are worded the same way. Against a
|
|
298
|
+
server without the route, `cleanup` says it can't list any and exits `1`. Values replaced before the
|
|
299
|
+
server kept them cannot be listed.
|
|
273
300
|
|
|
274
301
|
`9pm domains move <hostname> --to <app>` moves a domain to another app of the same account. It keeps
|
|
275
302
|
its certificate and the DNS records already published, so nothing is validated again. Without a
|
|
@@ -317,6 +344,7 @@ and none can be listed for it later.
|
|
|
317
344
|
9pm domains restart <app> <hostname> # only after a certificate failed; record values may change
|
|
318
345
|
9pm domains remove <app> <hostname> --confirm <hostname> [--json]
|
|
319
346
|
9pm domains move [<app>] <hostname> --to <app> [--json]
|
|
347
|
+
9pm domains removed [--hostname <hostname>] [--owner <organisation>] [--json] # records to delete after a removal that finished in the background
|
|
320
348
|
9pm access show <site>
|
|
321
349
|
9pm access public <site> [--switch-mode]
|
|
322
350
|
9pm access otp <site> [--switch-mode]
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { Agent } from "undici";
|
|
3
|
+
import { type ProjectQrAddress } from "./qr-code.js";
|
|
3
4
|
import { type DomainNext, type DomainReason, type DomainRecordStatus, type DomainState, type DomainStateDnsCheck, type DomainStateDnsInstruction, type DomainStateInput } from "./domain-state.js";
|
|
4
5
|
import type { AccessGrant, AccessGrantType, AccessProviderKey, AppAccessSettings, AppAccessServiceToken, AppAccessToken, AppDatabase, AppRuntime, AppUserFilesUsage, ContainerImageUploadInstruction, ContainerRegion, Deployment, ManagedFileObject, ManagedFileShare, ManagedFileUsage, Project } from "./cli-types.js";
|
|
5
6
|
export interface DeployOptions {
|
|
@@ -112,6 +113,8 @@ export interface DeletedSiteResult {
|
|
|
112
113
|
customDomainsReleasing?: unknown;
|
|
113
114
|
containerApplications?: number;
|
|
114
115
|
containerImages?: number;
|
|
116
|
+
flyTeardownsQueued?: number;
|
|
117
|
+
workerScripts?: unknown;
|
|
115
118
|
accessApps: number;
|
|
116
119
|
serviceTokens: number;
|
|
117
120
|
databases: number;
|
|
@@ -120,7 +123,7 @@ export interface DeletedSiteResult {
|
|
|
120
123
|
metadata: boolean;
|
|
121
124
|
errors?: string[];
|
|
122
125
|
}
|
|
123
|
-
export declare function deletedDomainLines(deleted: Pick<DeletedSiteResult, "customDomainCleanup" | "customDomainsReleasing"
|
|
126
|
+
export declare function deletedDomainLines(deleted: Pick<DeletedSiteResult, "customDomainCleanup" | "customDomainsReleasing">, options?: DomainFormatOptions): string[];
|
|
124
127
|
export interface CreatedRuntimeToken {
|
|
125
128
|
token: string;
|
|
126
129
|
appAccessToken: AppAccessToken;
|
|
@@ -130,7 +133,7 @@ export interface CreatedServiceToken {
|
|
|
130
133
|
clientSecret: string;
|
|
131
134
|
}
|
|
132
135
|
export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
|
|
133
|
-
export declare const CLI_VERSION = "0.
|
|
136
|
+
export declare const CLI_VERSION = "0.85.0";
|
|
134
137
|
type CredentialBackend = "macos-keychain" | "windows-dpapi" | "linux-secret-service" | "file-plaintext" | "none";
|
|
135
138
|
export interface StoredCredentialEntry {
|
|
136
139
|
token: string;
|
|
@@ -355,6 +358,8 @@ export declare function listSites(options: ApiOptions & {
|
|
|
355
358
|
owner?: string;
|
|
356
359
|
}): Promise<ListSitesResult>;
|
|
357
360
|
export declare function deleteWarningLines(slug: string): string[];
|
|
361
|
+
export declare const DELETE_SERVING_BOUND_LINE = "Its address stops serving the app within about a minute.";
|
|
362
|
+
export declare function deletedAppStopsServingQuickly(deleted: Pick<DeletedSiteResult, "workerScripts" | "containerApplications" | "flyTeardownsQueued" | "customDomains" | "customDomainsReleasing" | "errors">): boolean;
|
|
358
363
|
export declare function deleteSite(options: DeleteSiteOptions): Promise<DeletedSiteResult>;
|
|
359
364
|
export interface DeviceAuthFeedbackOptions {
|
|
360
365
|
progressStream?: NodeJS.WriteStream;
|
|
@@ -528,6 +533,7 @@ type CliCommand = {
|
|
|
528
533
|
confirmSlug: string;
|
|
529
534
|
apiUrl: string;
|
|
530
535
|
token: string;
|
|
536
|
+
apiUrlFrom?: ApiUrlSource;
|
|
531
537
|
} | {
|
|
532
538
|
kind: "apps";
|
|
533
539
|
apiUrl: string;
|
|
@@ -624,6 +630,17 @@ type CliCommand = {
|
|
|
624
630
|
};
|
|
625
631
|
apiUrl: string;
|
|
626
632
|
token: string;
|
|
633
|
+
} | {
|
|
634
|
+
kind: "qr";
|
|
635
|
+
site: string;
|
|
636
|
+
owner?: string;
|
|
637
|
+
address?: string;
|
|
638
|
+
format: "svg" | "png";
|
|
639
|
+
out?: string;
|
|
640
|
+
terminal: boolean;
|
|
641
|
+
json: boolean;
|
|
642
|
+
apiUrl: string;
|
|
643
|
+
token: string;
|
|
627
644
|
} | {
|
|
628
645
|
kind: "domains";
|
|
629
646
|
owner?: string;
|
|
@@ -648,6 +665,11 @@ type CliCommand = {
|
|
|
648
665
|
kind: "restart";
|
|
649
666
|
site: string;
|
|
650
667
|
hostname: string;
|
|
668
|
+
} | {
|
|
669
|
+
kind: "cleanup";
|
|
670
|
+
site: string;
|
|
671
|
+
hostname: string;
|
|
672
|
+
json: boolean;
|
|
651
673
|
} | {
|
|
652
674
|
kind: "remove";
|
|
653
675
|
site: string;
|
|
@@ -659,6 +681,10 @@ type CliCommand = {
|
|
|
659
681
|
hostname: string;
|
|
660
682
|
to: string;
|
|
661
683
|
json: boolean;
|
|
684
|
+
} | {
|
|
685
|
+
kind: "removed";
|
|
686
|
+
json: boolean;
|
|
687
|
+
hostname?: string;
|
|
662
688
|
};
|
|
663
689
|
apiUrl: string;
|
|
664
690
|
token: string;
|
|
@@ -866,7 +892,24 @@ export interface DomainCleanup {
|
|
|
866
892
|
}
|
|
867
893
|
export declare function parseDomainCleanup(value: unknown): DomainCleanup | null;
|
|
868
894
|
export declare function domainCleanupLines(cleanup: DomainCleanup): string[];
|
|
895
|
+
export declare function getDomainSetupCleanup(options: DomainCommandOptions & {
|
|
896
|
+
hostname: string;
|
|
897
|
+
}): Promise<unknown>;
|
|
898
|
+
export declare function domainSetupCleanupLines(body: unknown, hostname: string): string[];
|
|
899
|
+
export declare function setupCleanupLines(hostname: string, records: DomainCleanupRecord[]): string[];
|
|
869
900
|
export declare function domainRemovalPendingLines(hostname: string, app: string, options: DomainFormatOptions): string[];
|
|
901
|
+
export declare const FINISHED_REMOVAL_PAGES_PER_COMMAND = 20;
|
|
902
|
+
export declare function getFinishedDomainRemovals(options: ApiOptions & {
|
|
903
|
+
owner?: string;
|
|
904
|
+
hostname?: string;
|
|
905
|
+
}): Promise<unknown>;
|
|
906
|
+
export interface FinishedDomainRemoval {
|
|
907
|
+
hostname: string;
|
|
908
|
+
finishedAt: string | null;
|
|
909
|
+
cleanup: DomainCleanup;
|
|
910
|
+
}
|
|
911
|
+
export declare function parseFinishedDomainRemovals(body: unknown): FinishedDomainRemoval[] | null;
|
|
912
|
+
export declare function finishedDomainRemovalLines(body: unknown, options?: DomainFormatOptions): string[];
|
|
870
913
|
export interface DomainMove {
|
|
871
914
|
body: unknown;
|
|
872
915
|
hostname: string;
|
|
@@ -909,6 +952,23 @@ export declare function waitForDomain(options: DomainCommandOptions & {
|
|
|
909
952
|
onRetry?: (error: unknown) => void;
|
|
910
953
|
}): Promise<DomainWaitResult>;
|
|
911
954
|
export declare function healthWithReason(status: string | null | undefined, reason: string | null | undefined): string;
|
|
955
|
+
export declare const QR_PNG_PIXELS_PER_MODULE = 16;
|
|
956
|
+
/**
|
|
957
|
+
* The minimum width in centimetres, rounded UP to the millimetre: it is a floor, so rounding
|
|
958
|
+
* to nearest would print a 26.5 mm minimum as "2.6 cm", below what the code needs.
|
|
959
|
+
*/
|
|
960
|
+
export declare function qrMinimumWidthCmText(minimumWidthMm: number): string;
|
|
961
|
+
export declare const QR_ACCESS_NOTE = "This app is private. Scanning the code doesn't grant access: people still have to sign in and be allowed in.";
|
|
962
|
+
export declare function qrCustomDomainNote(hostname: string): string;
|
|
963
|
+
/**
|
|
964
|
+
* The returned address `--address` names, or an error listing the valid ones. The value is
|
|
965
|
+
* normalized first - a bare hostname gets `https://`, case is ignored, a trailing `/` is
|
|
966
|
+
* allowed - and must then match an address the server offered: no other host, path, query,
|
|
967
|
+
* fragment, credentials, port or scheme. The CLI never encodes a URL the server did not offer.
|
|
968
|
+
*/
|
|
969
|
+
export declare function pickQrAddress(addresses: readonly ProjectQrAddress[], requested: string | undefined): ProjectQrAddress;
|
|
970
|
+
/** An 8-bit greyscale PNG of a module matrix (quiet zone included), black on white. */
|
|
971
|
+
export declare function encodeQrPng(modules: readonly (readonly boolean[])[], scale?: number): Buffer;
|
|
912
972
|
export type ApiUrlSource = "flag" | "env" | "default";
|
|
913
973
|
export declare function workerPublicFiles(paths: readonly string[], serverEntry: string, selection: string | null): Array<{
|
|
914
974
|
path: string;
|