@xanots/sdk 0.0.1

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 (106) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +384 -0
  3. package/dist/agent-file-refresh-7XCACU34.js +95 -0
  4. package/dist/bin.d.ts +1 -0
  5. package/dist/bin.js +184 -0
  6. package/dist/capture-HUV5BNTC.js +32 -0
  7. package/dist/chunk-26CNBZE2.js +963 -0
  8. package/dist/chunk-33ND6LKO.js +78 -0
  9. package/dist/chunk-3DUAGYGP.js +1550 -0
  10. package/dist/chunk-3IGNIP6R.js +89 -0
  11. package/dist/chunk-47WDWMBJ.js +14 -0
  12. package/dist/chunk-4BXJGVZ3.js +318 -0
  13. package/dist/chunk-4HT3BNZ7.js +675 -0
  14. package/dist/chunk-4YMD2OOZ.js +23 -0
  15. package/dist/chunk-5WGEURVI.js +156 -0
  16. package/dist/chunk-5YTBTF25.js +29 -0
  17. package/dist/chunk-6DHBYBTO.js +166 -0
  18. package/dist/chunk-76QBEIGO.js +66 -0
  19. package/dist/chunk-7DKX2SPN.js +100 -0
  20. package/dist/chunk-7REDODS2.js +468 -0
  21. package/dist/chunk-C56BC2FY.js +254 -0
  22. package/dist/chunk-DGSF2Q5H.js +60 -0
  23. package/dist/chunk-EMCAWMHC.js +3982 -0
  24. package/dist/chunk-EZG76F7R.js +159 -0
  25. package/dist/chunk-FJ6ZS5KB.js +3607 -0
  26. package/dist/chunk-GNPVYOPB.js +17 -0
  27. package/dist/chunk-HJPTWBLH.js +38 -0
  28. package/dist/chunk-IZW6MK3U.js +248 -0
  29. package/dist/chunk-LH6Z6KFV.js +247 -0
  30. package/dist/chunk-MZUI3JNX.js +93 -0
  31. package/dist/chunk-NDZFBZHC.js +167 -0
  32. package/dist/chunk-NOO35BQ2.js +37 -0
  33. package/dist/chunk-NUQCEOKA.js +13 -0
  34. package/dist/chunk-QTNO2WD6.js +56 -0
  35. package/dist/chunk-RVB7ITKN.js +49 -0
  36. package/dist/chunk-TRU5OHQ5.js +6904 -0
  37. package/dist/chunk-VKFQJEMW.js +814 -0
  38. package/dist/chunk-VTIL47DT.js +125 -0
  39. package/dist/chunk-WHOJWOSV.js +112 -0
  40. package/dist/chunk-WKP4D5MO.js +1692 -0
  41. package/dist/chunk-X4DVXBFY.js +38 -0
  42. package/dist/chunk-XQ22GLYS.js +118 -0
  43. package/dist/chunk-YDZYMZBE.js +670 -0
  44. package/dist/chunk-YGPIY3WT.js +1146 -0
  45. package/dist/chunk-YYRDLFSJ.js +602 -0
  46. package/dist/chunk-ZUTSMMAG.js +46 -0
  47. package/dist/cli.d.ts +331 -0
  48. package/dist/cli.js +33 -0
  49. package/dist/codegen-command-OOKK6AZK.js +40 -0
  50. package/dist/codegen.d.ts +114 -0
  51. package/dist/codegen.js +71 -0
  52. package/dist/completion-TIPPZN7H.js +298 -0
  53. package/dist/config-NL33PN4D.js +84 -0
  54. package/dist/deploy-command-4EQ7XX5G.js +451 -0
  55. package/dist/env-target-IFJ5QDHC.js +16 -0
  56. package/dist/ephemeral-command-3X3I4ULC.js +242 -0
  57. package/dist/index.d.ts +4477 -0
  58. package/dist/index.js +300 -0
  59. package/dist/init-command-R6H7ZXW5.js +27 -0
  60. package/dist/internal.d.ts +74 -0
  61. package/dist/internal.js +2065 -0
  62. package/dist/io-AMIKRLPC.js +11 -0
  63. package/dist/live-diff-Y3AKETHE.js +196 -0
  64. package/dist/lock-3CVKALKT.js +37 -0
  65. package/dist/lock-commands-XTR2YKLY.js +232 -0
  66. package/dist/login-command-ACJF6KWQ.js +167 -0
  67. package/dist/logout-command-MX3MJS5U.js +68 -0
  68. package/dist/loop-OM3P2Z6O.js +93 -0
  69. package/dist/marketplace-command-RATXTKXN.js +379 -0
  70. package/dist/meta-client-OW5WKWW7.js +170 -0
  71. package/dist/node.d.ts +59 -0
  72. package/dist/node.js +442 -0
  73. package/dist/profile-command-SWJ3SPKR.js +77 -0
  74. package/dist/release-command-VV5UVZKL.js +427 -0
  75. package/dist/response-CVAE2kMj.d.ts +1915 -0
  76. package/dist/routes-manifest-SP3ZXLMR.js +244 -0
  77. package/dist/runtime-V4C3AC3A.js +13 -0
  78. package/dist/sandbox-details-command-HJE5SPVG.js +18 -0
  79. package/dist/sandbox-export-command-QCJY4GMV.js +24 -0
  80. package/dist/static-host-D6KS7X45.js +138 -0
  81. package/dist/store-BQ97nKIF.d.ts +7760 -0
  82. package/dist/test-command-TSPBQHBM.js +383 -0
  83. package/dist/validate-command-4ERHJSCO.js +122 -0
  84. package/dist/verify-rollout-FAVQ6EJY.js +40 -0
  85. package/dist/workspace-K72NP7SX.js +49 -0
  86. package/dist/workspace-command-OF23DPNI.js +156 -0
  87. package/dist/workspace-export-AJMGN3CQ.js +10 -0
  88. package/llms/fields.md +104 -0
  89. package/llms/filters.md +183 -0
  90. package/llms/kinds-agent-mcp.md +11 -0
  91. package/llms/kinds-core.md +68 -0
  92. package/llms/kinds-realtime.md +76 -0
  93. package/llms/lambda.md +111 -0
  94. package/llms/legacy.md +43 -0
  95. package/llms/object-kinds.md +31 -0
  96. package/llms/statements-calls.md +23 -0
  97. package/llms/statements-catalog.md +309 -0
  98. package/llms/statements-data.md +58 -0
  99. package/llms/statements-runtime.md +48 -0
  100. package/llms/tests.md +58 -0
  101. package/llms/triggers.md +22 -0
  102. package/llms/values.md +29 -0
  103. package/llms-full.txt +1672 -0
  104. package/llms.txt +483 -0
  105. package/manifest.json +9592 -0
  106. package/package.json +110 -0
@@ -0,0 +1,11 @@
1
+ import {
2
+ readLockFile,
3
+ writeLockFile
4
+ } from "./chunk-HJPTWBLH.js";
5
+ import "./chunk-GNPVYOPB.js";
6
+ import "./chunk-4HT3BNZ7.js";
7
+ export {
8
+ readLockFile,
9
+ writeLockFile
10
+ };
11
+ //# sourceMappingURL=io-AMIKRLPC.js.map
@@ -0,0 +1,196 @@
1
+ import {
2
+ deepEqual,
3
+ normalize
4
+ } from "./chunk-26CNBZE2.js";
5
+
6
+ // src/deploy/live-diff.ts
7
+ function rows(bundle, key) {
8
+ const payload = bundle?.payload;
9
+ if (payload === null || typeof payload !== "object") return [];
10
+ const value = payload[key];
11
+ return Array.isArray(value) ? value.filter((r) => r !== null && typeof r === "object") : [];
12
+ }
13
+ function columnsOf(table) {
14
+ 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);
18
+ }
19
+ function identify(table) {
20
+ const guid = table.guid;
21
+ if (typeof guid === "string" && guid !== "") return `guid:${guid}`;
22
+ const name = table.name;
23
+ return typeof name === "string" ? `name:${name}` : "";
24
+ }
25
+ function envOf(bundle) {
26
+ const payload = bundle?.payload;
27
+ const out = /* @__PURE__ */ new Map();
28
+ if (payload === null || typeof payload !== "object") return out;
29
+ const workspace = payload.workspace;
30
+ const candidates = [
31
+ payload.env,
32
+ workspace !== null && typeof workspace === "object" && !Array.isArray(workspace) ? workspace.env : void 0,
33
+ Array.isArray(workspace) && workspace[0] !== null && typeof workspace[0] === "object" ? workspace[0].env : void 0
34
+ ];
35
+ for (const candidate of candidates) {
36
+ if (!Array.isArray(candidate)) continue;
37
+ for (const entry of candidate) {
38
+ if (typeof entry === "string") {
39
+ const at = entry.indexOf("=");
40
+ if (at > 0) out.set(entry.slice(0, at), entry.slice(at + 1));
41
+ continue;
42
+ }
43
+ if (entry === null || typeof entry !== "object") continue;
44
+ const { name, value } = entry;
45
+ if (typeof name === "string" && name !== "") out.set(name, typeof value === "string" ? value : "");
46
+ }
47
+ }
48
+ return out;
49
+ }
50
+ function diffAgainstLive(outgoing, live, opts) {
51
+ const outgoingTables = new Map(rows(outgoing, "dbo").map((t) => [identify(t), t]));
52
+ const droppedColumns = [];
53
+ for (const liveTable of rows(live, "dbo")) {
54
+ const outgoingTable = outgoingTables.get(identify(liveTable));
55
+ if (outgoingTable === void 0) continue;
56
+ const kept = columnsOf(outgoingTable);
57
+ const name = typeof liveTable.name === "string" ? liveTable.name : "(unnamed)";
58
+ for (const column of columnsOf(liveTable)) {
59
+ if (!kept.has(column)) droppedColumns.push({ table: name, column });
60
+ }
61
+ }
62
+ const unchangedEnv = [];
63
+ if (opts.mode === "merge") {
64
+ const liveEnv = envOf(live);
65
+ for (const [name, value] of envOf(outgoing)) {
66
+ const current = liveEnv.get(name);
67
+ if (current !== void 0 && current !== value) unchangedEnv.push({ name });
68
+ }
69
+ }
70
+ return { droppedColumns, unchangedEnv };
71
+ }
72
+ var WORKSPACE_KEY = "workspace";
73
+ var ENV_KEY = "env";
74
+ var SETTINGS_KEYS_COMPARED_ELSEWHERE = /* @__PURE__ */ new Set([WORKSPACE_KEY, ENV_KEY, "canonical"]);
75
+ function isDeepSubset(ours, theirs) {
76
+ if (ours === null || typeof ours !== "object") return deepEqual(ours, theirs);
77
+ if (Array.isArray(ours) || Array.isArray(theirs)) return deepEqual(ours, theirs);
78
+ if (theirs === null || typeof theirs !== "object") return false;
79
+ const live = theirs;
80
+ return Object.entries(ours).every(
81
+ ([key, value]) => isDeepSubset(value, live[key])
82
+ );
83
+ }
84
+ function workspaceSettingsMatch(ours, theirs, outgoing, live) {
85
+ if (ours === null || typeof ours !== "object" || Array.isArray(ours)) {
86
+ return deepEqual(normalize(ours), normalize(theirs));
87
+ }
88
+ const authored = Object.fromEntries(
89
+ Object.entries(normalize(ours)).filter(
90
+ ([key]) => !SETTINGS_KEYS_COMPARED_ELSEWHERE.has(key)
91
+ )
92
+ );
93
+ if (!isDeepSubset(authored, normalize(theirs))) return false;
94
+ const liveEnv = envOf(live);
95
+ for (const name of envOf(outgoing).keys()) {
96
+ if (!liveEnv.has(name)) return false;
97
+ }
98
+ return true;
99
+ }
100
+ var SAMPLE = 5;
101
+ function payloadOf(bundle) {
102
+ const payload = bundle?.payload;
103
+ return payload !== null && typeof payload === "object" ? payload : {};
104
+ }
105
+ function guidOf(row) {
106
+ const guid = row.guid;
107
+ return typeof guid === "string" && guid !== "" ? guid : void 0;
108
+ }
109
+ function indexSection(rows2) {
110
+ const byGuid = /* @__PURE__ */ new Map();
111
+ const byName = /* @__PURE__ */ new Map();
112
+ const repeated = /* @__PURE__ */ new Set();
113
+ const all = [];
114
+ for (const row of rows2) {
115
+ if (row === null || typeof row !== "object") continue;
116
+ const record = row;
117
+ all.push(record);
118
+ const guid = guidOf(record);
119
+ if (guid !== void 0) byGuid.set(guid, record);
120
+ const name = record.name;
121
+ if (typeof name !== "string" || name === "") continue;
122
+ if (byName.has(name) || repeated.has(name)) {
123
+ byName.delete(name);
124
+ repeated.add(name);
125
+ continue;
126
+ }
127
+ byName.set(name, record);
128
+ }
129
+ return { byGuid, byName, all };
130
+ }
131
+ function byNameWithoutGuid(index, name, ourGuid) {
132
+ const candidate = index.byName.get(name);
133
+ if (candidate === void 0) return void 0;
134
+ return guidOf(candidate) === void 0 || ourGuid === void 0 ? candidate : void 0;
135
+ }
136
+ function nameOf(row) {
137
+ return typeof row.name === "string" && row.name !== "" ? row.name : "(unnamed)";
138
+ }
139
+ function compareToLive(outgoing, live) {
140
+ const ours = payloadOf(outgoing);
141
+ const theirs = payloadOf(live);
142
+ const differing = [];
143
+ const liveOnly = [];
144
+ let differingCount = 0;
145
+ let compared = 0;
146
+ const note = (key, name) => {
147
+ differingCount++;
148
+ if (differing.length < SAMPLE) differing.push(`${key}:${name}`);
149
+ };
150
+ for (const [key, value] of Object.entries(ours)) {
151
+ if (key === ENV_KEY) continue;
152
+ if (key === WORKSPACE_KEY) {
153
+ compared++;
154
+ if (!workspaceSettingsMatch(value, theirs[key], outgoing, live)) note(key, "(settings)");
155
+ continue;
156
+ }
157
+ if (!Array.isArray(value)) {
158
+ compared++;
159
+ if (!deepEqual(normalize(value), normalize(theirs[key]))) note(key, "(settings)");
160
+ continue;
161
+ }
162
+ const liveSection = theirs[key];
163
+ const index = indexSection(Array.isArray(liveSection) ? liveSection : []);
164
+ const matched = /* @__PURE__ */ new Set();
165
+ for (const row of value) {
166
+ compared++;
167
+ if (row === null || typeof row !== "object") {
168
+ note(key, "(unreadable)");
169
+ continue;
170
+ }
171
+ const record = row;
172
+ const guid = guidOf(record);
173
+ const name = typeof record.name === "string" ? record.name : void 0;
174
+ const counterpart = (guid !== void 0 ? index.byGuid.get(guid) : void 0) ?? // Name only answers what guid cannot. A live row that HAS a guid and
175
+ // does not have ours is a different object — the import would create
176
+ // ours alongside it — so the fallback is refused there and taken only
177
+ // when one side carries no guid at all.
178
+ (name !== void 0 ? byNameWithoutGuid(index, name, guid) : void 0);
179
+ if (counterpart === void 0) {
180
+ note(key, nameOf(record));
181
+ continue;
182
+ }
183
+ matched.add(counterpart);
184
+ if (!deepEqual(normalize(record), normalize(counterpart))) note(key, nameOf(record));
185
+ }
186
+ for (const row of index.all) {
187
+ if (!matched.has(row)) liveOnly.push(`${key}:${nameOf(row)}`);
188
+ }
189
+ }
190
+ return { converged: compared > 0 && differingCount === 0, compared, differing, differingCount, liveOnly };
191
+ }
192
+ export {
193
+ compareToLive,
194
+ diffAgainstLive
195
+ };
196
+ //# sourceMappingURL=live-diff-Y3AKETHE.js.map
@@ -0,0 +1,37 @@
1
+ import {
2
+ CANONICAL_PAYLOAD_KEYS,
3
+ LOCK_PAYLOAD_KEYS,
4
+ LOCK_VERSION,
5
+ WORKSPACE_KEY,
6
+ adoptFromBundle,
7
+ createLockContext,
8
+ emptyLock,
9
+ lockKey,
10
+ mergeObserved,
11
+ mintCanonical,
12
+ parseLock,
13
+ recordObserved,
14
+ renameLockEntry,
15
+ resolvePayloadKey,
16
+ serializeLock,
17
+ validateLockModel
18
+ } from "./chunk-4HT3BNZ7.js";
19
+ export {
20
+ CANONICAL_PAYLOAD_KEYS,
21
+ LOCK_PAYLOAD_KEYS,
22
+ LOCK_VERSION,
23
+ WORKSPACE_KEY,
24
+ adoptFromBundle,
25
+ createLockContext,
26
+ emptyLock,
27
+ lockKey,
28
+ mergeObserved,
29
+ mintCanonical,
30
+ parseLock,
31
+ recordObserved,
32
+ renameLockEntry,
33
+ resolvePayloadKey,
34
+ serializeLock,
35
+ validateLockModel
36
+ };
37
+ //# sourceMappingURL=lock-3CVKALKT.js.map
@@ -0,0 +1,232 @@
1
+ import {
2
+ loadDefault
3
+ } from "./chunk-YGPIY3WT.js";
4
+ import {
5
+ UsageError,
6
+ missingArgument,
7
+ unknownSubcommand
8
+ } from "./chunk-IZW6MK3U.js";
9
+ import "./chunk-EZG76F7R.js";
10
+ import {
11
+ Xano
12
+ } from "./chunk-3DUAGYGP.js";
13
+ import "./chunk-YYRDLFSJ.js";
14
+ import "./chunk-EMCAWMHC.js";
15
+ import "./chunk-WHOJWOSV.js";
16
+ import "./chunk-LH6Z6KFV.js";
17
+ import {
18
+ readLockFile,
19
+ writeLockFile
20
+ } from "./chunk-HJPTWBLH.js";
21
+ import "./chunk-GNPVYOPB.js";
22
+ import {
23
+ adoptFromBundle,
24
+ createLockContext,
25
+ emptyLock,
26
+ renameLockEntry,
27
+ resetLockOverrides,
28
+ resolvePayloadKey,
29
+ seedLockOverrides
30
+ } from "./chunk-4HT3BNZ7.js";
31
+
32
+ // src/emit/lock-commands.ts
33
+ import { existsSync, readFileSync } from "fs";
34
+ import { dirname, join, resolve } from "path";
35
+ async function runLockCommand(args) {
36
+ const [sub] = args.positionals;
37
+ switch (sub) {
38
+ case "rename":
39
+ return lockRename(args);
40
+ case "prune":
41
+ return lockPrune(args);
42
+ case "adopt":
43
+ return lockAdopt(args);
44
+ default:
45
+ throw unknownSubcommand("lock", sub);
46
+ }
47
+ }
48
+ function describeEntry(entry) {
49
+ const parts = [];
50
+ if (entry.guid !== void 0) parts.push(`guid ${entry.guid}`);
51
+ if (entry.canonical !== void 0) parts.push(`canonical ${entry.canonical}`);
52
+ return parts.join(", ");
53
+ }
54
+ function lockBesideEntry(entryFile) {
55
+ return join(dirname(resolve(entryFile)), "xano.lock");
56
+ }
57
+ function commandLockPath(args, subcommand) {
58
+ if (args.lockPath !== void 0) return resolve(args.lockPath);
59
+ if (args.entryPath !== void 0) return lockBesideEntry(args.entryPath);
60
+ const cwdLock = resolve("xano.lock");
61
+ if (existsSync(cwdLock)) return cwdLock;
62
+ const nested = resolve("xano", "xano.lock");
63
+ if (existsSync(nested)) {
64
+ throw new Error(
65
+ `lock ${subcommand}: no xano.lock in this directory, but one exists at xano/xano.lock \u2014 the layout \`xanots init\` scaffolds (the lock sits beside the entry file). Re-run with \`--entry=xano/index.ts\` (or \`--lock=xano/xano.lock\`).`
66
+ );
67
+ }
68
+ return cwdLock;
69
+ }
70
+ function lockRename(args) {
71
+ const [, kind, oldName, newName] = args.positionals;
72
+ if (!kind || !oldName || !newName) {
73
+ throw missingArgument(!kind ? "kind" : !oldName ? "old" : "new", { command: "lock", subcommand: "rename" });
74
+ }
75
+ const lockPath = commandLockPath(args, "rename");
76
+ const lock = readLockFile(lockPath);
77
+ const payloadKey = resolvePayloadKey(kind);
78
+ const { lock: renamed, discardedNewcomer } = renameLockEntry(lock, payloadKey, oldName, newName);
79
+ writeLockFile(lockPath, renamed);
80
+ process.stdout.write(
81
+ `Renamed lock entry "${payloadKey}:${oldName}" \u2192 "${payloadKey}:${newName}" (${describeEntry(renamed.objects[`${payloadKey}:${newName}`])}).
82
+ `
83
+ );
84
+ if (discardedNewcomer) {
85
+ process.stdout.write(
86
+ `Replaced the fresh entry the last export appended for "${payloadKey}:${newName}"` + (discardedNewcomer.canonical !== void 0 ? ` \u2014 its minted canonical ${discardedNewcomer.canonical} is discarded (that URL was never the object's real identity)` : "") + `.
87
+ `
88
+ );
89
+ }
90
+ process.stdout.write(`Re-run \`xanots export\` to emit the original guid under the new name.
91
+ `);
92
+ }
93
+ async function observedLockKeys(entryFile, lock) {
94
+ resetLockOverrides();
95
+ seedLockOverrides(lock);
96
+ let def;
97
+ try {
98
+ def = await loadDefault(entryFile);
99
+ } catch (err) {
100
+ const reason = err instanceof Error ? err.message : String(err);
101
+ throw new Error(
102
+ `lock prune evaluated "${entryFile}" to find out which lock entries are still live, and loading it failed:
103
+ ${reason}
104
+ Finding orphans requires running your workspace source \u2014 anything the entry file does at module scope (asserting env vars, reading config) runs too. To drop entries you can name yourself, no evaluation is needed: \`xanots lock prune --no-verify --yes <kind:name>\u2026\` with \`--lock=<path>\` or \`--entry=<path>\` to locate the lock.`,
105
+ { cause: err }
106
+ );
107
+ }
108
+ if (!Xano.isXano(def)) {
109
+ throw new Error(`Module "${entryFile}" must default-export a Xano registry for \`lock prune\`.`);
110
+ }
111
+ const ctx = createLockContext(lock);
112
+ def.export({ lock: ctx });
113
+ return new Set(Object.keys(ctx.observed));
114
+ }
115
+ async function lockPrune(args) {
116
+ const [, ...rest] = args.positionals;
117
+ if (args.noVerify) return lockPruneNamed(args, rest);
118
+ const [entryFile, ...keys] = rest;
119
+ if (!entryFile) {
120
+ throw missingArgument("entry-file", { command: "lock", subcommand: "prune" });
121
+ }
122
+ const lockPath = args.lockPath !== void 0 ? resolve(args.lockPath) : lockBesideEntry(entryFile);
123
+ const lock = readLockFile(lockPath);
124
+ const observed = await observedLockKeys(entryFile, lock);
125
+ const orphans = Object.keys(lock.objects).filter((key) => !observed.has(key));
126
+ let targets;
127
+ if (keys.length > 0) {
128
+ for (const key of keys) {
129
+ if (!(key in lock.objects)) {
130
+ throw new Error(`No lock entry "${key}" to prune.`);
131
+ }
132
+ if (!orphans.includes(key)) {
133
+ throw new Error(`Lock entry "${key}" still matches an exported object \u2014 not pruning it.`);
134
+ }
135
+ }
136
+ targets = keys;
137
+ } else {
138
+ targets = orphans;
139
+ }
140
+ if (targets.length === 0) {
141
+ process.stdout.write("Nothing to prune \u2014 every lock entry matches an exported object.\n");
142
+ return;
143
+ }
144
+ applyPrune(args, lockPath, lock, targets);
145
+ }
146
+ function lockPruneNamed(args, keys) {
147
+ if (keys.length === 0) {
148
+ throw new UsageError(
149
+ "`lock prune --no-verify` prunes the entries you name, so it needs at least one key (`table:users`). Without keys there is nothing to prune, because finding orphans is exactly the step --no-verify skips \u2014 drop the flag and pass the entry file to do that.",
150
+ { helpFor: { command: "lock", subcommand: "prune" } }
151
+ );
152
+ }
153
+ const lockPath = commandLockPath(args, "prune");
154
+ const lock = readLockFile(lockPath);
155
+ for (const key of keys) {
156
+ if (!(key in lock.objects)) {
157
+ throw new Error(`No lock entry "${key}" to prune.`);
158
+ }
159
+ }
160
+ process.stderr.write(
161
+ `xanots: --no-verify \u2014 nothing was evaluated, so nothing confirms ${keys.length === 1 ? "this key is" : "these keys are"} orphaned. A key the workspace still exports gets a NEW identity at the next export.
162
+ `
163
+ );
164
+ applyPrune(args, lockPath, lock, keys);
165
+ }
166
+ function applyPrune(args, lockPath, lock, targets) {
167
+ const lines = targets.sort().map((key) => ` ${key} (${describeEntry(lock.objects[key])})`).join("\n");
168
+ const discarded = targets.filter((key) => lock.objects[key].canonical !== void 0);
169
+ const canonicalNote = discarded.length > 0 ? `Discards ${discarded.length} canonical(s) \u2014 a pruned canonical's public URL is unrecoverable.
170
+ ` : "";
171
+ if (!args.yes) {
172
+ process.stdout.write(`Would prune ${targets.length} lock entr(y/ies):
173
+ ${lines}
174
+ ${canonicalNote}`);
175
+ throw new Error("lock prune is destructive \u2014 re-run with --yes to apply.");
176
+ }
177
+ const objects = { ...lock.objects };
178
+ for (const key of targets) delete objects[key];
179
+ writeLockFile(lockPath, { version: lock.version, objects });
180
+ process.stdout.write(`Pruned ${targets.length} lock entr(y/ies):
181
+ ${lines}
182
+ ${canonicalNote}`);
183
+ }
184
+ function lockAdopt(args) {
185
+ const [, bundlePath] = args.positionals;
186
+ if (!bundlePath) {
187
+ throw missingArgument("bundle.json", { command: "lock", subcommand: "adopt" });
188
+ }
189
+ const lockPath = commandLockPath(args, "adopt");
190
+ const lock = existsSync(lockPath) ? readLockFile(lockPath) : emptyLock();
191
+ let bundle;
192
+ try {
193
+ bundle = JSON.parse(readFileSync(bundlePath, "utf8"));
194
+ } catch (err) {
195
+ throw new Error(
196
+ `Cannot read ${bundlePath} as JSON: ${err instanceof Error ? err.message : String(err)}`
197
+ );
198
+ }
199
+ const { lock: adopted, added, changed, canonicalsSeen, vaultCount } = adoptFromBundle(
200
+ lock,
201
+ bundle,
202
+ bundlePath
203
+ );
204
+ if (changed.length > 0 && !args.yes) {
205
+ const lines = changed.map((c) => ` ${c.key}: ${describeEntry(c.before)} \u2192 ${describeEntry(c.after)}`).join("\n");
206
+ process.stdout.write(`Adoption would overwrite ${changed.length} existing lock entr(y/ies):
207
+ ${lines}
208
+ `);
209
+ throw new Error("lock adopt overwrites pinned identities \u2014 re-run with --yes to apply.");
210
+ }
211
+ if (vaultCount > 0) {
212
+ process.stderr.write(
213
+ `xanots: WARNING \u2014 ${bundlePath} contains ${vaultCount} vault entr(y/ies) (secrets). Do NOT commit the bundle file; delete it once adoption is done.
214
+ `
215
+ );
216
+ }
217
+ if (!canonicalsSeen) {
218
+ process.stderr.write(
219
+ `xanots: no canonicals found in ${bundlePath} \u2014 the engine's standard partial export strips them, so only guids were adopted. Existing public URLs are safe (the engine keeps the server-side canonical on guid-matched updates), but fresh imports elsewhere will mint new ones at the next locked export.
220
+ `
221
+ );
222
+ }
223
+ writeLockFile(lockPath, adopted);
224
+ process.stdout.write(
225
+ `Adopted ${bundlePath} into ${lockPath}: ${added.length} added, ${changed.length} updated.
226
+ `
227
+ );
228
+ }
229
+ export {
230
+ runLockCommand
231
+ };
232
+ //# sourceMappingURL=lock-commands-XTR2YKLY.js.map
@@ -0,0 +1,167 @@
1
+ import {
2
+ openBrowser,
3
+ startCallbackServer
4
+ } from "./chunk-VTIL47DT.js";
5
+ import {
6
+ envMetaCredentialVarsSet
7
+ } from "./chunk-C56BC2FY.js";
8
+ import {
9
+ CALLBACK_PATH,
10
+ DEFAULT_PORT,
11
+ OpenIdProvider,
12
+ assertHttpsOrigin,
13
+ decodeAudience,
14
+ ensureGitignored,
15
+ globalAuthFilePath,
16
+ oauthErrorCode,
17
+ readCredential,
18
+ resolveAuthFilePath,
19
+ resolveAuthHost,
20
+ resolveScope,
21
+ writeCredential
22
+ } from "./chunk-7REDODS2.js";
23
+ import {
24
+ blank,
25
+ detail,
26
+ hostLabel,
27
+ info,
28
+ step,
29
+ success,
30
+ warn
31
+ } from "./chunk-EZG76F7R.js";
32
+ import "./chunk-GNPVYOPB.js";
33
+
34
+ // src/emit/login-command.ts
35
+ import * as client from "openid-client";
36
+ async function runLoginCommand(args) {
37
+ const authHost = resolveAuthHost(args);
38
+ const scope = resolveScope(args);
39
+ const port = args.port ?? DEFAULT_PORT;
40
+ assertHttpsOrigin(authHost, "--origin");
41
+ if (!args.force && reportAlreadySignedIn(resolveAuthFilePath(args, "write"))) return;
42
+ step(`Signing in to ${hostLabel(authHost)}`);
43
+ let record;
44
+ try {
45
+ record = await attemptLogin({ authHost, scope, port });
46
+ } catch (err) {
47
+ if (oauthErrorCode(err) !== "invalid_client") throw err;
48
+ warn("The registered client was rejected \u2014 re-registering and retrying once.");
49
+ record = await attemptLogin({ authHost, scope, port });
50
+ }
51
+ const authFilePath = resolveAuthFilePath(args, "write");
52
+ writeCredential(authFilePath, record);
53
+ blank();
54
+ success(`Signed in to ${hostLabel(record.instance)}`);
55
+ detail(`Workspace ${record.workspace_id} (pinned \u2014 every command acts on this one)`);
56
+ detail(`Credentials saved to ${authFilePath}`);
57
+ const envVars = envMetaCredentialVarsSet();
58
+ if (envVars.length > 0) {
59
+ warn(
60
+ `${envVars.join(", ")} ${envVars.length === 1 ? "is" : "are"} set in this environment, outranking this credential \u2014 commands will keep using ${envVars.length === 3 ? "it" : "that environment credential, or fail because the set is incomplete"}. Unset ${envVars.length === 1 ? "it" : "them"} to act as the account you just signed in as.`
61
+ );
62
+ }
63
+ if (authFilePath === globalAuthFilePath()) {
64
+ detail("Using the shared ~/.xanots cache \u2014 available from any project directory.");
65
+ } else if (args.local) {
66
+ detail("Using the project-local .xano cache \u2014 scoped to this directory.");
67
+ }
68
+ try {
69
+ if (ensureGitignored(authFilePath)) {
70
+ detail("Added the credential file to .gitignore");
71
+ }
72
+ } catch (err) {
73
+ warn(
74
+ `Could not update .gitignore (${err instanceof Error ? err.message : String(err)}). Add ${authFilePath} to your ignore rules manually.`
75
+ );
76
+ }
77
+ if (!record.refresh_token) {
78
+ warn(
79
+ "No refresh token was issued (offline_access not granted); push will require re-login once the access token expires."
80
+ );
81
+ }
82
+ }
83
+ function reportAlreadySignedIn(authFilePath) {
84
+ let existing;
85
+ try {
86
+ existing = readCredential(authFilePath);
87
+ } catch {
88
+ return false;
89
+ }
90
+ if (!existing) return false;
91
+ if (existing.type === "oauth" && !existing.refresh_token && Date.now() >= existing.expires_at) return false;
92
+ const target = existing.type === "token" ? `${hostLabel(existing.instance_base_url)} with a hand-authored token` : hostLabel(existing.instance);
93
+ info(`Already signed in to ${target}, workspace ${existing.workspace_id}.`);
94
+ detail(`Credential: ${authFilePath}`);
95
+ detail("Re-run with --force to sign in again.");
96
+ return true;
97
+ }
98
+ async function attemptLogin(p) {
99
+ const verifier = client.randomPKCECodeVerifier();
100
+ const state = client.randomState();
101
+ let listener;
102
+ try {
103
+ listener = await startCallbackServer({ callbackPath: CALLBACK_PATH, expectedState: state, port: p.port });
104
+ } catch (err) {
105
+ const code = err.code;
106
+ if (code === "EADDRINUSE") {
107
+ throw new Error(`Loopback port ${p.port} is in use. Pass a free one with --port <n> and retry.`);
108
+ }
109
+ throw err;
110
+ }
111
+ const provider = new OpenIdProvider({ authHost: p.authHost, redirectUri: listener.redirectUri, scope: p.scope });
112
+ let authorizeUrl;
113
+ try {
114
+ authorizeUrl = await provider.buildAuthUrl({ verifier, state });
115
+ } catch (err) {
116
+ listener.close();
117
+ throw err;
118
+ }
119
+ detail("Opening your browser to authorize \u2014 waiting for you to finish\u2026");
120
+ detail("If it doesn't open, paste this URL into your browser:");
121
+ detail(authorizeUrl);
122
+ openBrowser(authorizeUrl);
123
+ let callbackUrl;
124
+ try {
125
+ ({ callbackUrl } = await listener.waitForCallback);
126
+ } catch (err) {
127
+ listener.close();
128
+ if (oauthErrorCode(err) === "invalid_client") await provider.reset();
129
+ throw err;
130
+ }
131
+ let tokens;
132
+ try {
133
+ tokens = await provider.exchange(callbackUrl, { verifier, state });
134
+ } catch (err) {
135
+ if (oauthErrorCode(err) === "invalid_client") await provider.reset();
136
+ throw err;
137
+ }
138
+ const boundInstance = decodeAudience(tokens.access_token);
139
+ if (!boundInstance) {
140
+ throw new Error(
141
+ `Could not determine the instance from the issued token (no readable \`aud\` claim). This is unexpected \u2014 please report it.`
142
+ );
143
+ }
144
+ const { resolveScopedWorkspaceId } = await import("./workspace-K72NP7SX.js");
145
+ detail("Resolving the workspace this token is scoped to\u2026");
146
+ const workspaceId = await resolveScopedWorkspaceId({
147
+ access_token: tokens.access_token,
148
+ instance: boundInstance
149
+ });
150
+ return {
151
+ type: "oauth",
152
+ access_token: tokens.access_token,
153
+ refresh_token: tokens.refresh_token,
154
+ expires_at: Date.now() + (tokens.expires_in ?? 0) * 1e3,
155
+ scope: tokens.scope ?? p.scope,
156
+ instance: boundInstance,
157
+ workspace_id: workspaceId,
158
+ auth_host: p.authHost,
159
+ // Record exactly which client minted the token — required to refresh/revoke
160
+ // it later. Resolved already (buildAuthUrl awaited the config).
161
+ client_id: provider.clientId()
162
+ };
163
+ }
164
+ export {
165
+ runLoginCommand
166
+ };
167
+ //# sourceMappingURL=login-command-ACJF6KWQ.js.map