@driggsby/deploy 0.2.4 → 0.3.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 +4 -1
- package/dist/base-url.d.ts +1 -0
- package/dist/base-url.js +23 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +8 -1
- package/dist/deploy.d.ts +1 -0
- package/dist/deploy.js +1 -0
- package/dist/entrypoint.js +6 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4 -1
- package/dist/live-addresses.d.ts +8 -0
- package/dist/live-addresses.js +45 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -25,7 +25,10 @@ npx @driggsby/deploy
|
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
This reads `driggsby.json` in the current directory, deploys the `serve`
|
|
28
|
-
folder, and makes it live.
|
|
28
|
+
folder, and makes it live. It prints two addresses: the app's page in
|
|
29
|
+
Driggsby first, where it runs with the person's data, then the app's own
|
|
30
|
+
`driggsby.dev` address, which shows no Driggsby data when opened
|
|
31
|
+
directly. A first deploy creates the app and saves its
|
|
29
32
|
assigned address back into `driggsby.json` — keep (commit) that updated
|
|
30
33
|
file, because it is the only record of the app's address; a checkout that
|
|
31
34
|
discards it makes the next deploy create a second app at a new address.
|
package/dist/base-url.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare const PUBLIC_BASE_URL = "https://app.driggsby.com";
|
|
2
2
|
export declare function isLoopbackBaseUrl(baseUrl: string): boolean;
|
|
3
3
|
export declare function resolveBaseUrl(env: NodeJS.ProcessEnv): string;
|
|
4
|
+
export declare function consoleUrlOnOrigin(consoleUrl: string | null, baseUrl: string): string | null;
|
package/dist/base-url.js
CHANGED
|
@@ -44,3 +44,26 @@ export function resolveBaseUrl(env) {
|
|
|
44
44
|
}
|
|
45
45
|
return trimmed;
|
|
46
46
|
}
|
|
47
|
+
// The Driggsby page address the server hands back after a deploy is printed
|
|
48
|
+
// first and unquoted, as this tool's own word on where to go, so it is
|
|
49
|
+
// accepted only on the origin this run is signed in to: an answer naming any
|
|
50
|
+
// other host (a lookalike included) yields null, and the caller prints the
|
|
51
|
+
// app's own address alone. Anything that does not parse as a URL, or that
|
|
52
|
+
// carries userinfo (which reads as a different host), is no address either.
|
|
53
|
+
// What comes back is the parsed href, so control bytes in a path arrive
|
|
54
|
+
// percent-encoded rather than raw.
|
|
55
|
+
export function consoleUrlOnOrigin(consoleUrl, baseUrl) {
|
|
56
|
+
if (consoleUrl === null) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
const parsed = new URL(consoleUrl);
|
|
61
|
+
if (parsed.username !== "" || parsed.password !== "") {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return parsed.origin === new URL(baseUrl).origin ? parsed.href : null;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
package/dist/client.d.ts
CHANGED
package/dist/client.js
CHANGED
|
@@ -265,9 +265,16 @@ function parseFinalized(parsed) {
|
|
|
265
265
|
appSlug: stringField(parsed, "app_slug"),
|
|
266
266
|
versionNumber: integerField(parsed, "version_number"),
|
|
267
267
|
live: parsed.live === true,
|
|
268
|
-
url:
|
|
268
|
+
url: optionalUrlField(parsed, "url"),
|
|
269
|
+
consoleUrl: optionalUrlField(parsed, "console_url"),
|
|
269
270
|
};
|
|
270
271
|
}
|
|
272
|
+
// A blank address is no address: it would otherwise take the printed slot
|
|
273
|
+
// meant for a real one.
|
|
274
|
+
function optionalUrlField(record, field) {
|
|
275
|
+
const value = record[field];
|
|
276
|
+
return typeof value === "string" && value.trim() !== "" ? value : null;
|
|
277
|
+
}
|
|
271
278
|
function stringField(record, field) {
|
|
272
279
|
const value = record[field];
|
|
273
280
|
if (typeof value !== "string") {
|
package/dist/deploy.d.ts
CHANGED
package/dist/deploy.js
CHANGED
|
@@ -85,6 +85,7 @@ export async function deployCollectedFiles(api, slug, collected, options) {
|
|
|
85
85
|
versionNumber: outcome.versionNumber,
|
|
86
86
|
live: outcome.live,
|
|
87
87
|
url: outcome.url,
|
|
88
|
+
consoleUrl: outcome.consoleUrl,
|
|
88
89
|
fileCount: collected.files.length,
|
|
89
90
|
uploadedBlobCount: uploadedShas.size,
|
|
90
91
|
uploadedBytes,
|
package/dist/entrypoint.js
CHANGED
|
@@ -8,6 +8,7 @@ import { resolveBaseUrl } from "./base-url.js";
|
|
|
8
8
|
import { deployProjectFiles } from "./deploy.js";
|
|
9
9
|
import { DeployApiError, DeployError } from "./errors.js";
|
|
10
10
|
import { collectDeployFiles, formatBytes } from "./manifest.js";
|
|
11
|
+
import { hasLiveAddress, liveAddresses, liveAddressLines } from "./live-addresses.js";
|
|
11
12
|
import { readProjectConfig } from "./project-config.js";
|
|
12
13
|
import { capForTerminal, quotedForTerminal, wrapProse } from "./terminal-text.js";
|
|
13
14
|
// Server-supplied error text is bounded like every other string this bin did
|
|
@@ -74,8 +75,11 @@ export async function runDeployEntrypoint(io) {
|
|
|
74
75
|
// sentence. The bounds never truncate legitimate values: a slug tops
|
|
75
76
|
// out at 63 characters and the app URL at 84.
|
|
76
77
|
io.out(`Deployed ${quotedForTerminal(outcome.appSlug, 80)} (v${outcome.versionNumber}, ${uploadedNote}).\n`);
|
|
77
|
-
|
|
78
|
-
|
|
78
|
+
// The Driggsby page for the app first, where it runs with the person's
|
|
79
|
+
// data, then the app's own address: the same lines the driggsby CLI prints.
|
|
80
|
+
const addresses = liveAddresses(outcome.url, outcome.consoleUrl, baseUrl);
|
|
81
|
+
if (hasLiveAddress(addresses)) {
|
|
82
|
+
io.out(`Live at:\n${liveAddressLines(addresses)}`);
|
|
79
83
|
}
|
|
80
84
|
return 0;
|
|
81
85
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { DeployApiError, DeployError } from "./errors.ts";
|
|
2
|
-
export { PUBLIC_BASE_URL, isLoopbackBaseUrl, resolveBaseUrl } from "./base-url.ts";
|
|
2
|
+
export { PUBLIC_BASE_URL, consoleUrlOnOrigin, isLoopbackBaseUrl, resolveBaseUrl } from "./base-url.ts";
|
|
3
3
|
export { MAX_FILE_BYTES, MAX_FILE_COUNT, MAX_PATH_LENGTH, MAX_TOTAL_BYTES, slugProblem, } from "./limits.ts";
|
|
4
4
|
export { type ProjectConfig, readProjectConfig, writeAssignedSlug } from "./project-config.ts";
|
|
5
5
|
export { type CollectedDeploy, type DeployFile, collectDeployFiles, formatBytes, } from "./manifest.ts";
|
|
6
6
|
export { type BlobsMissing, type CreatedApp, type CreatedVersion, type DeployApi, type FinalizedVersion, type ManifestFile, type VersionList, type VersionSummary, createApp, createVersion, finalizeVersion, listVersions, setLiveVersion, uploadBlob, } from "./client.ts";
|
|
7
7
|
export { type DeployOptions, type DeployOutcome, type ProjectDeployOptions, type ProjectDeployResult, deployCollectedFiles, deployProjectFiles, } from "./deploy.ts";
|
|
8
|
+
export { type LiveAddresses, MAX_LIVE_ADDRESS_CHARS, hasLiveAddress, liveAddresses, liveAddressLines, } from "./live-addresses.ts";
|
|
8
9
|
export { capForTerminal, quotedForTerminal, sanitizeForTerminal, wrapProse, } from "./terminal-text.ts";
|
package/dist/index.js
CHANGED
|
@@ -5,12 +5,15 @@ export { DeployApiError, DeployError } from "./errors.js";
|
|
|
5
5
|
// The base-URL policy: which origin the token travels to, and what
|
|
6
6
|
// DRIGGSBY_BASE_URL may override it with. One implementation for both this
|
|
7
7
|
// package's bin and the driggsby CLI.
|
|
8
|
-
export { PUBLIC_BASE_URL, isLoopbackBaseUrl, resolveBaseUrl } from "./base-url.js";
|
|
8
|
+
export { PUBLIC_BASE_URL, consoleUrlOnOrigin, isLoopbackBaseUrl, resolveBaseUrl } from "./base-url.js";
|
|
9
9
|
export { MAX_FILE_BYTES, MAX_FILE_COUNT, MAX_PATH_LENGTH, MAX_TOTAL_BYTES, slugProblem, } from "./limits.js";
|
|
10
10
|
export { readProjectConfig, writeAssignedSlug } from "./project-config.js";
|
|
11
11
|
export { collectDeployFiles, formatBytes, } from "./manifest.js";
|
|
12
12
|
export { createApp, createVersion, finalizeVersion, listVersions, setLiveVersion, uploadBlob, } from "./client.js";
|
|
13
13
|
export { deployCollectedFiles, deployProjectFiles, } from "./deploy.js";
|
|
14
|
+
// The addresses a deploy or rollback prints, shared by this package's bin
|
|
15
|
+
// and the driggsby CLI so both say the same thing.
|
|
16
|
+
export { MAX_LIVE_ADDRESS_CHARS, hasLiveAddress, liveAddresses, liveAddressLines, } from "./live-addresses.js";
|
|
14
17
|
// Terminal-safety helpers for anything that echoes untrusted text (file
|
|
15
18
|
// names, server strings) into CLI output. See terminal-text.ts for what the
|
|
16
19
|
// sanitizer strips and the deliberate boundary of that defense.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare const MAX_LIVE_ADDRESS_CHARS = 200;
|
|
2
|
+
export interface LiveAddresses {
|
|
3
|
+
url: string | null;
|
|
4
|
+
consoleUrl: string | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function liveAddresses(url: string | null, consoleUrl: string | null, baseUrl: string): LiveAddresses;
|
|
7
|
+
export declare function hasLiveAddress(addresses: LiveAddresses): boolean;
|
|
8
|
+
export declare function liveAddressLines(addresses: LiveAddresses): string;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// The addresses printed under a "Live ... at:" line, by the driggsby CLI
|
|
2
|
+
// and by this package's own bin alike. The Driggsby page for the app comes
|
|
3
|
+
// first: that is where the person sees it running with their own data. The
|
|
4
|
+
// app's own origin follows, named for what it is, because the app gets no
|
|
5
|
+
// Driggsby data when opened there. Both are server-supplied strings,
|
|
6
|
+
// sanitized and length-bounded before printing. A server that predates
|
|
7
|
+
// the Driggsby page hands back only the app's own address, which then
|
|
8
|
+
// prints alone, as it always did.
|
|
9
|
+
import { consoleUrlOnOrigin } from "./base-url.js";
|
|
10
|
+
import { capForTerminal, wrapProse } from "./terminal-text.js";
|
|
11
|
+
// Longer than any address Driggsby issues (a slug tops out at 63
|
|
12
|
+
// characters), short enough that a hostile answer cannot flood the terminal.
|
|
13
|
+
export const MAX_LIVE_ADDRESS_CHARS = 200;
|
|
14
|
+
// The Driggsby page is accepted only on the origin this run is signed in
|
|
15
|
+
// to (see consoleUrlOnOrigin). Both values are sanitized here, so what is
|
|
16
|
+
// decided on is exactly what prints; a value that sanitizes to nothing is
|
|
17
|
+
// no address.
|
|
18
|
+
export function liveAddresses(url, consoleUrl, baseUrl) {
|
|
19
|
+
return { url: printable(url), consoleUrl: printable(consoleUrlOnOrigin(consoleUrl, baseUrl)) };
|
|
20
|
+
}
|
|
21
|
+
export function hasLiveAddress(addresses) {
|
|
22
|
+
return addresses.consoleUrl !== null || addresses.url !== null;
|
|
23
|
+
}
|
|
24
|
+
// Empty when there is nothing to print, so "at:" is promised only when an
|
|
25
|
+
// address follows.
|
|
26
|
+
export function liveAddressLines(addresses) {
|
|
27
|
+
const primary = addresses.consoleUrl ?? addresses.url;
|
|
28
|
+
if (primary === null) {
|
|
29
|
+
return "";
|
|
30
|
+
}
|
|
31
|
+
let text = `\n ${primary}\n`;
|
|
32
|
+
if (addresses.consoleUrl !== null && addresses.url !== null) {
|
|
33
|
+
text +=
|
|
34
|
+
`\n${wrapProse("The app's own address, which shows no Driggsby data when opened directly:")}\n\n` +
|
|
35
|
+
` ${addresses.url}\n`;
|
|
36
|
+
}
|
|
37
|
+
return text;
|
|
38
|
+
}
|
|
39
|
+
function printable(value) {
|
|
40
|
+
if (value === null) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const clean = capForTerminal(value, MAX_LIVE_ADDRESS_CHARS).trim();
|
|
44
|
+
return clean === "" ? null : clean;
|
|
45
|
+
}
|