@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,68 @@
1
+ import {
2
+ OpenIdProvider,
3
+ clearCredential,
4
+ globalAuthFilePath,
5
+ readCredential,
6
+ resolveAuthFilePath,
7
+ resolveScope
8
+ } from "./chunk-7REDODS2.js";
9
+ import {
10
+ detail,
11
+ hostLabel,
12
+ info,
13
+ success,
14
+ warn
15
+ } from "./chunk-EZG76F7R.js";
16
+ import "./chunk-GNPVYOPB.js";
17
+
18
+ // src/emit/logout-command.ts
19
+ async function runLogoutCommand(args) {
20
+ const authFilePath = resolveAuthFilePath(args, "write");
21
+ const targetsGlobal = authFilePath === globalAuthFilePath();
22
+ let saved;
23
+ try {
24
+ saved = readCredential(authFilePath);
25
+ } catch (err) {
26
+ warn(`Could not read ${authFilePath} (${err instanceof Error ? err.message : String(err)}).`);
27
+ if (clearCredential(authFilePath)) {
28
+ success("Removed the unreadable credential file.");
29
+ detail(`Removed ${authFilePath}`);
30
+ }
31
+ return;
32
+ }
33
+ if (!saved) {
34
+ info(`Not signed in (no credential at ${authFilePath}). Nothing to do.`);
35
+ return;
36
+ }
37
+ if (targetsGlobal) {
38
+ warn("Clearing the shared ~/.xanots credential \u2014 this affects every project that reuses it.");
39
+ }
40
+ if (saved.type === "token") {
41
+ clearCredential(authFilePath);
42
+ success(`Removed the meta API token credential for ${hostLabel(saved.instance_base_url)}`);
43
+ detail(`Removed ${authFilePath}`);
44
+ detail("The token itself is still valid \u2014 revoke it at its source if you need it dead.");
45
+ return;
46
+ }
47
+ if (saved.refresh_token) {
48
+ const provider = new OpenIdProvider({
49
+ authHost: saved.auth_host,
50
+ scope: saved.scope ?? resolveScope(args),
51
+ clientId: saved.client_id
52
+ });
53
+ try {
54
+ await provider.revoke(saved.refresh_token);
55
+ } catch (err) {
56
+ warn(
57
+ `Could not revoke the refresh token at ${hostLabel(saved.auth_host)} (${err instanceof Error ? err.message : String(err)}). Clearing local credentials anyway.`
58
+ );
59
+ }
60
+ }
61
+ clearCredential(authFilePath);
62
+ success(`Signed out of ${hostLabel(saved.instance)}`);
63
+ detail(`Removed ${authFilePath}`);
64
+ }
65
+ export {
66
+ runLogoutCommand
67
+ };
68
+ //# sourceMappingURL=logout-command-MX3MJS5U.js.map
@@ -0,0 +1,93 @@
1
+ import {
2
+ ROUND_TRIP_KINDS,
3
+ indexByIdentity,
4
+ kindIsRunnable,
5
+ resolveMatch
6
+ } from "./chunk-76QBEIGO.js";
7
+ import {
8
+ normalize
9
+ } from "./chunk-26CNBZE2.js";
10
+
11
+ // src/validate/loop.ts
12
+ async function runValidateLoop(client, bundleText) {
13
+ const bundle = JSON.parse(bundleText);
14
+ const payload = bundle.payload ?? {};
15
+ let imported;
16
+ try {
17
+ imported = await client.importBundle(bundleText);
18
+ } catch (err) {
19
+ return {
20
+ accepted: false,
21
+ importError: err instanceof Error ? err.message : String(err),
22
+ workspaceId: void 0,
23
+ roundTrip: [],
24
+ unchecked: []
25
+ };
26
+ }
27
+ const workspaceId = imported.workspaceId;
28
+ const present = ROUND_TRIP_KINDS.map((k) => ({ kind: k.key, compiled: asRecords(payload[k.key]) })).filter(
29
+ (p) => p.compiled.length > 0
30
+ );
31
+ if (workspaceId === void 0 || present.length === 0) {
32
+ return {
33
+ accepted: true,
34
+ workspaceId,
35
+ roundTrip: [],
36
+ unchecked: present.map((p) => ({ kind: p.kind, count: p.compiled.length }))
37
+ };
38
+ }
39
+ const exported = await client.exportWorkspace(workspaceId);
40
+ const roundTrip = [];
41
+ const unchecked = [];
42
+ for (const { kind, compiled } of present) {
43
+ const fetched = asRecords(exported.payload[kind]);
44
+ if (fetched.length === 0) {
45
+ unchecked.push({ kind, count: compiled.length });
46
+ continue;
47
+ }
48
+ const index = indexByIdentity(fetched);
49
+ for (const obj of compiled) {
50
+ const name = typeof obj.name === "string" ? obj.name : "(unnamed)";
51
+ const match = resolveMatch(obj, index);
52
+ if (match.outcome !== "found") {
53
+ roundTrip.push({ kind, name, status: match.outcome, diffs: [], fetched: void 0 });
54
+ } else {
55
+ const diffs = deepDiff(normalize(obj), normalize(match.fetched));
56
+ roundTrip.push({ kind, name, status: diffs.length === 0 ? "match" : "diff", diffs, fetched: match.fetched });
57
+ }
58
+ }
59
+ }
60
+ return { accepted: true, workspaceId, roundTrip, unchecked };
61
+ }
62
+ function runnableFunctionNames(entries) {
63
+ return entries.filter((e) => kindIsRunnable(e.kind) && (e.status === "match" || e.status === "diff")).map((e) => e.name);
64
+ }
65
+ function asRecords(v) {
66
+ return Array.isArray(v) ? v.filter((o) => o !== null && typeof o === "object") : [];
67
+ }
68
+ function deepDiff(expected, actual, path = "$") {
69
+ if (expected === actual) return [];
70
+ const bothObjects = expected !== null && actual !== null && typeof expected === "object" && typeof actual === "object";
71
+ if (!bothObjects) return [{ path, expected, actual }];
72
+ const expIsArr = Array.isArray(expected);
73
+ const actIsArr = Array.isArray(actual);
74
+ if (expIsArr !== actIsArr) return [{ path, expected, actual }];
75
+ if (expIsArr && actIsArr) {
76
+ const len = Math.max(expected.length, actual.length);
77
+ const out2 = [];
78
+ for (let i = 0; i < len; i++) out2.push(...deepDiff(expected[i], actual[i], `${path}[${i}]`));
79
+ return out2;
80
+ }
81
+ const e = expected;
82
+ const a = actual;
83
+ const keys = /* @__PURE__ */ new Set([...Object.keys(e), ...Object.keys(a)]);
84
+ const out = [];
85
+ for (const k of keys) out.push(...deepDiff(e[k], a[k], `${path}.${k}`));
86
+ return out;
87
+ }
88
+ export {
89
+ deepDiff,
90
+ runValidateLoop,
91
+ runnableFunctionNames
92
+ };
93
+ //# sourceMappingURL=loop-OM3P2Z6O.js.map
@@ -0,0 +1,379 @@
1
+ import {
2
+ runNpm
3
+ } from "./chunk-47WDWMBJ.js";
4
+ import {
5
+ isMachineOutput,
6
+ writeJson
7
+ } from "./chunk-NUQCEOKA.js";
8
+ import {
9
+ serverMessage
10
+ } from "./chunk-3IGNIP6R.js";
11
+ import {
12
+ UsageError,
13
+ indentBlock,
14
+ missingArgument
15
+ } from "./chunk-IZW6MK3U.js";
16
+ import {
17
+ blank,
18
+ detail,
19
+ formatFields,
20
+ stdoutStyle,
21
+ step,
22
+ style,
23
+ success,
24
+ warn
25
+ } from "./chunk-EZG76F7R.js";
26
+ import "./chunk-YYRDLFSJ.js";
27
+
28
+ // src/emit/marketplace-command.ts
29
+ import { existsSync, readFileSync } from "fs";
30
+ import { join } from "path";
31
+
32
+ // src/emit/marketplace-catalogue.ts
33
+ var DEFAULT_BASE_URL = "https://xare-rvr8-mnnt.dev.xano.io";
34
+ var CATALOGUE_TIMEOUT_MS = 3e4;
35
+ function baseUrl() {
36
+ const override = process.env.XANOTS_MARKETPLACE_URL;
37
+ return override !== void 0 && override !== "" ? override : DEFAULT_BASE_URL;
38
+ }
39
+ function asString(v) {
40
+ return typeof v === "string" && v !== "" ? v : void 0;
41
+ }
42
+ function asStringArray(v) {
43
+ return Array.isArray(v) ? v.filter((x) => typeof x === "string" && x !== "") : [];
44
+ }
45
+ function asBoolean(v) {
46
+ return typeof v === "boolean" ? v : void 0;
47
+ }
48
+ function asRecord(v) {
49
+ return typeof v === "object" && v !== null && !Array.isArray(v) ? v : void 0;
50
+ }
51
+ function projectRow(raw) {
52
+ return {
53
+ id: typeof raw.id === "number" ? raw.id : void 0,
54
+ slug: asString(raw.slug),
55
+ npm_package: asString(raw.npm_package),
56
+ title: asString(raw.title),
57
+ tagline: asString(raw.tagline),
58
+ tags: asStringArray(raw.tags),
59
+ repo_url: asString(raw.repo_url),
60
+ docs_url: asString(raw.docs_url)
61
+ };
62
+ }
63
+ function projectRequirements(v) {
64
+ if (!Array.isArray(v)) return [];
65
+ return v.map((entry) => typeof entry === "string" ? entry : asString(asRecord(entry)?.text)).filter((t) => t !== void 0);
66
+ }
67
+ function projectIncludes(v) {
68
+ if (!Array.isArray(v)) return [];
69
+ return v.flatMap((entry) => {
70
+ const rec = asRecord(entry);
71
+ if (rec === void 0) return [];
72
+ return [{ kind: asString(rec.kind), name: asString(rec.name), summary: asString(rec.summary) }];
73
+ });
74
+ }
75
+ function projectModule(raw) {
76
+ return {
77
+ ...projectRow(raw),
78
+ description: asString(raw.description),
79
+ includes: projectIncludes(raw.includes),
80
+ requirements: projectRequirements(raw.requirements),
81
+ register_snippet: asString(raw.register_snippet),
82
+ agent_prompt: asString(raw.agent_prompt),
83
+ listed: asBoolean(raw.listed),
84
+ deleted: asBoolean(raw.deleted)
85
+ };
86
+ }
87
+ var ModuleNotFoundError = class extends Error {
88
+ name = "ModuleNotFoundError";
89
+ constructor(message) {
90
+ super(message);
91
+ }
92
+ };
93
+ var CatalogueHttpError = class extends Error {
94
+ constructor(status, detail2, message) {
95
+ super(message);
96
+ this.status = status;
97
+ this.detail = detail2;
98
+ }
99
+ status;
100
+ detail;
101
+ name = "CatalogueHttpError";
102
+ };
103
+ async function read(path, params) {
104
+ let url;
105
+ try {
106
+ url = new URL(path, baseUrl());
107
+ } catch {
108
+ throw new Error(
109
+ `XANOTS_MARKETPLACE_URL is not a valid URL: ${JSON.stringify(process.env.XANOTS_MARKETPLACE_URL)}`
110
+ );
111
+ }
112
+ for (const [key, value] of Object.entries(params ?? {})) {
113
+ url.searchParams.set(key, value);
114
+ }
115
+ let res;
116
+ try {
117
+ res = await fetch(url.href, {
118
+ headers: { accept: "application/json" },
119
+ signal: AbortSignal.timeout(CATALOGUE_TIMEOUT_MS)
120
+ });
121
+ } catch (err) {
122
+ throw new Error(
123
+ `Could not reach the marketplace catalogue at ${url.origin} \u2014 ${err instanceof Error ? err.message : String(err)}`
124
+ );
125
+ }
126
+ const text = await res.text();
127
+ if (!res.ok) {
128
+ const detail2 = serverMessage(text);
129
+ throw new CatalogueHttpError(
130
+ res.status,
131
+ detail2,
132
+ `The marketplace catalogue returned ${res.status} ${res.statusText} for ${url.pathname}` + (detail2 !== void 0 ? `:
133
+ ${detail2}` : ".")
134
+ );
135
+ }
136
+ try {
137
+ return JSON.parse(text);
138
+ } catch {
139
+ throw new Error(`Could not parse the ${url.pathname} response as JSON:
140
+ ${text}`);
141
+ }
142
+ }
143
+ function describe(value) {
144
+ if (value === null) return "null";
145
+ if (Array.isArray(value)) return "an array";
146
+ if (typeof value === "object") {
147
+ const keys = Object.keys(value);
148
+ return `an object with keys ${keys.length > 0 ? keys.join(", ") : "(none)"}`;
149
+ }
150
+ return typeof value;
151
+ }
152
+ function expectArray(value, path) {
153
+ if (!Array.isArray(value)) {
154
+ throw new Error(`Expected ${path} to return a list of modules, got ${describe(value)}.`);
155
+ }
156
+ return value.flatMap((entry) => {
157
+ const rec = asRecord(entry);
158
+ return rec === void 0 ? [] : [rec];
159
+ });
160
+ }
161
+ async function fetchCatalogue() {
162
+ const path = "/api:marketplace/plugins";
163
+ return expectArray(await read(path), path).filter((raw) => raw.deleted !== true).map(projectRow);
164
+ }
165
+ async function searchCatalogue(query) {
166
+ const path = "/api:marketplace/plugins-search";
167
+ return expectArray(await read(path, { q: query }), path).map(projectRow);
168
+ }
169
+ async function fetchModule(pkg) {
170
+ const path = "/api:marketplace/plugins-details";
171
+ let body;
172
+ try {
173
+ body = await read(path, { package: pkg });
174
+ } catch (err) {
175
+ if (err instanceof CatalogueHttpError && err.status === 404) {
176
+ throw new ModuleNotFoundError(err.detail ?? "No module is published under that name.");
177
+ }
178
+ throw err;
179
+ }
180
+ if (body === null) {
181
+ throw new ModuleNotFoundError("No module is published under that name.");
182
+ }
183
+ const raw = asRecord(body);
184
+ if (raw === void 0) {
185
+ throw new Error(`Expected ${path} to return one module, got ${describe(body)}.`);
186
+ }
187
+ return projectModule(raw);
188
+ }
189
+
190
+ // src/emit/marketplace-command.ts
191
+ function assertProjectDir(dir) {
192
+ const manifest = join(dir, "package.json");
193
+ if (!existsSync(manifest)) {
194
+ throw new Error(
195
+ `No package.json in ${dir} \u2014 \`xanots marketplace install\` runs inside a XanoTS project.
196
+ cd into your project first, or run \`xanots init\` to create one.`
197
+ );
198
+ }
199
+ try {
200
+ JSON.parse(readFileSync(manifest, "utf8"));
201
+ } catch (err) {
202
+ throw new Error(
203
+ `${manifest} is not valid JSON, so npm cannot install into it \u2014 fix it and re-run. (${err instanceof Error ? err.message : String(err)})`
204
+ );
205
+ }
206
+ }
207
+ function resolvePackage(args, verb = "install") {
208
+ const pkg = args.positionals[0];
209
+ if (pkg === void 0 || pkg === "") {
210
+ throw missingArgument("package", { command: "marketplace", subcommand: verb });
211
+ }
212
+ if (pkg.startsWith("-")) {
213
+ throw new UsageError(
214
+ verb === "install" ? `\`xanots marketplace install\`: "${pkg}" starts with a dash, so npm would read it as a flag, not a package.` : `\`xanots marketplace details\`: "${pkg}" starts with a dash, so it is a mistyped flag, not a package.`,
215
+ { helpFor: { command: "marketplace", subcommand: verb } }
216
+ );
217
+ }
218
+ return pkg;
219
+ }
220
+ async function runMarketplaceInstallCommand(args) {
221
+ refusePromptFlag(args, "install");
222
+ const pkg = resolvePackage(args);
223
+ const dir = process.cwd();
224
+ assertProjectDir(dir);
225
+ step(`Installing ${style.bold(pkg)}`);
226
+ const status = runNpm(["install", pkg], dir);
227
+ if (status !== 0) {
228
+ throw new Error(`npm install ${pkg} failed (exit ${status}).`);
229
+ }
230
+ blank();
231
+ success(`Installed ${pkg}.`);
232
+ detail(`Import it in your backend (\`xano/index.ts\`) and register it onto your workspace.`);
233
+ }
234
+ function refusePromptFlag(args, verb) {
235
+ if (!args.prompt) return;
236
+ throw new UsageError(
237
+ `\`xanots marketplace ${verb}\`: --prompt belongs to \`marketplace details <package>\`, which is the verb that has an agent prompt to print.`,
238
+ { helpFor: { command: "marketplace", subcommand: verb } }
239
+ );
240
+ }
241
+ function tagLine(tags) {
242
+ return tags.length > 0 ? tags.join(" \xB7 ") : void 0;
243
+ }
244
+ function renderRow(row) {
245
+ const s = stdoutStyle();
246
+ const name = row.npm_package ?? row.slug ?? "(unnamed)";
247
+ const title = row.title !== void 0 ? ` ${s.dim(row.title)}` : "";
248
+ const lines = [` ${s.bold(s.cyan(name))}${title}`];
249
+ if (row.tagline !== void 0) lines.push(` ${row.tagline}`);
250
+ const tags = tagLine(row.tags);
251
+ if (tags !== void 0) lines.push(` ${s.dim(tags)}`);
252
+ if (row.docs_url !== void 0) lines.push(` ${s.dim(row.docs_url)}`);
253
+ return lines.join("\n");
254
+ }
255
+ function writeRows(args, rows, empty) {
256
+ if (isMachineOutput(args)) {
257
+ writeJson(rows);
258
+ return;
259
+ }
260
+ const s = stdoutStyle();
261
+ if (rows.length === 0) {
262
+ process.stdout.write(`${empty}
263
+ `);
264
+ return;
265
+ }
266
+ const count = `${rows.length} add-on${rows.length === 1 ? "" : "s"}`;
267
+ process.stdout.write(
268
+ `
269
+ ${s.dim(count)}
270
+
271
+ ` + rows.map(renderRow).join("\n\n") + `
272
+
273
+ ${s.dim("xanots marketplace details <package> for what a module installs")}
274
+ `
275
+ );
276
+ }
277
+ async function runMarketplaceListCommand(args) {
278
+ refusePromptFlag(args, "list");
279
+ writeRows(args, await fetchCatalogue(), "No add-ons are published yet.");
280
+ }
281
+ async function runMarketplaceSearchCommand(args) {
282
+ refusePromptFlag(args, "search");
283
+ const query = args.positionals[0];
284
+ if (query === void 0 || query === "") {
285
+ throw missingArgument("string", { command: "marketplace", subcommand: "search" });
286
+ }
287
+ const q = args.positionals.join(" ");
288
+ writeRows(
289
+ args,
290
+ await searchCatalogue(q),
291
+ `Nothing matched "${q}". Run \`xanots marketplace list\` to see everything.`
292
+ );
293
+ }
294
+ function renderModule(mod) {
295
+ const s = stdoutStyle();
296
+ const out = [];
297
+ const name = mod.npm_package ?? mod.slug ?? "(unnamed)";
298
+ out.push(`
299
+ ${s.bold(s.cyan(mod.title ?? name))}`);
300
+ if (mod.tagline !== void 0) out.push(` ${mod.tagline}`);
301
+ if (mod.description !== void 0) {
302
+ out.push("");
303
+ out.push(s.dim(indentBlock(mod.description, " ")));
304
+ }
305
+ out.push("");
306
+ const fields = [["Package", s.bold(name)]];
307
+ const tags = tagLine(mod.tags);
308
+ if (tags !== void 0) fields.push(["Tags", s.dim(tags)]);
309
+ if (mod.docs_url !== void 0) fields.push(["Docs", mod.docs_url]);
310
+ if (mod.repo_url !== void 0) fields.push(["Repo", mod.repo_url]);
311
+ out.push(formatFields(fields).trimEnd());
312
+ if (mod.includes.length > 0) {
313
+ out.push(`
314
+ ${s.bold("Installs")}`);
315
+ const width = Math.max(...mod.includes.map((i) => (i.kind ?? "").length));
316
+ for (const item of mod.includes) {
317
+ const kind = s.dim((item.kind ?? "").padEnd(width));
318
+ const summary = item.summary !== void 0 ? s.dim(` \u2014 ${item.summary}`) : "";
319
+ out.push(` ${kind} ${item.name ?? ""}${summary}`);
320
+ }
321
+ }
322
+ if (mod.requirements.length > 0) {
323
+ out.push(`
324
+ ${s.bold("You supply")}`);
325
+ for (const req of mod.requirements) out.push(` \u2022 ${req}`);
326
+ }
327
+ if (mod.register_snippet !== void 0) {
328
+ out.push(`
329
+ ${s.bold("Register it")}`);
330
+ out.push(s.dim(indentBlock(mod.register_snippet, " ")));
331
+ }
332
+ if (mod.npm_package !== void 0) {
333
+ out.push(`
334
+ ${s.bold(s.green(`xanots marketplace install ${mod.npm_package}`))}`);
335
+ }
336
+ if (mod.agent_prompt !== void 0) {
337
+ out.push(
338
+ ` ${s.dim(`xanots marketplace details ${name} --prompt to hand the wiring to a coding agent`)}`
339
+ );
340
+ }
341
+ return out.join("\n") + "\n";
342
+ }
343
+ async function runMarketplaceDetailsCommand(args) {
344
+ const pkg = resolvePackage(args, "details");
345
+ let mod;
346
+ try {
347
+ mod = await fetchModule(pkg);
348
+ } catch (err) {
349
+ if (err instanceof ModuleNotFoundError) {
350
+ throw new Error(`${err.message} (looking for "${pkg}")
351
+ Try \`xanots marketplace search ${pkg}\`.`);
352
+ }
353
+ throw err;
354
+ }
355
+ if (mod.deleted === true) {
356
+ warn(`${mod.npm_package ?? pkg} has been removed from the marketplace.`);
357
+ }
358
+ if (args.prompt) {
359
+ if (mod.agent_prompt === void 0) {
360
+ throw new Error(
361
+ `${mod.npm_package ?? pkg} publishes no agent prompt. Run \`xanots marketplace details ${pkg}\` for its registration snippet instead.`
362
+ );
363
+ }
364
+ process.stdout.write(mod.agent_prompt + "\n");
365
+ return;
366
+ }
367
+ if (isMachineOutput(args)) {
368
+ writeJson(mod);
369
+ return;
370
+ }
371
+ process.stdout.write(renderModule(mod));
372
+ }
373
+ export {
374
+ runMarketplaceDetailsCommand,
375
+ runMarketplaceInstallCommand,
376
+ runMarketplaceListCommand,
377
+ runMarketplaceSearchCommand
378
+ };
379
+ //# sourceMappingURL=marketplace-command-RATXTKXN.js.map
@@ -0,0 +1,170 @@
1
+ import {
2
+ importWorkspaceArchive
3
+ } from "./chunk-5WGEURVI.js";
4
+ import {
5
+ createEphemeral,
6
+ deleteEphemeral,
7
+ isEphemeralDisabled,
8
+ waitUntilReady
9
+ } from "./chunk-6DHBYBTO.js";
10
+ import {
11
+ decodeWorkspaceArchive,
12
+ encodeWorkspaceArchive
13
+ } from "./chunk-ZUTSMMAG.js";
14
+ import "./chunk-X4DVXBFY.js";
15
+ import "./chunk-3IGNIP6R.js";
16
+
17
+ // src/validate/meta-client.ts
18
+ var REQUEST_TIMEOUT_MS = 6e4;
19
+ var ENV_WORKSPACE_ID = 1;
20
+ var DEFAULT_PARENT_WORKSPACE_ID = 1;
21
+ var ENV_EXPIRES_HOURS = 1;
22
+ var MetaClient = class {
23
+ constructor(config) {
24
+ this.config = config;
25
+ this.readBase = config.instance;
26
+ }
27
+ config;
28
+ /**
29
+ * Origin that post-import reads/runs target. The objects land in this run's
30
+ * ephemeral ENVIRONMENT, served under a `/tenant/<slug>` path, so reads must hit
31
+ * that env-scoped origin rather than the parent instance — this is switched to
32
+ * the env URL after a successful import (and starts at the parent instance, which
33
+ * is what `verifyToken` and any pre-import call use).
34
+ */
35
+ readBase;
36
+ /** This run's ephemeral env, once created — the handle `dispose()` deletes. */
37
+ env;
38
+ /**
39
+ * The validate config as the deploy transports' `ResolvedAuth`. Validate is
40
+ * engineer tooling authenticated by a bare instance token from the environment,
41
+ * never the interactive OAuth store — hence `credentialType: "token"`.
42
+ */
43
+ deployAuth(workspaceId) {
44
+ return {
45
+ access_token: this.config.token,
46
+ instance: this.config.instance,
47
+ workspaceId,
48
+ credentialType: "token"
49
+ };
50
+ }
51
+ authHeaders() {
52
+ return { Authorization: `Bearer ${this.config.token}` };
53
+ }
54
+ /**
55
+ * Build a read/run URL against {@link readBase}, APPENDING the route so any
56
+ * `/tenant/<slug>` path prefix survives (a leading-slash `new URL(path, base)`
57
+ * would drop it back to the origin).
58
+ */
59
+ readUrl(path) {
60
+ return new URL(`${this.readBase}${path}`);
61
+ }
62
+ /**
63
+ * Create this run's ephemeral environment and import the compiled bundle into
64
+ * it, as the `gzip(tar(workspace.json))` archive.
65
+ *
66
+ * There is no `reset` knob: importing with a workspace id is ALWAYS a full
67
+ * replace, and the env is brand new besides. A flag that could not change the
68
+ * outcome would only invite the belief that a merge import exists here.
69
+ */
70
+ async importBundle(bundle) {
71
+ const parentWorkspaceId = this.config.workspaceId ?? DEFAULT_PARENT_WORKSPACE_ID;
72
+ const auth = this.deployAuth(parentWorkspaceId);
73
+ const env = await createEphemeral(auth, {
74
+ parentWorkspaceId,
75
+ display: "xanots-validate",
76
+ description: "Disposable environment for `xanots validate`.",
77
+ expiresHours: ENV_EXPIRES_HOURS
78
+ }).catch((err) => {
79
+ if (!isEphemeralDisabled(err)) throw err;
80
+ throw new Error(
81
+ "Ephemeral environments are not enabled on this instance, so `xanots validate` has nowhere disposable to run. Ask whoever administers the instance to enable them, or deploy to the sandbox and exercise the endpoints there (`xanots deploy --dest sandbox`)."
82
+ );
83
+ });
84
+ this.env = { parentWorkspaceId, name: env.name };
85
+ await waitUntilReady(auth, { parentWorkspaceId, name: env.name });
86
+ const envUrl = env.url;
87
+ if (envUrl === void 0 || envUrl === "") {
88
+ throw new Error(
89
+ `The validation environment (${env.name}) came back without a URL, so there is nothing to deploy into.`
90
+ );
91
+ }
92
+ const result = await importWorkspaceArchive(auth, {
93
+ baseUrl: envUrl,
94
+ archive: encodeWorkspaceArchive(bundle),
95
+ workspaceId: ENV_WORKSPACE_ID
96
+ });
97
+ this.readBase = envUrl.replace(/\/+$/, "");
98
+ return {
99
+ workspaceId: result.workspaceId ?? ENV_WORKSPACE_ID,
100
+ baseUrl: env.url,
101
+ raw: result.raw
102
+ };
103
+ }
104
+ /**
105
+ * Delete this run's ephemeral environment. Safe to call when no env was ever
106
+ * created, and never throws: a cleanup failure must not mask the validation
107
+ * result the caller is about to report. The env's own expiry is the backstop.
108
+ */
109
+ async dispose() {
110
+ const env = this.env;
111
+ if (env === void 0) return { deleted: false };
112
+ this.env = void 0;
113
+ try {
114
+ await deleteEphemeral(this.deployAuth(env.parentWorkspaceId), {
115
+ parentWorkspaceId: env.parentWorkspaceId,
116
+ name: env.name
117
+ });
118
+ return { deleted: true };
119
+ } catch (err) {
120
+ return { deleted: false, error: err instanceof Error ? err.message : String(err) };
121
+ }
122
+ }
123
+ /**
124
+ * Export the workspace (this run's environment, post-import) as a `packageExport`
125
+ * bundle — the SAME shape the SDK emits, carrying full object logic. This is
126
+ * the faithful round-trip source: the response is a gzipped tar of
127
+ * `workspace.json`, decoded here into its bundle object.
128
+ */
129
+ async exportWorkspace(workspaceId) {
130
+ const url = this.readUrl(`/api:meta/workspace/${workspaceId}/export`);
131
+ const res = await fetch(url.href, {
132
+ method: "POST",
133
+ headers: { ...this.authHeaders(), "Content-Type": "application/json" },
134
+ body: JSON.stringify({ branch: "", password: "" }),
135
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
136
+ });
137
+ if (!res.ok) {
138
+ const text = await res.text();
139
+ throw new Error(`Export of workspace ${workspaceId} failed (${res.status} ${res.statusText}):
140
+ ${text}`);
141
+ }
142
+ const decoded = decodeWorkspaceArchive(new Uint8Array(await res.arrayBuffer()));
143
+ return { payload: decoded.payload ?? {} };
144
+ }
145
+ /**
146
+ * Run a named workspace function via the meta function-run route. Unlike the
147
+ * read methods this returns the status (rather than throwing) so a caller can
148
+ * report an engine error + logs as a runtime outcome.
149
+ */
150
+ async runFunction(workspaceId, name, input) {
151
+ const url = this.readUrl(`/api:meta/workspace/${workspaceId}/function/run`);
152
+ const res = await fetch(url.href, {
153
+ method: "POST",
154
+ headers: { ...this.authHeaders(), "Content-Type": "application/json" },
155
+ body: JSON.stringify({ name, input: input ?? {} }),
156
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
157
+ });
158
+ const text = await res.text();
159
+ let body = text;
160
+ try {
161
+ body = text === "" ? void 0 : JSON.parse(text);
162
+ } catch {
163
+ }
164
+ return { status: res.status, ok: res.ok, body };
165
+ }
166
+ };
167
+ export {
168
+ MetaClient
169
+ };
170
+ //# sourceMappingURL=meta-client-OW5WKWW7.js.map