@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,383 @@
1
+ import {
2
+ resolveMetaTarget
3
+ } from "./chunk-33ND6LKO.js";
4
+ import "./chunk-DGSF2Q5H.js";
5
+ import "./chunk-7DKX2SPN.js";
6
+ import "./chunk-NDZFBZHC.js";
7
+ import {
8
+ isMachineOutput,
9
+ writeJson
10
+ } from "./chunk-NUQCEOKA.js";
11
+ import {
12
+ fetchOrExplain,
13
+ httpFailure,
14
+ serverMessage
15
+ } from "./chunk-3IGNIP6R.js";
16
+ import {
17
+ getAccessToken
18
+ } from "./chunk-C56BC2FY.js";
19
+ import "./chunk-7REDODS2.js";
20
+ import {
21
+ unknownSubcommand
22
+ } from "./chunk-IZW6MK3U.js";
23
+ import {
24
+ blank,
25
+ detail,
26
+ stderrStyle,
27
+ step,
28
+ success,
29
+ warn
30
+ } from "./chunk-EZG76F7R.js";
31
+ import "./chunk-YYRDLFSJ.js";
32
+ import "./chunk-GNPVYOPB.js";
33
+
34
+ // src/deploy/tests.ts
35
+ var TIMEOUT_MS = 12e4;
36
+ var PAGE_SIZE = 100;
37
+ var MAX_PAGES = 100;
38
+ function qualifiedName(handle) {
39
+ return handle.object === void 0 ? handle.name : `${handle.object.type}:${handle.object.name}/${handle.name}`;
40
+ }
41
+ function asString(v) {
42
+ return typeof v === "string" && v !== "" ? v : void 0;
43
+ }
44
+ async function metaFetch(auth, url, action, init) {
45
+ return fetchOrExplain(
46
+ url,
47
+ {
48
+ ...init,
49
+ headers: {
50
+ accept: "application/json",
51
+ Authorization: `Bearer ${auth.access_token}`,
52
+ ...init?.headers ?? {}
53
+ },
54
+ signal: AbortSignal.timeout(TIMEOUT_MS)
55
+ },
56
+ action,
57
+ TIMEOUT_MS
58
+ );
59
+ }
60
+ function readPage(data, action) {
61
+ if (Array.isArray(data)) return { rows: data, nextPage: void 0 };
62
+ if (data !== null && typeof data === "object") {
63
+ const record = data;
64
+ if (Array.isArray(record.items)) {
65
+ return {
66
+ rows: record.items,
67
+ // Measured: a final page sends `nextPage: null`, not an absent key. The
68
+ // `typeof` check reads that as "no next page" — a truthiness check would
69
+ // too, but would also swallow a legitimate page 0.
70
+ nextPage: typeof record.nextPage === "number" ? record.nextPage : void 0
71
+ };
72
+ }
73
+ }
74
+ throw new Error(
75
+ `${action}: the response was 2xx but carried neither an array nor an \`items\` list \u2014 refusing to report an unread suite as empty. Body: ${JSON.stringify(data).slice(0, 200)}`
76
+ );
77
+ }
78
+ async function collectPages(auth, buildUrl, action, onTruncate) {
79
+ const rows = [];
80
+ for (let page = 1; page <= MAX_PAGES; page++) {
81
+ const res = await metaFetch(auth, buildUrl(page), action, { method: "GET" });
82
+ const text = await res.text();
83
+ if (!res.ok) throw new Error(httpFailure(action, res, text));
84
+ let parsed;
85
+ try {
86
+ parsed = JSON.parse(text);
87
+ } catch {
88
+ throw new Error(`${action}: could not parse the response as JSON:
89
+ ${text.slice(0, 200)}`);
90
+ }
91
+ const { rows: pageRows, nextPage } = readPage(parsed, action);
92
+ rows.push(...pageRows);
93
+ if (pageRows.length === 0 || nextPage === void 0) return rows;
94
+ }
95
+ onTruncate?.(rows.length);
96
+ return rows;
97
+ }
98
+ async function listUnitTests(auth, target, onTruncate) {
99
+ const rows = await collectPages(
100
+ auth,
101
+ (page) => `${target.base}/api:meta/workspace/${target.workspaceId}/unit_test?page=${page}&per_page=${PAGE_SIZE}`,
102
+ "list unit tests",
103
+ onTruncate
104
+ );
105
+ return rows.flatMap((row) => {
106
+ const id = asString(row.id);
107
+ const name = asString(row.name);
108
+ if (id === void 0 || name === void 0) return [];
109
+ const objectType = asString(row.obj_type);
110
+ const objectName = asString(row.obj_name);
111
+ return [
112
+ {
113
+ kind: "unit",
114
+ id,
115
+ name,
116
+ object: objectType !== void 0 && objectName !== void 0 ? { type: objectType, name: objectName } : void 0,
117
+ datasource: typeof row.datasource === "string" ? row.datasource : void 0
118
+ }
119
+ ];
120
+ });
121
+ }
122
+ async function listWorkflowTests(auth, target, onTruncate) {
123
+ const rows = await collectPages(
124
+ auth,
125
+ (page) => `${target.base}/api:meta/workspace/${target.workspaceId}/workflow_test?page=${page}&per_page=${PAGE_SIZE}&include_xanoscript=false`,
126
+ "list workflow tests",
127
+ onTruncate
128
+ );
129
+ return rows.flatMap((row) => {
130
+ const name = asString(row.name);
131
+ if (typeof row.id !== "number" || name === void 0) return [];
132
+ return [
133
+ {
134
+ kind: "workflow",
135
+ id: row.id,
136
+ name,
137
+ datasource: typeof row.datasource === "string" ? row.datasource : void 0
138
+ }
139
+ ];
140
+ });
141
+ }
142
+ async function listTests(auth, target, opts = {}) {
143
+ const out = [];
144
+ if (opts.kind !== "workflow") out.push(...await listUnitTests(auth, target, opts.onTruncate));
145
+ if (opts.kind !== "unit") out.push(...await listWorkflowTests(auth, target, opts.onTruncate));
146
+ return out;
147
+ }
148
+ function firstFailureMessage(results) {
149
+ if (!Array.isArray(results)) return void 0;
150
+ for (const entry of results) {
151
+ if (entry === null || typeof entry !== "object") continue;
152
+ const row = entry;
153
+ if (row.status === "fail" && typeof row.message === "string" && row.message !== "") return row.message;
154
+ }
155
+ return void 0;
156
+ }
157
+ async function runTest(auth, target, handle) {
158
+ const route = handle.kind === "unit" ? "unit_test" : "workflow_test";
159
+ const url = `${target.base}/api:meta/workspace/${target.workspaceId}/${route}/${handle.id}/run`;
160
+ const action = `run ${handle.kind} test "${handle.name}"`;
161
+ const res = await metaFetch(auth, url, action, {
162
+ method: "POST",
163
+ headers: { "Content-Type": "application/json" },
164
+ // The unit-test route reads an optional `{branch}`; XanoTS models no branch
165
+ // concept, so an empty object takes the engine's live-branch default. The
166
+ // workflow route reads no body at all and ignores this.
167
+ body: "{}"
168
+ });
169
+ const text = await res.text();
170
+ if (!res.ok) {
171
+ const detail2 = serverMessage(text);
172
+ return { ...handle, status: "fail", message: `${res.status} ${res.statusText}${detail2 ? `: ${detail2}` : ""}` };
173
+ }
174
+ let body;
175
+ try {
176
+ body = JSON.parse(text);
177
+ } catch {
178
+ return { ...handle, status: "fail", message: `the engine's response was not JSON: ${text.slice(0, 200)}` };
179
+ }
180
+ const passed = body.status === "ok";
181
+ return {
182
+ ...handle,
183
+ status: passed ? "pass" : "fail",
184
+ message: passed ? void 0 : firstFailureMessage(body.results) ?? asString(body.message) ?? `status: ${String(body.status)}`,
185
+ // Optional by contract — read defensively, never format unguarded.
186
+ timing: typeof body.timing === "number" ? body.timing : void 0
187
+ };
188
+ }
189
+
190
+ // src/emit/test-command.ts
191
+ var EXIT_TESTS_FAILED = 5;
192
+ var DEFAULT_DEST = "ephemeral";
193
+ async function mapWithConcurrency(items, limit, work) {
194
+ const results = new Array(items.length);
195
+ let next = 0;
196
+ const worker = async () => {
197
+ for (; ; ) {
198
+ const index = next++;
199
+ if (index >= items.length) return;
200
+ results[index] = await work(items[index], index);
201
+ }
202
+ };
203
+ await Promise.all(Array.from({ length: Math.min(Math.max(1, limit), items.length) }, worker));
204
+ return results;
205
+ }
206
+ function describe(handle) {
207
+ return handle.object === void 0 ? "[workflow]" : `[unit: ${handle.object.type} ${handle.object.name}]`;
208
+ }
209
+ function renderOutcome(outcome, width) {
210
+ const s = stderrStyle();
211
+ const verdict = outcome.status === "pass" ? s.green("PASS") : s.red("FAIL");
212
+ const timing = outcome.timing === void 0 ? "" : s.dim(` ${outcome.timing.toFixed(3)}s`);
213
+ process.stderr.write(` ${verdict} ${outcome.name.padEnd(width)} ${s.dim(describe(outcome))}${timing}
214
+ `);
215
+ if (outcome.status === "fail" && outcome.message !== void 0) {
216
+ process.stderr.write(` ${s.dim(outcome.message)}
217
+ `);
218
+ }
219
+ }
220
+ function summarize(dest, env, outcomes) {
221
+ return {
222
+ dest,
223
+ env,
224
+ total: outcomes.length,
225
+ passed: outcomes.filter((o) => o.status === "pass").length,
226
+ failed: outcomes.filter((o) => o.status === "fail").length,
227
+ results: outcomes.map((o) => ({
228
+ kind: o.kind,
229
+ name: o.name,
230
+ object: o.object,
231
+ status: o.status,
232
+ message: o.message,
233
+ timing: o.timing
234
+ }))
235
+ };
236
+ }
237
+ function report(args, dest, env, outcomes) {
238
+ const summary = summarize(dest, env, outcomes);
239
+ if (isMachineOutput(args)) {
240
+ writeJson(summary);
241
+ } else if (outcomes.length === 0) {
242
+ detail("No tests found.");
243
+ } else {
244
+ blank();
245
+ const s = stderrStyle();
246
+ const line = `${summary.passed} passed, ${summary.failed} failed`;
247
+ if (summary.failed > 0) process.stderr.write(` ${s.red(line)}
248
+ `);
249
+ else success(line);
250
+ }
251
+ if (summary.failed > 0) process.exitCode = EXIT_TESTS_FAILED;
252
+ }
253
+ async function resolveTarget(args, auth) {
254
+ const dest = args.dest ?? DEFAULT_DEST;
255
+ const target = await resolveMetaTarget(auth, { dest, name: args.name });
256
+ return { dest, env: target.env ?? null, target };
257
+ }
258
+ async function collect(auth, target, kind) {
259
+ return listTests(auth, target, {
260
+ kind,
261
+ onTruncate: (collected) => warn(`Stopped after ${collected} tests \u2014 the list did not terminate, so some may not have run.`)
262
+ });
263
+ }
264
+ function nameWidth(handles) {
265
+ return Math.max(0, ...handles.map((h) => h.name.length));
266
+ }
267
+ async function runList(args, auth) {
268
+ const { dest, env, target } = await resolveTarget(args, auth);
269
+ const handles = await collect(auth, target, args.kind);
270
+ if (isMachineOutput(args)) {
271
+ writeJson({
272
+ dest,
273
+ env,
274
+ total: handles.length,
275
+ tests: handles.map((h) => ({
276
+ kind: h.kind,
277
+ name: h.name,
278
+ qualified: qualifiedName(h),
279
+ object: h.object,
280
+ datasource: h.datasource
281
+ }))
282
+ });
283
+ return;
284
+ }
285
+ if (handles.length === 0) {
286
+ detail("No tests found.");
287
+ return;
288
+ }
289
+ const s = stderrStyle();
290
+ step(`${handles.length} test${handles.length === 1 ? "" : "s"} in ${target.label}`);
291
+ const width = nameWidth(handles);
292
+ for (const handle of handles) {
293
+ const ds = handle.datasource === void 0 || handle.datasource === "" ? "" : s.yellow(` datasource: ${handle.datasource}`);
294
+ process.stderr.write(` ${handle.name.padEnd(width)} ${s.dim(describe(handle))}${ds}
295
+ `);
296
+ }
297
+ }
298
+ function match(handles, needle) {
299
+ const qualified = handles.filter((h) => h.object !== void 0 && qualifiedName(h) === needle);
300
+ if (qualified.length > 0) return qualified;
301
+ return handles.filter((h) => h.name === needle);
302
+ }
303
+ async function runOne(args, auth, name) {
304
+ const { dest, env, target } = await resolveTarget(args, auth);
305
+ const handles = await collect(auth, target, args.kind);
306
+ const found = match(handles, name);
307
+ if (found.length === 0) {
308
+ throw new Error(
309
+ `No test named "${name}" in ${target.label}. Run \`xanots test list${args.dest ? ` --dest ${args.dest}` : ""}\` to see what is there.`
310
+ );
311
+ }
312
+ if (found.length > 1) {
313
+ throw new Error(
314
+ `"${name}" names ${found.length} tests in ${target.label}. Use the qualified form:
315
+ ` + found.map((h) => ` xanots test run "${qualifiedName(h)}"`).join("\n")
316
+ );
317
+ }
318
+ const handle = found[0];
319
+ step(`Running ${handle.name} in ${target.label}`);
320
+ const outcome = await runTest(auth, target, handle);
321
+ if (!isMachineOutput(args)) renderOutcome(outcome, handle.name.length);
322
+ report(args, dest, env, [outcome]);
323
+ }
324
+ async function runSuite(auth, target, opts) {
325
+ const handles = await collect(auth, target, opts.kind);
326
+ if (handles.length === 0) return [];
327
+ const units = handles.filter((h) => h.kind === "unit").length;
328
+ const flows = handles.length - units;
329
+ if (opts.human) {
330
+ step(
331
+ `Running ${handles.length} test${handles.length === 1 ? "" : "s"} against ${target.label} (${units} unit, ${flows} workflow)`
332
+ );
333
+ blank();
334
+ }
335
+ const width = nameWidth(handles);
336
+ let emitted = 0;
337
+ const settled = new Array(handles.length);
338
+ const flush = () => {
339
+ while (emitted < settled.length && settled[emitted] !== void 0) {
340
+ renderOutcome(settled[emitted], width);
341
+ emitted++;
342
+ }
343
+ };
344
+ return mapWithConcurrency(handles, opts.concurrency ?? 1, async (handle, index) => {
345
+ const outcome = await runTest(auth, target, handle);
346
+ settled[index] = outcome;
347
+ if (opts.human) flush();
348
+ return outcome;
349
+ });
350
+ }
351
+ async function runAll(args, auth) {
352
+ const { dest, env, target } = await resolveTarget(args, auth);
353
+ const outcomes = await runSuite(auth, target, {
354
+ kind: args.kind,
355
+ concurrency: args.concurrency,
356
+ human: !isMachineOutput(args)
357
+ });
358
+ report(args, dest, env, outcomes);
359
+ }
360
+ async function runTestCommand(args) {
361
+ const auth = await getAccessToken(args);
362
+ switch (args.subcommand) {
363
+ case "list":
364
+ return runList(args, auth);
365
+ case "run": {
366
+ const name = args.positionals[0];
367
+ if (name === void 0 || name === "") {
368
+ throw new Error('`xanots test run` needs a test name: `xanots test run "<name>"`.');
369
+ }
370
+ return runOne(args, auth, name);
371
+ }
372
+ case "run-all":
373
+ return runAll(args, auth);
374
+ default:
375
+ throw unknownSubcommand("test", args.subcommand);
376
+ }
377
+ }
378
+ export {
379
+ EXIT_TESTS_FAILED,
380
+ runSuite,
381
+ runTestCommand
382
+ };
383
+ //# sourceMappingURL=test-command-TSPBQHBM.js.map
@@ -0,0 +1,122 @@
1
+ import {
2
+ assertBundleInput,
3
+ loadBundleText
4
+ } from "./chunk-NOO35BQ2.js";
5
+ import "./chunk-YGPIY3WT.js";
6
+ import "./chunk-IZW6MK3U.js";
7
+ import {
8
+ blank,
9
+ detail,
10
+ info,
11
+ step,
12
+ success,
13
+ warn
14
+ } from "./chunk-EZG76F7R.js";
15
+ import "./chunk-3DUAGYGP.js";
16
+ import "./chunk-YYRDLFSJ.js";
17
+ import "./chunk-EMCAWMHC.js";
18
+ import "./chunk-WHOJWOSV.js";
19
+ import "./chunk-LH6Z6KFV.js";
20
+ import "./chunk-HJPTWBLH.js";
21
+ import "./chunk-GNPVYOPB.js";
22
+ import "./chunk-4HT3BNZ7.js";
23
+
24
+ // src/emit/validate-command.ts
25
+ var EXIT_VALIDATION_FAILED = 2;
26
+ async function runValidateCommand(args) {
27
+ assertBundleInput(args, { command: "validate" });
28
+ const { resolveValidateConfig, verifyToken } = await import("./config-NL33PN4D.js");
29
+ const { MetaClient } = await import("./meta-client-OW5WKWW7.js");
30
+ const config = resolveValidateConfig({ instance: args.instance });
31
+ const who = await verifyToken(config);
32
+ const host = new URL(config.instance).host;
33
+ step(`Validating against ${host}${who.name ? ` (as ${who.name})` : ""}`);
34
+ const { bundle } = await loadBundleText(args, { command: "validate" });
35
+ const client = new MetaClient(config);
36
+ try {
37
+ await validateWithClient(args, client, bundle);
38
+ } finally {
39
+ const teardown = await client.dispose();
40
+ if (teardown.error !== void 0) {
41
+ warn("Could not delete the validation environment; it will expire on its own:");
42
+ detail(teardown.error);
43
+ }
44
+ }
45
+ }
46
+ async function validateWithClient(args, client, bundle) {
47
+ const { runValidateLoop, runnableFunctionNames } = await import("./loop-OM3P2Z6O.js");
48
+ const result = await runValidateLoop(client, bundle);
49
+ if (!result.accepted) {
50
+ warn("Import rejected by the engine:");
51
+ detail(result.importError ?? "(no message)");
52
+ process.exitCode = EXIT_VALIDATION_FAILED;
53
+ return;
54
+ }
55
+ success(`Import accepted (workspace #${result.workspaceId ?? "?"})`);
56
+ let failed = false;
57
+ for (const entry of result.roundTrip) {
58
+ if (entry.status === "match") {
59
+ success(`round-trip \u2713 ${entry.kind} ${entry.name}`);
60
+ } else if (entry.status === "missing") {
61
+ warn(`round-trip ? ${entry.kind} ${entry.name} \u2014 not found in the imported workspace`);
62
+ failed = true;
63
+ } else if (entry.status === "ambiguous") {
64
+ warn(`round-trip ? ${entry.kind} ${entry.name} \u2014 multiple imported objects share its identity`);
65
+ failed = true;
66
+ } else {
67
+ warn(`round-trip \u2717 ${entry.kind} ${entry.name} \u2014 ${entry.diffs.length} field diff(s)`);
68
+ const shown = args.verbose ? entry.diffs : entry.diffs.slice(0, 10);
69
+ for (const d of shown) detail(`${d.path}: expected ${fmt(d.expected)}, got ${fmt(d.actual)}`);
70
+ if (!args.verbose && entry.diffs.length > shown.length) {
71
+ detail(`\u2026 ${entry.diffs.length - shown.length} more (run with --verbose)`);
72
+ }
73
+ failed = true;
74
+ }
75
+ }
76
+ for (const u of result.unchecked) {
77
+ info(`imported ${u.count} ${u.kind} object(s) \u2014 round-trip not checked`);
78
+ }
79
+ if (args.runtime && result.workspaceId !== void 0) {
80
+ const names = runnableFunctionNames(result.roundTrip);
81
+ if (names.length > 0) {
82
+ const { smokeRunFunctions } = await import("./runtime-V4C3AC3A.js");
83
+ blank();
84
+ const entries = await smokeRunFunctions(client, result.workspaceId, names);
85
+ for (const e of entries) {
86
+ if (e.ran) {
87
+ success(`runtime \u2713 ${e.name}`);
88
+ if (args.verbose) detail(fmt(e.detail));
89
+ } else {
90
+ warn(`runtime \u2717 ${e.name} (status ${e.status})`);
91
+ if (args.verbose) detail(fmt(e.detail));
92
+ failed = true;
93
+ }
94
+ }
95
+ }
96
+ }
97
+ if (args.capture) {
98
+ const { captureFixtures } = await import("./capture-HUV5BNTC.js");
99
+ const written = captureFixtures(result.roundTrip, args.out);
100
+ if (written.length === 0) warn("nothing to capture (no objects round-tripped)");
101
+ for (const w of written) detail(`captured ${w.name} \u2192 ${w.path}`);
102
+ }
103
+ if (failed) {
104
+ process.exitCode = EXIT_VALIDATION_FAILED;
105
+ } else {
106
+ blank();
107
+ success("Validation passed");
108
+ }
109
+ }
110
+ function fmt(v) {
111
+ if (typeof v === "string") return JSON.stringify(v);
112
+ if (v === void 0) return "(absent)";
113
+ try {
114
+ return JSON.stringify(v);
115
+ } catch {
116
+ return String(v);
117
+ }
118
+ }
119
+ export {
120
+ runValidateCommand
121
+ };
122
+ //# sourceMappingURL=validate-command-4ERHJSCO.js.map
@@ -0,0 +1,40 @@
1
+ // src/deploy/verify-rollout.ts
2
+ var CANONICAL_HEADER = "X-Xano-Canonical";
3
+ var FAST_POLL_MS = 1e3;
4
+ var FAST_PHASE_MS = 3e4;
5
+ var SLOW_POLL_MS = 2e3;
6
+ var REQUEST_TIMEOUT_MS = 1e4;
7
+ function cacheBust(url, nonce) {
8
+ try {
9
+ const u = new URL(url);
10
+ u.searchParams.set("_xc", String(nonce));
11
+ return u.toString();
12
+ } catch {
13
+ return `${url}${url.includes("?") ? "&" : "?"}_xc=${nonce}`;
14
+ }
15
+ }
16
+ async function verifyRollout(url, canonical, opts = {}) {
17
+ const fetchFn = opts.fetchFn ?? fetch;
18
+ const now = opts.now ?? Date.now;
19
+ const sleep = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
20
+ const totalDeadlineMs = opts.totalDeadlineMs ?? 12e4;
21
+ if (url === "" || canonical === "") return { live: false };
22
+ const start = now();
23
+ for (; ; ) {
24
+ try {
25
+ const res = await fetchFn(cacheBust(url, now()), {
26
+ method: "GET",
27
+ signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
28
+ });
29
+ if (res.headers.get(CANONICAL_HEADER) === canonical) return { live: true };
30
+ } catch {
31
+ }
32
+ const elapsed = now() - start;
33
+ if (elapsed >= totalDeadlineMs) return { live: false };
34
+ await sleep(elapsed < FAST_PHASE_MS ? FAST_POLL_MS : SLOW_POLL_MS);
35
+ }
36
+ }
37
+ export {
38
+ verifyRollout
39
+ };
40
+ //# sourceMappingURL=verify-rollout-FAVQ6EJY.js.map
@@ -0,0 +1,49 @@
1
+ import {
2
+ fetchReadOrExplain
3
+ } from "./chunk-3IGNIP6R.js";
4
+
5
+ // src/deploy/workspace.ts
6
+ var RESOLVE_TIMEOUT_MS = 3e4;
7
+ async function resolveScopedWorkspaceId(auth) {
8
+ const url = new URL("/api:meta/auth/me", auth.instance);
9
+ const res = await fetchReadOrExplain(
10
+ url.href,
11
+ {
12
+ headers: { Authorization: `Bearer ${auth.access_token}` },
13
+ signal: AbortSignal.timeout(RESOLVE_TIMEOUT_MS)
14
+ },
15
+ "resolve workspace",
16
+ RESOLVE_TIMEOUT_MS
17
+ );
18
+ const text = await res.text();
19
+ if (!res.ok) {
20
+ throw new Error(`resolve workspace failed (${res.status} ${res.statusText}):
21
+ ${text}`);
22
+ }
23
+ let data;
24
+ try {
25
+ data = JSON.parse(text);
26
+ } catch {
27
+ throw new Error(`resolve workspace: could not parse the ${url.pathname} response as JSON:
28
+ ${text}`);
29
+ }
30
+ const extras = data.extras ?? {};
31
+ const oauth = extras.oauth ?? {};
32
+ const instance = extras.instance ?? {};
33
+ const membership = instance.membership ?? {};
34
+ const list = Array.isArray(membership.workspace) ? membership.workspace : [];
35
+ const scopedGuid = typeof oauth.workspace === "string" ? oauth.workspace : void 0;
36
+ if (scopedGuid !== void 0 && scopedGuid !== "") {
37
+ const match = list.find((w) => w.guid === scopedGuid);
38
+ if (match !== void 0 && typeof match.id === "number") return match.id;
39
+ }
40
+ const ids = list.filter((w) => typeof w.id === "number");
41
+ if (ids.length === 1) return ids[0].id;
42
+ throw new Error(
43
+ `Could not resolve which workspace this token is scoped to (scoped workspace ${scopedGuid ?? "(none)"} not found among ${ids.length} membership workspaces). Run \`xanots login\` again and pick a single workspace at the consent screen. There is no workspace override \u2014 a credential addresses exactly one workspace.`
44
+ );
45
+ }
46
+ export {
47
+ resolveScopedWorkspaceId
48
+ };
49
+ //# sourceMappingURL=workspace-K72NP7SX.js.map