@tinycloud/cli 1.3.0-beta.35 → 1.3.0-beta.37
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/dist/index.js +13 -4
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +142 -4
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +5 -5
package/dist/legacy-entry.js
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
tinycloudConfigPath,
|
|
38
38
|
tinycloudHomePath
|
|
39
39
|
} from "@tinycloud/operations/state";
|
|
40
|
-
var CONFIG_DIR, PROFILES_DIR, CONFIG_FILE, DEFAULT_HOST, DEFAULT_OPENKEY_HOST, DEFAULT_OPENKEY_DEVICE_API_HOST, DEFAULT_SHARE_ORIGIN, DEFAULT_PROFILE, DEFAULT_CHAIN_ID, PROFILE_COMMIT_LOCK_TIMEOUT_MS, ExitCode;
|
|
40
|
+
var CONFIG_DIR, PROFILES_DIR, CONFIG_FILE, DEFAULT_HOST, DEFAULT_OPENKEY_HOST, DEFAULT_OPENKEY_DEVICE_API_HOST, DEFAULT_SHARE_ORIGIN, DEFAULT_PROFILE, DEFAULT_CHAIN_ID, PROFILE_COMMIT_LOCK_TIMEOUT_MS, ExitCode, OPENKEY_SPACE_SETUP_RETRY_HINT;
|
|
41
41
|
var init_constants = __esm({
|
|
42
42
|
"src/config/constants.ts"() {
|
|
43
43
|
"use strict";
|
|
@@ -67,6 +67,7 @@ var init_constants = __esm({
|
|
|
67
67
|
/** Interrupted by SIGINT/SIGTERM (`CANCELLED`). */
|
|
68
68
|
CANCELLED: 130
|
|
69
69
|
};
|
|
70
|
+
OPENKEY_SPACE_SETUP_RETRY_HINT = "Wait a minute and retry; approving again in OpenKey re-runs the setup.";
|
|
70
71
|
}
|
|
71
72
|
});
|
|
72
73
|
|
|
@@ -9604,17 +9605,25 @@ async function isRootAuthority(spaceUri, profileName2) {
|
|
|
9604
9605
|
const selfAddr = await resolveLocalAddress(profile, profileName2);
|
|
9605
9606
|
return selfAddr !== null && selfAddr === ownerAddr;
|
|
9606
9607
|
}
|
|
9608
|
+
async function primarySpaceUri(profileName2) {
|
|
9609
|
+
const session = await ProfileManager.getSession(profileName2);
|
|
9610
|
+
if (typeof session?.spaceId === "string" && session.spaceId !== "") return session.spaceId;
|
|
9611
|
+
const profile = await ProfileManager.getProfile(profileName2);
|
|
9612
|
+
return typeof profile.spaceId === "string" && profile.spaceId !== "" ? profile.spaceId : void 0;
|
|
9613
|
+
}
|
|
9607
9614
|
function spaceNameFromUri(spaceUri) {
|
|
9608
9615
|
return spaceUri.slice(spaceUri.lastIndexOf(":") + 1);
|
|
9609
9616
|
}
|
|
9610
|
-
async function unhostedSpaceError(error,
|
|
9611
|
-
if (!spaceUri) return null;
|
|
9617
|
+
async function unhostedSpaceError(error, requestedSpaceUri, profileName2) {
|
|
9612
9618
|
const status = error.meta?.status;
|
|
9613
9619
|
const isUnhosted = status === 404 && /space not found/i.test(error.message);
|
|
9614
9620
|
if (!isUnhosted) return null;
|
|
9621
|
+
const spaceUri = requestedSpaceUri ?? await primarySpaceUri(profileName2);
|
|
9622
|
+
if (!spaceUri) return null;
|
|
9615
9623
|
const spaceName = spaceNameFromUri(spaceUri);
|
|
9616
9624
|
const owner = await isRootAuthority(spaceUri, profileName2);
|
|
9617
|
-
const
|
|
9625
|
+
const openKeyOwner = owner && resolveProfilePosture(await ProfileManager.getProfile(profileName2)) === "owner-openkey";
|
|
9626
|
+
const hint = openKeyOwner ? `OpenKey is still setting up your space. ${OPENKEY_SPACE_SETUP_RETRY_HINT}` : owner ? [
|
|
9618
9627
|
"You are the owner. Host it once:",
|
|
9619
9628
|
` ${CLI_NAME8} space host ${spaceName}`,
|
|
9620
9629
|
"Then retry."
|
|
@@ -11886,6 +11895,132 @@ async function loginWithDeviceAuthorization(input) {
|
|
|
11886
11895
|
return { profile, result };
|
|
11887
11896
|
}
|
|
11888
11897
|
|
|
11898
|
+
// src/auth/space-setup.ts
|
|
11899
|
+
init_constants();
|
|
11900
|
+
init_sdk();
|
|
11901
|
+
init_errors();
|
|
11902
|
+
var SPACE_SETUP_TIMEOUT_MS = 15e4;
|
|
11903
|
+
var POLL_DELAYS_MS = [2e3, 3e3, 5e3, 8e3, 13e3, 15e3];
|
|
11904
|
+
var PROGRESS_INTERVAL_MS = 15e3;
|
|
11905
|
+
var SPACE_ERROR_MAX_LENGTH = 500;
|
|
11906
|
+
function spaceSetupReport(delegation) {
|
|
11907
|
+
const rawError = typeof delegation.spaceError === "string" ? delegation.spaceError : void 0;
|
|
11908
|
+
const error = rawError?.replace(/[\u0000-\u001f\u007f-\u009f\s]+/g, " ").trim().slice(0, SPACE_ERROR_MAX_LENGTH);
|
|
11909
|
+
const ready = delegation.spaceReady;
|
|
11910
|
+
if (ready === true) return void 0;
|
|
11911
|
+
const pending = delegation.spacePending === true || ready === null;
|
|
11912
|
+
if (!pending && !error && ready !== false) return void 0;
|
|
11913
|
+
return {
|
|
11914
|
+
ready: ready === false || ready === null ? ready : void 0,
|
|
11915
|
+
pending,
|
|
11916
|
+
...error ? { error } : {}
|
|
11917
|
+
};
|
|
11918
|
+
}
|
|
11919
|
+
async function awaitSpaceSetup(report, deps) {
|
|
11920
|
+
const write = deps.write ?? ((line) => {
|
|
11921
|
+
process.stderr.write(`${line}
|
|
11922
|
+
`);
|
|
11923
|
+
});
|
|
11924
|
+
const sleep = deps.sleep ?? ((ms2) => new Promise((resolve8) => setTimeout(resolve8, ms2)));
|
|
11925
|
+
const now = deps.now ?? Date.now;
|
|
11926
|
+
const timeoutMs = deps.timeoutMs ?? SPACE_SETUP_TIMEOUT_MS;
|
|
11927
|
+
const started = now();
|
|
11928
|
+
const deadline = started + timeoutMs;
|
|
11929
|
+
const probe = async () => deps.probe().catch(() => "transient");
|
|
11930
|
+
const unreadable = () => write(
|
|
11931
|
+
`Warning: this login cannot read your TinyCloud space to check it${report.error ? `; OpenKey reported: ${report.error}` : report.pending ? "; OpenKey is still setting it up" : ""}. If the first storage command fails with "Space not found", OpenKey is still setting up your space. ${OPENKEY_SPACE_SETUP_RETRY_HINT}`
|
|
11932
|
+
);
|
|
11933
|
+
let result = await probe();
|
|
11934
|
+
if (result === "hosted") {
|
|
11935
|
+
if (!report.pending && report.error) write(`Warning: OpenKey reported a problem finishing your account setup: ${report.error}`);
|
|
11936
|
+
return;
|
|
11937
|
+
}
|
|
11938
|
+
if (result === "unreadable") {
|
|
11939
|
+
unreadable();
|
|
11940
|
+
return;
|
|
11941
|
+
}
|
|
11942
|
+
if (!report.pending) {
|
|
11943
|
+
if (result === "transient") {
|
|
11944
|
+
write(`Warning: could not check whether your TinyCloud space is hosted${report.error ? `; OpenKey reported: ${report.error}` : ""}. ${OPENKEY_SPACE_SETUP_RETRY_HINT}`);
|
|
11945
|
+
return;
|
|
11946
|
+
}
|
|
11947
|
+
if (report.error) {
|
|
11948
|
+
throw new CLIError(
|
|
11949
|
+
"SPACE_SETUP_FAILED",
|
|
11950
|
+
`OpenKey could not finish setting up your space: ${report.error} Your login is saved, but storage commands will fail with "Space not found" until the space is hosted.`,
|
|
11951
|
+
ExitCode.ERROR,
|
|
11952
|
+
{ hint: "Approve again in OpenKey to re-run the setup, then retry." }
|
|
11953
|
+
);
|
|
11954
|
+
}
|
|
11955
|
+
write(
|
|
11956
|
+
'Warning: OpenKey did not set up your TinyCloud space (spaceReady: false), so storage commands will fail with "Space not found". Turn on Auto-Sign in OpenKey and approve again, or host the space from a wallet profile.'
|
|
11957
|
+
);
|
|
11958
|
+
return;
|
|
11959
|
+
}
|
|
11960
|
+
write(
|
|
11961
|
+
"Setting up your space\u2026 (OpenKey is hosting it; this can take a minute or two)" + (report.error ? ` OpenKey reported: ${report.error} It is still retrying.` : "")
|
|
11962
|
+
);
|
|
11963
|
+
let lastProgress = started;
|
|
11964
|
+
for (let attempt = 0; ; attempt++) {
|
|
11965
|
+
const current = now();
|
|
11966
|
+
if (current >= deadline) break;
|
|
11967
|
+
await sleep(Math.min(POLL_DELAYS_MS[Math.min(attempt, POLL_DELAYS_MS.length - 1)], deadline - current));
|
|
11968
|
+
result = await probe();
|
|
11969
|
+
if (result === "hosted") {
|
|
11970
|
+
write("Your space is ready.");
|
|
11971
|
+
return;
|
|
11972
|
+
}
|
|
11973
|
+
if (result === "unreadable") {
|
|
11974
|
+
unreadable();
|
|
11975
|
+
return;
|
|
11976
|
+
}
|
|
11977
|
+
const elapsed = now();
|
|
11978
|
+
if (elapsed < deadline && elapsed - lastProgress >= PROGRESS_INTERVAL_MS) {
|
|
11979
|
+
lastProgress = elapsed;
|
|
11980
|
+
write(`Still setting up your space\u2026 (${Math.round((elapsed - started) / 1e3)}s)`);
|
|
11981
|
+
}
|
|
11982
|
+
}
|
|
11983
|
+
throw new CLIError(
|
|
11984
|
+
"SPACE_SETUP_PENDING",
|
|
11985
|
+
`OpenKey is still setting up your space after ${Math.round(timeoutMs / 1e3)} seconds.${report.error ? ` OpenKey's last report: ${report.error}` : ""} Your login is saved, but storage commands will fail with "Space not found" until the space is hosted.`,
|
|
11986
|
+
ExitCode.ERROR,
|
|
11987
|
+
{ hint: OPENKEY_SPACE_SETUP_RETRY_HINT }
|
|
11988
|
+
);
|
|
11989
|
+
}
|
|
11990
|
+
function hasKvAction(permission, action) {
|
|
11991
|
+
return permission.actions.some((entry) => entry === action || entry === `tinycloud.kv/${action}`);
|
|
11992
|
+
}
|
|
11993
|
+
function readTarget(permissions) {
|
|
11994
|
+
const kv = (permissions ?? []).filter((permission) => permission.service === "tinycloud.kv" || permission.service === "kv");
|
|
11995
|
+
const list = kv.find((permission) => hasKvAction(permission, "list"));
|
|
11996
|
+
if (list) return { op: "list", prefix: list.path };
|
|
11997
|
+
const get = kv.find((permission) => hasKvAction(permission, "get"));
|
|
11998
|
+
if (!get) return void 0;
|
|
11999
|
+
return { op: "get", key: get.path === "" || get.path.endsWith("/") ? `${get.path}.tinycloud-space-probe` : get.path };
|
|
12000
|
+
}
|
|
12001
|
+
var UNHOSTED = /space not found/i;
|
|
12002
|
+
function kvSpaceProbe(ctx, permissions, restore2 = restoreProfileSessionNode) {
|
|
12003
|
+
const target = readTarget(permissions);
|
|
12004
|
+
let restored;
|
|
12005
|
+
return async () => {
|
|
12006
|
+
if (!target) return "unreadable";
|
|
12007
|
+
restored ??= await restore2(ctx);
|
|
12008
|
+
if ("unavailable" in restored) return "unreadable";
|
|
12009
|
+
const kv = restored.node.kv;
|
|
12010
|
+
const result = target.op === "list" ? await kv.list({ prefix: target.prefix, limit: 1 }) : await kv.get(target.key);
|
|
12011
|
+
if (result.ok) return "hosted";
|
|
12012
|
+
const status = result.error.meta?.status;
|
|
12013
|
+
if (status === 404 && UNHOSTED.test(result.error.message)) return "unhosted";
|
|
12014
|
+
if (status === 401 || status === 403) return "unreadable";
|
|
12015
|
+
return result.error.code === "KV_NOT_FOUND" || status === 404 ? "hosted" : "transient";
|
|
12016
|
+
};
|
|
12017
|
+
}
|
|
12018
|
+
async function ensureSpaceSetup(ctx, delegation, permissions) {
|
|
12019
|
+
const report = spaceSetupReport(delegation);
|
|
12020
|
+
if (!report) return;
|
|
12021
|
+
await awaitSpaceSetup(report, { probe: kvSpaceProbe(ctx, permissions) });
|
|
12022
|
+
}
|
|
12023
|
+
|
|
11889
12024
|
// src/commands/auth.ts
|
|
11890
12025
|
init_raw_encryption();
|
|
11891
12026
|
init_owner_did();
|
|
@@ -13176,6 +13311,7 @@ function registerAuthCommand(program, options) {
|
|
|
13176
13311
|
await persistReplicationLogin(ctx.profile, replicationOptions);
|
|
13177
13312
|
if (replicationOptions.allowSecrets) writeReplicationSecretsWarning();
|
|
13178
13313
|
reportDeclined(result.declined);
|
|
13314
|
+
await ensureSpaceSetup({ profile: ctx.profile, host: ctx.host }, result.session, result.session.permissions);
|
|
13179
13315
|
outputJson({
|
|
13180
13316
|
authenticated: true,
|
|
13181
13317
|
profile: ctx.profile,
|
|
@@ -14518,6 +14654,7 @@ async function handleLocalAuth(profileName2, host, options = {}) {
|
|
|
14518
14654
|
async function handleOpenKeyAuth(profileName2, host, options = {}) {
|
|
14519
14655
|
const { profile, delegationData, declined, legacyNested } = await refreshOpenKeySession(profileName2, host, options);
|
|
14520
14656
|
reportDeclined(declined, legacyNested);
|
|
14657
|
+
await ensureSpaceSetup({ profile: profileName2, host }, delegationData, delegationData.permissions);
|
|
14521
14658
|
outputJson({
|
|
14522
14659
|
authenticated: true,
|
|
14523
14660
|
profile: profileName2,
|
|
@@ -15516,6 +15653,7 @@ function registerInitCommand(program) {
|
|
|
15516
15653
|
noPopup: options.popup === false,
|
|
15517
15654
|
persistHost: true
|
|
15518
15655
|
});
|
|
15656
|
+
await ensureSpaceSetup({ profile: profileName2, host }, delegationData, delegationData.permissions);
|
|
15519
15657
|
outputJson({
|
|
15520
15658
|
profile: profileName2,
|
|
15521
15659
|
did,
|