@tinycloud/cli 1.1.0-beta.9 → 1.1.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/dist/index.js +194 -33
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +10314 -6569
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +8 -7
- package/skills/tc-cli/AUTH.md +7 -4
- package/skills/tc-cli/REFERENCE.md +38 -6
- package/skills/tc-cli/SKILL.md +2 -0
package/dist/index.js
CHANGED
|
@@ -32,7 +32,9 @@ var init_constants = __esm({
|
|
|
32
32
|
NOT_FOUND: 4,
|
|
33
33
|
PERMISSION_DENIED: 5,
|
|
34
34
|
NETWORK_ERROR: 6,
|
|
35
|
-
NODE_ERROR: 7
|
|
35
|
+
NODE_ERROR: 7,
|
|
36
|
+
/** A write was refused because the owner's TinyCloud storage is full. */
|
|
37
|
+
STORAGE_FULL: 10
|
|
36
38
|
};
|
|
37
39
|
}
|
|
38
40
|
});
|
|
@@ -72,8 +74,14 @@ var init_theme = __esm({
|
|
|
72
74
|
|
|
73
75
|
// src/output/formatter.ts
|
|
74
76
|
import ora from "ora";
|
|
75
|
-
function
|
|
76
|
-
|
|
77
|
+
function warningLine(warnings) {
|
|
78
|
+
const which = warnings.map((warning) => `${warning.grantCid ?? "unidentified"}: ${warning.reason}`).join(", ");
|
|
79
|
+
const subject = warnings.length === 1 ? "A stored grant was" : `${warnings.length} stored grants were`;
|
|
80
|
+
return `${subject} not used (${which}). Approve access again when a command needs it; the old grant expires on its own.`;
|
|
81
|
+
}
|
|
82
|
+
function outputError(code3, message, hint, details = {}) {
|
|
83
|
+
const { meta, warnings = [] } = details;
|
|
84
|
+
if (!shouldOutputJson()) {
|
|
77
85
|
process.stderr.write(
|
|
78
86
|
`${theme.error("\u2717")} ${theme.label(code3)}: ${message}
|
|
79
87
|
`
|
|
@@ -84,27 +92,127 @@ function outputError(code3, message, hint, meta) {
|
|
|
84
92
|
`);
|
|
85
93
|
}
|
|
86
94
|
}
|
|
95
|
+
if (warnings.length > 0) process.stderr.write(` ${theme.warn(warningLine(warnings))}
|
|
96
|
+
`);
|
|
87
97
|
} else {
|
|
88
98
|
const payload = {
|
|
89
99
|
error: { code: code3, message }
|
|
90
100
|
};
|
|
91
101
|
if (hint) payload.error.hint = hint;
|
|
92
102
|
if (meta) payload.error.meta = meta;
|
|
103
|
+
if (warnings.length > 0) payload.error.warnings = warnings;
|
|
93
104
|
process.stderr.write(JSON.stringify(payload, null, 2) + "\n");
|
|
94
105
|
}
|
|
95
106
|
}
|
|
107
|
+
function operationWarnings(value) {
|
|
108
|
+
if (!Array.isArray(value)) return [];
|
|
109
|
+
return value.flatMap((warning) => {
|
|
110
|
+
if (warning === null || typeof warning !== "object") return [];
|
|
111
|
+
const { code: code3, reason, grantCid } = warning;
|
|
112
|
+
if (typeof code3 !== "string" || !WARNING_CODE.test(code3) || typeof reason !== "string" || !WARNING_REASON.test(reason)) {
|
|
113
|
+
return [];
|
|
114
|
+
}
|
|
115
|
+
return [{ code: code3, reason, ...typeof grantCid === "string" && DELEGATION_CID.test(grantCid) ? { grantCid } : {} }];
|
|
116
|
+
});
|
|
117
|
+
}
|
|
96
118
|
function isInteractive() {
|
|
97
119
|
return Boolean(process.stdout.isTTY);
|
|
98
120
|
}
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
102
|
-
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
121
|
+
function setJsonOutputRequested(requested) {
|
|
122
|
+
globalThis[JSON_REQUESTED] = requested;
|
|
103
123
|
}
|
|
124
|
+
function shouldOutputJson() {
|
|
125
|
+
return !isInteractive() || (globalThis[JSON_REQUESTED] ?? process.argv.includes("--json"));
|
|
126
|
+
}
|
|
127
|
+
var WARNING_CODE, WARNING_REASON, DELEGATION_CID, JSON_REQUESTED;
|
|
104
128
|
var init_formatter = __esm({
|
|
105
129
|
"src/output/formatter.ts"() {
|
|
106
130
|
"use strict";
|
|
107
131
|
init_theme();
|
|
132
|
+
WARNING_CODE = /^[A-Z][A-Z_]{0,63}$/;
|
|
133
|
+
WARNING_REASON = /^[a-z][a-z_]{0,63}$/;
|
|
134
|
+
DELEGATION_CID = /^bafkr4i[a-z2-7]{52}$/;
|
|
135
|
+
JSON_REQUESTED = /* @__PURE__ */ Symbol.for("tinycloud.cli.jsonOutputRequested");
|
|
136
|
+
}
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
// src/output/storage.ts
|
|
140
|
+
function storageRejection(error) {
|
|
141
|
+
let node = error;
|
|
142
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null; depth += 1) {
|
|
143
|
+
const record = node;
|
|
144
|
+
let code3;
|
|
145
|
+
if (record.code === "STORAGE_QUOTA_EXCEEDED" || record.code === "STORAGE_LIMIT_REACHED") {
|
|
146
|
+
code3 = record.code;
|
|
147
|
+
} else if (record.code !== void 0) {
|
|
148
|
+
return void 0;
|
|
149
|
+
} else if (isStorageStatus(record)) {
|
|
150
|
+
code3 = storageCodeFromText(record.message);
|
|
151
|
+
}
|
|
152
|
+
if (code3) {
|
|
153
|
+
const account = accountTotals(record) ?? accountTotals(record.meta) ?? accountTotals(record.metadata);
|
|
154
|
+
return account ? { code: code3, account } : { code: code3 };
|
|
155
|
+
}
|
|
156
|
+
node = record.cause;
|
|
157
|
+
}
|
|
158
|
+
return void 0;
|
|
159
|
+
}
|
|
160
|
+
function describeStorageRejection(rejection, progress) {
|
|
161
|
+
const reason = rejection.code === "STORAGE_LIMIT_REACHED" ? "This write is larger than the TinyCloud storage you have left" : "TinyCloud storage is full";
|
|
162
|
+
const message = progress ? `${progress}${reason}.` : `${reason}; nothing was written.`;
|
|
163
|
+
const { account } = rejection;
|
|
164
|
+
const totals = account ? `${formatStorageBytes(account.usedBytes)} used of ${formatStorageBytes(account.limitBytes)}${account.plan ? ` (${account.plan} plan)` : ""}. ` : "";
|
|
165
|
+
return {
|
|
166
|
+
message,
|
|
167
|
+
hint: `${totals}Reading still works.
|
|
168
|
+
Free up space or upgrade: ${MANAGE_STORAGE_URL}`
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
function formatStorageBytes(bytes) {
|
|
172
|
+
const units = ["KiB", "MiB", "GiB", "TiB"];
|
|
173
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
174
|
+
let value = bytes / 1024;
|
|
175
|
+
let unit = 0;
|
|
176
|
+
while (value >= 1024 && unit < units.length - 1) {
|
|
177
|
+
value /= 1024;
|
|
178
|
+
unit += 1;
|
|
179
|
+
}
|
|
180
|
+
return `${value.toFixed(1).replace(/\.0$/, "")} ${units[unit]}`;
|
|
181
|
+
}
|
|
182
|
+
function storageCodeFromText(message) {
|
|
183
|
+
if (typeof message !== "string") return void 0;
|
|
184
|
+
if (message.includes("larger than the TinyCloud storage you have left")) return "STORAGE_LIMIT_REACHED";
|
|
185
|
+
if (message.includes("TinyCloud storage is full") || /storage quota exceeded/i.test(message)) {
|
|
186
|
+
return "STORAGE_QUOTA_EXCEEDED";
|
|
187
|
+
}
|
|
188
|
+
return void 0;
|
|
189
|
+
}
|
|
190
|
+
function isStorageStatus(record) {
|
|
191
|
+
const meta = "meta" in record && typeof record.meta === "object" && record.meta !== null ? record.meta : {};
|
|
192
|
+
const statuses = [
|
|
193
|
+
"status" in record ? record.status : void 0,
|
|
194
|
+
"statusCode" in record ? record.statusCode : void 0,
|
|
195
|
+
"status" in meta ? meta.status : void 0
|
|
196
|
+
];
|
|
197
|
+
return statuses.some((value) => value === 402 || value === 413);
|
|
198
|
+
}
|
|
199
|
+
function accountTotals(meta) {
|
|
200
|
+
if (typeof meta !== "object" || meta === null) return void 0;
|
|
201
|
+
const account = meta.account;
|
|
202
|
+
if (typeof account !== "object" || account === null) return void 0;
|
|
203
|
+
const { usedBytes, limitBytes, plan } = account;
|
|
204
|
+
if (!isByteCount(usedBytes) || !isByteCount(limitBytes) || limitBytes === 0) return void 0;
|
|
205
|
+
return typeof plan === "string" && /^[A-Za-z0-9][A-Za-z0-9 _.-]{0,31}$/.test(plan) ? { usedBytes, limitBytes, plan } : { usedBytes, limitBytes };
|
|
206
|
+
}
|
|
207
|
+
function isByteCount(value) {
|
|
208
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
209
|
+
}
|
|
210
|
+
var MANAGE_STORAGE_URL, MAX_CAUSE_DEPTH;
|
|
211
|
+
var init_storage = __esm({
|
|
212
|
+
"src/output/storage.ts"() {
|
|
213
|
+
"use strict";
|
|
214
|
+
MANAGE_STORAGE_URL = "https://account.tinycloud.xyz/billing";
|
|
215
|
+
MAX_CAUSE_DEPTH = 4;
|
|
108
216
|
}
|
|
109
217
|
});
|
|
110
218
|
|
|
@@ -117,6 +225,8 @@ function setActiveProfileName(name) {
|
|
|
117
225
|
activeProfileName = name;
|
|
118
226
|
}
|
|
119
227
|
function wrapError(error) {
|
|
228
|
+
const storageFull = storageFullError(error);
|
|
229
|
+
if (storageFull) return storageFull;
|
|
120
230
|
if (error instanceof CLIError) return error;
|
|
121
231
|
const message = error instanceof Error ? error.message : String(error);
|
|
122
232
|
const verdict = authorizationVerdictOf(error);
|
|
@@ -163,6 +273,13 @@ function missingPrivateKeyError() {
|
|
|
163
273
|
{ hint: `Sign in again with: tc --profile ${profileName} auth login --method openkey` }
|
|
164
274
|
);
|
|
165
275
|
}
|
|
276
|
+
function storageFullError(error, progress) {
|
|
277
|
+
if (error instanceof CLIError && error.exitCode === ExitCode.STORAGE_FULL) return error;
|
|
278
|
+
const rejection = storageRejection(error);
|
|
279
|
+
if (!rejection) return void 0;
|
|
280
|
+
const { message, hint } = describeStorageRejection(rejection, progress);
|
|
281
|
+
return new CLIError(rejection.code, message, ExitCode.STORAGE_FULL, { hint });
|
|
282
|
+
}
|
|
166
283
|
function handleError(error) {
|
|
167
284
|
const cliError = wrapError(error);
|
|
168
285
|
const prebuilt = typeof cliError.metadata?.hint === "string" ? cliError.metadata.hint : void 0;
|
|
@@ -175,7 +292,10 @@ function handleError(error) {
|
|
|
175
292
|
meta.resource = capability.resource;
|
|
176
293
|
meta.requiredAction = capability.requiredAction;
|
|
177
294
|
}
|
|
178
|
-
outputError(cliError.code, cliError.message, hint,
|
|
295
|
+
outputError(cliError.code, cliError.message, hint, {
|
|
296
|
+
...Object.keys(meta).length ? { meta } : {},
|
|
297
|
+
warnings: operationWarnings(cliError.metadata?.warnings)
|
|
298
|
+
});
|
|
179
299
|
process.exit(cliError.exitCode);
|
|
180
300
|
}
|
|
181
301
|
function buildAuthHint(error) {
|
|
@@ -245,6 +365,7 @@ var init_errors = __esm({
|
|
|
245
365
|
"use strict";
|
|
246
366
|
init_constants();
|
|
247
367
|
init_formatter();
|
|
368
|
+
init_storage();
|
|
248
369
|
CLIError = class extends Error {
|
|
249
370
|
constructor(code3, message, exitCode = ExitCode.ERROR, metadata) {
|
|
250
371
|
super(message);
|
|
@@ -312,7 +433,7 @@ async function listDirs(dirPath) {
|
|
|
312
433
|
}
|
|
313
434
|
}
|
|
314
435
|
var PRIVATE_FILE_MODE, PRIVATE_DIR_MODE;
|
|
315
|
-
var
|
|
436
|
+
var init_storage2 = __esm({
|
|
316
437
|
"src/config/storage.ts"() {
|
|
317
438
|
"use strict";
|
|
318
439
|
PRIVATE_FILE_MODE = 384;
|
|
@@ -570,7 +691,7 @@ var init_profiles = __esm({
|
|
|
570
691
|
"src/config/profiles.ts"() {
|
|
571
692
|
"use strict";
|
|
572
693
|
init_constants();
|
|
573
|
-
|
|
694
|
+
init_storage2();
|
|
574
695
|
init_errors();
|
|
575
696
|
ProfileManager = class _ProfileManager {
|
|
576
697
|
// ── Initialization ──────────────────────────────────────────────────
|
|
@@ -640,7 +761,7 @@ var init_profiles = __esm({
|
|
|
640
761
|
if (!profile) {
|
|
641
762
|
throw new CLIError(
|
|
642
763
|
"PROFILE_NOT_FOUND",
|
|
643
|
-
`Profile "${name}" does not exist.
|
|
764
|
+
`Profile "${name}" does not exist. Create it with \`tc init --name ${name}\`.`
|
|
644
765
|
);
|
|
645
766
|
}
|
|
646
767
|
return profile;
|
|
@@ -5651,6 +5772,37 @@ var init_zod = __esm({
|
|
|
5651
5772
|
}
|
|
5652
5773
|
});
|
|
5653
5774
|
|
|
5775
|
+
// src/auth/session-expired.ts
|
|
5776
|
+
function signInAgainHint(profileName, posture) {
|
|
5777
|
+
if (posture === "local-owner-key") {
|
|
5778
|
+
return `Sign in again with: tc --profile ${profileName} auth login --method local`;
|
|
5779
|
+
}
|
|
5780
|
+
if (posture === "delegate-session") {
|
|
5781
|
+
return `Have the owner approve a new scoped login: tc --profile ${profileName} auth login --method openkey --paste --manifest <manifest.json>. Pass the owner's code on stdin, newline-terminated.`;
|
|
5782
|
+
}
|
|
5783
|
+
return `Sign in again with: tc --profile ${profileName} auth login --method openkey`;
|
|
5784
|
+
}
|
|
5785
|
+
function sessionExpiredError(profileName, posture) {
|
|
5786
|
+
return new CLIError(
|
|
5787
|
+
"AUTH_REQUIRED",
|
|
5788
|
+
`The session for profile "${profileName}" has expired or is no longer valid.`,
|
|
5789
|
+
ExitCode.AUTH_REQUIRED,
|
|
5790
|
+
{ hint: signInAgainHint(profileName, posture), reason: SESSION_EXPIRED_REASON }
|
|
5791
|
+
);
|
|
5792
|
+
}
|
|
5793
|
+
function isSessionExpiredError(error) {
|
|
5794
|
+
return error instanceof CLIError && error.metadata?.reason === SESSION_EXPIRED_REASON;
|
|
5795
|
+
}
|
|
5796
|
+
var SESSION_EXPIRED_REASON;
|
|
5797
|
+
var init_session_expired = __esm({
|
|
5798
|
+
"src/auth/session-expired.ts"() {
|
|
5799
|
+
"use strict";
|
|
5800
|
+
init_constants();
|
|
5801
|
+
init_errors();
|
|
5802
|
+
SESSION_EXPIRED_REASON = "session_expired";
|
|
5803
|
+
}
|
|
5804
|
+
});
|
|
5805
|
+
|
|
5654
5806
|
// src/lib/raw-encryption.ts
|
|
5655
5807
|
var init_raw_encryption = __esm({
|
|
5656
5808
|
"src/lib/raw-encryption.ts"() {
|
|
@@ -5713,13 +5865,14 @@ async function replayAdditionalDelegations(node, profile, options) {
|
|
|
5713
5865
|
for (const stored of entries) {
|
|
5714
5866
|
const kind = storedDelegationKind(stored);
|
|
5715
5867
|
if (kind === "compact" || kind === "signed-login") {
|
|
5716
|
-
const
|
|
5868
|
+
const replay = await replayStoredDelegation(activator, stored, {
|
|
5717
5869
|
host: options.host,
|
|
5718
5870
|
migrated,
|
|
5719
5871
|
resolveSpace
|
|
5720
5872
|
});
|
|
5721
|
-
if (
|
|
5722
|
-
process.stderr.write(
|
|
5873
|
+
if (replay.status === "skipped" && process.env.TC_DEBUG_REPLAY === "1") {
|
|
5874
|
+
process.stderr.write(`[replay] skipping a stored delegation: ${replay.reason}
|
|
5875
|
+
`);
|
|
5723
5876
|
}
|
|
5724
5877
|
continue;
|
|
5725
5878
|
}
|
|
@@ -5750,7 +5903,7 @@ var init_permissions = __esm({
|
|
|
5750
5903
|
"src/lib/permissions.ts"() {
|
|
5751
5904
|
"use strict";
|
|
5752
5905
|
init_constants();
|
|
5753
|
-
|
|
5906
|
+
init_storage2();
|
|
5754
5907
|
init_profiles();
|
|
5755
5908
|
init_errors();
|
|
5756
5909
|
init_constants();
|
|
@@ -5797,6 +5950,16 @@ function signerJwkForProfile(profileName, sessionJwk, key) {
|
|
|
5797
5950
|
}
|
|
5798
5951
|
);
|
|
5799
5952
|
}
|
|
5953
|
+
async function restoreProfileSession(node, profileName, profile, sessionData) {
|
|
5954
|
+
try {
|
|
5955
|
+
await node.restoreSession(sessionData);
|
|
5956
|
+
} catch (error) {
|
|
5957
|
+
if (typeof error === "object" && error !== null && "code" in error && error.code === "AUTH_EXPIRED") {
|
|
5958
|
+
throw sessionExpiredError(profileName, profile === null ? void 0 : resolveProfilePosture(profile));
|
|
5959
|
+
}
|
|
5960
|
+
throw error;
|
|
5961
|
+
}
|
|
5962
|
+
}
|
|
5800
5963
|
async function createSDKInstance(ctx, options) {
|
|
5801
5964
|
const profile = options?.privateKey ? await ProfileManager.getProfile(ctx.profile).catch(() => null) : await ProfileManager.getProfile(ctx.profile);
|
|
5802
5965
|
const session = await ProfileManager.getSession(ctx.profile);
|
|
@@ -5805,7 +5968,7 @@ async function createSDKInstance(ctx, options) {
|
|
|
5805
5968
|
if (!key && !effectivePrivateKey && !(profile?.authMethod === "openkey" && session !== null)) {
|
|
5806
5969
|
throw new CLIError(
|
|
5807
5970
|
"AUTH_REQUIRED",
|
|
5808
|
-
`No key found for profile "${ctx.profile}". Run \`tc
|
|
5971
|
+
`No key found for profile "${ctx.profile}". Run \`tc --profile ${ctx.profile} auth rotate\` to create a new key and sign in.`,
|
|
5809
5972
|
ExitCode.AUTH_REQUIRED
|
|
5810
5973
|
);
|
|
5811
5974
|
}
|
|
@@ -5816,7 +5979,7 @@ async function createSDKInstance(ctx, options) {
|
|
|
5816
5979
|
});
|
|
5817
5980
|
let restoredOwnSession2 = false;
|
|
5818
5981
|
if (session && session.delegationHeader && session.delegationCid && session.spaceId) {
|
|
5819
|
-
await node2.
|
|
5982
|
+
await restoreProfileSession(node2, ctx.profile, profile, {
|
|
5820
5983
|
delegationHeader: session.delegationHeader,
|
|
5821
5984
|
delegationCid: session.delegationCid,
|
|
5822
5985
|
spaceId: session.spaceId,
|
|
@@ -5846,7 +6009,7 @@ async function createSDKInstance(ctx, options) {
|
|
|
5846
6009
|
if (options?.privateKey) {
|
|
5847
6010
|
await node.signIn();
|
|
5848
6011
|
} else if (session && session.delegationHeader && session.delegationCid && session.spaceId) {
|
|
5849
|
-
await node.
|
|
6012
|
+
await restoreProfileSession(node, ctx.profile, profile, {
|
|
5850
6013
|
delegationHeader: session.delegationHeader,
|
|
5851
6014
|
delegationCid: session.delegationCid,
|
|
5852
6015
|
spaceId: session.spaceId,
|
|
@@ -5990,6 +6153,7 @@ var init_sdk = __esm({
|
|
|
5990
6153
|
init_errors();
|
|
5991
6154
|
init_constants();
|
|
5992
6155
|
init_permissions();
|
|
6156
|
+
init_session_expired();
|
|
5993
6157
|
BOOTSTRAP_PROFILE_FIELDS = ["sessionDid", "spaceId"];
|
|
5994
6158
|
}
|
|
5995
6159
|
});
|
|
@@ -6088,7 +6252,7 @@ function formatBannerLine(version2) {
|
|
|
6088
6252
|
}
|
|
6089
6253
|
function emitBanner(version2) {
|
|
6090
6254
|
if (bannerEmitted) return;
|
|
6091
|
-
if (
|
|
6255
|
+
if (shouldOutputJson()) return;
|
|
6092
6256
|
if (process.env.TC_HIDE_BANNER === "1") return;
|
|
6093
6257
|
bannerEmitted = true;
|
|
6094
6258
|
process.stderr.write(formatBannerLine(version2) + "\n\n");
|
|
@@ -16699,7 +16863,6 @@ function parseDuration(input) {
|
|
|
16699
16863
|
}
|
|
16700
16864
|
|
|
16701
16865
|
// src/commands/share.ts
|
|
16702
|
-
init_formatter();
|
|
16703
16866
|
init_errors();
|
|
16704
16867
|
|
|
16705
16868
|
// src/share/output.ts
|
|
@@ -16965,9 +17128,8 @@ function shareCliError(error, operation = "publish") {
|
|
|
16965
17128
|
if (failure.kind === "registry-rejected") {
|
|
16966
17129
|
return new CLIError("REGISTRY_REJECTED", "the TinyCloud location registry rejected this session's location record, so nothing was shared; retrying will not help. Log in again, and report the problem if it persists", 6);
|
|
16967
17130
|
}
|
|
16968
|
-
if (failure.kind === "storage-
|
|
16969
|
-
|
|
16970
|
-
return new CLIError("STORAGE_QUOTA_EXCEEDED", `storage quota exceeded${sizes}; nothing was shared`, 4);
|
|
17131
|
+
if (failure.kind === "storage-full") {
|
|
17132
|
+
return storageFullError(failure);
|
|
16971
17133
|
}
|
|
16972
17134
|
if (failure.kind === "upload-failed") {
|
|
16973
17135
|
return new CLIError("UPLOAD_FAILED", "share source upload failed; nothing was shared", 4);
|
|
@@ -16987,6 +17149,8 @@ function shareCliError(error, operation = "publish") {
|
|
|
16987
17149
|
const code3 = error.code === "fetch-failed" ? "NOT_FOUND" : error.code.replaceAll("-", "_").toUpperCase();
|
|
16988
17150
|
return new CLIError(code3, error.message, exit);
|
|
16989
17151
|
}
|
|
17152
|
+
const storageFull = storageFullError(error);
|
|
17153
|
+
if (storageFull) return storageFull;
|
|
16990
17154
|
const message = error instanceof Error ? error.message : String(error);
|
|
16991
17155
|
const nodeCode = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
|
|
16992
17156
|
const known = {
|
|
@@ -17280,8 +17444,10 @@ function registerShareCommand(program2) {
|
|
|
17280
17444
|
}
|
|
17281
17445
|
|
|
17282
17446
|
// src/share/adapters.ts
|
|
17447
|
+
init_storage();
|
|
17283
17448
|
init_profiles();
|
|
17284
17449
|
init_constants();
|
|
17450
|
+
init_session_expired();
|
|
17285
17451
|
import { readFile as readFile4 } from "fs/promises";
|
|
17286
17452
|
import { join as join6 } from "path";
|
|
17287
17453
|
import { createHash } from "crypto";
|
|
@@ -17293,15 +17459,9 @@ function requiredKvAction(meta) {
|
|
|
17293
17459
|
const action = meta.requiredAction;
|
|
17294
17460
|
return action === "tinycloud.kv/put" || action === "tinycloud.kv/get" ? action : void 0;
|
|
17295
17461
|
}
|
|
17296
|
-
function isByteCount(value) {
|
|
17297
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
17298
|
-
}
|
|
17299
17462
|
function throwKvUploadFailure(error) {
|
|
17300
|
-
|
|
17301
|
-
|
|
17302
|
-
const { usedBytes, limitBytes } = meta;
|
|
17303
|
-
throw new SharePublishAuthorityError(isByteCount(usedBytes) && isByteCount(limitBytes) ? { kind: "storage-quota-exceeded", usedBytes, limitBytes } : { kind: "storage-quota-exceeded" });
|
|
17304
|
-
}
|
|
17463
|
+
const rejection = storageRejection(error);
|
|
17464
|
+
if (rejection) throw new SharePublishAuthorityError({ kind: "storage-full", ...rejection });
|
|
17305
17465
|
throw new SharePublishAuthorityError({ kind: "upload-failed" });
|
|
17306
17466
|
}
|
|
17307
17467
|
var DEFAULT_SHARE_ORIGIN = "https://share.tinycloud.xyz";
|
|
@@ -17600,7 +17760,7 @@ function createShareAuthorityAdapters(input = {}) {
|
|
|
17600
17760
|
} catch (error) {
|
|
17601
17761
|
const profileConfig = await ProfileManager.getProfile(profile).catch(() => void 0);
|
|
17602
17762
|
const code3 = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
|
|
17603
|
-
if (error instanceof InvalidRestoredSessionError || code3 === "AUTH_EXPIRED") {
|
|
17763
|
+
if (error instanceof InvalidRestoredSessionError || code3 === "AUTH_EXPIRED" || isSessionExpiredError(error)) {
|
|
17604
17764
|
throw new SharePublishAuthorityError({
|
|
17605
17765
|
kind: "owner-space-unresolved",
|
|
17606
17766
|
localKey: profileConfig?.authMethod === "local",
|
|
@@ -17962,6 +18122,7 @@ function selectedShareProfile() {
|
|
|
17962
18122
|
program.name("tc").description("TinyCloud CLI \u2014 self-sovereign storage from the terminal").version(version).option("-p, --profile <name>", "Profile to use").option("-H, --host <url>", "TinyCloud node URL").option("-v, --verbose", "Enable verbose output").option("--no-cache", "Disable caching").option("-q, --quiet", "Suppress non-essential output").option("--json", "Force JSON output");
|
|
17963
18123
|
program.hook("preAction", async (thisCommand) => {
|
|
17964
18124
|
const opts = thisCommand.optsWithGlobals();
|
|
18125
|
+
setJsonOutputRequested(opts.json === true);
|
|
17965
18126
|
const parentName = thisCommand.parent?.name();
|
|
17966
18127
|
const isShareCommand = parentName === "share" || thisCommand.name() === "share";
|
|
17967
18128
|
if (!opts.quiet && !isShareCommand) {
|
|
@@ -17970,7 +18131,7 @@ program.hook("preAction", async (thisCommand) => {
|
|
|
17970
18131
|
const commandName = thisCommand.name();
|
|
17971
18132
|
const fullCommand = parentName && parentName !== "tc" ? `${parentName} ${commandName}` : commandName;
|
|
17972
18133
|
const skipGuard = ["tc", "init", "doctor", "completion", "help", "upgrade", "status"].includes(commandName) || fullCommand === "profile create";
|
|
17973
|
-
if (!skipGuard && !opts.quiet &&
|
|
18134
|
+
if (!skipGuard && !opts.quiet && !shouldOutputJson()) {
|
|
17974
18135
|
try {
|
|
17975
18136
|
const config = await ProfileManager.getConfig();
|
|
17976
18137
|
const profileName = opts.profile || config.defaultProfile;
|