@tinycloud/cli 1.1.0-beta.12 → 1.1.0-beta.13
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 +103 -21
- package/dist/index.js.map +1 -1
- package/dist/legacy-entry.js +104 -19
- package/dist/legacy-entry.js.map +1 -1
- package/package.json +2 -2
- package/skills/tc-cli/REFERENCE.md +5 -3
package/dist/legacy-entry.js
CHANGED
|
@@ -59,7 +59,9 @@ var init_constants = __esm({
|
|
|
59
59
|
NOT_FOUND: 4,
|
|
60
60
|
PERMISSION_DENIED: 5,
|
|
61
61
|
NETWORK_ERROR: 6,
|
|
62
|
-
NODE_ERROR: 7
|
|
62
|
+
NODE_ERROR: 7,
|
|
63
|
+
/** A write was refused because the owner's TinyCloud storage is full. */
|
|
64
|
+
STORAGE_FULL: 10
|
|
63
65
|
};
|
|
64
66
|
}
|
|
65
67
|
});
|
|
@@ -258,6 +260,86 @@ var init_formatter = __esm({
|
|
|
258
260
|
}
|
|
259
261
|
});
|
|
260
262
|
|
|
263
|
+
// src/output/storage.ts
|
|
264
|
+
function storageRejection(error) {
|
|
265
|
+
let node = error;
|
|
266
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH && typeof node === "object" && node !== null; depth += 1) {
|
|
267
|
+
const record = node;
|
|
268
|
+
let code3;
|
|
269
|
+
if (record.code === "STORAGE_QUOTA_EXCEEDED" || record.code === "STORAGE_LIMIT_REACHED") {
|
|
270
|
+
code3 = record.code;
|
|
271
|
+
} else if (record.code !== void 0) {
|
|
272
|
+
return void 0;
|
|
273
|
+
} else if (isStorageStatus(record)) {
|
|
274
|
+
code3 = storageCodeFromText(record.message);
|
|
275
|
+
}
|
|
276
|
+
if (code3) {
|
|
277
|
+
const account = accountTotals(record) ?? accountTotals(record.meta) ?? accountTotals(record.metadata);
|
|
278
|
+
return account ? { code: code3, account } : { code: code3 };
|
|
279
|
+
}
|
|
280
|
+
node = record.cause;
|
|
281
|
+
}
|
|
282
|
+
return void 0;
|
|
283
|
+
}
|
|
284
|
+
function describeStorageRejection(rejection, progress) {
|
|
285
|
+
const reason = rejection.code === "STORAGE_LIMIT_REACHED" ? "This write is larger than the TinyCloud storage you have left" : "TinyCloud storage is full";
|
|
286
|
+
const message = progress ? `${progress}${reason}.` : `${reason}; nothing was written.`;
|
|
287
|
+
const { account } = rejection;
|
|
288
|
+
const totals = account ? `${formatStorageBytes(account.usedBytes)} used of ${formatStorageBytes(account.limitBytes)}${account.plan ? ` (${account.plan} plan)` : ""}. ` : "";
|
|
289
|
+
return {
|
|
290
|
+
message,
|
|
291
|
+
hint: `${totals}Reading still works.
|
|
292
|
+
Free up space or upgrade: ${MANAGE_STORAGE_URL}`
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function formatStorageBytes(bytes) {
|
|
296
|
+
const units = ["KiB", "MiB", "GiB", "TiB"];
|
|
297
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
298
|
+
let value = bytes / 1024;
|
|
299
|
+
let unit = 0;
|
|
300
|
+
while (value >= 1024 && unit < units.length - 1) {
|
|
301
|
+
value /= 1024;
|
|
302
|
+
unit += 1;
|
|
303
|
+
}
|
|
304
|
+
return `${value.toFixed(1).replace(/\.0$/, "")} ${units[unit]}`;
|
|
305
|
+
}
|
|
306
|
+
function storageCodeFromText(message) {
|
|
307
|
+
if (typeof message !== "string") return void 0;
|
|
308
|
+
if (message.includes("larger than the TinyCloud storage you have left")) return "STORAGE_LIMIT_REACHED";
|
|
309
|
+
if (message.includes("TinyCloud storage is full") || /storage quota exceeded/i.test(message)) {
|
|
310
|
+
return "STORAGE_QUOTA_EXCEEDED";
|
|
311
|
+
}
|
|
312
|
+
return void 0;
|
|
313
|
+
}
|
|
314
|
+
function isStorageStatus(record) {
|
|
315
|
+
const meta = "meta" in record && typeof record.meta === "object" && record.meta !== null ? record.meta : {};
|
|
316
|
+
const statuses = [
|
|
317
|
+
"status" in record ? record.status : void 0,
|
|
318
|
+
"statusCode" in record ? record.statusCode : void 0,
|
|
319
|
+
"status" in meta ? meta.status : void 0
|
|
320
|
+
];
|
|
321
|
+
return statuses.some((value) => value === 402 || value === 413);
|
|
322
|
+
}
|
|
323
|
+
function accountTotals(meta) {
|
|
324
|
+
if (typeof meta !== "object" || meta === null) return void 0;
|
|
325
|
+
const account = meta.account;
|
|
326
|
+
if (typeof account !== "object" || account === null) return void 0;
|
|
327
|
+
const { usedBytes, limitBytes, plan } = account;
|
|
328
|
+
if (!isByteCount(usedBytes) || !isByteCount(limitBytes) || limitBytes === 0) return void 0;
|
|
329
|
+
return typeof plan === "string" && /^[A-Za-z0-9][A-Za-z0-9 _.-]{0,31}$/.test(plan) ? { usedBytes, limitBytes, plan } : { usedBytes, limitBytes };
|
|
330
|
+
}
|
|
331
|
+
function isByteCount(value) {
|
|
332
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
333
|
+
}
|
|
334
|
+
var MANAGE_STORAGE_URL, MAX_CAUSE_DEPTH;
|
|
335
|
+
var init_storage2 = __esm({
|
|
336
|
+
"src/output/storage.ts"() {
|
|
337
|
+
"use strict";
|
|
338
|
+
MANAGE_STORAGE_URL = "https://account.tinycloud.xyz/billing";
|
|
339
|
+
MAX_CAUSE_DEPTH = 4;
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
|
|
261
343
|
// src/output/errors.ts
|
|
262
344
|
import { readFileSync, readdirSync } from "fs";
|
|
263
345
|
import { join as join2 } from "path";
|
|
@@ -268,6 +350,8 @@ function setActiveProfileName(name) {
|
|
|
268
350
|
}
|
|
269
351
|
function cliErrorFromService(error, message = error.message) {
|
|
270
352
|
if (error instanceof CLIError) return error;
|
|
353
|
+
const storageFull = storageFullError(error);
|
|
354
|
+
if (storageFull) return storageFull;
|
|
271
355
|
const meta = { ...error.meta };
|
|
272
356
|
delete meta.hint;
|
|
273
357
|
const status = error.status ?? error.statusCode;
|
|
@@ -286,6 +370,8 @@ function cliErrorFromService(error, message = error.message) {
|
|
|
286
370
|
);
|
|
287
371
|
}
|
|
288
372
|
function wrapError(error) {
|
|
373
|
+
const storageFull = storageFullError(error);
|
|
374
|
+
if (storageFull) return storageFull;
|
|
289
375
|
if (error instanceof CLIError) return error;
|
|
290
376
|
const message = error instanceof Error ? error.message : String(error);
|
|
291
377
|
const verdict = authorizationVerdictOf(error);
|
|
@@ -332,6 +418,13 @@ function missingPrivateKeyError() {
|
|
|
332
418
|
{ hint: `Sign in again with: tc --profile ${profileName} auth login --method openkey` }
|
|
333
419
|
);
|
|
334
420
|
}
|
|
421
|
+
function storageFullError(error, progress) {
|
|
422
|
+
if (error instanceof CLIError && error.exitCode === ExitCode.STORAGE_FULL) return error;
|
|
423
|
+
const rejection = storageRejection(error);
|
|
424
|
+
if (!rejection) return void 0;
|
|
425
|
+
const { message, hint } = describeStorageRejection(rejection, progress);
|
|
426
|
+
return new CLIError(rejection.code, message, ExitCode.STORAGE_FULL, { hint });
|
|
427
|
+
}
|
|
335
428
|
function handleError(error) {
|
|
336
429
|
const cliError = wrapError(error);
|
|
337
430
|
const prebuilt = typeof cliError.metadata?.hint === "string" ? cliError.metadata.hint : void 0;
|
|
@@ -414,6 +507,7 @@ var init_errors = __esm({
|
|
|
414
507
|
"use strict";
|
|
415
508
|
init_constants();
|
|
416
509
|
init_formatter();
|
|
510
|
+
init_storage2();
|
|
417
511
|
CLIError = class extends Error {
|
|
418
512
|
constructor(code3, message, exitCode = ExitCode.ERROR, metadata) {
|
|
419
513
|
super(message);
|
|
@@ -7055,7 +7149,7 @@ function validatedCapabilityOf2(error) {
|
|
|
7055
7149
|
if (verdict !== "unauthenticated" && verdict !== "forbidden") return void 0;
|
|
7056
7150
|
const seen = /* @__PURE__ */ new Set();
|
|
7057
7151
|
let node = error;
|
|
7058
|
-
for (let depth = 0; depth <
|
|
7152
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH2 && typeof node === "object" && node !== null && !seen.has(node); depth += 1) {
|
|
7059
7153
|
seen.add(node);
|
|
7060
7154
|
const record = node;
|
|
7061
7155
|
const status = errorStatusOf(record);
|
|
@@ -7075,7 +7169,7 @@ function validatedCapabilityOf2(error) {
|
|
|
7075
7169
|
}
|
|
7076
7170
|
return void 0;
|
|
7077
7171
|
}
|
|
7078
|
-
var
|
|
7172
|
+
var MAX_CAUSE_DEPTH2 = 8;
|
|
7079
7173
|
function errorStatusOf(node) {
|
|
7080
7174
|
const meta = node.meta;
|
|
7081
7175
|
const candidates = [
|
|
@@ -7094,7 +7188,7 @@ function authorizationVerdictOf2(error) {
|
|
|
7094
7188
|
const seen = /* @__PURE__ */ new Set();
|
|
7095
7189
|
let sawUnauthorizedCode = false;
|
|
7096
7190
|
let node = error;
|
|
7097
|
-
for (let depth = 0; depth <
|
|
7191
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH2 && typeof node === "object" && node !== null && !seen.has(node); depth += 1) {
|
|
7098
7192
|
seen.add(node);
|
|
7099
7193
|
const record = node;
|
|
7100
7194
|
const status = errorStatusOf(record);
|
|
@@ -17531,15 +17625,6 @@ async function throwKvError(error, spaceUri, profileName) {
|
|
|
17531
17625
|
if (hosted) throw hosted;
|
|
17532
17626
|
throw cliErrorFromService(error);
|
|
17533
17627
|
}
|
|
17534
|
-
function isByteCount(value) {
|
|
17535
|
-
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
17536
|
-
}
|
|
17537
|
-
function storageQuotaError(error) {
|
|
17538
|
-
if (error.code !== "STORAGE_QUOTA_EXCEEDED") return void 0;
|
|
17539
|
-
const { usedBytes, limitBytes } = typeof error.meta === "object" && error.meta !== null ? error.meta : {};
|
|
17540
|
-
const sizes = isByteCount(usedBytes) && isByteCount(limitBytes) ? ` (${formatBytes(usedBytes)} used of ${formatBytes(limitBytes)} limit)` : "";
|
|
17541
|
-
return new CLIError("STORAGE_QUOTA_EXCEEDED", `storage quota exceeded${sizes}; nothing was written`, ExitCode.ERROR);
|
|
17542
|
-
}
|
|
17543
17628
|
function assertAddressableKey(key) {
|
|
17544
17629
|
for (let i = 0; i < key.length; i++) {
|
|
17545
17630
|
const code3 = key.charCodeAt(i);
|
|
@@ -17635,8 +17720,6 @@ function registerKvCommand(program) {
|
|
|
17635
17720
|
const { kv: kv2, spaceUri } = await kvHandle(node, options.space, ctx.profile);
|
|
17636
17721
|
const result = await withSpinner(`Writing ${key}...`, () => kv2.put(key, putValue));
|
|
17637
17722
|
if (!result.ok) {
|
|
17638
|
-
const quota = storageQuotaError(result.error);
|
|
17639
|
-
if (quota) throw quota;
|
|
17640
17723
|
await throwKvError(result.error, spaceUri, ctx.profile);
|
|
17641
17724
|
}
|
|
17642
17725
|
outputJson({ key, written: true });
|
|
@@ -29312,7 +29395,6 @@ var MAX_INLINE_BYTES2 = 256 * 1024;
|
|
|
29312
29395
|
|
|
29313
29396
|
// src/commands/share.ts
|
|
29314
29397
|
import { ProfileLockTimeoutError as ProfileLockTimeoutError3 } from "@tinycloud/operations/state";
|
|
29315
|
-
init_formatter();
|
|
29316
29398
|
init_errors();
|
|
29317
29399
|
|
|
29318
29400
|
// src/share/output.ts
|
|
@@ -29575,9 +29657,8 @@ function shareCliError(error, operation = "publish") {
|
|
|
29575
29657
|
if (failure.kind === "registry-rejected") {
|
|
29576
29658
|
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);
|
|
29577
29659
|
}
|
|
29578
|
-
if (failure.kind === "storage-
|
|
29579
|
-
|
|
29580
|
-
return new CLIError("STORAGE_QUOTA_EXCEEDED", `storage quota exceeded${sizes}; nothing was shared`, 4);
|
|
29660
|
+
if (failure.kind === "storage-full") {
|
|
29661
|
+
return storageFullError(failure);
|
|
29581
29662
|
}
|
|
29582
29663
|
if (failure.kind === "upload-failed") {
|
|
29583
29664
|
return new CLIError("UPLOAD_FAILED", "share source upload failed; nothing was shared", 4);
|
|
@@ -29597,6 +29678,8 @@ function shareCliError(error, operation = "publish") {
|
|
|
29597
29678
|
const code3 = error.code === "fetch-failed" ? "NOT_FOUND" : error.code.replaceAll("-", "_").toUpperCase();
|
|
29598
29679
|
return new CLIError(code3, error.message, exit);
|
|
29599
29680
|
}
|
|
29681
|
+
const storageFull = storageFullError(error);
|
|
29682
|
+
if (storageFull) return storageFull;
|
|
29600
29683
|
const message = error instanceof Error ? error.message : String(error);
|
|
29601
29684
|
const nodeCode = typeof error === "object" && error !== null && "code" in error ? error.code : void 0;
|
|
29602
29685
|
const known = {
|
|
@@ -30054,6 +30137,8 @@ async function dbHandle(node, dbName, spaceInput, profileName) {
|
|
|
30054
30137
|
return { handle: sql.db(dbName), spaceUri };
|
|
30055
30138
|
}
|
|
30056
30139
|
async function throwSqlError(error, spaceUri, profileName, prefix) {
|
|
30140
|
+
const storageFull = storageFullError(error, prefix);
|
|
30141
|
+
if (storageFull) throw storageFull;
|
|
30057
30142
|
const hosted = await unhostedSpaceError(error, spaceUri, profileName);
|
|
30058
30143
|
if (hosted) throw hosted;
|
|
30059
30144
|
const message = prefix ? `${prefix}${error.message}` : error.message;
|