@dropthis/cli 0.31.0 → 0.33.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 +36 -10
- package/dist/cli.cjs +658 -114
- package/dist/cli.cjs.map +1 -1
- package/node_modules/@dropthis/node/README.md +2 -2
- package/node_modules/@dropthis/node/dist/edge.cjs +21 -1
- package/node_modules/@dropthis/node/dist/edge.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/edge.d.cts +1 -1
- package/node_modules/@dropthis/node/dist/edge.d.ts +1 -1
- package/node_modules/@dropthis/node/dist/edge.mjs +21 -1
- package/node_modules/@dropthis/node/dist/edge.mjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.cjs +100 -1
- package/node_modules/@dropthis/node/dist/index.cjs.map +1 -1
- package/node_modules/@dropthis/node/dist/index.d.cts +43 -3
- package/node_modules/@dropthis/node/dist/index.d.ts +43 -3
- package/node_modules/@dropthis/node/dist/index.mjs +98 -1
- package/node_modules/@dropthis/node/dist/index.mjs.map +1 -1
- package/node_modules/@dropthis/node/dist/{workspaces-Xmo2L46y.d.cts → workspaces-CebiV4DS.d.cts} +59 -1
- package/node_modules/@dropthis/node/dist/{workspaces-Xmo2L46y.d.ts → workspaces-CebiV4DS.d.ts} +59 -1
- package/node_modules/@dropthis/node/package.json +1 -1
- package/package.json +49 -49
package/dist/cli.cjs
CHANGED
|
@@ -305,6 +305,16 @@ function exitCodeFor(code) {
|
|
|
305
305
|
if (code === "verify_timeout") return 7;
|
|
306
306
|
return 1;
|
|
307
307
|
}
|
|
308
|
+
var EXIT_CODES = {
|
|
309
|
+
"0": "success",
|
|
310
|
+
"1": "api_error \u2014 the server returned an error (see the error envelope)",
|
|
311
|
+
"2": "invalid_usage \u2014 bad arguments, bad options, or an unknown command",
|
|
312
|
+
"3": "auth_error \u2014 missing or invalid credential; re-authenticate (dropthis login)",
|
|
313
|
+
"4": "local_input_error \u2014 a local file or path could not be read",
|
|
314
|
+
"5": "network_error \u2014 could not reach the API; safe to retry",
|
|
315
|
+
"6": "verify_pending \u2014 a domain is not verified yet; retry later (domains verify)",
|
|
316
|
+
"7": "verify_timeout \u2014 domain verification timed out while waiting (--wait)"
|
|
317
|
+
};
|
|
308
318
|
|
|
309
319
|
// src/program.ts
|
|
310
320
|
var import_commander = require("commander");
|
|
@@ -324,7 +334,8 @@ async function resolveCredential(input) {
|
|
|
324
334
|
...stored.keyId ? { keyId: stored.keyId } : {},
|
|
325
335
|
...stored.keyLast4 ? { keyLast4: stored.keyLast4 } : {},
|
|
326
336
|
...stored.accountId ? { accountId: stored.accountId } : {},
|
|
327
|
-
...stored.email ? { email: stored.email } : {}
|
|
337
|
+
...stored.email ? { email: stored.email } : {},
|
|
338
|
+
...stored.scopes?.length ? { scopes: stored.scopes } : {}
|
|
328
339
|
};
|
|
329
340
|
}
|
|
330
341
|
async function requireCredential(input) {
|
|
@@ -673,14 +684,55 @@ async function runApiKeysCreate(input, deps) {
|
|
|
673
684
|
} catch {
|
|
674
685
|
return writeAuthError(deps);
|
|
675
686
|
}
|
|
676
|
-
const
|
|
687
|
+
const keyType = input.type ?? "delegated";
|
|
688
|
+
if (input.workspace && keyType !== "service") {
|
|
689
|
+
return writeError(
|
|
690
|
+
deps,
|
|
691
|
+
"invalid_usage",
|
|
692
|
+
"--workspace is only valid with --service (it pins a CI service key to one workspace). A delegated login key is account-scoped and switchable \u2014 use `dropthis workspace use <slug>` to change its active workspace."
|
|
693
|
+
);
|
|
694
|
+
}
|
|
695
|
+
if (input.allowedWorkspaces?.length && keyType === "service") {
|
|
696
|
+
return writeError(
|
|
697
|
+
deps,
|
|
698
|
+
"invalid_usage",
|
|
699
|
+
"--allowed-workspace is only valid for delegated keys; do not combine it with --service."
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
if (keyType === "service" && !input.workspace) {
|
|
703
|
+
return writeError(
|
|
704
|
+
deps,
|
|
705
|
+
"invalid_usage",
|
|
706
|
+
"Service keys must be pinned to a workspace.",
|
|
707
|
+
"Run: dropthis workspace list to see slugs, then: dropthis api-keys create --service --workspace <slug>"
|
|
708
|
+
);
|
|
709
|
+
}
|
|
710
|
+
const label = input.label ?? (keyType === "service" ? `Service key${input.workspace ? ` (${input.workspace})` : ""}` : "CLI key");
|
|
711
|
+
const createInput = {
|
|
712
|
+
label,
|
|
713
|
+
type: keyType
|
|
714
|
+
};
|
|
715
|
+
if (keyType === "service" && input.workspace) {
|
|
716
|
+
createInput.workspace = input.workspace;
|
|
717
|
+
}
|
|
718
|
+
if (input.allowedWorkspaces?.length) {
|
|
719
|
+
createInput.allowedWorkspaces = input.allowedWorkspaces;
|
|
720
|
+
}
|
|
721
|
+
const result = await deps.client.apiKeys.create(createInput);
|
|
677
722
|
if (result.error) return writeApiError(deps, result.error);
|
|
678
723
|
const data = result.data;
|
|
679
724
|
const pairs = [];
|
|
680
725
|
if (data.id) pairs.push(["ID", String(data.id)]);
|
|
681
726
|
if (data.key) pairs.push(["Key", String(data.key)]);
|
|
682
727
|
if (data.keyLast4) pairs.push(["Last 4", String(data.keyLast4)]);
|
|
728
|
+
if (data.label) pairs.push(["Label", String(data.label)]);
|
|
683
729
|
writeKv(deps, pairs, { ok: true, api_key: result.data });
|
|
730
|
+
if (deps.outputMode === "human") {
|
|
731
|
+
deps.stderr(
|
|
732
|
+
`${hint("Store this key now \u2014 it will not be shown again.")}
|
|
733
|
+
`
|
|
734
|
+
);
|
|
735
|
+
}
|
|
684
736
|
return { exitCode: 0 };
|
|
685
737
|
}
|
|
686
738
|
async function runApiKeysList(_input, deps) {
|
|
@@ -845,7 +897,10 @@ var COMMAND_ANNOTATIONS = {
|
|
|
845
897
|
},
|
|
846
898
|
"api-keys create": {
|
|
847
899
|
auth: "required",
|
|
848
|
-
examples: [
|
|
900
|
+
examples: [
|
|
901
|
+
"dropthis api-keys create --label CI --json",
|
|
902
|
+
"dropthis api-keys create --service --workspace acme --json"
|
|
903
|
+
]
|
|
849
904
|
},
|
|
850
905
|
"api-keys list": {
|
|
851
906
|
auth: "required",
|
|
@@ -870,17 +925,6 @@ var COMMAND_ANNOTATIONS = {
|
|
|
870
925
|
"dropthis workspace use ws_team123"
|
|
871
926
|
]
|
|
872
927
|
},
|
|
873
|
-
keys: {
|
|
874
|
-
auth: "required",
|
|
875
|
-
examples: ["dropthis keys create --service --workspace acme --json"]
|
|
876
|
-
},
|
|
877
|
-
"keys create": {
|
|
878
|
-
auth: "required",
|
|
879
|
-
examples: [
|
|
880
|
-
"dropthis keys create --json",
|
|
881
|
-
"dropthis keys create --service --workspace acme --json"
|
|
882
|
-
]
|
|
883
|
-
},
|
|
884
928
|
login: {
|
|
885
929
|
examples: [
|
|
886
930
|
"dropthis login",
|
|
@@ -908,7 +952,9 @@ var COMMAND_ANNOTATIONS = {
|
|
|
908
952
|
auth: "required",
|
|
909
953
|
examples: ["dropthis account delete --yes --json"]
|
|
910
954
|
},
|
|
911
|
-
doctor: {
|
|
955
|
+
doctor: {
|
|
956
|
+
examples: ["dropthis doctor --json", "dropthis doctor --online --json"]
|
|
957
|
+
},
|
|
912
958
|
upgrade: { examples: ["dropthis upgrade", "dropthis upgrade --json"] },
|
|
913
959
|
commands: { examples: ["dropthis commands --json"] }
|
|
914
960
|
};
|
|
@@ -935,6 +981,12 @@ function toEntry(cmd, path) {
|
|
|
935
981
|
function buildCatalog(program) {
|
|
936
982
|
return program.commands.map((cmd) => toEntry(cmd, []));
|
|
937
983
|
}
|
|
984
|
+
function buildGlobalOptions(program) {
|
|
985
|
+
return program.options.map((o) => ({
|
|
986
|
+
flags: o.flags,
|
|
987
|
+
description: o.description
|
|
988
|
+
}));
|
|
989
|
+
}
|
|
938
990
|
|
|
939
991
|
// src/commands/commands.ts
|
|
940
992
|
async function runCommands(_input, deps) {
|
|
@@ -942,7 +994,9 @@ async function runCommands(_input, deps) {
|
|
|
942
994
|
`${JSON.stringify({
|
|
943
995
|
ok: true,
|
|
944
996
|
output: "JSON by default in CI, pipes, non-TTY, --json, or --quiet.",
|
|
945
|
-
commands: buildCatalog(deps.program)
|
|
997
|
+
commands: buildCatalog(deps.program),
|
|
998
|
+
global_options: buildGlobalOptions(deps.program),
|
|
999
|
+
exit_codes: EXIT_CODES
|
|
946
1000
|
})}
|
|
947
1001
|
`
|
|
948
1002
|
);
|
|
@@ -1032,10 +1086,76 @@ function spreadData(data) {
|
|
|
1032
1086
|
}
|
|
1033
1087
|
|
|
1034
1088
|
// src/version.ts
|
|
1035
|
-
var CLI_VERSION = true ? "0.
|
|
1089
|
+
var CLI_VERSION = true ? "0.33.0" : "0.0.0-dev";
|
|
1036
1090
|
|
|
1037
1091
|
// src/commands/doctor.ts
|
|
1038
|
-
async function
|
|
1092
|
+
async function onlineChecks(deps, hasCredential) {
|
|
1093
|
+
if (!hasCredential) {
|
|
1094
|
+
return {
|
|
1095
|
+
checks: [
|
|
1096
|
+
{
|
|
1097
|
+
name: "auth",
|
|
1098
|
+
status: "fail",
|
|
1099
|
+
detail: "No credential found \u2014 run `dropthis login` or set DROPTHIS_API_KEY."
|
|
1100
|
+
}
|
|
1101
|
+
],
|
|
1102
|
+
exitCode: exitCodeFor("auth_error")
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
1105
|
+
const account = await deps.client.account.get();
|
|
1106
|
+
if (account.error) {
|
|
1107
|
+
const code = cliErrorCodeFor(account.error);
|
|
1108
|
+
const isAuth = code === "auth_error";
|
|
1109
|
+
return {
|
|
1110
|
+
checks: [
|
|
1111
|
+
{
|
|
1112
|
+
name: "api_reachable",
|
|
1113
|
+
status: isAuth ? "ok" : "fail",
|
|
1114
|
+
detail: isAuth ? "reached the API" : `could not reach the API: ${account.error.message}`
|
|
1115
|
+
},
|
|
1116
|
+
{
|
|
1117
|
+
name: "auth",
|
|
1118
|
+
status: isAuth ? "fail" : "warn",
|
|
1119
|
+
detail: isAuth ? "credential rejected \u2014 re-authenticate with `dropthis login`" : account.error.message
|
|
1120
|
+
}
|
|
1121
|
+
],
|
|
1122
|
+
exitCode: exitCodeFor(code)
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
const data = account.data;
|
|
1126
|
+
const checks = [
|
|
1127
|
+
{ name: "api_reachable", status: "ok", detail: "reached the API" },
|
|
1128
|
+
{ name: "auth", status: "ok", detail: "credential accepted" }
|
|
1129
|
+
];
|
|
1130
|
+
const ws = data?.workspace;
|
|
1131
|
+
checks.push(
|
|
1132
|
+
ws?.name ? {
|
|
1133
|
+
name: "workspace",
|
|
1134
|
+
status: "ok",
|
|
1135
|
+
detail: `active: ${String(ws.name)} (${String(ws.kind)})`
|
|
1136
|
+
} : {
|
|
1137
|
+
name: "workspace",
|
|
1138
|
+
status: "warn",
|
|
1139
|
+
detail: "no active workspace resolved \u2014 pass --workspace or run `dropthis workspace use`"
|
|
1140
|
+
}
|
|
1141
|
+
);
|
|
1142
|
+
if (data?.plan) {
|
|
1143
|
+
checks.push({ name: "plan", status: "ok", detail: String(data.plan) });
|
|
1144
|
+
}
|
|
1145
|
+
const domains = await deps.client.domains.list();
|
|
1146
|
+
if (!domains.error) {
|
|
1147
|
+
const list = domains.data?.domains ?? [];
|
|
1148
|
+
const live = list.filter((d) => d.status === "live").length;
|
|
1149
|
+
const pending = list.length - live;
|
|
1150
|
+
checks.push({
|
|
1151
|
+
name: "domains",
|
|
1152
|
+
status: pending > 0 ? "warn" : "ok",
|
|
1153
|
+
detail: `${list.length} connected, ${live} live${pending > 0 ? `, ${pending} pending verification` : ""}`
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
return { checks, exitCode: 0 };
|
|
1157
|
+
}
|
|
1158
|
+
async function runDoctor(input, deps) {
|
|
1039
1159
|
const stored = await deps.store.read();
|
|
1040
1160
|
const credential = await resolveCredential({
|
|
1041
1161
|
env: deps.env,
|
|
@@ -1048,13 +1168,30 @@ async function runDoctor(_input, deps) {
|
|
|
1048
1168
|
["Auth", authSource],
|
|
1049
1169
|
["Storage", storageBackend]
|
|
1050
1170
|
];
|
|
1171
|
+
if (!input.online) {
|
|
1172
|
+
writeKv(deps, pairs, {
|
|
1173
|
+
ok: true,
|
|
1174
|
+
version: CLI_VERSION,
|
|
1175
|
+
auth: { source: authSource },
|
|
1176
|
+
storage: { backend: storageBackend }
|
|
1177
|
+
});
|
|
1178
|
+
return { exitCode: 0 };
|
|
1179
|
+
}
|
|
1180
|
+
const { checks, exitCode } = await onlineChecks(
|
|
1181
|
+
deps,
|
|
1182
|
+
credential !== void 0
|
|
1183
|
+
);
|
|
1184
|
+
for (const c of checks) {
|
|
1185
|
+
pairs.push([c.name, `${c.status} \u2014 ${c.detail}`]);
|
|
1186
|
+
}
|
|
1051
1187
|
writeKv(deps, pairs, {
|
|
1052
|
-
ok:
|
|
1188
|
+
ok: exitCode === 0,
|
|
1053
1189
|
version: CLI_VERSION,
|
|
1054
1190
|
auth: { source: authSource },
|
|
1055
|
-
storage: { backend: storageBackend }
|
|
1191
|
+
storage: { backend: storageBackend },
|
|
1192
|
+
checks
|
|
1056
1193
|
});
|
|
1057
|
-
return { exitCode
|
|
1194
|
+
return { exitCode };
|
|
1058
1195
|
}
|
|
1059
1196
|
|
|
1060
1197
|
// src/commands/domains.ts
|
|
@@ -1635,8 +1772,8 @@ async function runDropsDelete(target, input, deps) {
|
|
|
1635
1772
|
return { exitCode: 0 };
|
|
1636
1773
|
}
|
|
1637
1774
|
|
|
1638
|
-
// src/commands/
|
|
1639
|
-
async function
|
|
1775
|
+
// src/commands/invitations.ts
|
|
1776
|
+
async function runInvitationsList(_input, deps) {
|
|
1640
1777
|
try {
|
|
1641
1778
|
await requireCredential({
|
|
1642
1779
|
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
@@ -1646,45 +1783,67 @@ async function runKeysCreate(input, deps) {
|
|
|
1646
1783
|
} catch {
|
|
1647
1784
|
return writeAuthError(deps);
|
|
1648
1785
|
}
|
|
1649
|
-
const
|
|
1650
|
-
if (
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1786
|
+
const result = await deps.client.invitations.list();
|
|
1787
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
1788
|
+
const raw = unwrapListData(result.data, "invitations");
|
|
1789
|
+
const items = Array.isArray(raw) ? raw : [];
|
|
1790
|
+
if (deps.outputMode === "human") {
|
|
1791
|
+
if (items.length === 0) {
|
|
1792
|
+
writeEmpty(deps, "No pending invitations.", {
|
|
1793
|
+
ok: true,
|
|
1794
|
+
invitations: []
|
|
1795
|
+
});
|
|
1796
|
+
} else {
|
|
1797
|
+
for (const inv of items) {
|
|
1798
|
+
deps.stdout(`${inv.email} ${inv.role} ${inv.status} ${inv.id}
|
|
1799
|
+
`);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
} else {
|
|
1803
|
+
writeJson(deps, { ok: true, invitations: items });
|
|
1664
1804
|
}
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1805
|
+
return { exitCode: 0 };
|
|
1806
|
+
}
|
|
1807
|
+
async function runInvitationsAccept(input, deps) {
|
|
1808
|
+
try {
|
|
1809
|
+
await requireCredential({
|
|
1810
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
1811
|
+
env: deps.env,
|
|
1812
|
+
store: deps.store
|
|
1813
|
+
});
|
|
1814
|
+
} catch {
|
|
1815
|
+
return writeAuthError(deps);
|
|
1672
1816
|
}
|
|
1673
|
-
const result = await deps.client.
|
|
1817
|
+
const result = await deps.client.invitations.accept({ token: input.token });
|
|
1674
1818
|
if (result.error) return writeApiError(deps, result.error);
|
|
1675
|
-
const
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1819
|
+
const ws = result.data;
|
|
1820
|
+
writeHumanOrJson(
|
|
1821
|
+
deps,
|
|
1822
|
+
success(`Joined ${ws.name} (${ws.slug}) \u2014 now your active workspace.`),
|
|
1823
|
+
{ ok: true, workspace: ws }
|
|
1824
|
+
);
|
|
1825
|
+
return { exitCode: 0 };
|
|
1826
|
+
}
|
|
1827
|
+
async function runInvitationsAcceptById(input, deps) {
|
|
1828
|
+
try {
|
|
1829
|
+
await requireCredential({
|
|
1830
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
1831
|
+
env: deps.env,
|
|
1832
|
+
store: deps.store
|
|
1833
|
+
});
|
|
1834
|
+
} catch {
|
|
1835
|
+
return writeAuthError(deps);
|
|
1687
1836
|
}
|
|
1837
|
+
const result = await deps.client.invitations.acceptById({
|
|
1838
|
+
invitationId: input.invitationId
|
|
1839
|
+
});
|
|
1840
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
1841
|
+
const ws = result.data;
|
|
1842
|
+
writeHumanOrJson(
|
|
1843
|
+
deps,
|
|
1844
|
+
success(`Joined ${ws.name} (${ws.slug}) \u2014 now your active workspace.`),
|
|
1845
|
+
{ ok: true, workspace: ws }
|
|
1846
|
+
);
|
|
1688
1847
|
return { exitCode: 0 };
|
|
1689
1848
|
}
|
|
1690
1849
|
|
|
@@ -1747,7 +1906,8 @@ async function runLoginInteractive(deps) {
|
|
|
1747
1906
|
const authedClient = deps.createClient(session.data.token);
|
|
1748
1907
|
const apiKey = await authedClient.apiKeys.create({
|
|
1749
1908
|
label: "CLI",
|
|
1750
|
-
type: "delegated"
|
|
1909
|
+
type: "delegated",
|
|
1910
|
+
...deps.scope ? { scopes: [deps.scope] } : {}
|
|
1751
1911
|
});
|
|
1752
1912
|
if (apiKey.error) {
|
|
1753
1913
|
prompts4.cancel(apiKey.error.message);
|
|
@@ -1759,6 +1919,7 @@ async function runLoginInteractive(deps) {
|
|
|
1759
1919
|
keyLast4: apiKey.data.keyLast4,
|
|
1760
1920
|
accountId: apiKey.data.accountId ?? session.data.accountId,
|
|
1761
1921
|
email,
|
|
1922
|
+
...apiKey.data.scopes ? { scopes: apiKey.data.scopes } : {},
|
|
1762
1923
|
storage: "secure"
|
|
1763
1924
|
});
|
|
1764
1925
|
prompts4.outro("Logged in successfully.");
|
|
@@ -1793,7 +1954,10 @@ async function runLoginVerify(input, deps) {
|
|
|
1793
1954
|
const authedClient = deps.createClient(session.data.token);
|
|
1794
1955
|
const apiKey = await authedClient.apiKeys.create({
|
|
1795
1956
|
label: "CLI",
|
|
1796
|
-
type: "delegated"
|
|
1957
|
+
type: "delegated",
|
|
1958
|
+
// A single bundle name (e.g. "team") requests a capability-scoped key; the
|
|
1959
|
+
// server returns the resolved scope list on the mint response.
|
|
1960
|
+
...input.scope ? { scopes: [input.scope] } : {}
|
|
1797
1961
|
});
|
|
1798
1962
|
if (apiKey.error) {
|
|
1799
1963
|
return writeApiError(deps, apiKey.error);
|
|
@@ -1804,6 +1968,7 @@ async function runLoginVerify(input, deps) {
|
|
|
1804
1968
|
keyLast4: apiKey.data.keyLast4,
|
|
1805
1969
|
accountId: apiKey.data.accountId ?? session.data.accountId,
|
|
1806
1970
|
email: input.email,
|
|
1971
|
+
...apiKey.data.scopes ? { scopes: apiKey.data.scopes } : {},
|
|
1807
1972
|
storage: "secure"
|
|
1808
1973
|
});
|
|
1809
1974
|
writeHumanOrJson(deps, success(`Logged in as ${input.email}.`), {
|
|
@@ -1832,6 +1997,115 @@ async function runLogout(input, deps) {
|
|
|
1832
1997
|
return { exitCode: 0 };
|
|
1833
1998
|
}
|
|
1834
1999
|
|
|
2000
|
+
// src/commands/members.ts
|
|
2001
|
+
var prompts5 = __toESM(require("@clack/prompts"), 1);
|
|
2002
|
+
async function runMembersList(workspaceId, _input, deps) {
|
|
2003
|
+
try {
|
|
2004
|
+
await requireCredential({
|
|
2005
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
2006
|
+
env: deps.env,
|
|
2007
|
+
store: deps.store
|
|
2008
|
+
});
|
|
2009
|
+
} catch {
|
|
2010
|
+
return writeAuthError(deps);
|
|
2011
|
+
}
|
|
2012
|
+
const result = await deps.client.members.list(workspaceId);
|
|
2013
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
2014
|
+
const raw = unwrapListData(result.data, "members");
|
|
2015
|
+
const items = Array.isArray(raw) ? raw : [];
|
|
2016
|
+
if (deps.outputMode === "human") {
|
|
2017
|
+
if (items.length === 0) {
|
|
2018
|
+
writeEmpty(deps, "No members.", { ok: true, members: [] });
|
|
2019
|
+
} else {
|
|
2020
|
+
for (const m of items) {
|
|
2021
|
+
const who = m.email || m.accountId;
|
|
2022
|
+
const you = m.isYou ? "(you)" : "";
|
|
2023
|
+
deps.stdout(`${who} ${m.role} ${you}
|
|
2024
|
+
`);
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
} else {
|
|
2028
|
+
writeJson(deps, { ok: true, members: items });
|
|
2029
|
+
}
|
|
2030
|
+
return { exitCode: 0 };
|
|
2031
|
+
}
|
|
2032
|
+
async function runMembersInvite(workspaceId, input, deps) {
|
|
2033
|
+
try {
|
|
2034
|
+
await requireCredential({
|
|
2035
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
2036
|
+
env: deps.env,
|
|
2037
|
+
store: deps.store
|
|
2038
|
+
});
|
|
2039
|
+
} catch {
|
|
2040
|
+
return writeAuthError(deps);
|
|
2041
|
+
}
|
|
2042
|
+
const role = input.role ?? "member";
|
|
2043
|
+
const result = await deps.client.members.invite(workspaceId, {
|
|
2044
|
+
email: input.email,
|
|
2045
|
+
role
|
|
2046
|
+
});
|
|
2047
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
2048
|
+
writeHumanOrJson(deps, success(`Invited ${input.email} as ${role}`), {
|
|
2049
|
+
ok: true,
|
|
2050
|
+
invitation: result.data
|
|
2051
|
+
});
|
|
2052
|
+
return { exitCode: 0 };
|
|
2053
|
+
}
|
|
2054
|
+
async function runMembersRole(workspaceId, accountId, input, deps) {
|
|
2055
|
+
try {
|
|
2056
|
+
await requireCredential({
|
|
2057
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
2058
|
+
env: deps.env,
|
|
2059
|
+
store: deps.store
|
|
2060
|
+
});
|
|
2061
|
+
} catch {
|
|
2062
|
+
return writeAuthError(deps);
|
|
2063
|
+
}
|
|
2064
|
+
const result = await deps.client.members.updateRole(workspaceId, accountId, {
|
|
2065
|
+
role: input.role
|
|
2066
|
+
});
|
|
2067
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
2068
|
+
writeHumanOrJson(deps, success(`Set ${accountId} to ${input.role}`), {
|
|
2069
|
+
ok: true,
|
|
2070
|
+
member: result.data
|
|
2071
|
+
});
|
|
2072
|
+
return { exitCode: 0 };
|
|
2073
|
+
}
|
|
2074
|
+
async function runMembersRemove(workspaceId, accountId, input, deps) {
|
|
2075
|
+
if (!input.yes && input.interactive === false) {
|
|
2076
|
+
return writeError(
|
|
2077
|
+
deps,
|
|
2078
|
+
"invalid_usage",
|
|
2079
|
+
"Pass --yes to remove in non-interactive mode."
|
|
2080
|
+
);
|
|
2081
|
+
}
|
|
2082
|
+
if (!input.yes && input.interactive !== false) {
|
|
2083
|
+
const confirmed = await prompts5.confirm({
|
|
2084
|
+
message: `Remove ${accountId} from workspace ${workspaceId}?`
|
|
2085
|
+
});
|
|
2086
|
+
if (prompts5.isCancel(confirmed) || !confirmed) {
|
|
2087
|
+
return { exitCode: 0 };
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
try {
|
|
2091
|
+
await requireCredential({
|
|
2092
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
2093
|
+
env: deps.env,
|
|
2094
|
+
store: deps.store
|
|
2095
|
+
});
|
|
2096
|
+
} catch {
|
|
2097
|
+
return writeAuthError(deps);
|
|
2098
|
+
}
|
|
2099
|
+
const result = await deps.client.members.remove(workspaceId, accountId);
|
|
2100
|
+
if (result?.error) return writeApiError(deps, result.error);
|
|
2101
|
+
writeHumanOrJson(deps, success(`Removed ${accountId}`), {
|
|
2102
|
+
ok: true,
|
|
2103
|
+
removed: true,
|
|
2104
|
+
account_id: accountId
|
|
2105
|
+
});
|
|
2106
|
+
return { exitCode: 0 };
|
|
2107
|
+
}
|
|
2108
|
+
|
|
1835
2109
|
// src/drop-operations.ts
|
|
1836
2110
|
var import_node_crypto = require("crypto");
|
|
1837
2111
|
var import_promises = require("fs/promises");
|
|
@@ -1968,6 +2242,9 @@ async function parseDropOptions(raw) {
|
|
|
1968
2242
|
if (raw.noindex && raw.index) {
|
|
1969
2243
|
throw new Error("Use either --noindex or --index, not both.");
|
|
1970
2244
|
}
|
|
2245
|
+
if (raw.expiresAt && raw.noExpires) {
|
|
2246
|
+
throw new Error("Use either --expires-at or --no-expires, not both.");
|
|
2247
|
+
}
|
|
1971
2248
|
if (raw.shared && raw.domain) {
|
|
1972
2249
|
throw new Error("Use either --shared or --domain <hostname>, not both.");
|
|
1973
2250
|
}
|
|
@@ -1996,6 +2273,7 @@ async function parseDropOptions(raw) {
|
|
|
1996
2273
|
...raw.noindex ? { noindex: true } : {},
|
|
1997
2274
|
...raw.index ? { noindex: false } : {},
|
|
1998
2275
|
...raw.expiresAt ? { expiresAt: raw.expiresAt } : {},
|
|
2276
|
+
...raw.noExpires ? { expiresAt: null } : {},
|
|
1999
2277
|
...metadata ? { metadata } : {},
|
|
2000
2278
|
...raw.entry ? { entry: raw.entry } : {},
|
|
2001
2279
|
...raw.contentType ? { contentType: raw.contentType } : {},
|
|
@@ -2197,7 +2475,9 @@ async function runPull(target, input, deps) {
|
|
|
2197
2475
|
const dropId = resolved.dropId;
|
|
2198
2476
|
const defaultDirName = resolved.slug || resolved.dropId;
|
|
2199
2477
|
const spin = shouldSpin(deps.outputMode) ? createSpinner("Pulling content\u2026", deps.stderr) : void 0;
|
|
2200
|
-
const
|
|
2478
|
+
const deploymentId = input.deployment;
|
|
2479
|
+
const manifestOptions = deploymentId ? { deploymentId } : void 0;
|
|
2480
|
+
const manifestResult = manifestOptions ? await deps.client.drops.getContent(dropId, manifestOptions) : await deps.client.drops.getContent(dropId);
|
|
2201
2481
|
if (manifestResult.error) {
|
|
2202
2482
|
spin?.fail();
|
|
2203
2483
|
return writeApiError(deps, manifestResult.error);
|
|
@@ -2221,7 +2501,10 @@ async function runPull(target, input, deps) {
|
|
|
2221
2501
|
try {
|
|
2222
2502
|
await (0, import_promises3.mkdir)(outDir, { recursive: true });
|
|
2223
2503
|
for (const { path, dest } of destinations) {
|
|
2224
|
-
const fileResult = await deps.client.drops.getContent(dropId, {
|
|
2504
|
+
const fileResult = await deps.client.drops.getContent(dropId, {
|
|
2505
|
+
path,
|
|
2506
|
+
...deploymentId ? { deploymentId } : {}
|
|
2507
|
+
});
|
|
2225
2508
|
if (fileResult.error) {
|
|
2226
2509
|
spin?.fail();
|
|
2227
2510
|
return writeApiError(deps, {
|
|
@@ -2408,9 +2691,9 @@ async function handleDryRun(dropId, input, raw, deps) {
|
|
|
2408
2691
|
}
|
|
2409
2692
|
|
|
2410
2693
|
// src/commands/update-settings.ts
|
|
2411
|
-
var
|
|
2694
|
+
var prompts6 = __toESM(require("@clack/prompts"), 1);
|
|
2412
2695
|
var NO_SETTINGS_MESSAGE = "Nothing to update. Provide at least one settings option.";
|
|
2413
|
-
var NO_SETTINGS_NEXT_ACTION = "Run dropthis update-settings --help, or retry with one of: --title, --visibility, --password, --no-password, --noindex, --index, --expires-at, --metadata, or --metadata-file. To replace the content at the URL instead, use dropthis update-content <dropId> ./dist.";
|
|
2696
|
+
var NO_SETTINGS_NEXT_ACTION = "Run dropthis update-settings --help, or retry with one of: --title, --visibility, --password, --no-password, --noindex, --index, --expires-at, --no-expires, --domain, --shared, --slug, --metadata, or --metadata-file. To replace the content at the URL instead, use dropthis update-content <dropId> ./dist.";
|
|
2414
2697
|
async function runUpdateSettings(target, raw, deps) {
|
|
2415
2698
|
const apiKey = raw.apiKey ?? deps.apiKey;
|
|
2416
2699
|
try {
|
|
@@ -2440,7 +2723,7 @@ async function runUpdateSettings(target, raw, deps) {
|
|
|
2440
2723
|
if (shouldPrompt(deps)) {
|
|
2441
2724
|
const prompted = await promptForSettings(
|
|
2442
2725
|
dropId,
|
|
2443
|
-
deps.prompts ??
|
|
2726
|
+
deps.prompts ?? prompts6
|
|
2444
2727
|
);
|
|
2445
2728
|
if (!prompted) return { exitCode: 0 };
|
|
2446
2729
|
parsed = { ...parsed, ...prompted };
|
|
@@ -2629,8 +2912,10 @@ async function handleDryRun2(dropId, raw, deps) {
|
|
|
2629
2912
|
if (options.visibility) fields.visibility = options.visibility;
|
|
2630
2913
|
if (options.password !== void 0) fields.password = options.password;
|
|
2631
2914
|
if (options.noindex !== void 0) fields.noindex = options.noindex;
|
|
2632
|
-
if (options.expiresAt) fields.expires_at = options.expiresAt;
|
|
2915
|
+
if (options.expiresAt !== void 0) fields.expires_at = options.expiresAt;
|
|
2633
2916
|
if (options.metadata) fields.metadata = options.metadata;
|
|
2917
|
+
if (options.domain) fields.domain = options.domain;
|
|
2918
|
+
if (options.slug) fields.slug = options.slug;
|
|
2634
2919
|
deps.stdout(
|
|
2635
2920
|
`${JSON.stringify({ ok: true, dryRun: true, kind: "settings_update", target: dropId, fields }, null, 2)}
|
|
2636
2921
|
`
|
|
@@ -2778,6 +3063,8 @@ async function runWhoami(_input, deps) {
|
|
|
2778
3063
|
pairs.push(["Source", credential.source]);
|
|
2779
3064
|
if (credential.accountId ?? account.id)
|
|
2780
3065
|
pairs.push(["Account", String(credential.accountId ?? account.id)]);
|
|
3066
|
+
if (credential.scopes?.length)
|
|
3067
|
+
pairs.push(["Scopes", credential.scopes.join(", ")]);
|
|
2781
3068
|
const jsonEnvelope = {
|
|
2782
3069
|
ok: true,
|
|
2783
3070
|
authenticated: true,
|
|
@@ -2786,13 +3073,15 @@ async function runWhoami(_input, deps) {
|
|
|
2786
3073
|
...credential.keyId ? { key_id: credential.keyId } : {},
|
|
2787
3074
|
...last4 ? { key_last4: last4 } : {},
|
|
2788
3075
|
...credential.accountId ?? account.id ? { account_id: String(credential.accountId ?? account.id) } : {},
|
|
2789
|
-
...credential.email ?? account.email ? { email: String(credential.email ?? account.email) } : {}
|
|
3076
|
+
...credential.email ?? account.email ? { email: String(credential.email ?? account.email) } : {},
|
|
3077
|
+
...credential.scopes?.length ? { scopes: credential.scopes } : {}
|
|
2790
3078
|
};
|
|
2791
3079
|
writeKv(deps, pairs, jsonEnvelope);
|
|
2792
3080
|
return { exitCode: 0 };
|
|
2793
3081
|
}
|
|
2794
3082
|
|
|
2795
3083
|
// src/commands/workspace.ts
|
|
3084
|
+
var prompts7 = __toESM(require("@clack/prompts"), 1);
|
|
2796
3085
|
async function runWorkspaceList(_input, deps) {
|
|
2797
3086
|
try {
|
|
2798
3087
|
await requireCredential({
|
|
@@ -2845,6 +3134,104 @@ async function runWorkspaceUse(slugOrId, _input, deps) {
|
|
|
2845
3134
|
);
|
|
2846
3135
|
return { exitCode: 0 };
|
|
2847
3136
|
}
|
|
3137
|
+
async function runWorkspaceCreate(input, deps) {
|
|
3138
|
+
try {
|
|
3139
|
+
await requireCredential({
|
|
3140
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
3141
|
+
env: deps.env,
|
|
3142
|
+
store: deps.store
|
|
3143
|
+
});
|
|
3144
|
+
} catch {
|
|
3145
|
+
return writeAuthError(deps);
|
|
3146
|
+
}
|
|
3147
|
+
const createInput = { name: input.name };
|
|
3148
|
+
if (input.slug !== void 0) createInput.slug = input.slug;
|
|
3149
|
+
const result = await deps.client.workspaces.create(createInput);
|
|
3150
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
3151
|
+
const ws = result.data;
|
|
3152
|
+
writeHumanOrJson(
|
|
3153
|
+
deps,
|
|
3154
|
+
success(`Created workspace: ${ws.name} (${ws.slug})`),
|
|
3155
|
+
{
|
|
3156
|
+
ok: true,
|
|
3157
|
+
workspace: ws
|
|
3158
|
+
}
|
|
3159
|
+
);
|
|
3160
|
+
if (ws.creatorCanReach === false && deps.outputMode === "human") {
|
|
3161
|
+
deps.stderr(
|
|
3162
|
+
`${hint("This key can't reach the new workspace \u2014 re-authenticate (dropthis login) to pick it up.")}
|
|
3163
|
+
`
|
|
3164
|
+
);
|
|
3165
|
+
}
|
|
3166
|
+
return { exitCode: 0 };
|
|
3167
|
+
}
|
|
3168
|
+
async function runWorkspaceRename(workspaceId, input, deps) {
|
|
3169
|
+
if (input.name === void 0 && input.slug === void 0) {
|
|
3170
|
+
return writeError(
|
|
3171
|
+
deps,
|
|
3172
|
+
"invalid_usage",
|
|
3173
|
+
"Provide --name and/or --slug to rename."
|
|
3174
|
+
);
|
|
3175
|
+
}
|
|
3176
|
+
try {
|
|
3177
|
+
await requireCredential({
|
|
3178
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
3179
|
+
env: deps.env,
|
|
3180
|
+
store: deps.store
|
|
3181
|
+
});
|
|
3182
|
+
} catch {
|
|
3183
|
+
return writeAuthError(deps);
|
|
3184
|
+
}
|
|
3185
|
+
const renameInput = {};
|
|
3186
|
+
if (input.name !== void 0) renameInput.name = input.name;
|
|
3187
|
+
if (input.slug !== void 0) renameInput.slug = input.slug;
|
|
3188
|
+
const result = await deps.client.workspaces.rename(workspaceId, renameInput);
|
|
3189
|
+
if (result.error) return writeApiError(deps, result.error);
|
|
3190
|
+
const ws = result.data;
|
|
3191
|
+
writeHumanOrJson(
|
|
3192
|
+
deps,
|
|
3193
|
+
success(`Renamed workspace: ${ws.name} (${ws.slug})`),
|
|
3194
|
+
{
|
|
3195
|
+
ok: true,
|
|
3196
|
+
workspace: ws
|
|
3197
|
+
}
|
|
3198
|
+
);
|
|
3199
|
+
return { exitCode: 0 };
|
|
3200
|
+
}
|
|
3201
|
+
async function runWorkspaceDelete(workspaceId, input, deps) {
|
|
3202
|
+
if (!input.yes && input.interactive === false) {
|
|
3203
|
+
return writeError(
|
|
3204
|
+
deps,
|
|
3205
|
+
"invalid_usage",
|
|
3206
|
+
"Pass --yes to delete in non-interactive mode."
|
|
3207
|
+
);
|
|
3208
|
+
}
|
|
3209
|
+
if (!input.yes && input.interactive !== false) {
|
|
3210
|
+
const confirmed = await prompts7.confirm({
|
|
3211
|
+
message: `Delete workspace ${workspaceId}?`
|
|
3212
|
+
});
|
|
3213
|
+
if (prompts7.isCancel(confirmed) || !confirmed) {
|
|
3214
|
+
return { exitCode: 0 };
|
|
3215
|
+
}
|
|
3216
|
+
}
|
|
3217
|
+
try {
|
|
3218
|
+
await requireCredential({
|
|
3219
|
+
...deps.apiKey ? { apiKey: deps.apiKey } : {},
|
|
3220
|
+
env: deps.env,
|
|
3221
|
+
store: deps.store
|
|
3222
|
+
});
|
|
3223
|
+
} catch {
|
|
3224
|
+
return writeAuthError(deps);
|
|
3225
|
+
}
|
|
3226
|
+
const result = await deps.client.workspaces.delete(workspaceId);
|
|
3227
|
+
if (result?.error) return writeApiError(deps, result.error);
|
|
3228
|
+
writeHumanOrJson(deps, success(`Deleted workspace ${workspaceId}`), {
|
|
3229
|
+
ok: true,
|
|
3230
|
+
deleted: true,
|
|
3231
|
+
id: workspaceId
|
|
3232
|
+
});
|
|
3233
|
+
return { exitCode: 0 };
|
|
3234
|
+
}
|
|
2848
3235
|
|
|
2849
3236
|
// src/context.ts
|
|
2850
3237
|
var import_node2 = require("@dropthis/node");
|
|
@@ -3170,7 +3557,8 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3170
3557
|
return;
|
|
3171
3558
|
}
|
|
3172
3559
|
}
|
|
3173
|
-
|
|
3560
|
+
const publishWasExplicit = (program.rawArgs ?? []).includes("publish");
|
|
3561
|
+
if (!publishWasExplicit && inputs.length === 1 && typeof publishInput === "string" && isBareWordToken(publishInput) && !await pathExists(publishInput)) {
|
|
3174
3562
|
const suggestion = suggestCommand(
|
|
3175
3563
|
publishInput,
|
|
3176
3564
|
program.commands.map((c) => c.name())
|
|
@@ -3184,13 +3572,15 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3184
3572
|
).exitCode;
|
|
3185
3573
|
return;
|
|
3186
3574
|
}
|
|
3187
|
-
|
|
3188
|
-
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
3193
|
-
|
|
3575
|
+
if (deps.outputMode === "human" && deps.interactive) {
|
|
3576
|
+
const prompts8 = await import("@clack/prompts");
|
|
3577
|
+
const confirmed = await prompts8.confirm({
|
|
3578
|
+
message: `Publish '${publishInput}' as inline text?`,
|
|
3579
|
+
initialValue: false
|
|
3580
|
+
});
|
|
3581
|
+
if (prompts8.isCancel(confirmed) || !confirmed) {
|
|
3582
|
+
return;
|
|
3583
|
+
}
|
|
3194
3584
|
}
|
|
3195
3585
|
}
|
|
3196
3586
|
let dropOpts;
|
|
@@ -3281,10 +3671,19 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3281
3671
|
);
|
|
3282
3672
|
program.command("update-settings <dropId>").description(
|
|
3283
3673
|
"Change a drop's title, visibility, password, expiry, or metadata (pass the full drop_\u2026 id, not the slug).\nContent stays unchanged \u2014 use update-content to replace the files at the URL."
|
|
3284
|
-
).option("--title <title>", "Change title").option("--visibility <v>", "Set to public or unlisted").option("--password <password>", "Require password to view").option("--no-password", "Remove password protection").option("--noindex", "Prevent search-engine indexing").option("--index", "Allow search-engine indexing").option("--expires-at <datetime>", "Auto-delete after this ISO 8601 date").option(
|
|
3674
|
+
).option("--title <title>", "Change title").option("--visibility <v>", "Set to public or unlisted").option("--password <password>", "Require password to view").option("--no-password", "Remove password protection").option("--noindex", "Prevent search-engine indexing").option("--index", "Allow search-engine indexing").option("--expires-at <datetime>", "Auto-delete after this ISO 8601 date").option("--no-expires", "Clear the auto-delete expiry").option(
|
|
3285
3675
|
"--metadata <json>",
|
|
3286
3676
|
`Attach JSON key-value pairs, e.g. '{"source":"ci"}'`
|
|
3287
3677
|
).option("--metadata-file <path>", "Read metadata JSON from a file").option(
|
|
3678
|
+
"--domain <hostname>",
|
|
3679
|
+
"Move this drop to a connected custom domain (must be live \u2014 see: dropthis domains list)."
|
|
3680
|
+
).option(
|
|
3681
|
+
"--shared",
|
|
3682
|
+
"Unmount this drop back to the shared dropthis pool. Cannot combine with --domain."
|
|
3683
|
+
).option(
|
|
3684
|
+
"--slug <vanity-slug>",
|
|
3685
|
+
"Rename the vanity slug on a path-mode custom domain (1\u201363 lowercase letters/digits/hyphens). 409 on conflict \u2014 does not auto-suffix."
|
|
3686
|
+
).option(
|
|
3288
3687
|
"--if-revision <n>",
|
|
3289
3688
|
"Fail if current revision doesn't match (optimistic lock)",
|
|
3290
3689
|
parseInteger
|
|
@@ -3316,7 +3715,7 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3316
3715
|
);
|
|
3317
3716
|
program.command("pull <target>").description(
|
|
3318
3717
|
"Download a drop's files into a local directory (accepts the drop_\u2026 id, the drop URL, or its slug).\nFetches the current deployment's file manifest and writes every file. Pull, edit, then update-content to ship the changes back to the same URL \u2014 also the rollback path."
|
|
3319
|
-
).option("-o, --output <dir>", "Output directory (default: ./<slug-or-id>)").option("--json", "Force JSON output").addHelpText(
|
|
3718
|
+
).option("-o, --output <dir>", "Output directory (default: ./<slug-or-id>)").option("--deployment <deploymentId>", "Download a specific deployment").option("--json", "Force JSON output").addHelpText(
|
|
3320
3719
|
"after",
|
|
3321
3720
|
examplesBlock([
|
|
3322
3721
|
"dropthis pull drop_abc123 -o ./site # download the drop's files",
|
|
@@ -3452,7 +3851,7 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3452
3851
|
process.exitCode = result.exitCode;
|
|
3453
3852
|
});
|
|
3454
3853
|
domains.command("verify <hostname>").description(
|
|
3455
|
-
"Trigger a DNS verification check. With --wait, polls until live or failed.\nUse after adding the DNS records from: dropthis domains connect\n\nExit codes: 0=live, 1=failed, 6=still pending (retry).
|
|
3854
|
+
"Trigger a DNS verification check. With --wait, polls until live or failed.\nUse after adding the DNS records from: dropthis domains connect\n\nExit codes (one-shot): 0=live, 1=failed, 6=still pending (retry). With --wait: 0=live, 1=failed, 7=timed out."
|
|
3456
3855
|
).option("--wait", "Poll until live (or failed/timeout)").option(
|
|
3457
3856
|
"--timeout <secs>",
|
|
3458
3857
|
"Max seconds to wait (default: 300)",
|
|
@@ -3508,11 +3907,35 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3508
3907
|
}
|
|
3509
3908
|
);
|
|
3510
3909
|
const apiKeys = program.command("api-keys").description("Manage API keys");
|
|
3511
|
-
apiKeys.command("create").description(
|
|
3512
|
-
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3910
|
+
apiKeys.command("create").description(
|
|
3911
|
+
"Create an API key. Without --service, mints a delegated account-scoped key (default for login). With --service --workspace <ws>, mints a CI key pinned to that workspace."
|
|
3912
|
+
).option("--label <label>", "API key label").option(
|
|
3913
|
+
"--service",
|
|
3914
|
+
"Mint a pinned service key for CI/automation (requires --workspace to pin it)"
|
|
3915
|
+
).option(
|
|
3916
|
+
"--workspace <slugOrId>",
|
|
3917
|
+
"Pin this service key to the given workspace slug or id (only valid with --service)"
|
|
3918
|
+
).option(
|
|
3919
|
+
"--allowed-workspace <slugOrId>",
|
|
3920
|
+
"Allow a delegated key to access the given workspace slug or id",
|
|
3921
|
+
collect,
|
|
3922
|
+
[]
|
|
3923
|
+
).option("--json", "Force JSON output").action(
|
|
3924
|
+
async (commandOptions) => {
|
|
3925
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
3926
|
+
const result = await runApiKeysCreate(
|
|
3927
|
+
{
|
|
3928
|
+
...commandOptions.label !== void 0 ? { label: commandOptions.label } : {},
|
|
3929
|
+
type: commandOptions.service ? "service" : "delegated",
|
|
3930
|
+
...commandOptions.workspace !== void 0 ? { workspace: commandOptions.workspace } : {},
|
|
3931
|
+
...commandOptions.allowedWorkspace?.length ? { allowedWorkspaces: commandOptions.allowedWorkspace } : {},
|
|
3932
|
+
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
3933
|
+
},
|
|
3934
|
+
deps
|
|
3935
|
+
);
|
|
3936
|
+
process.exitCode = result.exitCode;
|
|
3937
|
+
}
|
|
3938
|
+
);
|
|
3516
3939
|
apiKeys.command("list").description("List API keys").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
3517
3940
|
const deps = await commandDeps(program, options, store, commandOptions);
|
|
3518
3941
|
const result = await runApiKeysList(commandOptions, deps);
|
|
@@ -3549,25 +3972,28 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3549
3972
|
const result = await runWorkspaceUse(slugOrId, commandOptions, deps);
|
|
3550
3973
|
process.exitCode = result.exitCode;
|
|
3551
3974
|
});
|
|
3552
|
-
|
|
3553
|
-
|
|
3975
|
+
workspace.command("create <name>").description("Create a new team workspace").option("--slug <slug>", "Vanity slug for the workspace").option("--json", "Force JSON output").action(
|
|
3976
|
+
async (name, commandOptions) => {
|
|
3977
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
3978
|
+
const result = await runWorkspaceCreate(
|
|
3979
|
+
{
|
|
3980
|
+
name,
|
|
3981
|
+
...commandOptions.slug !== void 0 ? { slug: commandOptions.slug } : {},
|
|
3982
|
+
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
3983
|
+
},
|
|
3984
|
+
deps
|
|
3985
|
+
);
|
|
3986
|
+
process.exitCode = result.exitCode;
|
|
3987
|
+
}
|
|
3554
3988
|
);
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
).option("--label <label>", "Key label").option(
|
|
3558
|
-
"--service",
|
|
3559
|
-
"Mint a pinned service key for CI/automation (requires --workspace to pin it)"
|
|
3560
|
-
).option(
|
|
3561
|
-
"--workspace <slugOrId>",
|
|
3562
|
-
"Pin this service key to the given workspace slug or id (only valid with --service)"
|
|
3563
|
-
).option("--json", "Force JSON output").action(
|
|
3564
|
-
async (commandOptions) => {
|
|
3989
|
+
workspace.command("rename <workspaceId>").description("Rename a workspace or change its vanity slug").option("--name <name>", "New workspace name").option("--slug <slug>", "New vanity slug").option("--json", "Force JSON output").action(
|
|
3990
|
+
async (workspaceId, commandOptions) => {
|
|
3565
3991
|
const deps = await commandDeps(program, options, store, commandOptions);
|
|
3566
|
-
const result = await
|
|
3992
|
+
const result = await runWorkspaceRename(
|
|
3993
|
+
workspaceId,
|
|
3567
3994
|
{
|
|
3568
|
-
...commandOptions.
|
|
3569
|
-
|
|
3570
|
-
...commandOptions.workspace !== void 0 ? { workspace: commandOptions.workspace } : {},
|
|
3995
|
+
...commandOptions.name !== void 0 ? { name: commandOptions.name } : {},
|
|
3996
|
+
...commandOptions.slug !== void 0 ? { slug: commandOptions.slug } : {},
|
|
3571
3997
|
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
3572
3998
|
},
|
|
3573
3999
|
deps
|
|
@@ -3575,7 +4001,103 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3575
4001
|
process.exitCode = result.exitCode;
|
|
3576
4002
|
}
|
|
3577
4003
|
);
|
|
3578
|
-
|
|
4004
|
+
workspace.command("delete <workspaceId>").description("Delete a workspace").option("--yes", "Confirm deletion").option("--json", "Force JSON output").action(
|
|
4005
|
+
async (workspaceId, commandOptions) => {
|
|
4006
|
+
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
4007
|
+
const global = globalOptions(program, commandOptions);
|
|
4008
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
4009
|
+
const result = await runWorkspaceDelete(
|
|
4010
|
+
workspaceId,
|
|
4011
|
+
{
|
|
4012
|
+
...commandOptions,
|
|
4013
|
+
interactive: isInteractive(stdinIsTTY, deps.env, global)
|
|
4014
|
+
},
|
|
4015
|
+
deps
|
|
4016
|
+
);
|
|
4017
|
+
process.exitCode = result.exitCode;
|
|
4018
|
+
}
|
|
4019
|
+
);
|
|
4020
|
+
const members = program.command("members").description("Manage team members");
|
|
4021
|
+
members.command("list <workspaceId>").description("List members of a workspace").option("--json", "Force JSON output").action(async (workspaceId, commandOptions) => {
|
|
4022
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
4023
|
+
const result = await runMembersList(workspaceId, commandOptions, deps);
|
|
4024
|
+
process.exitCode = result.exitCode;
|
|
4025
|
+
});
|
|
4026
|
+
members.command("invite <workspaceId>").description("Invite someone to a workspace by email").requiredOption("--email <email>", "Email address to invite").option("--role <role>", "Role to grant (admin or member)", "member").option("--json", "Force JSON output").action(
|
|
4027
|
+
async (workspaceId, commandOptions) => {
|
|
4028
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
4029
|
+
const result = await runMembersInvite(
|
|
4030
|
+
workspaceId,
|
|
4031
|
+
{
|
|
4032
|
+
email: commandOptions.email,
|
|
4033
|
+
...commandOptions.role !== void 0 ? { role: commandOptions.role } : {},
|
|
4034
|
+
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
4035
|
+
},
|
|
4036
|
+
deps
|
|
4037
|
+
);
|
|
4038
|
+
process.exitCode = result.exitCode;
|
|
4039
|
+
}
|
|
4040
|
+
);
|
|
4041
|
+
members.command("role <workspaceId> <accountId>").description("Change a member's role").requiredOption("--role <role>", "New role (owner, admin, or member)").option("--json", "Force JSON output").action(
|
|
4042
|
+
async (workspaceId, accountId, commandOptions) => {
|
|
4043
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
4044
|
+
const result = await runMembersRole(
|
|
4045
|
+
workspaceId,
|
|
4046
|
+
accountId,
|
|
4047
|
+
{
|
|
4048
|
+
role: commandOptions.role,
|
|
4049
|
+
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
4050
|
+
},
|
|
4051
|
+
deps
|
|
4052
|
+
);
|
|
4053
|
+
process.exitCode = result.exitCode;
|
|
4054
|
+
}
|
|
4055
|
+
);
|
|
4056
|
+
members.command("remove <workspaceId> <accountId>").description("Remove a member from a workspace").option("--yes", "Confirm removal").option("--json", "Force JSON output").action(
|
|
4057
|
+
async (workspaceId, accountId, commandOptions) => {
|
|
4058
|
+
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
4059
|
+
const global = globalOptions(program, commandOptions);
|
|
4060
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
4061
|
+
const result = await runMembersRemove(
|
|
4062
|
+
workspaceId,
|
|
4063
|
+
accountId,
|
|
4064
|
+
{
|
|
4065
|
+
...commandOptions,
|
|
4066
|
+
interactive: isInteractive(stdinIsTTY, deps.env, global)
|
|
4067
|
+
},
|
|
4068
|
+
deps
|
|
4069
|
+
);
|
|
4070
|
+
process.exitCode = result.exitCode;
|
|
4071
|
+
}
|
|
4072
|
+
);
|
|
4073
|
+
const invitations = program.command("invitations").description("Manage your workspace invitations");
|
|
4074
|
+
invitations.command("list", { isDefault: true }).description("List your pending workspace invitations").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
4075
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
4076
|
+
const result = await runInvitationsList(commandOptions, deps);
|
|
4077
|
+
process.exitCode = result.exitCode;
|
|
4078
|
+
});
|
|
4079
|
+
invitations.command("accept").description("Accept a workspace invitation by token").requiredOption("--token <token>", "Invitation token").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
4080
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
4081
|
+
const result = await runInvitationsAccept(commandOptions, deps);
|
|
4082
|
+
process.exitCode = result.exitCode;
|
|
4083
|
+
});
|
|
4084
|
+
invitations.command("accept-by-id <invitationId>").description("Accept a workspace invitation by its id").option("--json", "Force JSON output").action(
|
|
4085
|
+
async (invitationId, commandOptions) => {
|
|
4086
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
4087
|
+
const result = await runInvitationsAcceptById(
|
|
4088
|
+
{
|
|
4089
|
+
invitationId,
|
|
4090
|
+
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
4091
|
+
},
|
|
4092
|
+
deps
|
|
4093
|
+
);
|
|
4094
|
+
process.exitCode = result.exitCode;
|
|
4095
|
+
}
|
|
4096
|
+
);
|
|
4097
|
+
program.command("login").description("Authenticate with email OTP").option("--email <email>", "Email address").option("--otp <otp>", "One-time passcode").option(
|
|
4098
|
+
"--scope <scope>",
|
|
4099
|
+
"Capability scope to request for the minted key (e.g. team)"
|
|
4100
|
+
).option("--json", "Force JSON output").action(
|
|
3579
4101
|
async (commandOptions) => {
|
|
3580
4102
|
if (!commandOptions.email || !commandOptions.otp) {
|
|
3581
4103
|
const deps2 = await commandDeps(program, options, store, commandOptions);
|
|
@@ -3593,7 +4115,8 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3593
4115
|
const context = createContext({ global: global2 });
|
|
3594
4116
|
const result2 = await runLoginInteractive({
|
|
3595
4117
|
...deps2,
|
|
3596
|
-
createClient: (apiKey) => context.createClient(apiKey)
|
|
4118
|
+
createClient: (apiKey) => context.createClient(apiKey),
|
|
4119
|
+
...commandOptions.scope ? { scope: commandOptions.scope } : {}
|
|
3597
4120
|
});
|
|
3598
4121
|
process.exitCode = result2.exitCode;
|
|
3599
4122
|
return;
|
|
@@ -3605,6 +4128,7 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3605
4128
|
{
|
|
3606
4129
|
email: commandOptions.email,
|
|
3607
4130
|
otp: commandOptions.otp,
|
|
4131
|
+
...commandOptions.scope ? { scope: commandOptions.scope } : {},
|
|
3608
4132
|
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
3609
4133
|
},
|
|
3610
4134
|
{
|
|
@@ -3621,7 +4145,10 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3621
4145
|
const result = await runLoginRequest(commandOptions, deps);
|
|
3622
4146
|
process.exitCode = result.exitCode;
|
|
3623
4147
|
});
|
|
3624
|
-
login?.command("verify").description("Verify email OTP and store an API key").requiredOption("--email <email>", "Email address").requiredOption("--otp <otp>", "One-time passcode").option(
|
|
4148
|
+
login?.command("verify").description("Verify email OTP and store an API key").requiredOption("--email <email>", "Email address").requiredOption("--otp <otp>", "One-time passcode").option(
|
|
4149
|
+
"--scope <scope>",
|
|
4150
|
+
"Capability scope to request for the minted key (e.g. team)"
|
|
4151
|
+
).option("--json", "Force JSON output").action(
|
|
3625
4152
|
async (commandOptions) => {
|
|
3626
4153
|
const deps = await commandDeps(program, options, store, commandOptions);
|
|
3627
4154
|
const global = globalOptions(program, commandOptions);
|
|
@@ -3659,17 +4186,30 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3659
4186
|
const result = await runAccountGet(commandOptions, deps);
|
|
3660
4187
|
process.exitCode = result.exitCode;
|
|
3661
4188
|
});
|
|
3662
|
-
account.command("update").description("Update account display name").
|
|
3663
|
-
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
4189
|
+
account.command("update").description("Update account display name").option("--display-name <name>", "Set the display name").option("--clear-display-name", "Clear the display name").option("--json", "Force JSON output").action(
|
|
4190
|
+
async (commandOptions) => {
|
|
4191
|
+
if (commandOptions.displayName === void 0 && !commandOptions.clearDisplayName || commandOptions.displayName !== void 0 && commandOptions.clearDisplayName) {
|
|
4192
|
+
const writer = outputWriter(program, options, commandOptions);
|
|
4193
|
+
process.exitCode = writeError(
|
|
4194
|
+
writer,
|
|
4195
|
+
"invalid_usage",
|
|
4196
|
+
"Use either --display-name <name> or --clear-display-name."
|
|
4197
|
+
).exitCode;
|
|
4198
|
+
return;
|
|
4199
|
+
}
|
|
4200
|
+
const displayName = commandOptions.clearDisplayName ? null : commandOptions.displayName;
|
|
4201
|
+
if (displayName === void 0) return;
|
|
4202
|
+
const deps = await commandDeps(program, options, store, commandOptions);
|
|
4203
|
+
const result = await runAccountUpdate(
|
|
4204
|
+
{
|
|
4205
|
+
displayName,
|
|
4206
|
+
...commandOptions.json !== void 0 ? { json: commandOptions.json } : {}
|
|
4207
|
+
},
|
|
4208
|
+
deps
|
|
4209
|
+
);
|
|
4210
|
+
process.exitCode = result.exitCode;
|
|
4211
|
+
}
|
|
4212
|
+
);
|
|
3673
4213
|
account.command("delete").description("Delete your account").option("--yes", "Confirm deletion").option("--json", "Force JSON output").action(async (commandOptions) => {
|
|
3674
4214
|
const stdinIsTTY = options.stdinIsTTY ?? process.stdin.isTTY ?? false;
|
|
3675
4215
|
const global = globalOptions(program, commandOptions);
|
|
@@ -3683,7 +4223,10 @@ ${import_picocolors6.default.bold("Canonical vs raw URLs:")}`,
|
|
|
3683
4223
|
);
|
|
3684
4224
|
process.exitCode = result.exitCode;
|
|
3685
4225
|
});
|
|
3686
|
-
program.command("doctor").description("Report CLI diagnostics").option("--json", "Force JSON output").
|
|
4226
|
+
program.command("doctor").description("Report CLI diagnostics").option("--json", "Force JSON output").option(
|
|
4227
|
+
"--online",
|
|
4228
|
+
"Run a network preflight (auth + active workspace + custom-domain status) \u2014 exits 3 on auth failure, 5 on a network failure"
|
|
4229
|
+
).action(async (commandOptions) => {
|
|
3687
4230
|
const deps = await commandDeps(
|
|
3688
4231
|
program,
|
|
3689
4232
|
options,
|
|
@@ -3818,6 +4361,7 @@ function toDropOptions(options) {
|
|
|
3818
4361
|
...options.noindex ? { noindex: true } : {},
|
|
3819
4362
|
...options.index ? { index: true } : {},
|
|
3820
4363
|
...options.expiresAt ? { expiresAt: options.expiresAt } : {},
|
|
4364
|
+
...options.expires === false || options.noExpires ? { noExpires: true } : {},
|
|
3821
4365
|
...options.metadata ? { metadata: options.metadata } : {},
|
|
3822
4366
|
...options.metadataFile ? { metadataFile: options.metadataFile } : {},
|
|
3823
4367
|
...options.entry ? { entry: options.entry } : {},
|