@tinycloud/cli 1.3.0-beta.23 → 1.3.0-beta.24

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.
@@ -11231,11 +11231,12 @@ function announceFirstOwner(profileName2, expectedOwner, ownerDid) {
11231
11231
  `);
11232
11232
  }
11233
11233
  function ownerLoginPermissions(owner) {
11234
- const space = ownerSpaceId("default", owner);
11234
+ const space = owner === void 0 ? "default" : ownerSpaceId("default", owner);
11235
11235
  return [
11236
11236
  { service: "tinycloud.kv", space, path: "", actions: ["tinycloud.kv/put", "tinycloud.kv/get", "tinycloud.kv/del", "tinycloud.kv/list", "tinycloud.kv/metadata"] },
11237
11237
  { service: "tinycloud.sql", space, path: "", actions: ["tinycloud.sql/read", "tinycloud.sql/write", "tinycloud.sql/admin"] },
11238
- { service: "tinycloud.capabilities", space, path: "", actions: ["tinycloud.capabilities/read"] }
11238
+ { service: "tinycloud.capabilities", space, path: "", actions: ["tinycloud.capabilities/read"] },
11239
+ { service: "tinycloud.delegation", space, path: "", actions: ["tinycloud.delegation/list"] }
11239
11240
  ];
11240
11241
  }
11241
11242
 
@@ -14452,9 +14453,10 @@ async function refreshOpenKeySession(profileName2, host, options = {}) {
14452
14453
  jwk: key,
14453
14454
  host,
14454
14455
  openkeyHost: resolveOpenKeyHost(profile),
14455
- // A plain login for a pinned owner (or --owner) names that owner's space,
14456
- // so OpenKey preselects its key; the signed owner is verified below.
14457
- permissions: permissions ?? (expectedOwner === void 0 ? void 0 : ownerLoginPermissions(expectedOwner)),
14456
+ // A plain login sends the default abilities plus delegation/list explicitly. With a pinned
14457
+ // owner (or --owner) the space is that owner's, so OpenKey preselects its key; the signed
14458
+ // owner is verified below.
14459
+ permissions: permissions ?? ownerLoginPermissions(expectedOwner),
14458
14460
  expiry: openKeyExpiry,
14459
14461
  ...permissions ? { reason: "Allow this TinyCloud CLI profile to use the permissions in the requested manifest." } : {}
14460
14462
  });
@@ -14686,14 +14688,42 @@ init_formatter();
14686
14688
  init_errors();
14687
14689
  init_constants();
14688
14690
  init_sdk();
14689
- function normalizeDid2(input) {
14690
- const normalized = input.trim();
14691
- const fragmentIndex = normalized.indexOf("#");
14692
- return (fragmentIndex === -1 ? normalized : normalized.slice(0, fragmentIndex)).toLowerCase();
14691
+ import { CLI_NAME as CLI_NAME17 } from "@tinycloud/operations/cli-name";
14692
+ import { PermissionNotInManifestError } from "@tinycloud/node-sdk";
14693
+ async function queryDelegations(node, options, until) {
14694
+ const found = [];
14695
+ let cursor;
14696
+ do {
14697
+ const page = await node.account.delegations.query({ ...options, limit: 100, cursor });
14698
+ if (!page.ok) {
14699
+ if (page.error.code === "PERMISSION_DENIED") {
14700
+ throw new CLIError(
14701
+ "PERMISSION_DENIED",
14702
+ `This session cannot read delegations: it lacks tinycloud.delegation/list. Run \`${CLI_NAME17} auth login\` again to grant it.`,
14703
+ ExitCode.PERMISSION_DENIED
14704
+ );
14705
+ }
14706
+ throw cliErrorFromService(page.error);
14707
+ }
14708
+ found.push(...page.data.items);
14709
+ cursor = page.data.nextCursor;
14710
+ } while (cursor && !(until && found.some((d) => d.cid === until)));
14711
+ return found;
14693
14712
  }
14694
- function didMatches(actual, expected) {
14695
- if (!actual) return false;
14696
- return normalizeDid2(actual) === normalizeDid2(expected);
14713
+ function listedDelegation(d) {
14714
+ const resources = d.resources.map((r) => {
14715
+ const [space, service, ...path] = r.resource.split("/");
14716
+ return { space, service, path: path.join("/"), actions: r.actions };
14717
+ });
14718
+ return {
14719
+ cid: d.cid,
14720
+ delegatee: d.delegateDid,
14721
+ delegator: d.delegatorDid,
14722
+ direction: d.direction,
14723
+ status: d.status,
14724
+ expiry: d.expiresAt?.toISOString() ?? null,
14725
+ resources
14726
+ };
14697
14727
  }
14698
14728
  async function confirmCurrentSessionRevoke(yes) {
14699
14729
  if (yes) return;
@@ -14724,69 +14754,87 @@ function registerDelegationCommand(program, configuration = {}) {
14724
14754
  const trimmed = a.trim();
14725
14755
  return trimmed.startsWith("tinycloud.") ? trimmed : `tinycloud.${trimmed}`;
14726
14756
  });
14757
+ const byService = {};
14758
+ for (const action of actions) {
14759
+ const slash = action.indexOf("/");
14760
+ if (slash <= "tinycloud.".length || slash === action.length - 1) {
14761
+ throw new CLIError("USAGE_ERROR", `Invalid action "${action}"; use service/action, e.g. kv/get`, ExitCode.USAGE_ERROR);
14762
+ }
14763
+ (byService[action.slice(0, slash)] ??= []).push(action);
14764
+ }
14727
14765
  const expiry = parseExpiry2(options.expiry);
14728
- const result = await node.delegationManager.create({
14729
- delegateDID: options.to,
14730
- path: options.path,
14731
- actions,
14732
- expiry
14766
+ const recipient = options.to.split("#")[0];
14767
+ const { delegation: created } = await node.delegateTo(
14768
+ recipient,
14769
+ Object.entries(byService).map(([service, serviceActions]) => ({
14770
+ service,
14771
+ space: "default",
14772
+ path: options.path,
14773
+ actions: serviceActions
14774
+ })),
14775
+ { expiry: expiry.getTime() - Date.now(), requireActivation: true }
14776
+ ).catch((error) => {
14777
+ if (error instanceof PermissionNotInManifestError) {
14778
+ const needed = error.missing.map((m) => `${m.actions.join(", ")} on space "${m.space ?? "default"}" path "${m.path}"`).join("; ");
14779
+ throw new CLIError(
14780
+ "PERMISSION_DENIED",
14781
+ `This session cannot delegate what was requested. Missing: ${needed}. Sign in again with these permissions.`,
14782
+ ExitCode.PERMISSION_DENIED
14783
+ );
14784
+ }
14785
+ throw error;
14733
14786
  });
14734
- if (!result.ok) {
14735
- throw cliErrorFromService(result.error);
14787
+ const confirmed = (await queryDelegations(node, { direction: "granted" }, created.cid)).find((d) => d.cid === created.cid);
14788
+ if (confirmed?.status !== "active") {
14789
+ throw new CLIError(
14790
+ "DELEGATION_NOT_CONFIRMED",
14791
+ confirmed ? `The node lists delegation ${created.cid} as ${confirmed.status}, not active; treat it as not created.` : `The node accepted delegation ${created.cid} but does not list it; treat it as not created.`,
14792
+ ExitCode.ERROR
14793
+ );
14736
14794
  }
14737
14795
  outputJson({
14738
- cid: result.data.cid,
14739
- delegateDid: options.to,
14796
+ cid: created.cid,
14797
+ delegateDid: recipient,
14798
+ delegatorDid: confirmed.delegatorDid,
14740
14799
  path: options.path,
14741
14800
  actions,
14742
- expiry: expiry.toISOString()
14801
+ expiry: created.expiry.toISOString(),
14802
+ status: confirmed.status
14743
14803
  });
14744
14804
  } catch (error) {
14745
14805
  return handleError(error);
14746
14806
  }
14747
14807
  });
14748
- delegation.command("list").description("List delegations").option("--granted", "Show only delegations I've granted").option("--received", "Show only delegations I've received").action(async (options, cmd) => {
14808
+ delegation.command("list").description("List delegations").option("--granted", "Show only delegations I've granted").option("--received", "Show only delegations I've received").option("--space <space>", "Filter by space name or ID").action(async (options, cmd) => {
14749
14809
  try {
14750
14810
  const globalOpts = cmd.optsWithGlobals();
14751
14811
  const ctx = await ProfileManager.resolveContext(globalOpts);
14752
14812
  const node = await ensureAuthenticated(ctx);
14753
- const result = await node.delegationManager.list();
14754
- if (!result.ok) {
14755
- throw cliErrorFromService(result.error);
14756
- }
14757
- let delegations = result.data;
14758
- if (options.granted) {
14759
- const myDid = node.did;
14760
- delegations = delegations.filter((d) => didMatches(d.delegatorDID, myDid));
14761
- } else if (options.received) {
14762
- const myDid = node.did;
14763
- delegations = delegations.filter((d) => didMatches(d.delegateDID, myDid));
14813
+ if (options.granted && options.received) {
14814
+ throw new CLIError("USAGE_ERROR", "Use only one of --granted or --received.", ExitCode.USAGE_ERROR);
14764
14815
  }
14816
+ const delegations = await queryDelegations(node, {
14817
+ direction: options.granted ? "granted" : options.received ? "received" : "all",
14818
+ space: options.space
14819
+ });
14765
14820
  outputJson({
14766
- delegations: delegations.map((d) => ({
14767
- cid: d.cid,
14768
- delegatee: d.delegateDID,
14769
- delegator: d.delegatorDID,
14770
- path: d.path,
14771
- actions: d.actions,
14772
- expiry: d.expiry instanceof Date ? d.expiry.toISOString() : d.expiry
14773
- })),
14821
+ delegations: delegations.map(listedDelegation),
14774
14822
  count: delegations.length
14775
14823
  });
14776
14824
  } catch (error) {
14777
14825
  return handleError(error);
14778
14826
  }
14779
14827
  });
14780
- delegation.command("info <cid>").description("Get delegation details").action(async (cid, _options, cmd) => {
14828
+ delegation.command("info <cid>").description("Get delegation details").option("--space <space>", "Filter by space name or ID").action(async (cid, options, cmd) => {
14781
14829
  try {
14782
14830
  const globalOpts = cmd.optsWithGlobals();
14783
14831
  const ctx = await ProfileManager.resolveContext(globalOpts);
14784
14832
  const node = await ensureAuthenticated(ctx);
14785
- const result = await node.delegationManager.get(cid);
14786
- if (!result.ok) {
14787
- throw new CLIError("NOT_FOUND", `Delegation "${cid}" not found`, ExitCode.NOT_FOUND);
14833
+ const found = (await queryDelegations(node, { direction: "all", space: options.space })).find((d) => d.cid === cid);
14834
+ if (!found) {
14835
+ throw new CLIError("NOT_FOUND", `Delegation "${cid}" not found in this account's delegations`, ExitCode.NOT_FOUND);
14788
14836
  }
14789
- outputJson(result.data);
14837
+ outputJson(listedDelegation(found));
14790
14838
  } catch (error) {
14791
14839
  return handleError(error);
14792
14840
  }
@@ -14826,7 +14874,7 @@ init_constants();
14826
14874
  init_formatter();
14827
14875
  init_theme();
14828
14876
  init_errors();
14829
- import { CLI_NAME as CLI_NAME17 } from "@tinycloud/operations/cli-name";
14877
+ import { CLI_NAME as CLI_NAME18 } from "@tinycloud/operations/cli-name";
14830
14878
  init_session_expired();
14831
14879
  init_types();
14832
14880
  function registerDoctorCommand(program) {
@@ -14860,7 +14908,7 @@ function registerDoctorCommand(program) {
14860
14908
  const profile = await ProfileManager.getProfile(profileName2);
14861
14909
  keyDetail = profile.did ? `${profile.did.slice(0, 20)}...` : "key found";
14862
14910
  } else {
14863
- keyDetail = `no key \u2014 run ${CLI_NAME17} init`;
14911
+ keyDetail = `no key \u2014 run ${CLI_NAME18} init`;
14864
14912
  }
14865
14913
  } catch {
14866
14914
  keyDetail = "error reading key";
@@ -14882,7 +14930,7 @@ function registerDoctorCommand(program) {
14882
14930
  } else if (state2 === "unverified") {
14883
14931
  sessionDetail = `not usable (no signed OpenKey proof) \u2014 ${signInAgainHint(profileName2, resolveProfilePosture(profile))}`;
14884
14932
  } else {
14885
- sessionDetail = sessionOk ? "active" : `no session \u2014 run ${CLI_NAME17} auth login`;
14933
+ sessionDetail = sessionOk ? "active" : `no session \u2014 run ${CLI_NAME18} auth login`;
14886
14934
  }
14887
14935
  } catch {
14888
14936
  sessionDetail = "error reading session";
@@ -14910,7 +14958,7 @@ function registerDoctorCommand(program) {
14910
14958
  try {
14911
14959
  const profile = await ProfileManager.getProfile(profileName2);
14912
14960
  spaceOk = Boolean(profile.spaceId);
14913
- spaceDetail = spaceOk ? `${profile.spaceId.slice(0, 16)}...` : `no space \u2014 run ${CLI_NAME17} space create`;
14961
+ spaceDetail = spaceOk ? `${profile.spaceId.slice(0, 16)}...` : `no space \u2014 run ${CLI_NAME18} space create`;
14914
14962
  } catch {
14915
14963
  spaceDetail = "error checking space";
14916
14964
  }
@@ -15100,7 +15148,7 @@ ${rowCount} row${rowCount === 1 ? "" : "s"} returned`) + "\n");
15100
15148
  }
15101
15149
 
15102
15150
  // src/commands/enable.ts
15103
- import { CLI_NAME as CLI_NAME18 } from "@tinycloud/operations/cli-name";
15151
+ import { CLI_NAME as CLI_NAME19 } from "@tinycloud/operations/cli-name";
15104
15152
  init_constants();
15105
15153
  init_profiles();
15106
15154
  init_errors();
@@ -15108,7 +15156,7 @@ init_formatter();
15108
15156
  init_publishing_manifest();
15109
15157
  function registerEnableCommand(program) {
15110
15158
  const enable = program.command("enable").description("Enable a narrowly scoped TinyCloud service");
15111
- enable.command("share").description(`Approve Share publishing scope through OpenKey device authorization (same as \`${CLI_NAME18} auth login --device --manifest builtin:share-publishing\`). Use a dedicated profile, e.g. \`${CLI_NAME18} init --name publisher --key-only && ${CLI_NAME18} --profile publisher enable share\`; keep existing profiles for their apps.`).option("--replace-session", "Replace this profile's live session even though the new scope would narrow, change or shorten it (prefer a new profile)").action(async (options, command) => {
15159
+ enable.command("share").description(`Approve Share publishing scope through OpenKey device authorization (same as \`${CLI_NAME19} auth login --device --manifest builtin:share-publishing\`). Use a dedicated profile, e.g. \`${CLI_NAME19} init --name publisher --key-only && ${CLI_NAME19} --profile publisher enable share\`; keep existing profiles for their apps.`).option("--replace-session", "Replace this profile's live session even though the new scope would narrow, change or shorten it (prefer a new profile)").action(async (options, command) => {
15112
15160
  try {
15113
15161
  const globalOptions = command.optsWithGlobals();
15114
15162
  const context = await ProfileManager.resolveContext(globalOptions, { storedSession: "unused" });
@@ -15144,7 +15192,7 @@ init_profiles();
15144
15192
  init_formatter();
15145
15193
  init_errors();
15146
15194
  init_constants();
15147
- import { CLI_NAME as CLI_NAME19 } from "@tinycloud/operations/cli-name";
15195
+ import { CLI_NAME as CLI_NAME20 } from "@tinycloud/operations/cli-name";
15148
15196
  function registerInitCommand(program) {
15149
15197
  program.command("init").description("Initialize a new TinyCloud profile").option("--name <profile>", "Profile name", "default").option("--key-only", "Only generate key, skip authentication").option("--host <url>", "TinyCloud node URL").option("--paste", "Use manual paste mode for authentication").option("--no-popup", "Print the OpenKey URL without opening a browser").option("--default-space <name>", "Default space used when --space is omitted (e.g. applications)").action(async (options, cmd) => {
15150
15198
  try {
@@ -15162,7 +15210,7 @@ function registerInitCommand(program) {
15162
15210
  if (await ProfileManager.profileExists(profileName2)) {
15163
15211
  throw new CLIError(
15164
15212
  "PROFILE_EXISTS",
15165
- `Profile "${profileName2}" already exists. Use \`${CLI_NAME19} profile delete ${profileName2}\` first or choose a different name.`,
15213
+ `Profile "${profileName2}" already exists. Use \`${CLI_NAME20} profile delete ${profileName2}\` first or choose a different name.`,
15166
15214
  ExitCode.ERROR
15167
15215
  );
15168
15216
  }
@@ -15512,7 +15560,7 @@ init_errors();
15512
15560
  init_constants();
15513
15561
  init_theme();
15514
15562
  import { resolveManifestKnowledgeRoot as resolveManifestKnowledgeRoot2 } from "@tinycloud/sdk-core";
15515
- import { CLI_NAME as CLI_NAME20 } from "@tinycloud/operations/cli-name";
15563
+ import { CLI_NAME as CLI_NAME21 } from "@tinycloud/operations/cli-name";
15516
15564
  import { readFile as readFile11 } from "fs/promises";
15517
15565
  var DEFAULT_APP_SPACE = "applications";
15518
15566
  function registerManifestCommand(program) {
@@ -15520,8 +15568,8 @@ function registerManifestCommand(program) {
15520
15568
  manifest.command("resolve <source>").description("Resolve a manifest file or URL to its effective space, paths, and DB basenames").addHelpText("after", `
15521
15569
 
15522
15570
  Examples:
15523
- $ ${CLI_NAME20} manifest resolve ./manifest.json
15524
- $ ${CLI_NAME20} manifest resolve https://app.example.com/manifest.json --json
15571
+ $ ${CLI_NAME21} manifest resolve ./manifest.json
15572
+ $ ${CLI_NAME21} manifest resolve https://app.example.com/manifest.json --json
15525
15573
 
15526
15574
  What it shows:
15527
15575
  - app_id, name, manifest_version
@@ -15531,7 +15579,7 @@ What it shows:
15531
15579
 
15532
15580
  This command is read-only and does NOT contact the node \u2014 it just resolves
15533
15581
  the manifest against the active profile's address/chain so you know which
15534
- \`--space\` and \`--db\` values to pass to other ${CLI_NAME20} commands.
15582
+ \`--space\` and \`--db\` values to pass to other ${CLI_NAME21} commands.
15535
15583
  `).action(async (source, _options, cmd) => {
15536
15584
  try {
15537
15585
  const globalOpts = cmd.optsWithGlobals();
@@ -15600,7 +15648,7 @@ ${theme.heading("SQL databases")}
15600
15648
  `);
15601
15649
  }
15602
15650
  process.stdout.write(theme.muted(`
15603
- Use with: ${CLI_NAME20} sql query --space ${spaceName} --db <db> "..."
15651
+ Use with: ${CLI_NAME21} sql query --space ${spaceName} --db <db> "..."
15604
15652
  `));
15605
15653
  }
15606
15654
  if (permissions.length > 0) {
@@ -15720,7 +15768,7 @@ init_profiles();
15720
15768
  init_formatter();
15721
15769
  init_errors();
15722
15770
  init_constants();
15723
- import { CLI_NAME as CLI_NAME21 } from "@tinycloud/operations/cli-name";
15771
+ import { CLI_NAME as CLI_NAME22 } from "@tinycloud/operations/cli-name";
15724
15772
  import { createInterface as createInterface5 } from "readline";
15725
15773
  init_theme();
15726
15774
  init_types();
@@ -15866,9 +15914,9 @@ profile at command time. Precedence for every kv/sql command:
15866
15914
  explicit --space flag > profile defaultSpace > primary space.
15867
15915
 
15868
15916
  Examples:
15869
- $ ${CLI_NAME21} profile set-default-space applications
15870
- $ ${CLI_NAME21} profile set-default-space applications --profile cli-test
15871
- $ ${CLI_NAME21} profile set-default-space --unset
15917
+ $ ${CLI_NAME22} profile set-default-space applications
15918
+ $ ${CLI_NAME22} profile set-default-space applications --profile cli-test
15919
+ $ ${CLI_NAME22} profile set-default-space --unset
15872
15920
  `).action(async (name, options, cmd) => {
15873
15921
  try {
15874
15922
  const globalOpts = cmd.optsWithGlobals();
@@ -15880,7 +15928,7 @@ Examples:
15880
15928
  if (!options.unset && (name === void 0 || name === "")) {
15881
15929
  throw new CLIError(
15882
15930
  "USAGE_ERROR",
15883
- `Provide a space name (e.g. \`${CLI_NAME21} profile set-default-space applications\`) or pass --unset.`,
15931
+ `Provide a space name (e.g. \`${CLI_NAME22} profile set-default-space applications\`) or pass --unset.`,
15884
15932
  ExitCode.USAGE_ERROR
15885
15933
  );
15886
15934
  }
@@ -15939,7 +15987,7 @@ function parseOperatorType(raw) {
15939
15987
 
15940
15988
  // src/commands/replica.ts
15941
15989
  init_profile_replicas();
15942
- import { CLI_NAME as CLI_NAME22 } from "@tinycloud/operations/cli-name";
15990
+ import { CLI_NAME as CLI_NAME23 } from "@tinycloud/operations/cli-name";
15943
15991
  import { randomBytes as randomBytes7 } from "crypto";
15944
15992
  import { constants as fsConstants5 } from "fs";
15945
15993
  import { mkdir as mkdir5, open as open9, readdir as readdir6, rename as rename4, unlink as unlink4, lstat as lstat9 } from "fs/promises";
@@ -16080,11 +16128,11 @@ var EXIT_BY_CODE = {
16080
16128
  var READ_FAILURE = {
16081
16129
  absent: { code: "KEY_ABSENT", exit: ExitCode.NOT_FOUND, what: "is not in the replica (the replica covers its whole prefix)" },
16082
16130
  deleted: { code: "KEY_DELETED", exit: ExitCode.NOT_FOUND, what: "was deleted at the source" },
16083
- content_missing: { code: "CONTENT_MISSING", exit: ExitCode.NOT_FOUND, what: `is known but its content has not been fetched yet; run ${CLI_NAME22} replica sync` },
16131
+ content_missing: { code: "CONTENT_MISSING", exit: ExitCode.NOT_FOUND, what: `is known but its content has not been fetched yet; run ${CLI_NAME23} replica sync` },
16084
16132
  coverage_incomplete: {
16085
16133
  code: "COVERAGE_INCOMPLETE",
16086
16134
  exit: ExitCode.NOT_FOUND,
16087
- what: `is not in the replica, which has not finished its first sync; run ${CLI_NAME22} replica sync`
16135
+ what: `is not in the replica, which has not finished its first sync; run ${CLI_NAME23} replica sync`
16088
16136
  },
16089
16137
  not_covered: { code: "NOT_COVERED", exit: ExitCode.USAGE_ERROR, what: "is outside the replica's prefix" }
16090
16138
  };
@@ -16202,7 +16250,7 @@ async function existingReplicaName(profile, option) {
16202
16250
  const names = await replicaNames(profile);
16203
16251
  if (names.length === 1) return names[0];
16204
16252
  if (names.length === 0) {
16205
- throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, `Profile "${profile}" has no replicas. Create one with: ${CLI_NAME22} replica sync --prefix <prefix>`);
16253
+ throw new ReplicaError(ReplicaErrorCode.NOT_FOUND, `Profile "${profile}" has no replicas. Create one with: ${CLI_NAME23} replica sync --prefix <prefix>`);
16206
16254
  }
16207
16255
  throw new CLIError("USAGE_ERROR", `Profile "${profile}" has several replicas (${names.join(", ")}); pass --replica <name>.`, ExitCode.USAGE_ERROR);
16208
16256
  }
@@ -16310,9 +16358,9 @@ async function storedGrants(profile) {
16310
16358
  function grantHint(space, prefix) {
16311
16359
  return [
16312
16360
  "A replica needs a device grant with get and sync on its prefix:",
16313
- ` device: ${CLI_NAME22} auth request --cap tinycloud.kv:${space}:${prefix}:get,list,metadata,sync --expiry 30d --emit req.json`,
16314
- ` owner: ${CLI_NAME22} auth grant req.json > grant.json`,
16315
- ` device: ${CLI_NAME22} auth import grant.json`
16361
+ ` device: ${CLI_NAME23} auth request --cap tinycloud.kv:${space}:${prefix}:get,list,metadata,sync --expiry 30d --emit req.json`,
16362
+ ` owner: ${CLI_NAME23} auth grant req.json > grant.json`,
16363
+ ` device: ${CLI_NAME23} auth import grant.json`
16316
16364
  ].join("\n");
16317
16365
  }
16318
16366
  function resolveSpace(input, prefix, grants) {
@@ -16403,7 +16451,7 @@ function describeStatus(status) {
16403
16451
  formatField("Size", formatBytes(status.bytes)),
16404
16452
  formatField("Grant", status.device.delegationCid),
16405
16453
  formatField("Last error", status.lastError ? `${status.lastError.code}: ${status.lastError.message}` : null),
16406
- formatField("Purge", status.purgePending ? `incomplete: content files remain; the next ${CLI_NAME22} replica command retries` : null)
16454
+ formatField("Purge", status.purgePending ? `incomplete: content files remain; the next ${CLI_NAME23} replica command retries` : null)
16407
16455
  ].join("\n");
16408
16456
  }
16409
16457
  async function writeFileAtomic(path, bytes) {
@@ -16567,7 +16615,7 @@ or coverage incomplete; 5 grant expired, revoked or not yet valid; 6 network;
16567
16615
  (options, cmd) => run(async () => {
16568
16616
  const profile = await profileName(cmd);
16569
16617
  if (options.purge) {
16570
- throw new CLIError("REPORT_READ_ONLY", `Replica report is read-only. To remove a named local replica, run ${CLI_NAME22} replica reset --replica <name> --purge; flag-owned purge has no equivalent yet (TC-1309).`, ExitCode.USAGE_ERROR);
16618
+ throw new CLIError("REPORT_READ_ONLY", `Replica report is read-only. To remove a named local replica, run ${CLI_NAME23} replica reset --replica <name> --purge; flag-owned purge has no equivalent yet (TC-1309).`, ExitCode.USAGE_ERROR);
16571
16619
  }
16572
16620
  if (options.clearPending) {
16573
16621
  throw new CLIError("REPORT_READ_ONLY", "Clearing pending replica writes has no equivalent yet; see TC-1309 for a safe replacement command.", ExitCode.USAGE_ERROR);
@@ -16669,7 +16717,7 @@ or coverage incomplete; 5 grant expired, revoked or not yet valid; 6 network;
16669
16717
  if (differs !== void 0) {
16670
16718
  throw new ReplicaError(
16671
16719
  ReplicaErrorCode.CONFIG_MISMATCH,
16672
- `Replica ${name} already follows ${differs}. Use another --replica name, or ${CLI_NAME22} replica reset --replica ${name} --purge first.`
16720
+ `Replica ${name} already follows ${differs}. Use another --replica name, or ${CLI_NAME23} replica reset --replica ${name} --purge first.`
16673
16721
  );
16674
16722
  }
16675
16723
  }
@@ -16834,7 +16882,7 @@ init_theme();
16834
16882
  init_errors();
16835
16883
  init_warnings();
16836
16884
  init_constants();
16837
- import { CLI_NAME as CLI_NAME24 } from "@tinycloud/operations/cli-name";
16885
+ import { CLI_NAME as CLI_NAME25 } from "@tinycloud/operations/cli-name";
16838
16886
  import { readFile as readFile12 } from "fs/promises";
16839
16887
  import { join as join16 } from "path";
16840
16888
  import { homedir, hostname, userInfo } from "os";
@@ -17045,7 +17093,7 @@ function parseStatusEnvelope(line) {
17045
17093
  // src/lib/secrets-wait.ts
17046
17094
  init_constants();
17047
17095
  init_errors();
17048
- import { CLI_NAME as CLI_NAME23 } from "@tinycloud/operations/cli-name";
17096
+ import { CLI_NAME as CLI_NAME24 } from "@tinycloud/operations/cli-name";
17049
17097
  var WAIT_BACKOFF_MS = [3e3, 4500, 6750, 10125];
17050
17098
  var WAIT_STEADY_INTERVAL_MS = 15e3;
17051
17099
  var DEFAULT_WAIT_TIMEOUT = "5m";
@@ -17053,7 +17101,7 @@ var MAX_WAIT_TIMEOUT_MS = 9 * 6e4;
17053
17101
  var MAX_CONSECUTIVE_FAILURES = 5;
17054
17102
  var TIMEOUT_RE = /^(0|\d+s|\d+m)$/;
17055
17103
  var RETRYABLE_STATUS_ERRORS = { NODE_UNREACHABLE: true, NODE_ERROR: true };
17056
- var EXPLICIT_KEY_HINT = `${CLI_NAME23} secrets wait never signs in, and an explicit private key has no stored session. Use a local profile signed in once with ${CLI_NAME23} --profile <profile> auth login --method local, without TC_PRIVATE_KEY.`;
17104
+ var EXPLICIT_KEY_HINT = `${CLI_NAME24} secrets wait never signs in, and an explicit private key has no stored session. Use a local profile signed in once with ${CLI_NAME24} --profile <profile> auth login --method local, without TC_PRIVATE_KEY.`;
17057
17105
  function abortableSleep(ms2, signal) {
17058
17106
  return new Promise((resolve8) => {
17059
17107
  if (signal.aborted) {
@@ -17089,7 +17137,7 @@ async function runSecretsWait(request, deps) {
17089
17137
  let step = 0;
17090
17138
  const cancelled = () => new CLIError(
17091
17139
  "CANCELLED",
17092
- `Interrupted: ${CLI_NAME23} secrets wait stopped before the secrets were ready.`,
17140
+ `Interrupted: ${CLI_NAME24} secrets wait stopped before the secrets were ready.`,
17093
17141
  ExitCode.CANCELLED,
17094
17142
  progress === void 0 ? {} : { progress }
17095
17143
  );
@@ -17233,13 +17281,13 @@ function statusError(error, profile, warnings) {
17233
17281
  if (error.code === "AUTH_REQUIRED" || error.code === "SESSION_NOT_FOUND") {
17234
17282
  const recovery = recoveryOf(error, "sign_in");
17235
17283
  if (recovery !== void 0) {
17236
- const hint = recovery.command !== void 0 ? `Sign in once with: ${recovery.command}, then retry.` : `Sign in to profile "${profile}" once with ${CLI_NAME23} auth login, then retry.`;
17284
+ const hint = recovery.command !== void 0 ? `Sign in once with: ${recovery.command}, then retry.` : `Sign in to profile "${profile}" once with ${CLI_NAME24} auth login, then retry.`;
17237
17285
  return new CLIError("AUTH_REQUIRED", error.message, ExitCode.AUTH_REQUIRED, { hint, recovery, ...extra });
17238
17286
  }
17239
17287
  }
17240
17288
  if (error.code === "PROFILE_MIGRATION_REQUIRED") {
17241
17289
  const recovery = recoveryOf(error, "complete_migration");
17242
- const hint = recovery?.command !== void 0 ? `Run ${recovery.command} once to finish this profile's one-time upgrade, then retry wait.` : `Run ${CLI_NAME23} auth caps once with profile "${profile}" to finish its one-time upgrade, then retry wait.`;
17290
+ const hint = recovery?.command !== void 0 ? `Run ${recovery.command} once to finish this profile's one-time upgrade, then retry wait.` : `Run ${CLI_NAME24} auth caps once with profile "${profile}" to finish its one-time upgrade, then retry wait.`;
17243
17291
  return new CLIError("PROFILE_MIGRATION_REQUIRED", error.message, ExitCode.ERROR, {
17244
17292
  hint,
17245
17293
  ...recovery === void 0 ? {} : { recovery },
@@ -17431,11 +17479,11 @@ async function runSecretOperation(params) {
17431
17479
  }
17432
17480
  function secretPermissionReason(action, name) {
17433
17481
  const target = name ? ` secret "${name}"` : " secrets";
17434
- return `Allow \`${CLI_NAME24} secrets ${action}${name ? ` ${name}` : ""}\` to access${target} with the required TinyCloud permissions.`;
17482
+ return `Allow \`${CLI_NAME25} secrets ${action}${name ? ` ${name}` : ""}\` to access${target} with the required TinyCloud permissions.`;
17435
17483
  }
17436
17484
  function assertOwnerApprovalPossible(profileName2, profile, action, name, missing = []) {
17437
17485
  if (profile.authMethod !== "openkey" || process.stdin.isTTY || process.stderr.isTTY) return;
17438
- const command = `${CLI_NAME24} secrets ${action === "del" ? "delete" : action}${name ? ` ${name}` : ""}`;
17486
+ const command = `${CLI_NAME25} secrets ${action === "del" ? "delete" : action}${name ? ` ${name}` : ""}`;
17439
17487
  throw new CLIError(
17440
17488
  "PERMISSION_DENIED",
17441
17489
  action === "get" ? missing.length > 0 && missing.every((permission) => permission.service === "tinycloud.encryption" && Array.isArray(permission.actions) && permission.actions.length > 0 && permission.actions.every((capability) => capability === SECRET_DECRYPT_CAPABILITY)) ? `Profile "${profileName2}" lacks the scoped decrypt authority (${SECRET_DECRYPT_CAPABILITY}) needed to read secret "${name}", and requesting it needs an interactive browser approval.` : `Profile "${profileName2}" lacks a scoped read or decrypt grant needed to read secret "${name}", and requesting it needs an interactive browser approval.` : `Profile "${profileName2}" holds no grant for \`${command}\`, and requesting one needs an interactive browser approval.`,
@@ -17446,7 +17494,7 @@ function assertOwnerApprovalPossible(profileName2, profile, action, name, missin
17446
17494
  );
17447
17495
  }
17448
17496
  function scopedSecretLoginHint(profileName2) {
17449
- return `Have the owner approve a scoped login whose manifest names the secret: ${CLI_NAME24} --profile ${profileName2} auth login --method openkey --paste --manifest <manifest.json>. Pass the owner's code on stdin, newline-terminated.`;
17497
+ return `Have the owner approve a scoped login whose manifest names the secret: ${CLI_NAME25} --profile ${profileName2} auth login --method openkey --paste --manifest <manifest.json>. Pass the owner's code on stdin, newline-terminated.`;
17450
17498
  }
17451
17499
  async function runSecretOperationAttempt(label, operation) {
17452
17500
  try {
@@ -17580,7 +17628,7 @@ ${message}`,
17580
17628
  "AUTH_REQUIRED",
17581
17629
  "Not signed in to TinyCloud.",
17582
17630
  ExitCode.AUTH_REQUIRED,
17583
- { hint: `Sign in with: ${CLI_NAME24} --profile ${result.context.profile} auth login` }
17631
+ { hint: `Sign in with: ${CLI_NAME25} --profile ${result.context.profile} auth login` }
17584
17632
  );
17585
17633
  }
17586
17634
  if (result.error.code === "NODE_UNREACHABLE") {
@@ -18057,7 +18105,7 @@ function registerSecretsCommand(program, openKeyAcquisition) {
18057
18105
  name: "Encryption network",
18058
18106
  ok: false,
18059
18107
  detail: `${networkName} not found`,
18060
- hint: `${CLI_NAME24} secrets network init ${networkName}`
18108
+ hint: `${CLI_NAME25} secrets network init ${networkName}`
18061
18109
  }
18062
18110
  ];
18063
18111
  let secret;
@@ -18103,7 +18151,7 @@ function registerSecretsCommand(program, openKeyAcquisition) {
18103
18151
  name: "Secret access",
18104
18152
  ok: false,
18105
18153
  detail: notFound ? `${resolved.permissionPaths.vault} not found` : result.error.message,
18106
- hint: notFound ? local ? `${CLI_NAME24} secrets put ${resolved.name}${formatSecretScopeFlag(scopeOptions)} --stdin` : `${CLI_NAME24} secrets request ${resolved.name}${formatSecretScopeFlag(scopeOptions)}` : `Ask the owner profile to grant ${secretCapabilityAction("get")} and ${SECRET_DECRYPT_CAPABILITY}.`
18154
+ hint: notFound ? local ? `${CLI_NAME25} secrets put ${resolved.name}${formatSecretScopeFlag(scopeOptions)} --stdin` : `${CLI_NAME25} secrets request ${resolved.name}${formatSecretScopeFlag(scopeOptions)}` : `Ask the owner profile to grant ${secretCapabilityAction("get")} and ${SECRET_DECRYPT_CAPABILITY}.`
18107
18155
  });
18108
18156
  }
18109
18157
  } else {
@@ -18347,7 +18395,7 @@ function registerSecretsCommand(program, openKeyAcquisition) {
18347
18395
  if (effectiveLocal(profile, options)) {
18348
18396
  throw new CLIError(
18349
18397
  "LOCAL_OWNER_PROFILE",
18350
- `Profile "${ctx.profile}" uses a local key, which owns its secrets: store them with ${CLI_NAME24} secrets put NAME --stdin instead of requesting them.`,
18398
+ `Profile "${ctx.profile}" uses a local key, which owns its secrets: store them with ${CLI_NAME25} secrets put NAME --stdin instead of requesting them.`,
18351
18399
  ExitCode.USAGE_ERROR
18352
18400
  );
18353
18401
  }
@@ -18470,7 +18518,7 @@ function registerSecretsCommand(program, openKeyAcquisition) {
18470
18518
 
18471
18519
  // src/commands/share.ts
18472
18520
  import { Option } from "commander";
18473
- import { CLI_NAME as CLI_NAME25 } from "@tinycloud/operations/cli-name";
18521
+ import { CLI_NAME as CLI_NAME26 } from "@tinycloud/operations/cli-name";
18474
18522
 
18475
18523
  // ../share-sdk/dist/artifact.js
18476
18524
  init_sha256();
@@ -36601,12 +36649,12 @@ function shareCliError(error, operation = "publish") {
36601
36649
  const profileName2 = "profileName" in failure ? failure.profileName : void 0;
36602
36650
  const localKey = "localKey" in failure && failure.localKey === true;
36603
36651
  const profileHint = profileName2 === void 0 ? "" : `--profile ${profileName2} `;
36604
- const loginHint = localKey ? `\`${CLI_NAME25} ${profileHint}auth login --method local\`` : `\`${CLI_NAME25} ${profileHint}auth login --device --manifest builtin:share-publishing\` (or \`${CLI_NAME25} ${profileHint}enable share\`)`;
36652
+ const loginHint = localKey ? `\`${CLI_NAME26} ${profileHint}auth login --method local\`` : `\`${CLI_NAME26} ${profileHint}auth login --device --manifest builtin:share-publishing\` (or \`${CLI_NAME26} ${profileHint}enable share\`)`;
36605
36653
  if (failure.kind === "caveated-session") {
36606
36654
  const holder = profileName2 === void 0 ? "this session" : `profile ${profileName2}'s session`;
36607
36655
  return new CLIError(
36608
36656
  "PERMISSION_DENIED",
36609
- `${holder} carries signed restrictions (caveats) on the authority an anyone-with-link share needs, so it cannot create the share link; nothing was shared. Approve Share publishing without restrictions on a new, dedicated profile (any unused name): \`${CLI_NAME25} init --name publisher --key-only && ${CLI_NAME25} --profile publisher enable share\``,
36657
+ `${holder} carries signed restrictions (caveats) on the authority an anyone-with-link share needs, so it cannot create the share link; nothing was shared. Approve Share publishing without restrictions on a new, dedicated profile (any unused name): \`${CLI_NAME26} init --name publisher --key-only && ${CLI_NAME26} --profile publisher enable share\``,
36610
36658
  5
36611
36659
  );
36612
36660
  }
@@ -37011,7 +37059,7 @@ init_constants();
37011
37059
  init_sdk();
37012
37060
  init_host();
37013
37061
  init_theme();
37014
- import { CLI_NAME as CLI_NAME26 } from "@tinycloud/operations/cli-name";
37062
+ import { CLI_NAME as CLI_NAME27 } from "@tinycloud/operations/cli-name";
37015
37063
  import { ACCOUNT_REGISTRY_SPACE } from "@tinycloud/node-sdk";
37016
37064
  import { randomBytes as randomBytes9 } from "crypto";
37017
37065
  import { mkdir as mkdir7, writeFile as writeFile4 } from "fs/promises";
@@ -37058,7 +37106,7 @@ function registerSpaceCommand(program) {
37058
37106
  } else {
37059
37107
  const profile = await ProfileManager.getProfile(ctx.profile);
37060
37108
  const cap = "tinycloud.kv:account:spaces/:get,list";
37061
- const hint = resolveProfilePosture(profile) === "delegate-session" ? `Ask the space owner to grant it. Create the request with: ${CLI_NAME26} --profile ${ctx.profile} auth request --cap ${cap} --emit` : `Grant it to this session with: ${CLI_NAME26} --profile ${ctx.profile} auth request --grant --cap ${cap}. The default OpenKey owner sign-in covers only the default space, so it includes neither.`;
37109
+ const hint = resolveProfilePosture(profile) === "delegate-session" ? `Ask the space owner to grant it. Create the request with: ${CLI_NAME27} --profile ${ctx.profile} auth request --cap ${cap} --emit` : `Grant it to this session with: ${CLI_NAME27} --profile ${ctx.profile} auth request --grant --cap ${cap}. The default OpenKey owner sign-in covers only the default space, so it includes neither.`;
37062
37110
  throw new CLIError(
37063
37111
  "PERMISSION_DENIED",
37064
37112
  `Listing spaces needs tinycloud.kv/get and tinycloud.kv/list on the account space's spaces/ registry (${accountSpaceId ?? ACCOUNT_REGISTRY_SPACE}), or tinycloud.space/list. This session holds neither.`,
@@ -37095,10 +37143,10 @@ function registerSpaceCommand(program) {
37095
37143
 
37096
37144
  A delegate cannot host a space \u2014 only its owner (root authority) can. This
37097
37145
  emits a tinycloud.host.request artifact naming the space and its owner so you
37098
- can hand it to the owner; they run \`${CLI_NAME26} space host <name>\` and confirm.
37146
+ can hand it to the owner; they run \`${CLI_NAME27} space host <name>\` and confirm.
37099
37147
 
37100
37148
  If you ARE the owner of the resolved space, this refuses and tells you to host
37101
- it directly with \`${CLI_NAME26} space host <name>\` (no request needed).
37149
+ it directly with \`${CLI_NAME27} space host <name>\` (no request needed).
37102
37150
  `).action(async (name, options, cmd) => {
37103
37151
  try {
37104
37152
  const globalOpts = cmd.optsWithGlobals();
@@ -37109,7 +37157,7 @@ it directly with \`${CLI_NAME26} space host <name>\` (no request needed).
37109
37157
  if (await isRootAuthority(spaceId, ctx.profile)) {
37110
37158
  throw new CLIError(
37111
37159
  "ALREADY_ROOT_AUTHORITY",
37112
- `You are the owner of ${spaceId}. Host it directly: ${CLI_NAME26} space host ${spaceName}`,
37160
+ `You are the owner of ${spaceId}. Host it directly: ${CLI_NAME27} space host ${spaceName}`,
37113
37161
  ExitCode.USAGE_ERROR
37114
37162
  );
37115
37163
  }
@@ -37195,7 +37243,7 @@ init_sdk();
37195
37243
  init_space();
37196
37244
  init_host();
37197
37245
  init_theme();
37198
- import { CLI_NAME as CLI_NAME27 } from "@tinycloud/operations/cli-name";
37246
+ import { CLI_NAME as CLI_NAME28 } from "@tinycloud/operations/cli-name";
37199
37247
  import { writeFile as writeFile5 } from "fs/promises";
37200
37248
  import { resolve as resolve7 } from "path";
37201
37249
  async function dbHandle(node, dbName, spaceInput, profileName2) {
@@ -37219,12 +37267,12 @@ database for simple apps, or pass --db to target a named database. Pass
37219
37267
  --space to target a non-primary space (e.g. the manifest "applications" space).
37220
37268
 
37221
37269
  Common workflows:
37222
- $ ${CLI_NAME27} sql execute "CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT)"
37223
- $ ${CLI_NAME27} sql execute "INSERT INTO notes (body) VALUES (?)" --params '["ship docs"]'
37224
- $ ${CLI_NAME27} sql query "SELECT id, body FROM notes ORDER BY id"
37225
- $ ${CLI_NAME27} sql query "SELECT * FROM events WHERE type = ?" --db analytics --params '["signup"]'
37226
- $ ${CLI_NAME27} sql query "SELECT count(*) FROM conversation" --space applications --db xyz.tinycloud.listen/conversations
37227
- $ ${CLI_NAME27} sql export --db analytics --output analytics.db
37270
+ $ ${CLI_NAME28} sql execute "CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT)"
37271
+ $ ${CLI_NAME28} sql execute "INSERT INTO notes (body) VALUES (?)" --params '["ship docs"]'
37272
+ $ ${CLI_NAME28} sql query "SELECT id, body FROM notes ORDER BY id"
37273
+ $ ${CLI_NAME28} sql query "SELECT * FROM events WHERE type = ?" --db analytics --params '["signup"]'
37274
+ $ ${CLI_NAME28} sql query "SELECT count(*) FROM conversation" --space applications --db xyz.tinycloud.listen/conversations
37275
+ $ ${CLI_NAME28} sql export --db analytics --output analytics.db
37228
37276
 
37229
37277
  Commands:
37230
37278
  query Read rows with SELECT statements
@@ -37241,10 +37289,10 @@ Tips:
37241
37289
  sql.command("query <sql>").description("Run a read-only SELECT query").option("--db <name>", "SQLite database name within the current space", "default").option("--space <name|uri>", "Target a non-primary space (short name or full URI)").option("--params <json>", "Bind parameters as a JSON array for ? placeholders").addHelpText("after", `
37242
37290
 
37243
37291
  Examples:
37244
- $ ${CLI_NAME27} sql query "SELECT * FROM notes ORDER BY id"
37245
- $ ${CLI_NAME27} sql query "SELECT * FROM notes WHERE id = ?" --params '[42]'
37246
- $ ${CLI_NAME27} sql query "SELECT count(*) AS total FROM events" --db analytics --json
37247
- $ ${CLI_NAME27} sql query "SELECT count(*) FROM conversation" --space applications --db xyz.tinycloud.listen/conversations
37292
+ $ ${CLI_NAME28} sql query "SELECT * FROM notes ORDER BY id"
37293
+ $ ${CLI_NAME28} sql query "SELECT * FROM notes WHERE id = ?" --params '[42]'
37294
+ $ ${CLI_NAME28} sql query "SELECT count(*) AS total FROM events" --db analytics --json
37295
+ $ ${CLI_NAME28} sql query "SELECT count(*) FROM conversation" --space applications --db xyz.tinycloud.listen/conversations
37248
37296
 
37249
37297
  Output:
37250
37298
  Human output is formatted as a table. Piped output or --json returns
@@ -37285,11 +37333,11 @@ ${rowCount} row${rowCount === 1 ? "" : "s"} returned`) + "\n");
37285
37333
  sql.command("execute <sql>").description("Run a write or schema statement").option("--db <name>", "SQLite database name within the current space", "default").option("--space <name|uri>", "Target a non-primary space (short name or full URI)").option("--params <json>", "Bind parameters as a JSON array for ? placeholders").addHelpText("after", `
37286
37334
 
37287
37335
  Examples:
37288
- $ ${CLI_NAME27} sql execute "CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT)"
37289
- $ ${CLI_NAME27} sql execute "INSERT INTO notes (body) VALUES (?)" --params '["first note"]'
37290
- $ ${CLI_NAME27} sql execute "UPDATE notes SET body = ? WHERE id = ?" --params '["edited", 1]'
37291
- $ ${CLI_NAME27} sql execute "DROP TABLE old_notes" --db archive
37292
- $ ${CLI_NAME27} sql execute "DELETE FROM conversation WHERE id = ?" --space applications --db xyz.tinycloud.listen/conversations --params '["abc"]'
37336
+ $ ${CLI_NAME28} sql execute "CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT)"
37337
+ $ ${CLI_NAME28} sql execute "INSERT INTO notes (body) VALUES (?)" --params '["first note"]'
37338
+ $ ${CLI_NAME28} sql execute "UPDATE notes SET body = ? WHERE id = ?" --params '["edited", 1]'
37339
+ $ ${CLI_NAME28} sql execute "DROP TABLE old_notes" --db archive
37340
+ $ ${CLI_NAME28} sql execute "DELETE FROM conversation WHERE id = ?" --space applications --db xyz.tinycloud.listen/conversations --params '["abc"]'
37293
37341
 
37294
37342
  Output:
37295
37343
  Returns JSON with the changed row count and last inserted row id when available.
@@ -37318,9 +37366,9 @@ Output:
37318
37366
  sql.command("export").description("Export a SQLite database as a binary .db file").option("--db <name>", "SQLite database name within the current space", "default").option("--space <name|uri>", "Target a non-primary space (short name or full URI)").option("-o, --output <file>", "Output file path", "export.db").addHelpText("after", `
37319
37367
 
37320
37368
  Examples:
37321
- $ ${CLI_NAME27} sql export
37322
- $ ${CLI_NAME27} sql export --db analytics --output analytics.db
37323
- $ ${CLI_NAME27} sql export --space applications --db xyz.tinycloud.listen/conversations --output listen.db
37369
+ $ ${CLI_NAME28} sql export
37370
+ $ ${CLI_NAME28} sql export --db analytics --output analytics.db
37371
+ $ ${CLI_NAME28} sql export --space applications --db xyz.tinycloud.listen/conversations --output listen.db
37324
37372
 
37325
37373
  Output:
37326
37374
  Writes the database file locally and returns JSON with the path and size.
@@ -37353,19 +37401,19 @@ Output:
37353
37401
  sql.command("copy").description("Copy rows between SQL databases (optionally across spaces)").requiredOption("--from-db <name>", "Source database name").requiredOption("--to-db <name>", "Destination database name").option("--from-space <name|uri>", "Source space (defaults to primary)").option("--to-space <name|uri>", "Destination space (defaults to primary)").option("--table <name...>", "Restrict copy to specific tables (repeat or comma-separated)").option("--dry-run", "Print the plan without writing", false).addHelpText("after", `
37354
37402
 
37355
37403
  Examples:
37356
- $ ${CLI_NAME27} sql copy --from-db com.tinycloud.conversation-sync/conversations \\
37404
+ $ ${CLI_NAME28} sql copy --from-db com.tinycloud.conversation-sync/conversations \\
37357
37405
  --to-db xyz.tinycloud.listen/conversations \\
37358
37406
  --space applications --dry-run
37359
- $ ${CLI_NAME27} sql copy --from-space applications --from-db com.foo/data \\
37407
+ $ ${CLI_NAME28} sql copy --from-space applications --from-db com.foo/data \\
37360
37408
  --to-space applications --to-db com.bar/data \\
37361
37409
  --table conversation --table participant
37362
37410
 
37363
37411
  Notes:
37364
37412
  - Refuses to run when (resolved space, db) is identical for source and destination.
37365
- - Does NOT create destination tables. Run the target app once (or use \`${CLI_NAME27} sql execute\`)
37413
+ - Does NOT create destination tables. Run the target app once (or use \`${CLI_NAME28} sql execute\`)
37366
37414
  to materialize the schema before copying.
37367
37415
  - One row at a time; suitable for small/medium datasets. Large copies should
37368
- use \`${CLI_NAME27} sql export\` + bulk import.
37416
+ use \`${CLI_NAME28} sql export\` + bulk import.
37369
37417
  - Authorization: the active session/delegation must cover sql/read on source
37370
37418
  AND sql/write on destination. Otherwise the relevant operation will fail.
37371
37419
  `).action(async (options, cmd) => {
@@ -37465,7 +37513,7 @@ init_errors();
37465
37513
  init_formatter();
37466
37514
  init_theme();
37467
37515
  init_permissions();
37468
- import { CLI_NAME as CLI_NAME28 } from "@tinycloud/operations/cli-name";
37516
+ import { CLI_NAME as CLI_NAME29 } from "@tinycloud/operations/cli-name";
37469
37517
  import {
37470
37518
  NodeWasmBindings as NodeWasmBindings2
37471
37519
  } from "@tinycloud/node-sdk";
@@ -37739,7 +37787,7 @@ function formatStatus(summary) {
37739
37787
  lines.push(`Default profile: ${theme.value(summary.defaultProfile)}`);
37740
37788
  lines.push("");
37741
37789
  if (summary.profiles.length === 0) {
37742
- lines.push(theme.muted(`No profiles configured. Run: ${CLI_NAME28} init`));
37790
+ lines.push(theme.muted(`No profiles configured. Run: ${CLI_NAME29} init`));
37743
37791
  return `${lines.join("\n")}
37744
37792
  `;
37745
37793
  }