@xanots/sdk 0.0.5 → 0.0.7

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.
Files changed (83) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +3 -3
  3. package/dist/.build-fingerprint +1 -1
  4. package/dist/{agent-file-refresh-IJ7GN2FJ.js → agent-file-refresh-4W37DGXS.js} +4 -4
  5. package/dist/bin.js +8 -8
  6. package/dist/branch-commands-PBQ36L4A.js +134 -0
  7. package/dist/{chunk-CYJ7R3AD.js → chunk-2V3JUXTF.js} +24 -11
  8. package/dist/{chunk-OR43PDCW.js → chunk-3EYUR3TX.js} +2 -2
  9. package/dist/{chunk-SG4UBJ47.js → chunk-3QW5NFZJ.js} +26 -5
  10. package/dist/{chunk-7SISR3CS.js → chunk-4PE4ZAB7.js} +3 -3
  11. package/dist/{chunk-PGBK64U5.js → chunk-4PTSTDIG.js} +2 -2
  12. package/dist/{live-diff-FP4SFNT4.js → chunk-5HCDZ2XN.js} +67 -6
  13. package/dist/{chunk-OARSPAIE.js → chunk-5PDOAR77.js} +58 -38
  14. package/dist/{chunk-5WGEURVI.js → chunk-6AAT2AYQ.js} +21 -1
  15. package/dist/{chunk-QA5ICJ4M.js → chunk-7BUTRVKA.js} +3 -3
  16. package/dist/{chunk-YUBJLB6G.js → chunk-7JDT4PBU.js} +75 -8
  17. package/dist/{chunk-LLWK6H77.js → chunk-BKDJN76G.js} +31 -1
  18. package/dist/{chunk-MS3BRZAZ.js → chunk-CL2H2WYE.js} +50 -27
  19. package/dist/{chunk-KXCPZUUM.js → chunk-DBHE35JM.js} +8 -67
  20. package/dist/chunk-EQW3YT5U.js +159 -0
  21. package/dist/{chunk-BPEEGJJA.js → chunk-FAWNUE2U.js} +39 -8
  22. package/dist/{chunk-ZGA5MUNC.js → chunk-FDKR4YMN.js} +2 -2
  23. package/dist/{chunk-APOR6TCV.js → chunk-H2DEDWQF.js} +4 -4
  24. package/dist/{chunk-PXXLBXOP.js → chunk-JAVB27HL.js} +2 -2
  25. package/dist/{chunk-AAFBSOSD.js → chunk-JQJPFUZI.js} +3 -3
  26. package/dist/{chunk-IVP6TS26.js → chunk-JQLR64UC.js} +6 -5
  27. package/dist/{chunk-FN4OQT2J.js → chunk-JUHKEAHJ.js} +4 -4
  28. package/dist/{chunk-WJYB7DSI.js → chunk-MDXR5E5Q.js} +2 -2
  29. package/dist/{chunk-WGDAOOXG.js → chunk-MU3O43L2.js} +3 -3
  30. package/dist/{chunk-YUPQOLFX.js → chunk-NJGNUVXR.js} +15 -4
  31. package/dist/{chunk-F5T45NAM.js → chunk-OKNSR7MT.js} +45 -2
  32. package/dist/{chunk-MFIHIS6B.js → chunk-OYMR5AMJ.js} +2 -2
  33. package/dist/{chunk-QUUB7HYK.js → chunk-P5C2YKAM.js} +2 -2
  34. package/dist/{chunk-6DHJVLYP.js → chunk-Q77KNEUL.js} +1 -1
  35. package/dist/{chunk-D6OGU2AI.js → chunk-QIWBCS7N.js} +2 -2
  36. package/dist/cli.d.ts +28 -2
  37. package/dist/cli.js +7 -7
  38. package/dist/{codegen-command-BLOS3GR3.js → codegen-command-DYH4H4TD.js} +18 -18
  39. package/dist/{completion-GHP5RRLQ.js → completion-A6BZ3XGU.js} +8 -7
  40. package/dist/{deploy-command-XOH76USO.js → deploy-command-HM57BINV.js} +15 -15
  41. package/dist/{env-target-POGJMD6Q.js → env-target-WA3BH5YU.js} +6 -6
  42. package/dist/{ephemeral-command-46SL27GJ.js → ephemeral-command-SD2KLX4P.js} +10 -10
  43. package/dist/index.d.ts +69 -26
  44. package/dist/index.js +6 -6
  45. package/dist/init-command-VIPWAQYS.js +30 -0
  46. package/dist/internal.d.ts +2 -2
  47. package/dist/internal.js +120 -62
  48. package/dist/{io-7VIA5SON.js → io-M7XZEMK7.js} +3 -3
  49. package/dist/live-diff-QK4KC2FJ.js +12 -0
  50. package/dist/{lock-KXOJIGCG.js → lock-GFXD6G2E.js} +6 -2
  51. package/dist/{lock-commands-6UONZW26.js → lock-commands-7VJKAXV6.js} +8 -8
  52. package/dist/{login-command-SG7IWTHW.js → login-command-DFCURZLC.js} +6 -6
  53. package/dist/{logout-command-J2AG5NKC.js → logout-command-WXVZQCAV.js} +2 -2
  54. package/dist/{marketplace-command-NKTQ3VPS.js → marketplace-command-BCOAAN2I.js} +3 -3
  55. package/dist/{meta-client-OW5WKWW7.js → meta-client-57ZWVHST.js} +2 -2
  56. package/dist/node.d.ts +2 -2
  57. package/dist/node.js +10 -10
  58. package/dist/{profile-command-ZPC2DPFV.js → profile-command-QJAAUZIV.js} +3 -3
  59. package/dist/{release-command-FKQ6E3TD.js → release-command-3IET7YII.js} +206 -26
  60. package/dist/{sandbox-details-command-DMY2KGA2.js → sandbox-details-command-EDO56IY3.js} +4 -4
  61. package/dist/{sandbox-export-command-R6QMEK3D.js → sandbox-export-command-MO6DEZ7Z.js} +5 -5
  62. package/dist/scaffold.d.ts +10 -13
  63. package/dist/scaffold.js +3 -3
  64. package/dist/{store-BJONDJoZ.d.ts → store-DfuWu1tE.d.ts} +1 -1
  65. package/dist/{test-command-56IAEYHX.js → test-command-S7SMRWMP.js} +8 -8
  66. package/dist/{upgrade-command-M2DZ3ZPD.js → upgrade-command-TZYSGXP7.js} +13 -13
  67. package/dist/{validate-command-CIBQJND7.js → validate-command-MMXEVHH3.js} +10 -10
  68. package/dist/{workspace-command-HZS43PHJ.js → workspace-command-X6L7HTXO.js} +24 -20
  69. package/guides/environment.md +6 -3
  70. package/guides/scaffold.md +3 -2
  71. package/llms/fields.md +8 -0
  72. package/llms/kinds-core.md +2 -1
  73. package/llms/lambda.md +1 -1
  74. package/llms/legacy.md +1 -1
  75. package/llms/lock.md +32 -0
  76. package/llms/object-kinds.md +2 -2
  77. package/llms/statements-calls.md +10 -3
  78. package/llms/statements-data.md +2 -1
  79. package/llms-full.txt +108 -58
  80. package/llms.txt +49 -49
  81. package/manifest.json +2 -2
  82. package/package.json +1 -1
  83. package/dist/init-command-NCRPVFGE.js +0 -30
package/CHANGELOG.md CHANGED
@@ -11,6 +11,35 @@ listed here.
11
11
 
12
12
  ---
13
13
 
14
+ ## 0.0.6 — The action identity fix
15
+
16
+ _2026-08-28_ · [release notes](https://github.com/xanots/sdk/releases/tag/v0.0.6)
17
+
18
+ `action.call` and `action.package.call` now take the identity the instance assigned at install
19
+ instead of deriving one from a name. A derived id is well-formed and addresses nothing, so those
20
+ calls exported clean and never resolved — if you have either in a workspace, this is a call-site
21
+ change you need to make. Alongside it: a lock-file false positive that refused a legal workspace,
22
+ and a grounding correction about what an omitted column on `db.add` actually stores.
23
+
24
+ - ⚠️ `action.call` takes the id the instance assigned, not one derived from a name
25
+ - One canonical on two different kinds is no longer a lock error
26
+ - An omitted column on `db.add` lands on its own default, not `null`
27
+ - `xanots init` asks two questions instead of three
28
+
29
+ ---
30
+
31
+ ## 0.0.5 — Sign in without a loopback
32
+
33
+ _2026-08-26_ · [release notes](https://github.com/xanots/sdk/releases/tag/v0.0.5)
34
+
35
+ `xanots login` only ever worked when the browser finishing consent could reach your machine's `127.0.0.1`. On a remote shell, a container, or a Codespace it can't — the redirect lands nowhere and login sits there for five minutes before timing out. `xanots login --paste` fixes that: it binds nothing, prints the URL for you to open anywhere, and you paste the redirect back. This release also corrects two documented promises that were wrong, one of which was actively misleading for exactly this case.
36
+
37
+ - `xanots login --paste` signs you in where the loopback can't be reached
38
+ - `XANO_NO_BROWSER` never covered remote shells, despite saying it did
39
+ - `--port` documented a default it did not have
40
+
41
+ ---
42
+
14
43
  ## 0.0.4 — The markdown your agents read
15
44
 
16
45
  _2026-08-26_ · [release notes](https://github.com/xanots/sdk/releases/tag/v0.0.4)
package/README.md CHANGED
@@ -106,9 +106,9 @@ npx @xanots/sdk init my-app && cd my-app
106
106
  npm run dev # the frontend runs immediately
107
107
  ```
108
108
 
109
- In a terminal it asks three questions — framework, theme, AI instruction files — each with a
110
- default. The theme is shadcn's own: a base color plus an optional accent, rendered into the
111
- token stylesheet, with a complete dark palette either way.
109
+ In a terminal it asks two questions — framework and AI instruction files — each with a
110
+ default. The theme is a flag, not a question: it is shadcn's own, a base color plus an
111
+ optional accent, rendered into the token stylesheet with a complete dark palette either way.
112
112
 
113
113
  ```bash
114
114
  npx @xanots/sdk init my-app --theme zinc-blue --dark toggle
@@ -1 +1 @@
1
- c0021219c47ba8aba005451538637f3d324faefad89c71468080cbe5bd443fa1
1
+ 12b76c8975e939f33a9312372b45a4090256a351870c259c08c96691cbda54af
@@ -3,10 +3,10 @@ import {
3
3
  codingAgentDetected,
4
4
  isCI,
5
5
  refreshAgentFiles
6
- } from "./chunk-D6OGU2AI.js";
7
- import "./chunk-7SISR3CS.js";
6
+ } from "./chunk-QIWBCS7N.js";
7
+ import "./chunk-4PE4ZAB7.js";
8
8
  import "./chunk-ZSYZTGJH.js";
9
- import "./chunk-6DHJVLYP.js";
9
+ import "./chunk-Q77KNEUL.js";
10
10
  import "./chunk-EZG76F7R.js";
11
11
  export {
12
12
  CI_ENV_VARS,
@@ -14,4 +14,4 @@ export {
14
14
  isCI,
15
15
  refreshAgentFiles
16
16
  };
17
- //# sourceMappingURL=agent-file-refresh-IJ7GN2FJ.js.map
17
+ //# sourceMappingURL=agent-file-refresh-4W37DGXS.js.map
package/dist/bin.js CHANGED
@@ -1,27 +1,27 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  maybeNotifyUpdate
4
- } from "./chunk-ZGA5MUNC.js";
4
+ } from "./chunk-FDKR4YMN.js";
5
5
  import {
6
6
  readVersion,
7
7
  run
8
- } from "./chunk-MS3BRZAZ.js";
8
+ } from "./chunk-CL2H2WYE.js";
9
9
  import {
10
10
  exitCodeOf,
11
11
  reportFailure
12
- } from "./chunk-IVP6TS26.js";
13
- import "./chunk-MFIHIS6B.js";
12
+ } from "./chunk-JQLR64UC.js";
13
+ import "./chunk-OYMR5AMJ.js";
14
14
  import "./chunk-GNPVYOPB.js";
15
15
  import {
16
16
  clearProgress,
17
17
  error
18
18
  } from "./chunk-EZG76F7R.js";
19
- import "./chunk-BPEEGJJA.js";
20
- import "./chunk-F5T45NAM.js";
21
- import "./chunk-YUPQOLFX.js";
19
+ import "./chunk-FAWNUE2U.js";
20
+ import "./chunk-OKNSR7MT.js";
21
+ import "./chunk-NJGNUVXR.js";
22
22
  import "./chunk-WHOJWOSV.js";
23
23
  import "./chunk-5XZ744TS.js";
24
- import "./chunk-YUBJLB6G.js";
24
+ import "./chunk-7JDT4PBU.js";
25
25
 
26
26
  // src/emit/interrupt.ts
27
27
  var EXIT_SIGINT = 130;
@@ -0,0 +1,134 @@
1
+ import {
2
+ deleteBranch,
3
+ listBranches,
4
+ requireBranch,
5
+ setLiveBranch
6
+ } from "./chunk-EQW3YT5U.js";
7
+ import {
8
+ confirm
9
+ } from "./chunk-4PTSTDIG.js";
10
+ import {
11
+ getAccessToken
12
+ } from "./chunk-3QW5NFZJ.js";
13
+ import "./chunk-BKDJN76G.js";
14
+ import {
15
+ isMachineOutput,
16
+ writeJson
17
+ } from "./chunk-NUQCEOKA.js";
18
+ import "./chunk-3IGNIP6R.js";
19
+ import {
20
+ UsageError
21
+ } from "./chunk-JQLR64UC.js";
22
+ import "./chunk-GNPVYOPB.js";
23
+ import {
24
+ blank,
25
+ detail,
26
+ info,
27
+ step,
28
+ success,
29
+ warn
30
+ } from "./chunk-EZG76F7R.js";
31
+ import "./chunk-OKNSR7MT.js";
32
+
33
+ // src/emit/branch-commands.ts
34
+ var VERBS = ["list", "set-live", "delete"];
35
+ function assertVerb(verb) {
36
+ if (verb !== void 0 && VERBS.includes(verb)) return verb;
37
+ throw new UsageError(
38
+ verb === void 0 ? `\`xanots workspace branch\` needs a verb: ${VERBS.join(", ")}.` : `\`xanots workspace branch ${verb}\` is not a verb. Expected one of: ${VERBS.join(", ")}.`,
39
+ { helpFor: { command: "workspace", subcommand: "branch" } }
40
+ );
41
+ }
42
+ function requireLabel(label, verb) {
43
+ if (label !== void 0 && label.trim() !== "") return label;
44
+ throw new UsageError(`\`xanots workspace branch ${verb}\` needs a branch label.`, {
45
+ helpFor: { command: "workspace", subcommand: "branch" }
46
+ });
47
+ }
48
+ function renderList(branches, workspaceId) {
49
+ blank();
50
+ step(`Branches in workspace #${workspaceId}`);
51
+ if (branches.length === 0) {
52
+ detail("none reported");
53
+ return;
54
+ }
55
+ for (const b of branches) {
56
+ const tags = [b.live ? "live" : "", b.backup ? "backup" : ""].filter(Boolean).join(", ");
57
+ detail(`${b.label}${tags === "" ? "" : ` (${tags})`}`);
58
+ }
59
+ blank();
60
+ detail("Branches scope logic. Tables and microservices are shared by every branch.");
61
+ }
62
+ async function runBranchCommand(args) {
63
+ const verb = assertVerb(args.positionals[0]);
64
+ const auth = await getAccessToken(args);
65
+ const workspaceId = auth.workspaceId;
66
+ const target = { baseUrl: auth.instance, workspaceId };
67
+ const branches = await listBranches(auth, target);
68
+ if (verb === "list") {
69
+ if (isMachineOutput(args)) {
70
+ writeJson({ workspaceId, instance: auth.instance, branches });
71
+ return;
72
+ }
73
+ renderList(branches, workspaceId);
74
+ return;
75
+ }
76
+ const label = requireLabel(args.positionals[1], verb);
77
+ const branch = requireBranch(branches, label);
78
+ if (verb === "set-live") {
79
+ if (branch.live) {
80
+ success(`Branch "${label}" is already live in workspace #${workspaceId} \u2014 nothing to do.`);
81
+ if (isMachineOutput(args)) writeJson({ workspaceId, branch: label, setLive: false, alreadyLive: true });
82
+ return;
83
+ }
84
+ const outgoing = branches.find((b) => b.live)?.label;
85
+ blank();
86
+ warn(`This is a production cutover for workspace #${workspaceId}.`);
87
+ if (outgoing !== void 0) detail(`The runtime stops serving "${outgoing}" and starts serving "${label}".`);
88
+ detail("Table data is unaffected \u2014 it is shared by every branch either way.");
89
+ blank();
90
+ if (!args.yes && !args.force) {
91
+ const ok = await confirm(`Make "${label}" the live branch?`, {
92
+ flag: "--yes",
93
+ helpFor: { command: "workspace", subcommand: "branch" }
94
+ });
95
+ if (!ok) {
96
+ info("Cancelled \u2014 the live branch is unchanged.");
97
+ return;
98
+ }
99
+ }
100
+ await setLiveBranch(auth, { ...target, label });
101
+ success(`Branch "${label}" is now live in workspace #${workspaceId}.`);
102
+ if (outgoing !== void 0) {
103
+ detail(`Roll back with \`xanots workspace branch set-live ${outgoing}\`.`);
104
+ }
105
+ if (isMachineOutput(args)) {
106
+ writeJson({ workspaceId, branch: label, setLive: true, previousBranch: outgoing });
107
+ }
108
+ return;
109
+ }
110
+ if (branch.live) {
111
+ throw new UsageError(
112
+ `Branch "${label}" is the LIVE branch of workspace #${workspaceId} and cannot be deleted.
113
+ Promote another branch first (\`xanots workspace branch set-live <other>\`), then delete this one.`,
114
+ { helpFor: { command: "workspace", subcommand: "branch" } }
115
+ );
116
+ }
117
+ if (!args.yes && !args.force) {
118
+ const ok = await confirm(`Delete branch "${label}" from workspace #${workspaceId}?`, {
119
+ flag: "--yes",
120
+ helpFor: { command: "workspace", subcommand: "branch" }
121
+ });
122
+ if (!ok) {
123
+ info("Cancelled \u2014 nothing was deleted.");
124
+ return;
125
+ }
126
+ }
127
+ await deleteBranch(auth, { ...target, label });
128
+ success(`Deleted branch "${label}" from workspace #${workspaceId}.`);
129
+ if (isMachineOutput(args)) writeJson({ workspaceId, branch: label, deleted: true });
130
+ }
131
+ export {
132
+ runBranchCommand
133
+ };
134
+ //# sourceMappingURL=branch-commands-PBQ36L4A.js.map
@@ -35,7 +35,7 @@ import {
35
35
  registerKind,
36
36
  tableColumns,
37
37
  withFilters
38
- } from "./chunk-YUPQOLFX.js";
38
+ } from "./chunk-NJGNUVXR.js";
39
39
  import {
40
40
  assertPathParamInputs,
41
41
  fillPathParams,
@@ -50,8 +50,9 @@ import {
50
50
  import {
51
51
  deriveGuid,
52
52
  realtimeChannelSeedName,
53
+ resolveQueryRef,
53
54
  resolveRef
54
- } from "./chunk-YUBJLB6G.js";
55
+ } from "./chunk-7JDT4PBU.js";
55
56
 
56
57
  // src/statements/set-var.ts
57
58
  var SET_VAR = "mvp:set_var";
@@ -482,7 +483,7 @@ function functionCall(args) {
482
483
  function apiCall(args) {
483
484
  args = argsOrEmpty(args);
484
485
  assertArg("mvp:workspace_run_endpoint", "api", args.api);
485
- const context = { id: resolveRef("query", args.api) };
486
+ const context = { id: resolveQueryRef(args.api) };
486
487
  const headers = coerceHeaders(args.headers);
487
488
  if (headers) context.headers = vf(headers);
488
489
  if (args.auth) {
@@ -546,29 +547,41 @@ function addonCall(args) {
546
547
  input: encodeCallInput(args.input)
547
548
  }, args);
548
549
  }
550
+ function refuseDerivedIdentity(statement, args) {
551
+ const legacy = args;
552
+ if (legacy.action === void 0 && legacy.package === void 0) return;
553
+ throw new Error(
554
+ `Statement "${statement}": \`action\`/\`package\` named an action and let the SDK derive its id. An action is a third-party package installed onto the instance, so its id is assigned at install and cannot be derived from a name \u2014 a derived one addresses nothing. Pass the installed id instead: \`actionId\` for action.call, or \`traceId\`/\`versionId\`/\`slug\` for action.package.call. Read them off an existing call in a pulled workspace.`
555
+ );
556
+ }
549
557
  function actionCall(args) {
550
558
  args = argsOrEmpty(args);
551
- assertArg("mvp:action", "action", args.action);
559
+ refuseDerivedIdentity("mvp:action", args);
560
+ assertArg("mvp:action", "actionId", args.actionId);
552
561
  return annotate({
553
562
  name: "mvp:action",
554
- context: { run_version: { id: resolveRef("function", args.action) } },
563
+ context: { run_version: { id: args.actionId } },
555
564
  as: args.as,
556
565
  input: encodeCallInput(args.input),
557
- settings_registry: []
566
+ settings_registry: encodeCallInput(args.registry)
558
567
  }, args);
559
568
  }
560
569
  function actionPackageCall(args) {
561
570
  args = argsOrEmpty(args);
571
+ refuseDerivedIdentity("mvp:action_package", args);
572
+ assertArg("mvp:action_package", "traceId", args.traceId);
573
+ assertArg("mvp:action_package", "versionId", args.versionId);
574
+ assertArg("mvp:action_package", "slug", args.slug);
562
575
  return annotate({
563
576
  name: "mvp:action_package",
564
577
  context: {
565
- action: { trace_id: "" },
566
- package: { slug: args.package ?? "" },
567
- package_version: { id: "" }
578
+ action: { trace_id: args.traceId },
579
+ package: { slug: args.slug },
580
+ package_version: { id: args.versionId }
568
581
  },
569
582
  as: args.as,
570
583
  input: encodeCallInput(args.input),
571
- settings_registry: []
584
+ settings_registry: encodeCallInput(args.registry)
572
585
  }, args);
573
586
  }
574
587
  function workflowTestCall(args) {
@@ -3721,4 +3734,4 @@ export {
3721
3734
  workspaceKind,
3722
3735
  workspaceConfig
3723
3736
  };
3724
- //# sourceMappingURL=chunk-CYJ7R3AD.js.map
3737
+ //# sourceMappingURL=chunk-2V3JUXTF.js.map
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-NDZFBZHC.js";
5
5
  import {
6
6
  getAccessToken
7
- } from "./chunk-SG4UBJ47.js";
7
+ } from "./chunk-3QW5NFZJ.js";
8
8
  import {
9
9
  isMachineOutput,
10
10
  writeJson
@@ -97,4 +97,4 @@ export {
97
97
  fetchSandboxDetails,
98
98
  runSandboxDetailsCommand
99
99
  };
100
- //# sourceMappingURL=chunk-OR43PDCW.js.map
100
+ //# sourceMappingURL=chunk-3EYUR3TX.js.map
@@ -7,12 +7,14 @@ import {
7
7
  globalAuthFilePath,
8
8
  localAuthFilePath,
9
9
  oauthErrorCode,
10
+ oauthErrorResponse,
10
11
  readCredential,
11
12
  resolveAuthFilePath,
12
13
  resolveAuthHost,
14
+ resolveOAuthErrorCode,
13
15
  resolveScope,
14
16
  writeCredential
15
- } from "./chunk-LLWK6H77.js";
17
+ } from "./chunk-BKDJN76G.js";
16
18
  import {
17
19
  detail,
18
20
  hostLabel,
@@ -40,7 +42,26 @@ function refreshAccessToken(authHost, clientId, refreshToken, scope) {
40
42
  return provider.refresh(refreshToken, { scope });
41
43
  }
42
44
  function isTransientRefreshError(err) {
43
- return oauthErrorCode(err) === void 0;
45
+ if (oauthErrorCode(err) !== void 0) return false;
46
+ const res = oauthErrorResponse(err);
47
+ if (res === void 0) return true;
48
+ return res.status >= 500;
49
+ }
50
+ async function describeRefreshFailure(err) {
51
+ const base = err instanceof Error ? err.message : String(err);
52
+ const res = oauthErrorResponse(err);
53
+ if (res === void 0) return base;
54
+ const parts = [`HTTP ${res.status}`];
55
+ const code = await resolveOAuthErrorCode(err);
56
+ if (code !== void 0) parts.push(code);
57
+ else if (!res.bodyUsed) {
58
+ try {
59
+ const text = (await res.clone().text()).trim();
60
+ if (text !== "") parts.push(text.length > 200 ? `${text.slice(0, 197)}\u2026` : text);
61
+ } catch {
62
+ }
63
+ }
64
+ return `${base} (${parts.join(" \u2014 ")})`;
44
65
  }
45
66
  async function refreshWithRetry(authHost, clientId, refreshToken, scope) {
46
67
  try {
@@ -215,8 +236,8 @@ async function refreshUnderLock(authFilePath, saved) {
215
236
  try {
216
237
  set = await refreshWithRetry(current.auth_host, current.client_id, current.refresh_token, current.scope);
217
238
  } catch (err) {
218
- const message = err instanceof Error ? err.message : String(err);
219
- if (oauthErrorCode(err) === "invalid_grant") {
239
+ const message = await describeRefreshFailure(err);
240
+ if (await resolveOAuthErrorCode(err) === "invalid_grant") {
220
241
  clearCredential(authFilePath);
221
242
  throw new Error(
222
243
  `Session for ${instance} has expired or was revoked (the refresh token was rejected). Run \`xanots login\` to sign in again.`
@@ -251,4 +272,4 @@ export {
251
272
  envMetaCredentialVarsSet,
252
273
  getAccessToken
253
274
  };
254
- //# sourceMappingURL=chunk-SG4UBJ47.js.map
275
+ //# sourceMappingURL=chunk-3QW5NFZJ.js.map
@@ -5,7 +5,7 @@ import {
5
5
  defaultThemeChoice,
6
6
  reactPreset,
7
7
  themeGuidanceSection
8
- } from "./chunk-6DHJVLYP.js";
8
+ } from "./chunk-Q77KNEUL.js";
9
9
  import {
10
10
  detail,
11
11
  step,
@@ -31,7 +31,7 @@ that reads well, type-checks, and is wrong. Read before writing:
31
31
  conditions are for.
32
32
  3. \`node_modules/@xanots/sdk/manifest.json\` \u2014 only for per-entry detail neither
33
33
  carries: a statement's full field schema with engine defaults, a filter's
34
- complete argument list. Grep or \`jq\` the one entry you need; it is ~55k
34
+ complete argument list. Grep or \`jq\` the one entry you need; it is ~65k
35
35
  tokens, so never read it whole.
36
36
 
37
37
  The published types and JSDoc (\`node_modules/@xanots/sdk/**/*.d.ts\`) are that
@@ -442,4 +442,4 @@ export {
442
442
  resolveAiPresets,
443
443
  scaffoldProject
444
444
  };
445
- //# sourceMappingURL=chunk-7SISR3CS.js.map
445
+ //# sourceMappingURL=chunk-4PE4ZAB7.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  UsageError
3
- } from "./chunk-IVP6TS26.js";
3
+ } from "./chunk-JQLR64UC.js";
4
4
  import {
5
5
  style
6
6
  } from "./chunk-EZG76F7R.js";
@@ -56,4 +56,4 @@ export {
56
56
  confirm,
57
57
  promptLine
58
58
  };
59
- //# sourceMappingURL=chunk-PGBK64U5.js.map
59
+ //# sourceMappingURL=chunk-4PTSTDIG.js.map
@@ -11,10 +11,19 @@ function rows(bundle, key) {
11
11
  return Array.isArray(value) ? value.filter((r) => r !== null && typeof r === "object") : [];
12
12
  }
13
13
  function columnsOf(table) {
14
+ return new Set(typedColumnsOf(table).keys());
15
+ }
16
+ function typedColumnsOf(table) {
17
+ const out = /* @__PURE__ */ new Map();
14
18
  const schema = table.schema;
15
- if (!Array.isArray(schema)) return /* @__PURE__ */ new Set();
16
- const names = schema.map((c) => c !== null && typeof c === "object" ? c.name : void 0).filter((n) => typeof n === "string" && n !== "");
17
- return new Set(names);
19
+ if (!Array.isArray(schema)) return out;
20
+ for (const entry of schema) {
21
+ if (entry === null || typeof entry !== "object") continue;
22
+ const { name, type } = entry;
23
+ if (typeof name !== "string" || name === "") continue;
24
+ out.set(name, typeof type === "string" ? type : "");
25
+ }
26
+ return out;
18
27
  }
19
28
  function identify(table) {
20
29
  const guid = table.guid;
@@ -69,6 +78,56 @@ function diffAgainstLive(outgoing, live, opts) {
69
78
  }
70
79
  return { droppedColumns, unchangedEnv };
71
80
  }
81
+ function sharedSchemaChanges(outgoing, live, opts = {}) {
82
+ if (live === void 0) return void 0;
83
+ const changes = [];
84
+ for (const kind of ["dbo", "microservice"]) {
85
+ const liveRows = new Map(rows(live, kind).map((r) => [identify(r), r]));
86
+ const outgoingRows = new Map(rows(outgoing, kind).map((r) => [identify(r), r]));
87
+ for (const [key, out] of outgoingRows) {
88
+ const current = liveRows.get(key);
89
+ const name = nameOf(out);
90
+ if (current === void 0) {
91
+ changes.push({ kind, name, action: "create" });
92
+ continue;
93
+ }
94
+ const details = kind === "dbo" ? tableDelta(current, out) : objectDelta(current, out);
95
+ if (details.length > 0) changes.push({ kind, name, action: "alter", details });
96
+ }
97
+ if (opts.prune === true) {
98
+ for (const [key, current] of liveRows) {
99
+ if (!outgoingRows.has(key)) changes.push({ kind, name: nameOf(current), action: "remove" });
100
+ }
101
+ }
102
+ }
103
+ return changes;
104
+ }
105
+ function tableDelta(live, outgoing) {
106
+ const details = [];
107
+ const before = typedColumnsOf(live);
108
+ const after = typedColumnsOf(outgoing);
109
+ const liveName = nameOf(live);
110
+ const outgoingName = nameOf(outgoing);
111
+ if (liveName !== outgoingName) details.push(`renamed from "${liveName}" to "${outgoingName}"`);
112
+ for (const [column, type] of after) {
113
+ const current = before.get(column);
114
+ if (current === void 0) {
115
+ details.push(`add column "${column}"`);
116
+ } else if (current !== type) {
117
+ details.push(`retype column "${column}" (${current} \u2192 ${type})`);
118
+ }
119
+ }
120
+ for (const column of before.keys()) {
121
+ if (!after.has(column)) details.push(`drop column "${column}"`);
122
+ }
123
+ return details;
124
+ }
125
+ function objectDelta(live, outgoing) {
126
+ const liveName = nameOf(live);
127
+ const outgoingName = nameOf(outgoing);
128
+ if (liveName !== outgoingName) return [`renamed from "${liveName}" to "${outgoingName}"`];
129
+ return deepEqual(normalize(live), normalize(outgoing)) ? [] : ["configuration differs"];
130
+ }
72
131
  var WORKSPACE_KEY = "workspace";
73
132
  var ENV_KEY = "env";
74
133
  var SETTINGS_KEYS_COMPARED_ELSEWHERE = /* @__PURE__ */ new Set([WORKSPACE_KEY, ENV_KEY, "canonical"]);
@@ -189,8 +248,10 @@ function compareToLive(outgoing, live) {
189
248
  }
190
249
  return { converged: compared > 0 && differingCount === 0, compared, differing, differingCount, liveOnly };
191
250
  }
251
+
192
252
  export {
193
- compareToLive,
194
- diffAgainstLive
253
+ diffAgainstLive,
254
+ sharedSchemaChanges,
255
+ compareToLive
195
256
  };
196
- //# sourceMappingURL=live-diff-FP4SFNT4.js.map
257
+ //# sourceMappingURL=chunk-5HCDZ2XN.js.map