drop2run 0.3.0 → 0.4.1
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 +15 -2
- package/dist/index.js +90 -24
- package/dist/{package-B5PgBI_i.js → package-sLisZctX.js} +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,7 @@ drop2run login [--device] Sign in and store a token
|
|
|
16
16
|
drop2run logout Remove the stored token
|
|
17
17
|
drop2run init [dir] [--site <subdomain>] Tie this folder to a site
|
|
18
18
|
drop2run deploy [dir] [--site <subdomain>] Publish a folder
|
|
19
|
+
drop2run init|deploy --subdomain <name> Create a new site under a name you pick
|
|
19
20
|
drop2run ls List your sites
|
|
20
21
|
drop2run open [site] Open a site in a browser
|
|
21
22
|
drop2run rollback <deployId> [--site X] Put an earlier version back live
|
|
@@ -30,14 +31,26 @@ drop2run --version Print the version
|
|
|
30
31
|
|
|
31
32
|
## Which site a command acts on
|
|
32
33
|
|
|
33
|
-
`--site`, then `drop2run.json`, then a new
|
|
34
|
-
normal project:
|
|
34
|
+
`--subdomain` creates one under the name you give; otherwise `--site`, then `drop2run.json`, then a new
|
|
35
|
+
site with a generated name. `init` writes that file, so this is the whole of a normal project:
|
|
35
36
|
|
|
36
37
|
```bash
|
|
37
38
|
drop2run init dist # creates a site, writes drop2run.json
|
|
38
39
|
drop2run deploy # publishes dist to it, no arguments
|
|
39
40
|
```
|
|
40
41
|
|
|
42
|
+
```bash
|
|
43
|
+
drop2run init dist --subdomain my-docs # same, but you choose the address
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Lowercase letters, digits and hyphens, not starting or ending with one. A name that is taken, reserved,
|
|
47
|
+
or past the number of self-picked names your plan allows is refused with the reason. It cannot be changed
|
|
48
|
+
later — a site is reached by the address it was created with — so a wrong name means deleting the site,
|
|
49
|
+
which is not undoable.
|
|
50
|
+
|
|
51
|
+
`--site` never creates anything: it finds a site you already have, and fails when nothing matches. That
|
|
52
|
+
is what keeps a subdomain typed one letter wrong from quietly becoming a second site.
|
|
53
|
+
|
|
41
54
|
`deploy` never creates a second site while a `drop2run.json` sits next to it — that would leave the real
|
|
42
55
|
site untouched and you looking at a URL you did not expect.
|
|
43
56
|
|
package/dist/index.js
CHANGED
|
@@ -55,11 +55,17 @@ async function listSites(credentials) {
|
|
|
55
55
|
const body = await call(credentials, "sites");
|
|
56
56
|
return body.sites;
|
|
57
57
|
}
|
|
58
|
-
async function createSite(credentials) {
|
|
58
|
+
async function createSite(credentials, subdomain) {
|
|
59
59
|
const created = await call(
|
|
60
60
|
credentials,
|
|
61
61
|
"sites",
|
|
62
|
-
{
|
|
62
|
+
{
|
|
63
|
+
method: "POST",
|
|
64
|
+
// An absent field rather than a null one, because the API reads null, empty and missing the
|
|
65
|
+
// same way and a body carrying only what was asked for is the one that reads correctly in a
|
|
66
|
+
// log.
|
|
67
|
+
body: JSON.stringify(subdomain === void 0 ? {} : { subdomain })
|
|
68
|
+
}
|
|
63
69
|
);
|
|
64
70
|
return { ...created, name: null };
|
|
65
71
|
}
|
|
@@ -369,6 +375,7 @@ const ClientErrorCode = {
|
|
|
369
375
|
/** An upload kept failing after every retry. */
|
|
370
376
|
UploadFailed: "upload_failed"
|
|
371
377
|
};
|
|
378
|
+
const ACCOUNT_HEADER = "X-Drop2Run-Account";
|
|
372
379
|
const CLAIM_TOKEN_HEADER = "X-Claim-Token";
|
|
373
380
|
async function prepareDeploy(siteId, files, options, signal) {
|
|
374
381
|
const manifest = files.map((file) => ({
|
|
@@ -405,6 +412,7 @@ async function request(path, body, options, signal) {
|
|
|
405
412
|
if (body !== void 0) headers["Content-Type"] = "application/json";
|
|
406
413
|
if (options.claimToken) headers[CLAIM_TOKEN_HEADER] = options.claimToken;
|
|
407
414
|
if (options.token) headers.Authorization = `Bearer ${options.token}`;
|
|
415
|
+
if (options.accountId) headers[ACCOUNT_HEADER] = options.accountId;
|
|
408
416
|
const response = await doFetch(`${base}/${path}`, {
|
|
409
417
|
method: "POST",
|
|
410
418
|
headers,
|
|
@@ -865,7 +873,15 @@ function escapesRoot(root, candidate) {
|
|
|
865
873
|
const inside = relative(root, candidate);
|
|
866
874
|
return inside === "" || inside.startsWith("..");
|
|
867
875
|
}
|
|
868
|
-
async function resolveSite(credentials, site) {
|
|
876
|
+
async function resolveSite(credentials, site, subdomain) {
|
|
877
|
+
if (subdomain !== void 0) {
|
|
878
|
+
if (site !== void 0) {
|
|
879
|
+
throw new Error(
|
|
880
|
+
"Give either an existing site or a subdomain for a new one, not both: publishing over a site and creating one are different requests."
|
|
881
|
+
);
|
|
882
|
+
}
|
|
883
|
+
return await createSite(credentials, subdomain);
|
|
884
|
+
}
|
|
869
885
|
if (site === void 0) return await createSite(credentials);
|
|
870
886
|
const wanted = site.trim().toLowerCase();
|
|
871
887
|
const found = (await listSites(credentials)).find(
|
|
@@ -878,8 +894,8 @@ async function resolveSite(credentials, site) {
|
|
|
878
894
|
}
|
|
879
895
|
return found;
|
|
880
896
|
}
|
|
881
|
-
async function publish(credentials, source, site, onProgress) {
|
|
882
|
-
const target = await resolveSite(credentials, site);
|
|
897
|
+
async function publish(credentials, source, site, onProgress, subdomain) {
|
|
898
|
+
const target = await resolveSite(credentials, site, subdomain);
|
|
883
899
|
let files = 0;
|
|
884
900
|
let url = target.url;
|
|
885
901
|
let unchanged = false;
|
|
@@ -910,8 +926,11 @@ async function publish(credentials, source, site, onProgress) {
|
|
|
910
926
|
});
|
|
911
927
|
return { url, siteId: target.siteId, subdomain: target.subdomain, files, unchanged };
|
|
912
928
|
}
|
|
913
|
-
function publishDirectory(credentials, directory, site, onProgress) {
|
|
914
|
-
|
|
929
|
+
async function publishDirectory(credentials, directory, site, onProgress, subdomain) {
|
|
930
|
+
const found = await stat(directory).catch(() => null);
|
|
931
|
+
if (found === null) throw new Error(`There is no folder at ${directory}.`);
|
|
932
|
+
if (!found.isDirectory()) throw new Error(`${directory} is a file, not a folder to publish.`);
|
|
933
|
+
return await publish(credentials, directorySource(directory), site, onProgress, subdomain);
|
|
915
934
|
}
|
|
916
935
|
const silentProgress = Object.assign(() => {
|
|
917
936
|
}, { done: () => {
|
|
@@ -1122,14 +1141,20 @@ async function list() {
|
|
|
1122
1141
|
code: 0
|
|
1123
1142
|
};
|
|
1124
1143
|
}
|
|
1125
|
-
async function deployCommand(directory, site, report = silentProgress) {
|
|
1144
|
+
async function deployCommand(directory, site, report = silentProgress, subdomain) {
|
|
1126
1145
|
const found = credentialsOr();
|
|
1127
1146
|
if ("result" in found) return found.result;
|
|
1128
1147
|
const project = readProject();
|
|
1129
|
-
const target = site ?? project?.siteId;
|
|
1130
1148
|
const folder = directory ?? project?.dir ?? ".";
|
|
1149
|
+
const target = subdomain === void 0 ? site ?? project?.siteId : void 0;
|
|
1131
1150
|
try {
|
|
1132
|
-
const result = await publishDirectory(
|
|
1151
|
+
const result = await publishDirectory(
|
|
1152
|
+
found.credentials,
|
|
1153
|
+
resolve(folder),
|
|
1154
|
+
target,
|
|
1155
|
+
report,
|
|
1156
|
+
subdomain
|
|
1157
|
+
);
|
|
1133
1158
|
const what = result.unchanged ? "Already up to date — nothing needed publishing." : `Published ${result.files.toLocaleString()} ${result.files === 1 ? "file" : "files"}.`;
|
|
1134
1159
|
return {
|
|
1135
1160
|
text: `${what}
|
|
@@ -1143,7 +1168,7 @@ ${result.url}`,
|
|
|
1143
1168
|
report.done();
|
|
1144
1169
|
}
|
|
1145
1170
|
}
|
|
1146
|
-
async function init(directory, site) {
|
|
1171
|
+
async function init(directory, site, subdomain) {
|
|
1147
1172
|
const found = credentialsOr();
|
|
1148
1173
|
if ("result" in found) return found.result;
|
|
1149
1174
|
if (readProject() !== null) {
|
|
@@ -1152,7 +1177,7 @@ async function init(directory, site) {
|
|
|
1152
1177
|
);
|
|
1153
1178
|
}
|
|
1154
1179
|
try {
|
|
1155
|
-
const target = site === void 0 ? await createSite(found.credentials) : await findSite(found.credentials, site);
|
|
1180
|
+
const target = site === void 0 ? await createSite(found.credentials, subdomain) : await findSite(found.credentials, site);
|
|
1156
1181
|
const project = {
|
|
1157
1182
|
siteId: target.siteId,
|
|
1158
1183
|
subdomain: target.subdomain,
|
|
@@ -1290,6 +1315,7 @@ const HELP = `drop2run — publish a static site from the command line
|
|
|
1290
1315
|
drop2run logout Remove the stored token
|
|
1291
1316
|
drop2run init [dir] [--site <subdomain>] Tie this folder to a site (writes drop2run.json)
|
|
1292
1317
|
drop2run deploy [dir] [--site <subdomain>] Publish a folder (default: . or drop2run.json)
|
|
1318
|
+
drop2run init|deploy --subdomain <name> Create a new site under a name you pick
|
|
1293
1319
|
drop2run ls List your sites
|
|
1294
1320
|
drop2run open [site] Open a site in a browser
|
|
1295
1321
|
drop2run rollback <deployId> [--site X] Put an earlier version back live
|
|
@@ -1300,14 +1326,19 @@ const HELP = `drop2run — publish a static site from the command line
|
|
|
1300
1326
|
drop2run --version Print the version
|
|
1301
1327
|
|
|
1302
1328
|
Flags
|
|
1303
|
-
--json
|
|
1304
|
-
--site X
|
|
1305
|
-
--
|
|
1306
|
-
--
|
|
1329
|
+
--json Print machine-readable output instead of text
|
|
1330
|
+
--site X Act on an existing site rather than the one in drop2run.json
|
|
1331
|
+
--subdomain X Create a new site under this name (init and deploy only)
|
|
1332
|
+
--device Sign in by approving a code on another machine
|
|
1333
|
+
--yes Confirm a deletion, which cannot be undone
|
|
1307
1334
|
|
|
1308
1335
|
Where a site comes from
|
|
1309
|
-
--
|
|
1310
|
-
|
|
1336
|
+
--subdomain creates one under the name you give. Otherwise: --site, then
|
|
1337
|
+
drop2run.json, then a new site with a generated name. \`init\` writes that
|
|
1338
|
+
file, so \`deploy\` in the same folder needs no arguments at all.
|
|
1339
|
+
|
|
1340
|
+
--site only ever finds a site you already have; it never creates one, so a
|
|
1341
|
+
subdomain typed wrong fails instead of quietly becoming a second site.
|
|
1311
1342
|
|
|
1312
1343
|
Signing in
|
|
1313
1344
|
\`login\` opens a browser and listens on 127.0.0.1, so it needs both on this
|
|
@@ -1324,12 +1355,40 @@ function flagValue(args, flag) {
|
|
|
1324
1355
|
const value = args[at + 1];
|
|
1325
1356
|
return value === void 0 || value.startsWith("-") ? void 0 : value;
|
|
1326
1357
|
}
|
|
1358
|
+
const VALUE_FLAGS = ["--site", "--subdomain"];
|
|
1359
|
+
function positionals(argv) {
|
|
1360
|
+
const found = [];
|
|
1361
|
+
for (let at = 0; at < argv.length; at++) {
|
|
1362
|
+
const argument = argv[at];
|
|
1363
|
+
if (argument === void 0) continue;
|
|
1364
|
+
if (VALUE_FLAGS.includes(argument)) {
|
|
1365
|
+
const value = argv[at + 1];
|
|
1366
|
+
if (value !== void 0 && !value.startsWith("-")) at++;
|
|
1367
|
+
continue;
|
|
1368
|
+
}
|
|
1369
|
+
if (!argument.startsWith("-")) found.push(argument);
|
|
1370
|
+
}
|
|
1371
|
+
return found;
|
|
1372
|
+
}
|
|
1373
|
+
function subdomainFlagProblem(argv, command, site, subdomain) {
|
|
1374
|
+
if (!argv.includes("--subdomain")) return void 0;
|
|
1375
|
+
if (subdomain === void 0) {
|
|
1376
|
+
return "`--subdomain` needs a name after it, for example `--subdomain my-docs`.";
|
|
1377
|
+
}
|
|
1378
|
+
if (site !== void 0) {
|
|
1379
|
+
return "`--site` and `--subdomain` cannot both be given: `--site` publishes to a site you already have, and `--subdomain` creates a new one. Drop whichever is not what you meant.";
|
|
1380
|
+
}
|
|
1381
|
+
if (command !== "init" && command !== "deploy") {
|
|
1382
|
+
return `\`--subdomain\` only applies to \`init\` and \`deploy\`, which can create a site. Use \`--site\` to tell \`${command}\` which of your sites to act on.`;
|
|
1383
|
+
}
|
|
1384
|
+
return void 0;
|
|
1385
|
+
}
|
|
1327
1386
|
async function run(argv) {
|
|
1328
1387
|
const json = argv.includes("--json");
|
|
1329
|
-
const positional = argv
|
|
1388
|
+
const positional = positionals(argv);
|
|
1330
1389
|
const [command, ...rest] = positional;
|
|
1331
1390
|
if (argv.includes("--version")) {
|
|
1332
|
-
const { version } = await import("./package-
|
|
1391
|
+
const { version } = await import("./package-sLisZctX.js").then(
|
|
1333
1392
|
(module) => module.default
|
|
1334
1393
|
);
|
|
1335
1394
|
return { text: version, json: { version }, code: 0 };
|
|
@@ -1338,17 +1397,24 @@ async function run(argv) {
|
|
|
1338
1397
|
if (askedForHelp) return { text: HELP, json: { help: HELP }, code: 0 };
|
|
1339
1398
|
if (command === void 0) return { text: HELP, json: { help: HELP }, code: 1 };
|
|
1340
1399
|
const site = flagValue(argv, "--site");
|
|
1400
|
+
const subdomain = flagValue(argv, "--subdomain");
|
|
1401
|
+
const refusal = subdomainFlagProblem(argv, command, site, subdomain);
|
|
1402
|
+
if (refusal !== void 0) {
|
|
1403
|
+
const failed = { text: refusal, json: { error: refusal }, code: 1 };
|
|
1404
|
+
return json ? { ...failed, text: JSON.stringify(failed.json, null, 2) } : failed;
|
|
1405
|
+
}
|
|
1341
1406
|
const result = await dispatch(
|
|
1342
1407
|
command,
|
|
1343
1408
|
rest,
|
|
1344
1409
|
site,
|
|
1345
1410
|
json,
|
|
1346
1411
|
argv.includes("--device"),
|
|
1347
|
-
argv.includes("--yes")
|
|
1412
|
+
argv.includes("--yes"),
|
|
1413
|
+
subdomain
|
|
1348
1414
|
);
|
|
1349
1415
|
return json ? { ...result, text: JSON.stringify(result.json, null, 2) } : result;
|
|
1350
1416
|
}
|
|
1351
|
-
async function dispatch(command, rest, site, json, device, confirmed) {
|
|
1417
|
+
async function dispatch(command, rest, site, json, device, confirmed, subdomain) {
|
|
1352
1418
|
switch (command) {
|
|
1353
1419
|
case "login": {
|
|
1354
1420
|
const print = json ? () => {
|
|
@@ -1358,14 +1424,14 @@ async function dispatch(command, rest, site, json, device, confirmed) {
|
|
|
1358
1424
|
case "logout":
|
|
1359
1425
|
return logout();
|
|
1360
1426
|
case "init":
|
|
1361
|
-
return await init(rest[0] ?? ".", site);
|
|
1427
|
+
return await init(rest[0] ?? ".", site, subdomain);
|
|
1362
1428
|
case "deploy": {
|
|
1363
1429
|
const report = json ? silentProgress : progressWriter(
|
|
1364
1430
|
(text) => process.stderr.write(text),
|
|
1365
1431
|
process.stderr.isTTY === true,
|
|
1366
1432
|
process.stderr.columns ?? 80
|
|
1367
1433
|
);
|
|
1368
|
-
return await deployCommand(rest[0], site, report);
|
|
1434
|
+
return await deployCommand(rest[0], site, report, subdomain);
|
|
1369
1435
|
}
|
|
1370
1436
|
case "ls":
|
|
1371
1437
|
case "list":
|