@tinycloud/cli 0.7.0-beta.7 → 0.7.0-beta.8
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 +216 -4
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -912,8 +912,8 @@ async function callbackFlow(did, options = {}) {
|
|
|
912
912
|
}
|
|
913
913
|
if (openBrowser) {
|
|
914
914
|
try {
|
|
915
|
-
const
|
|
916
|
-
await
|
|
915
|
+
const open2 = (await import("open")).default;
|
|
916
|
+
await open2(authUrl);
|
|
917
917
|
} catch {
|
|
918
918
|
server.close();
|
|
919
919
|
throw new Error("Failed to open browser");
|
|
@@ -14257,8 +14257,8 @@ function registerSecretsCommand(program2) {
|
|
|
14257
14257
|
});
|
|
14258
14258
|
secrets.command("manage").description("Open the TinyCloud Secrets Manager in your browser").action(async () => {
|
|
14259
14259
|
try {
|
|
14260
|
-
const
|
|
14261
|
-
await
|
|
14260
|
+
const open2 = (await import("open")).default;
|
|
14261
|
+
await open2("https://secrets.tinycloud.xyz");
|
|
14262
14262
|
outputJson({ opened: "https://secrets.tinycloud.xyz" });
|
|
14263
14263
|
} catch (error) {
|
|
14264
14264
|
handleError(error);
|
|
@@ -15474,6 +15474,216 @@ function plural(count, label) {
|
|
|
15474
15474
|
return `${count} ${label}${count === 1 ? "" : "s"}`;
|
|
15475
15475
|
}
|
|
15476
15476
|
|
|
15477
|
+
// src/commands/account.ts
|
|
15478
|
+
import open from "open";
|
|
15479
|
+
import { readFile as readFile10 } from "fs/promises";
|
|
15480
|
+
var ACCOUNT_BILLING_URL = "https://account.tinycloud.xyz/billing";
|
|
15481
|
+
function registerAccountCommand(program2) {
|
|
15482
|
+
const account = program2.command("account").description("Account applications, delegations, and billing");
|
|
15483
|
+
account.command("status").description("Show account status").action(async (_options, cmd) => {
|
|
15484
|
+
try {
|
|
15485
|
+
const node = await authenticatedNode(cmd);
|
|
15486
|
+
const status = await node.account.status();
|
|
15487
|
+
assertOk(status);
|
|
15488
|
+
outputJson(status.data);
|
|
15489
|
+
} catch (error) {
|
|
15490
|
+
handleError(error);
|
|
15491
|
+
}
|
|
15492
|
+
});
|
|
15493
|
+
const apps = account.command("apps").description("Manage account application registry");
|
|
15494
|
+
apps.command("list").description("List applications registered under account/applications").option("--index", "Read from the materialized account SQLite index").action(async (_options, cmd) => {
|
|
15495
|
+
try {
|
|
15496
|
+
const options = _options;
|
|
15497
|
+
const node = await authenticatedNode(cmd);
|
|
15498
|
+
const result = options.index ? await node.account.index.applications.list() : await node.account.applications.list();
|
|
15499
|
+
assertOk(result);
|
|
15500
|
+
const payload = { applications: result.data, count: result.data.length };
|
|
15501
|
+
if (shouldOutputJson()) {
|
|
15502
|
+
outputJson(payload);
|
|
15503
|
+
return;
|
|
15504
|
+
}
|
|
15505
|
+
if (result.data.length === 0) {
|
|
15506
|
+
process.stdout.write(theme.muted("No account applications registered.") + "\n");
|
|
15507
|
+
return;
|
|
15508
|
+
}
|
|
15509
|
+
process.stdout.write(
|
|
15510
|
+
formatTable(
|
|
15511
|
+
["App ID", "Name", "Manifests", "Updated"],
|
|
15512
|
+
result.data.map((app) => [
|
|
15513
|
+
app.appId,
|
|
15514
|
+
app.name ?? "\u2014",
|
|
15515
|
+
String(app.manifests.length),
|
|
15516
|
+
app.updatedAt ?? "\u2014"
|
|
15517
|
+
])
|
|
15518
|
+
) + "\n"
|
|
15519
|
+
);
|
|
15520
|
+
} catch (error) {
|
|
15521
|
+
handleError(error);
|
|
15522
|
+
}
|
|
15523
|
+
});
|
|
15524
|
+
apps.command("info <app-id>").description("Show a registered account application").action(async (appId, _options, cmd) => {
|
|
15525
|
+
try {
|
|
15526
|
+
const node = await authenticatedNode(cmd);
|
|
15527
|
+
const result = await node.account.applications.get(appId);
|
|
15528
|
+
assertOk(result);
|
|
15529
|
+
outputJson(result.data);
|
|
15530
|
+
} catch (error) {
|
|
15531
|
+
handleError(error);
|
|
15532
|
+
}
|
|
15533
|
+
});
|
|
15534
|
+
apps.command("register <manifest>").description("Register an app manifest in account/applications").action(async (manifestSource, _options, cmd) => {
|
|
15535
|
+
try {
|
|
15536
|
+
const node = await authenticatedNode(cmd);
|
|
15537
|
+
const manifest = await loadManifestSource2(manifestSource);
|
|
15538
|
+
const result = await node.account.applications.register(manifest);
|
|
15539
|
+
assertOk(result);
|
|
15540
|
+
outputJson({ application: result.data, registered: true });
|
|
15541
|
+
} catch (error) {
|
|
15542
|
+
handleError(error);
|
|
15543
|
+
}
|
|
15544
|
+
});
|
|
15545
|
+
apps.command("remove <app-id>").alias("delete").description("Remove an application registry entry").action(async (appId, _options, cmd) => {
|
|
15546
|
+
try {
|
|
15547
|
+
const node = await authenticatedNode(cmd);
|
|
15548
|
+
const result = await node.account.applications.remove(appId);
|
|
15549
|
+
assertOk(result);
|
|
15550
|
+
outputJson({ appId, removed: true });
|
|
15551
|
+
} catch (error) {
|
|
15552
|
+
handleError(error);
|
|
15553
|
+
}
|
|
15554
|
+
});
|
|
15555
|
+
const delegations = account.command("delegations").description("View and revoke account delegations");
|
|
15556
|
+
delegations.command("list").description("List delegations granted by or to this account").option("--granted", "Show only delegations granted by this account").option("--received", "Show only delegations granted to this account").option("--space <space>", "Filter by space name or ID").option("--index", "Read from the materialized account SQLite index").action(async (options, cmd) => {
|
|
15557
|
+
try {
|
|
15558
|
+
if (options.granted && options.received) {
|
|
15559
|
+
throw new CLIError("USAGE_ERROR", "Use only one of --granted or --received.", ExitCode.USAGE_ERROR);
|
|
15560
|
+
}
|
|
15561
|
+
const node = await authenticatedNode(cmd);
|
|
15562
|
+
const direction = options.granted ? "granted" : options.received ? "received" : "all";
|
|
15563
|
+
const result = options.index ? await node.account.index.delegations.list({ direction, space: options.space }) : await node.account.delegations.list({ direction, space: options.space });
|
|
15564
|
+
assertOk(result);
|
|
15565
|
+
const payload = { delegations: result.data.map(formatDelegation2), count: result.data.length };
|
|
15566
|
+
if (shouldOutputJson()) {
|
|
15567
|
+
outputJson(payload);
|
|
15568
|
+
return;
|
|
15569
|
+
}
|
|
15570
|
+
if (result.data.length === 0) {
|
|
15571
|
+
process.stdout.write(theme.muted("No delegations found.") + "\n");
|
|
15572
|
+
return;
|
|
15573
|
+
}
|
|
15574
|
+
process.stdout.write(
|
|
15575
|
+
formatTable(
|
|
15576
|
+
["CID", "Direction", "Space", "Counterparty", "Status", "Expiry"],
|
|
15577
|
+
result.data.map((delegation) => [
|
|
15578
|
+
delegation.cid,
|
|
15579
|
+
delegation.direction,
|
|
15580
|
+
delegation.spaceName ?? delegation.spaceId,
|
|
15581
|
+
delegation.counterpartyDid,
|
|
15582
|
+
delegation.status,
|
|
15583
|
+
delegation.expiry.toISOString()
|
|
15584
|
+
])
|
|
15585
|
+
) + "\n"
|
|
15586
|
+
);
|
|
15587
|
+
} catch (error) {
|
|
15588
|
+
handleError(error);
|
|
15589
|
+
}
|
|
15590
|
+
});
|
|
15591
|
+
delegations.command("revoke <cid>").description("Revoke an active delegation granted by this account").requiredOption("--space <space>", "Space name or ID containing the delegation").action(async (cid, options, cmd) => {
|
|
15592
|
+
try {
|
|
15593
|
+
const node = await authenticatedNode(cmd);
|
|
15594
|
+
const result = await node.account.delegations.revoke({ cid, space: options.space });
|
|
15595
|
+
assertOk(result);
|
|
15596
|
+
outputJson({ cid, space: options.space, revoked: true });
|
|
15597
|
+
} catch (error) {
|
|
15598
|
+
handleError(error);
|
|
15599
|
+
}
|
|
15600
|
+
});
|
|
15601
|
+
const index = account.command("index").description("Manage the materialized account SQLite index");
|
|
15602
|
+
index.command("rebuild").description("Rebuild account SQLite index from canonical account data").action(async (_options, cmd) => {
|
|
15603
|
+
try {
|
|
15604
|
+
const node = await authenticatedNode(cmd);
|
|
15605
|
+
const result = await node.account.index.rebuild();
|
|
15606
|
+
assertOk(result);
|
|
15607
|
+
outputJson(result.data);
|
|
15608
|
+
} catch (error) {
|
|
15609
|
+
handleError(error);
|
|
15610
|
+
}
|
|
15611
|
+
});
|
|
15612
|
+
index.command("query <sql>").description("Query the materialized account SQLite index").option("--params <json>", "Bind parameters as a JSON array for ? placeholders").action(async (sql, options, cmd) => {
|
|
15613
|
+
try {
|
|
15614
|
+
const node = await authenticatedNode(cmd);
|
|
15615
|
+
const params = parseParams(options.params);
|
|
15616
|
+
const result = await node.account.index.query(sql, params);
|
|
15617
|
+
assertOk(result);
|
|
15618
|
+
outputJson(result.data);
|
|
15619
|
+
} catch (error) {
|
|
15620
|
+
handleError(error);
|
|
15621
|
+
}
|
|
15622
|
+
});
|
|
15623
|
+
const billing = account.command("billing").description("Open account billing");
|
|
15624
|
+
for (const name of ["status", "checkout", "portal"]) {
|
|
15625
|
+
billing.command(name).description(`${name === "status" ? "Show" : "Open"} account billing page`).option("--open", "Open account.tinycloud.xyz in your browser").action(async (options) => {
|
|
15626
|
+
try {
|
|
15627
|
+
if (options.open) {
|
|
15628
|
+
await open(ACCOUNT_BILLING_URL);
|
|
15629
|
+
}
|
|
15630
|
+
outputJson({ url: ACCOUNT_BILLING_URL, opened: Boolean(options.open) });
|
|
15631
|
+
} catch (error) {
|
|
15632
|
+
handleError(error);
|
|
15633
|
+
}
|
|
15634
|
+
});
|
|
15635
|
+
}
|
|
15636
|
+
}
|
|
15637
|
+
async function authenticatedNode(cmd) {
|
|
15638
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
15639
|
+
const ctx = await ProfileManager.resolveContext(globalOpts);
|
|
15640
|
+
return ensureAuthenticated(ctx);
|
|
15641
|
+
}
|
|
15642
|
+
function assertOk(result) {
|
|
15643
|
+
if (!result.ok) {
|
|
15644
|
+
throw new CLIError(result.error.code, result.error.message, ExitCode.ERROR);
|
|
15645
|
+
}
|
|
15646
|
+
}
|
|
15647
|
+
async function loadManifestSource2(source) {
|
|
15648
|
+
const raw = /^https?:\/\//i.test(source) ? await fetchManifest(source) : await readFile10(source, "utf8");
|
|
15649
|
+
return JSON.parse(raw);
|
|
15650
|
+
}
|
|
15651
|
+
async function fetchManifest(source) {
|
|
15652
|
+
const response = await fetch(source);
|
|
15653
|
+
if (!response.ok) {
|
|
15654
|
+
throw new CLIError(
|
|
15655
|
+
"MANIFEST_FETCH_FAILED",
|
|
15656
|
+
`Failed to fetch manifest from ${source}: ${response.status} ${response.statusText}`,
|
|
15657
|
+
ExitCode.NETWORK_ERROR
|
|
15658
|
+
);
|
|
15659
|
+
}
|
|
15660
|
+
return response.text();
|
|
15661
|
+
}
|
|
15662
|
+
function parseParams(input) {
|
|
15663
|
+
if (!input) return void 0;
|
|
15664
|
+
const parsed = JSON.parse(input);
|
|
15665
|
+
if (!Array.isArray(parsed)) {
|
|
15666
|
+
throw new CLIError("INVALID_PARAMS", "--params must be a JSON array.", ExitCode.USAGE_ERROR);
|
|
15667
|
+
}
|
|
15668
|
+
return parsed;
|
|
15669
|
+
}
|
|
15670
|
+
function formatDelegation2(delegation) {
|
|
15671
|
+
return {
|
|
15672
|
+
cid: delegation.cid,
|
|
15673
|
+
direction: delegation.direction,
|
|
15674
|
+
spaceId: delegation.spaceId,
|
|
15675
|
+
spaceName: delegation.spaceName,
|
|
15676
|
+
counterpartyDid: delegation.counterpartyDid,
|
|
15677
|
+
delegateDid: delegation.delegateDid,
|
|
15678
|
+
delegatorDid: delegation.delegatorDid,
|
|
15679
|
+
path: delegation.path,
|
|
15680
|
+
actions: delegation.actions,
|
|
15681
|
+
expiry: delegation.expiry.toISOString(),
|
|
15682
|
+
status: delegation.status,
|
|
15683
|
+
createdAt: delegation.createdAt?.toISOString()
|
|
15684
|
+
};
|
|
15685
|
+
}
|
|
15686
|
+
|
|
15477
15687
|
// src/index.ts
|
|
15478
15688
|
var { version } = JSON.parse(
|
|
15479
15689
|
readFileSync3(new URL("../package.json", import.meta.url), "utf-8")
|
|
@@ -15524,6 +15734,7 @@ registerDuckdbCommand(program);
|
|
|
15524
15734
|
registerManifestCommand(program);
|
|
15525
15735
|
registerUpgradeCommand(program);
|
|
15526
15736
|
registerStatusCommand(program);
|
|
15737
|
+
registerAccountCommand(program);
|
|
15527
15738
|
program.addHelpText("before", () => `${theme.label("Version:")} ${theme.value(version)}
|
|
15528
15739
|
`);
|
|
15529
15740
|
program.addHelpText("afterAll", () => {
|
|
@@ -15535,6 +15746,7 @@ ${theme.heading("Examples:")}
|
|
|
15535
15746
|
${theme.command('tc kv put greeting "Hello"')} ${theme.muted("Store a value")}
|
|
15536
15747
|
${theme.command("tc kv list")} ${theme.muted("List all keys")}
|
|
15537
15748
|
${theme.command("tc secrets network init")} ${theme.muted("Create the default secrets network")}
|
|
15749
|
+
${theme.command("tc account apps list")} ${theme.muted("List registered account apps")}
|
|
15538
15750
|
${theme.command("tc delegation create --to did:pkh:...")} ${theme.muted("Grant access to another user")}
|
|
15539
15751
|
${theme.command("tc space list")} ${theme.muted("Show your spaces")}
|
|
15540
15752
|
|