@databrainhq/mcp-server 0.3.0-rc.12 → 0.3.0-rc.14

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 (46) hide show
  1. package/.mcp.json +6 -1
  2. package/dist/apps/server.d.ts +102 -389
  3. package/dist/apps/server.js +5 -5
  4. package/dist/apps/stdio.d.ts +1 -2
  5. package/dist/apps/stdio.js +6 -6
  6. package/dist/{bundle-TDQXWIPM.js → bundle-QJNCUMNY.js} +2 -2
  7. package/dist/{chunk-Q5EYDKSA.js → chunk-2F7V6RZR.js} +511 -107
  8. package/dist/chunk-2F7V6RZR.js.map +1 -0
  9. package/dist/{chunk-347U6GXR.js → chunk-AWICHHDU.js} +153 -61
  10. package/dist/chunk-AWICHHDU.js.map +1 -0
  11. package/dist/{chunk-Z3ZHN4UW.js → chunk-CEGHG5U3.js} +59 -18
  12. package/dist/chunk-CEGHG5U3.js.map +1 -0
  13. package/dist/{chunk-ZTHGF27R.js → chunk-NIC5MAGC.js} +317 -147
  14. package/dist/chunk-NIC5MAGC.js.map +1 -0
  15. package/dist/{chunk-V3UW3B6U.js → chunk-S65KA3Z7.js} +26 -11
  16. package/dist/chunk-S65KA3Z7.js.map +1 -0
  17. package/dist/{chunk-OLOC2MTA.js → chunk-UYFFFAYV.js} +11722 -10560
  18. package/dist/chunk-UYFFFAYV.js.map +1 -0
  19. package/dist/{chunk-LACJHQYH.js → chunk-VQ5G5AZV.js} +10 -7
  20. package/dist/chunk-VQ5G5AZV.js.map +1 -0
  21. package/dist/cli.d.ts +16 -15
  22. package/dist/cli.js +134 -36
  23. package/dist/cli.js.map +1 -1
  24. package/dist/custom-chart/custom-runtime.js +6 -6
  25. package/dist/custom-chart/template/chart.ts +116 -28
  26. package/dist/custom-chart/template/icon.svg +1 -1
  27. package/dist/custom-chart/template/manifest.json +66 -12
  28. package/dist/custom-chart/template/sample-data.json +21 -3
  29. package/dist/index.d.ts +1 -2
  30. package/dist/index.js +20 -10
  31. package/dist/index.js.map +1 -1
  32. package/dist/{main-IUV24DMP.js → main-QCBVJSSR.js} +363 -155
  33. package/dist/main-QCBVJSSR.js.map +1 -0
  34. package/dist/{test-only-K7QTSVO4.js → test-only-6474NMTR.js} +12 -8
  35. package/dist/test-only-6474NMTR.js.map +1 -0
  36. package/package.json +20 -9
  37. package/dist/chunk-347U6GXR.js.map +0 -1
  38. package/dist/chunk-LACJHQYH.js.map +0 -1
  39. package/dist/chunk-OLOC2MTA.js.map +0 -1
  40. package/dist/chunk-Q5EYDKSA.js.map +0 -1
  41. package/dist/chunk-V3UW3B6U.js.map +0 -1
  42. package/dist/chunk-Z3ZHN4UW.js.map +0 -1
  43. package/dist/chunk-ZTHGF27R.js.map +0 -1
  44. package/dist/main-IUV24DMP.js.map +0 -1
  45. package/dist/test-only-K7QTSVO4.js.map +0 -1
  46. /package/dist/{bundle-TDQXWIPM.js.map → bundle-QJNCUMNY.js.map} +0 -0
@@ -1,25 +1,28 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  registerChartApps
4
- } from "./chunk-ZTHGF27R.js";
4
+ } from "./chunk-NIC5MAGC.js";
5
5
  import {
6
6
  enableChartApps,
7
7
  registerAllPrompts,
8
8
  registerAllResources,
9
9
  registerAllTools
10
- } from "./chunk-OLOC2MTA.js";
10
+ } from "./chunk-UYFFFAYV.js";
11
11
  import {
12
12
  DatabrainClient,
13
13
  MCP_SERVER_VERSION
14
- } from "./chunk-347U6GXR.js";
14
+ } from "./chunk-AWICHHDU.js";
15
15
 
16
16
  // src/apps/server.ts
17
17
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
18
18
  function createChartAppServer(config, backend) {
19
19
  const client = new DatabrainClient(config);
20
- const server = new McpServer({ name: "databrain-chart-apps", version: MCP_SERVER_VERSION }, {
21
- instructions: "Use read-only chart previews to inspect analytics. Chart interactions inherit guest scope. Never request or expose credentials. Mutation tools retain their existing dry-run and confirmation requirements."
22
- });
20
+ const server = new McpServer(
21
+ { name: "databrain-chart-apps", version: MCP_SERVER_VERSION },
22
+ {
23
+ instructions: "Use read-only chart previews to inspect analytics. Chart interactions inherit guest scope. Never request or expose credentials. Mutation tools retain their existing dry-run and confirmation requirements."
24
+ }
25
+ );
23
26
  enableChartApps(server);
24
27
  registerAllTools(server, client);
25
28
  registerAllResources(server);
@@ -31,4 +34,4 @@ function createChartAppServer(config, backend) {
31
34
  export {
32
35
  createChartAppServer
33
36
  };
34
- //# sourceMappingURL=chunk-LACJHQYH.js.map
37
+ //# sourceMappingURL=chunk-VQ5G5AZV.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/apps/server.ts"],"sourcesContent":["import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { DatabrainClient } from '../client/databrain-client.js';\nimport { registerAllPrompts } from '../prompts/registry.js';\nimport { registerAllResources } from '../resources/registry.js';\nimport { registerAllTools } from '../tools/registry.js';\nimport type { Config } from '../utils/config.js';\nimport { MCP_SERVER_VERSION } from '../version.js';\nimport type { ChartBackend } from './backend.js';\nimport { enableChartApps } from './feature.js';\nimport { registerChartApps } from './registry.js';\n\n/** Reviewable composition seam; hosted owners must retain their principal-bound client/policy. */\nexport function createChartAppServer(\n config: Config,\n backend?: ChartBackend\n): McpServer {\n const client = new DatabrainClient(config);\n const server = new McpServer(\n { name: 'databrain-chart-apps', version: MCP_SERVER_VERSION },\n {\n instructions:\n 'Use read-only chart previews to inspect analytics. Chart interactions inherit guest scope. ' +\n 'Never request or expose credentials. Mutation tools retain their existing dry-run and confirmation requirements.',\n }\n );\n enableChartApps(server);\n registerAllTools(server, client);\n registerAllResources(server);\n registerAllPrompts(server);\n registerChartApps(server, client, backend);\n return server;\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAAA,SAAS,iBAAiB;AAYnB,SAAS,qBACd,QACA,SACW;AACX,QAAM,SAAS,IAAI,gBAAgB,MAAM;AACzC,QAAM,SAAS,IAAI;AAAA,IACjB,EAAE,MAAM,wBAAwB,SAAS,mBAAmB;AAAA,IAC5D;AAAA,MACE,cACE;AAAA,IAEJ;AAAA,EACF;AACA,kBAAgB,MAAM;AACtB,mBAAiB,QAAQ,MAAM;AAC/B,uBAAqB,MAAM;AAC3B,qBAAmB,MAAM;AACzB,oBAAkB,QAAQ,QAAQ,OAAO;AACzC,SAAO;AACT;","names":[]}
package/dist/cli.d.ts CHANGED
@@ -1,15 +1,16 @@
1
- /**
2
- * Shared shapes for the custom chart package pipeline (DAT-925).
3
- * Problem is the one error shape used by the manifest validator, the bundle
4
- * builder, the icon check and the backend API (section 5 of the brief).
5
- */
6
- interface Problem {
7
- code: string;
8
- path: string;
9
- message: string;
10
- }
11
-
12
- declare function formatProblemLines(problems: Problem[]): string[];
13
- declare function runCli(argv: string[]): Promise<number>;
14
-
15
- export { formatProblemLines, runCli };
1
+ export declare function formatProblemLines(problems: Problem[]): string[];
2
+
3
+ /**
4
+ * Shared shapes for the custom chart package pipeline (DAT-925).
5
+ * Problem is the one error shape used by the manifest validator, the bundle
6
+ * builder, the icon check and the backend API (section 5 of the brief).
7
+ */
8
+ declare interface Problem {
9
+ code: string;
10
+ path: string;
11
+ message: string;
12
+ }
13
+
14
+ export declare function runCli(argv: string[]): Promise<number>;
15
+
16
+ export { }
package/dist/cli.js CHANGED
@@ -9,12 +9,12 @@ import {
9
9
  redactSecrets,
10
10
  registerSecret,
11
11
  scaffoldProject
12
- } from "./chunk-347U6GXR.js";
12
+ } from "./chunk-AWICHHDU.js";
13
13
  import {
14
14
  buildProject,
15
15
  readProject,
16
16
  validateProject
17
- } from "./chunk-Q5EYDKSA.js";
17
+ } from "./chunk-2F7V6RZR.js";
18
18
 
19
19
  // src/cli/index.ts
20
20
  import { existsSync, mkdirSync, readdirSync, writeFileSync } from "fs";
@@ -33,7 +33,16 @@ var LIGHT_THEME = {
33
33
  borderColor: "#e5e7eb",
34
34
  borderRadius: 6,
35
35
  primaryColor: "#3366cc",
36
- palette: ["#3366cc", "#dc3912", "#ff9900", "#109618", "#990099", "#0099c6", "#dd4477", "#66aa00"]
36
+ palette: [
37
+ "#3366cc",
38
+ "#dc3912",
39
+ "#ff9900",
40
+ "#109618",
41
+ "#990099",
42
+ "#0099c6",
43
+ "#dd4477",
44
+ "#66aa00"
45
+ ]
37
46
  };
38
47
  var DARK_THEME = {
39
48
  ...LIGHT_THEME,
@@ -43,15 +52,34 @@ var DARK_THEME = {
43
52
  surfaceColor: "#1f2937",
44
53
  borderColor: "#374151",
45
54
  primaryColor: "#60a5fa",
46
- palette: ["#60a5fa", "#f87171", "#fbbf24", "#34d399", "#c084fc", "#22d3ee", "#f472b6", "#a3e635"]
55
+ palette: [
56
+ "#60a5fa",
57
+ "#f87171",
58
+ "#fbbf24",
59
+ "#34d399",
60
+ "#c084fc",
61
+ "#22d3ee",
62
+ "#f472b6",
63
+ "#a3e635"
64
+ ]
47
65
  };
48
66
  function defaultOptions(manifest) {
49
67
  const options = {};
50
- for (const option of manifest.options) options[option.id] = option.default;
68
+ for (const option of manifest.options)
69
+ options[option.id] = option.default;
51
70
  return options;
52
71
  }
53
72
  function generateSampleData(manifest) {
54
- const labels = ["North", "South", "East", "West", "Central", "Coast", "Island", "Valley"];
73
+ const labels = [
74
+ "North",
75
+ "South",
76
+ "East",
77
+ "West",
78
+ "Central",
79
+ "Coast",
80
+ "Island",
81
+ "Valley"
82
+ ];
55
83
  const columns = manifest.slots.map((slot, index) => ({
56
84
  id: `${slot.id}_${index}`,
57
85
  label: slot.label,
@@ -64,7 +92,9 @@ function generateSampleData(manifest) {
64
92
  const type = slot.types[0];
65
93
  if (type === "string") return `${label}${column > 0 ? ` ${column}` : ""}`;
66
94
  if (type === "boolean") return (row + column) % 2 === 0;
67
- return Math.round(1e3 - row * 97 + column * 53 + (row * 31 + column * 17) % 90);
95
+ return Math.round(
96
+ 1e3 - row * 97 + column * 53 + (row * 31 + column * 17) % 90
97
+ );
68
98
  })
69
99
  );
70
100
  return { columns, rows };
@@ -161,23 +191,37 @@ async function startDevServer(options) {
161
191
  const server = createServer(async (req, res) => {
162
192
  const url = new URL(req.url ?? "/", "http://127.0.0.1");
163
193
  const json = (status, body) => {
164
- res.writeHead(status, { "Content-Type": "application/json; charset=utf-8", "Cache-Control": "no-store" });
194
+ res.writeHead(status, {
195
+ "Content-Type": "application/json; charset=utf-8",
196
+ "Cache-Control": "no-store"
197
+ });
165
198
  res.end(JSON.stringify(body));
166
199
  };
167
200
  try {
168
201
  if (url.pathname === "/") {
169
- res.writeHead(200, { "Content-Type": "text/html; charset=utf-8", "Cache-Control": "no-store" });
202
+ res.writeHead(200, {
203
+ "Content-Type": "text/html; charset=utf-8",
204
+ "Cache-Control": "no-store"
205
+ });
170
206
  res.end(PAGE);
171
207
  return;
172
208
  }
173
209
  if (url.pathname === "/bundle.js") {
174
210
  const result = await buildProject(options.dir, { write: false });
175
211
  if (!result.ok || !result.outputs) {
176
- res.writeHead(422, { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" });
177
- res.end(result.problems.map((p) => `${p.path || "/"} ${p.code} ${p.message}`).join("\n"));
212
+ res.writeHead(422, {
213
+ "Content-Type": "text/plain; charset=utf-8",
214
+ "Cache-Control": "no-store"
215
+ });
216
+ res.end(
217
+ result.problems.map((p) => `${p.path || "/"} ${p.code} ${p.message}`).join("\n")
218
+ );
178
219
  return;
179
220
  }
180
- res.writeHead(200, { "Content-Type": "text/javascript; charset=utf-8", "Cache-Control": "no-store" });
221
+ res.writeHead(200, {
222
+ "Content-Type": "text/javascript; charset=utf-8",
223
+ "Cache-Control": "no-store"
224
+ });
181
225
  res.end(result.outputs.bundleJs);
182
226
  return;
183
227
  }
@@ -197,7 +241,10 @@ async function startDevServer(options) {
197
241
  return;
198
242
  }
199
243
  if (url.pathname === "/index.css") {
200
- res.writeHead(200, { "Content-Type": "text/css; charset=utf-8", "Cache-Control": "no-store" });
244
+ res.writeHead(200, {
245
+ "Content-Type": "text/css; charset=utf-8",
246
+ "Cache-Control": "no-store"
247
+ });
201
248
  res.end(project.css ?? "");
202
249
  return;
203
250
  }
@@ -267,10 +314,12 @@ function parseArgs(argv) {
267
314
  return { positional, flags };
268
315
  }
269
316
  var out = (line) => {
270
- process.stdout.write(redactSecrets(line) + "\n");
317
+ process.stdout.write(`${redactSecrets(line)}
318
+ `);
271
319
  };
272
320
  var err = (line) => {
273
- process.stderr.write(redactSecrets(line) + "\n");
321
+ process.stderr.write(`${redactSecrets(line)}
322
+ `);
274
323
  };
275
324
  function formatProblemLines(problems) {
276
325
  return problems.map((p) => `${p.path || "/"} ${p.code} ${p.message}`);
@@ -285,7 +334,9 @@ function keyFromDir(dir) {
285
334
  }
286
335
  function nameFromKey(key) {
287
336
  const words = key.split(/[-_]+/).filter(Boolean);
288
- return words.map((word, index) => index === 0 ? word[0].toUpperCase() + word.slice(1) : word).join(" ");
337
+ return words.map(
338
+ (word, index) => index === 0 ? word[0].toUpperCase() + word.slice(1) : word
339
+ ).join(" ");
289
340
  }
290
341
  function commandInit(args) {
291
342
  const dir = args.positional[0];
@@ -324,26 +375,34 @@ function commandValidate(args) {
324
375
  const dir = resolve(args.positional[0] ?? ".");
325
376
  const result = validateProject(dir);
326
377
  if (!result.ok) {
327
- err(`${result.problems.length} problem${result.problems.length === 1 ? "" : "s"} in ${dir}:`);
378
+ err(
379
+ `${result.problems.length} problem${result.problems.length === 1 ? "" : "s"} in ${dir}:`
380
+ );
328
381
  printProblems(result.problems);
329
382
  return 1;
330
383
  }
331
384
  const manifest = result.project.manifest;
332
- out(`Valid: custom:${manifest.id} (${manifest.slots.length} slots, ${manifest.options.length} options) in ${dir}`);
385
+ out(
386
+ `Valid: custom:${manifest.id} (${manifest.slots.length} slots, ${manifest.options.length} options) in ${dir}`
387
+ );
333
388
  return 0;
334
389
  }
335
390
  async function commandBuild(args) {
336
391
  const dir = resolve(args.positional[0] ?? ".");
337
392
  const result = await buildProject(dir);
338
393
  if (!result.ok || !result.outputs) {
339
- err(`Build failed with ${result.problems.length} problem${result.problems.length === 1 ? "" : "s"}:`);
394
+ err(
395
+ `Build failed with ${result.problems.length} problem${result.problems.length === 1 ? "" : "s"}:`
396
+ );
340
397
  printProblems(result.problems);
341
398
  return 1;
342
399
  }
343
400
  out(`Built custom:${result.outputs.manifest.id}`);
344
401
  for (const path of result.written) out(` ${path}`);
345
402
  out(` contentHash ${result.outputs.contentHash}`);
346
- out(` size ${result.outputs.sizeBytes} bytes (bundle ${Buffer.byteLength(result.outputs.bundleJs, "utf8")} of 2097152)`);
403
+ out(
404
+ ` size ${result.outputs.sizeBytes} bytes (bundle ${Buffer.byteLength(result.outputs.bundleJs, "utf8")} of 2097152)`
405
+ );
347
406
  return 0;
348
407
  }
349
408
  async function confirm(question) {
@@ -352,7 +411,9 @@ async function confirm(question) {
352
411
  return false;
353
412
  }
354
413
  const rl = createInterface({ input: process.stdin, output: process.stdout });
355
- const answer = await new Promise((resolveAnswer) => rl.question(question, resolveAnswer));
414
+ const answer = await new Promise(
415
+ (resolveAnswer) => rl.question(question, resolveAnswer)
416
+ );
356
417
  rl.close();
357
418
  return answer.trim().toLowerCase() === "y" || answer.trim().toLowerCase() === "yes";
358
419
  }
@@ -360,12 +421,15 @@ async function commandUpload(args) {
360
421
  const dir = resolve(args.positional[0] ?? ".");
361
422
  const serviceToken = process.env.DATABRAIN_SERVICE_TOKEN;
362
423
  if (!serviceToken) {
363
- err("DATABRAIN_SERVICE_TOKEN is not set. Create one in Settings > Service Tokens and export it, then try again.");
424
+ err(
425
+ "DATABRAIN_SERVICE_TOKEN is not set. Create one in Settings > Service Tokens and export it, then try again."
426
+ );
364
427
  return 1;
365
428
  }
366
429
  registerSecret(serviceToken);
367
430
  const apiUrl = process.env.DATABRAIN_API_URL || "https://api.usedatabrain.com";
368
- if (!process.env.DATABRAIN_API_URL) out(`DATABRAIN_API_URL is not set, using ${apiUrl}`);
431
+ if (!process.env.DATABRAIN_API_URL)
432
+ out(`DATABRAIN_API_URL is not set, using ${apiUrl}`);
369
433
  const built = await buildProject(dir);
370
434
  if (!built.ok || !built.outputs) {
371
435
  err("Build failed:");
@@ -374,11 +438,22 @@ async function commandUpload(args) {
374
438
  }
375
439
  const { manifest, bundleJs, bundleCss, iconSvg } = built.outputs;
376
440
  const key = manifest.id;
377
- out(`Built custom:${key} (${built.outputs.contentHash.slice(0, 12)}, ${built.outputs.sizeBytes} bytes)`);
378
- const client = new DatabrainClient({ serviceToken, apiUrl, demoDomain: "https://demo.usedatabrain.com" });
441
+ out(
442
+ `Built custom:${key} (${built.outputs.contentHash.slice(0, 12)}, ${built.outputs.sizeBytes} bytes)`
443
+ );
444
+ const client = new DatabrainClient({
445
+ serviceToken,
446
+ apiUrl,
447
+ demoDomain: "https://demo.usedatabrain.com"
448
+ });
379
449
  const api = createCustomChartsApi(client);
380
450
  try {
381
- const validation = await api.validate({ manifest, bundleJs, bundleCss, iconSvg });
451
+ const validation = await api.validate({
452
+ manifest,
453
+ bundleJs,
454
+ bundleCss,
455
+ iconSvg
456
+ });
382
457
  if (!validation.ok) {
383
458
  err("The server refused the bundle:");
384
459
  printProblems(validation.problems);
@@ -388,7 +463,10 @@ async function commandUpload(args) {
388
463
  const existing = (await api.list()).find((chart) => chart.key === key);
389
464
  const plan = planUpload(key, existing);
390
465
  out(`Plan: ${plan.summary}`);
391
- if (args.flags.publish === true) out("Then: publish that version (every dashboard using this key will render it).");
466
+ if (args.flags.publish === true)
467
+ out(
468
+ "Then: publish that version (every dashboard using this key will render it)."
469
+ );
392
470
  if (args.flags.yes !== true) {
393
471
  const go = await confirm("Continue? [y/N] ");
394
472
  if (!go) {
@@ -396,21 +474,37 @@ async function commandUpload(args) {
396
474
  return 1;
397
475
  }
398
476
  }
399
- const uploaded = await api.upload({ manifest, bundleJs, bundleCss, iconSvg });
477
+ const uploaded = await api.upload({
478
+ manifest,
479
+ bundleJs,
480
+ bundleCss,
481
+ iconSvg
482
+ });
400
483
  const versionNumber = uploaded.version?.versionNumber ?? "?";
401
- if (uploaded.created === "none") out(`This exact bundle is already v${versionNumber} of custom:${key}.`);
402
- else if (uploaded.created === "chart") out(`Created custom:${key} (v${versionNumber}, private).`);
403
- else out(`Uploaded v${versionNumber} of custom:${key}. It is in preview until you publish it.`);
484
+ if (uploaded.created === "none")
485
+ out(`This exact bundle is already v${versionNumber} of custom:${key}.`);
486
+ else if (uploaded.created === "chart")
487
+ out(`Created custom:${key} (v${versionNumber}, private).`);
488
+ else
489
+ out(
490
+ `Uploaded v${versionNumber} of custom:${key}. It is in preview until you publish it.`
491
+ );
404
492
  if (args.flags.publish === true) {
405
493
  const published = await api.publish(key, uploaded.version?.id);
406
- out(`Published v${versionNumber} of custom:${key} (status ${published.chart?.status ?? "published"}).`);
494
+ out(
495
+ `Published v${versionNumber} of custom:${key} (status ${published.chart?.status ?? "published"}).`
496
+ );
407
497
  } else if (uploaded.created !== "none") {
408
- out(`Publish it with: databrain custom-chart upload --publish, the publish_custom_chart tool, or Settings > Developers > Custom charts.`);
498
+ out(
499
+ `Publish it with: databrain custom-chart upload --publish, the publish_custom_chart tool, or Settings > Developers > Custom charts.`
500
+ );
409
501
  }
410
502
  return 0;
411
503
  } catch (error) {
412
504
  if (error instanceof DatabrainApiError) {
413
- err(`Error ${error.status || ""} ${error.code}: ${error.message}`.replace(/\s+/g, " ").trim());
505
+ err(
506
+ `Error ${error.status || ""} ${error.code}: ${error.message}`.replace(/\s+/g, " ").trim()
507
+ );
414
508
  printProblems(apiProblems(error));
415
509
  return 1;
416
510
  }
@@ -432,7 +526,9 @@ async function commandDev(args) {
432
526
  return 1;
433
527
  }
434
528
  const server = await startDevServer({ dir, port });
435
- out(`Custom chart dev page: http://127.0.0.1:${server.port}/ (Ctrl+C to stop)`);
529
+ out(
530
+ `Custom chart dev page: http://127.0.0.1:${server.port}/ (Ctrl+C to stop)`
531
+ );
436
532
  out("The page rebuilds on every reload. Edit chart.ts, save, reload.");
437
533
  await new Promise((resolveDone) => {
438
534
  const stop = () => {
@@ -473,7 +569,9 @@ async function runCli(argv) {
473
569
  case "dev":
474
570
  return commandDev(sub);
475
571
  default:
476
- err(command ? `Unknown custom-chart command "${command}".` : "custom-chart needs a command.");
572
+ err(
573
+ command ? `Unknown custom-chart command "${command}".` : "custom-chart needs a command."
574
+ );
477
575
  out(USAGE);
478
576
  return 1;
479
577
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli/index.ts","../src/cli/dev-server.ts"],"sourcesContent":["import { existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs';\nimport { basename, join, resolve } from 'node:path';\nimport { createInterface } from 'node:readline';\nimport { DatabrainClient } from '../client/databrain-client.js';\nimport { buildProject, validateProject } from '../custom-chart/bundle.js';\nimport { apiProblems, createCustomChartsApi, planUpload } from '../custom-chart/api.js';\nimport { scaffoldProject } from '../custom-chart/scaffold.js';\nimport type { Problem } from '../custom-chart/types.js';\nimport { DatabrainApiError } from '../utils/errors.js';\nimport { redactSecrets, registerSecret } from '../utils/logger.js';\nimport { MCP_SERVER_VERSION } from '../version.js';\nimport { startDevServer } from './dev-server.js';\n\n/**\n * The `databrain` bin (DAT-925). One command family today: custom-chart.\n * Output is for people: short lines, problems as `path code message`,\n * exit code 0 on success and 1 on any problem.\n */\n\nconst USAGE = `databrain ${MCP_SERVER_VERSION}\n\nUsage:\n databrain custom-chart init <dir> [--key <key>] [--name <name>] [--force]\n databrain custom-chart validate [dir]\n databrain custom-chart build [dir]\n databrain custom-chart upload [dir] [--publish] [--yes]\n databrain custom-chart dev [dir] [--port <port>]\n\nCommands:\n init Create a chart project from the template (manifest.json, chart.ts, chart.css, icon.svg, guide).\n validate Check manifest.json, icon.svg and chart.css against the rules. No build.\n build Compile chart.ts with esbuild and write dist/index.js, manifest.json, icon.svg, index.css, bundle.zip.\n upload Build, validate on the server, show the plan, then upload as a private chart or a preview version.\n Needs DATABRAIN_SERVICE_TOKEN (and DATABRAIN_API_URL for self hosted). --publish publishes it.\n dev Serve dist/index.js with sample-data.json in a local sandbox page for a quick look.\n\nOptions:\n --yes Skip the confirmation prompt on upload.\n --publish Publish the uploaded version right away.\n --force Let init write into a folder that is not empty.\n --help Show this help.\n --version Show the version.\n`;\n\ninterface ParsedArgs {\n positional: string[];\n flags: Record<string, string | boolean>;\n}\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const positional: string[] = [];\n const flags: Record<string, string | boolean> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg.startsWith('--')) {\n const [name, inlineValue] = arg.slice(2).split('=', 2);\n if (inlineValue !== undefined) {\n flags[name] = inlineValue;\n } else if (['key', 'name', 'port'].includes(name) && i + 1 < argv.length && !argv[i + 1].startsWith('--')) {\n flags[name] = argv[++i];\n } else {\n flags[name] = true;\n }\n } else {\n positional.push(arg);\n }\n }\n return { positional, flags };\n}\n\n// The service token must never reach a terminal or a CI log, wherever it is\n// quoted from (a server error body that echoes the Authorization header, a\n// wrapped fetch error, a problem message). It is registered with the logger\n// in commandUpload; every line printed here is scrubbed the same way.\nconst out = (line: string): void => {\n process.stdout.write(redactSecrets(line) + '\\n');\n};\nconst err = (line: string): void => {\n process.stderr.write(redactSecrets(line) + '\\n');\n};\n\nexport function formatProblemLines(problems: Problem[]): string[] {\n return problems.map((p) => `${p.path || '/'} ${p.code} ${p.message}`);\n}\n\nfunction printProblems(problems: Problem[]): void {\n for (const line of formatProblemLines(problems)) err(line);\n}\n\nfunction keyFromDir(dir: string): string {\n const raw = basename(resolve(dir)).toLowerCase().replace(/[^a-z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');\n const key = raw.length === 0 ? 'my-chart' : /^[a-z]/.test(raw) ? raw : `chart-${raw}`;\n return key.slice(0, 64);\n}\n\nfunction nameFromKey(key: string): string {\n const words = key.split(/[-_]+/).filter(Boolean);\n return words.map((word, index) => (index === 0 ? word[0].toUpperCase() + word.slice(1) : word)).join(' ');\n}\n\nfunction commandInit(args: ParsedArgs): number {\n const dir = args.positional[0];\n if (!dir) {\n err('init needs a folder: databrain custom-chart init <dir>');\n return 1;\n }\n const target = resolve(dir);\n if (existsSync(target) && readdirSync(target).length > 0 && args.flags.force !== true) {\n err(`${target} is not empty. Pick another folder or pass --force.`);\n return 1;\n }\n const key = typeof args.flags.key === 'string' ? args.flags.key : keyFromDir(target);\n const name = typeof args.flags.name === 'string' ? args.flags.name : nameFromKey(key);\n const result = scaffoldProject({ key, name });\n if (!result.ok) {\n printProblems(result.problems);\n return 1;\n }\n mkdirSync(target, { recursive: true });\n for (const [file, content] of Object.entries(result.files)) {\n writeFileSync(join(target, file), content);\n }\n out(`Created chart project ${key} in ${target}`);\n for (const file of Object.keys(result.files)) out(` ${file}`);\n out('');\n out('Next:');\n out(` cd ${dir}`);\n out(' edit chart.ts (read AGENTS.md first)');\n out(' databrain custom-chart validate');\n out(' databrain custom-chart build');\n out(' databrain custom-chart upload');\n return 0;\n}\n\nfunction commandValidate(args: ParsedArgs): number {\n const dir = resolve(args.positional[0] ?? '.');\n const result = validateProject(dir);\n if (!result.ok) {\n err(`${result.problems.length} problem${result.problems.length === 1 ? '' : 's'} in ${dir}:`);\n printProblems(result.problems);\n return 1;\n }\n const manifest = result.project.manifest as { id: string; slots: unknown[]; options: unknown[] };\n out(`Valid: custom:${manifest.id} (${manifest.slots.length} slots, ${manifest.options.length} options) in ${dir}`);\n return 0;\n}\n\nasync function commandBuild(args: ParsedArgs): Promise<number> {\n const dir = resolve(args.positional[0] ?? '.');\n const result = await buildProject(dir);\n if (!result.ok || !result.outputs) {\n err(`Build failed with ${result.problems.length} problem${result.problems.length === 1 ? '' : 's'}:`);\n printProblems(result.problems);\n return 1;\n }\n out(`Built custom:${result.outputs.manifest.id}`);\n for (const path of result.written) out(` ${path}`);\n out(` contentHash ${result.outputs.contentHash}`);\n out(` size ${result.outputs.sizeBytes} bytes (bundle ${Buffer.byteLength(result.outputs.bundleJs, 'utf8')} of 2097152)`);\n return 0;\n}\n\nasync function confirm(question: string): Promise<boolean> {\n if (!process.stdin.isTTY) {\n err('stdin is not a terminal. Pass --yes to upload without a prompt.');\n return false;\n }\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolveAnswer) => rl.question(question, resolveAnswer));\n rl.close();\n return answer.trim().toLowerCase() === 'y' || answer.trim().toLowerCase() === 'yes';\n}\n\nasync function commandUpload(args: ParsedArgs): Promise<number> {\n const dir = resolve(args.positional[0] ?? '.');\n const serviceToken = process.env.DATABRAIN_SERVICE_TOKEN;\n if (!serviceToken) {\n err('DATABRAIN_SERVICE_TOKEN is not set. Create one in Settings > Service Tokens and export it, then try again.');\n return 1;\n }\n registerSecret(serviceToken);\n const apiUrl = process.env.DATABRAIN_API_URL || 'https://api.usedatabrain.com';\n if (!process.env.DATABRAIN_API_URL) out(`DATABRAIN_API_URL is not set, using ${apiUrl}`);\n\n const built = await buildProject(dir);\n if (!built.ok || !built.outputs) {\n err('Build failed:');\n printProblems(built.problems);\n return 1;\n }\n const { manifest, bundleJs, bundleCss, iconSvg } = built.outputs;\n const key = manifest.id;\n out(`Built custom:${key} (${built.outputs.contentHash.slice(0, 12)}, ${built.outputs.sizeBytes} bytes)`);\n\n const client = new DatabrainClient({ serviceToken, apiUrl, demoDomain: 'https://demo.usedatabrain.com' });\n const api = createCustomChartsApi(client);\n try {\n const validation = await api.validate({ manifest, bundleJs, bundleCss, iconSvg });\n if (!validation.ok) {\n err('The server refused the bundle:');\n printProblems(validation.problems);\n return 1;\n }\n out('Server validation: ok');\n const existing = (await api.list()).find((chart) => chart.key === key);\n const plan = planUpload(key, existing);\n out(`Plan: ${plan.summary}`);\n if (args.flags.publish === true) out('Then: publish that version (every dashboard using this key will render it).');\n\n if (args.flags.yes !== true) {\n const go = await confirm('Continue? [y/N] ');\n if (!go) {\n out('Cancelled. Nothing was uploaded.');\n return 1;\n }\n }\n\n const uploaded = await api.upload({ manifest, bundleJs, bundleCss, iconSvg });\n const versionNumber = uploaded.version?.versionNumber ?? '?';\n if (uploaded.created === 'none') out(`This exact bundle is already v${versionNumber} of custom:${key}.`);\n else if (uploaded.created === 'chart') out(`Created custom:${key} (v${versionNumber}, private).`);\n else out(`Uploaded v${versionNumber} of custom:${key}. It is in preview until you publish it.`);\n\n if (args.flags.publish === true) {\n const published = await api.publish(key, uploaded.version?.id);\n out(`Published v${versionNumber} of custom:${key} (status ${published.chart?.status ?? 'published'}).`);\n } else if (uploaded.created !== 'none') {\n out(`Publish it with: databrain custom-chart upload --publish, the publish_custom_chart tool, or Settings > Developers > Custom charts.`);\n }\n return 0;\n } catch (error) {\n if (error instanceof DatabrainApiError) {\n err(`Error ${error.status || ''} ${error.code}: ${error.message}`.replace(/\\s+/g, ' ').trim());\n printProblems(apiProblems(error));\n return 1;\n }\n err(`Unexpected error: ${(error as Error).message}`);\n return 1;\n }\n}\n\nasync function commandDev(args: ParsedArgs): Promise<number> {\n const dir = resolve(args.positional[0] ?? '.');\n const port = typeof args.flags.port === 'string' ? Number(args.flags.port) : 4174;\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n err('--port must be a number between 1 and 65535.');\n return 1;\n }\n const built = await buildProject(dir);\n if (!built.ok) {\n err('Build failed:');\n printProblems(built.problems);\n return 1;\n }\n const server = await startDevServer({ dir, port });\n out(`Custom chart dev page: http://127.0.0.1:${server.port}/ (Ctrl+C to stop)`);\n out('The page rebuilds on every reload. Edit chart.ts, save, reload.');\n await new Promise<void>((resolveDone) => {\n const stop = () => {\n server.close();\n resolveDone();\n };\n process.once('SIGINT', stop);\n process.once('SIGTERM', stop);\n });\n return 0;\n}\n\nexport async function runCli(argv: string[]): Promise<number> {\n const args = parseArgs(argv);\n if (args.flags.version === true) {\n out(MCP_SERVER_VERSION);\n return 0;\n }\n const [family, command, ...rest] = args.positional;\n if (args.flags.help === true || !family) {\n out(USAGE);\n return family ? 0 : 1;\n }\n if (family !== 'custom-chart') {\n err(`Unknown command \"${family}\".`);\n out(USAGE);\n return 1;\n }\n const sub: ParsedArgs = { positional: rest, flags: args.flags };\n switch (command) {\n case 'init':\n return commandInit(sub);\n case 'validate':\n return commandValidate(sub);\n case 'build':\n return commandBuild(sub);\n case 'upload':\n return commandUpload(sub);\n case 'dev':\n return commandDev(sub);\n default:\n err(command ? `Unknown custom-chart command \"${command}\".` : 'custom-chart needs a command.');\n out(USAGE);\n return 1;\n }\n}\n\nconst invokedDirectly =\n typeof process.argv[1] === 'string' && /(^|[\\\\/])(cli\\.(js|mjs|ts)|databrain)$/.test(process.argv[1]);\nif (invokedDirectly) {\n runCli(process.argv.slice(2)).then(\n (code) => {\n process.exitCode = code;\n },\n (error: Error) => {\n err(`Unexpected error: ${error.message}`);\n process.exitCode = 1;\n },\n );\n}\n","import { createServer, type Server } from 'node:http';\nimport { buildProject, readProject } from '../custom-chart/bundle.js';\nimport type { CustomChartManifest, CustomChartOption } from '../custom-chart/types.js';\n\n/**\n * `databrain custom-chart dev`: a local page that hosts dist/index.js the way\n * the product does, in a sandboxed frame that only sees the sandbox protocol.\n * It is a tiny copy of the plugin relay, enough to see the chart draw, click\n * and resize with sample-data.json. Like the product host it injects\n * chart.css into the frame; the bundle itself carries no css. It is not the\n * product sandbox: no CSP, no relay frame, no limits. Never point it at real\n * data.\n */\nexport interface DevServerOptions {\n dir: string;\n port: number;\n}\n\nconst LIGHT_THEME = {\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSize: 12,\n textColor: '#1f2937',\n textSecondaryColor: '#6b7280',\n background: '#ffffff',\n surfaceColor: '#f9fafb',\n borderColor: '#e5e7eb',\n borderRadius: 6,\n primaryColor: '#3366cc',\n palette: ['#3366cc', '#dc3912', '#ff9900', '#109618', '#990099', '#0099c6', '#dd4477', '#66aa00'],\n};\n\nconst DARK_THEME = {\n ...LIGHT_THEME,\n textColor: '#f3f4f6',\n textSecondaryColor: '#9ca3af',\n background: '#111827',\n surfaceColor: '#1f2937',\n borderColor: '#374151',\n primaryColor: '#60a5fa',\n palette: ['#60a5fa', '#f87171', '#fbbf24', '#34d399', '#c084fc', '#22d3ee', '#f472b6', '#a3e635'],\n};\n\nfunction defaultOptions(manifest: CustomChartManifest): Record<string, string | number | boolean> {\n const options: Record<string, string | number | boolean> = {};\n for (const option of manifest.options as CustomChartOption[]) options[option.id] = option.default;\n return options;\n}\n\n/** Deterministic sample data from the manifest slots when sample-data.json is absent. */\nfunction generateSampleData(manifest: CustomChartManifest): { columns: unknown[]; rows: unknown[][] } {\n const labels = ['North', 'South', 'East', 'West', 'Central', 'Coast', 'Island', 'Valley'];\n const columns = manifest.slots.map((slot, index) => ({\n id: `${slot.id}_${index}`,\n label: slot.label,\n type: slot.types[0],\n filterable: slot.role === 'dimension',\n slotId: slot.id,\n }));\n const rows = labels.map((label, row) =>\n manifest.slots.map((slot, column) => {\n const type = slot.types[0];\n if (type === 'string') return `${label}${column > 0 ? ` ${column}` : ''}`;\n if (type === 'boolean') return (row + column) % 2 === 0;\n return Math.round(1000 - row * 97 + column * 53 + ((row * 31 + column * 17) % 90));\n }),\n );\n return { columns, rows };\n}\n\nconst PAGE = `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Custom chart dev</title>\n<style>\n :root { color-scheme: light dark; }\n body { margin: 0; font: 14px system-ui, sans-serif; display: grid; grid-template-rows: auto 1fr; height: 100vh; }\n header { display: flex; gap: 12px; align-items: center; padding: 10px 16px; border-bottom: 1px solid #8884; }\n header code { font-size: 12px; opacity: 0.8; }\n main { display: grid; grid-template-columns: 1fr 320px; min-height: 0; }\n #stage { padding: 16px; display: flex; align-items: flex-start; justify-content: center; overflow: auto; }\n #frame { border: 1px solid #8886; border-radius: 8px; background: transparent; }\n aside { border-left: 1px solid #8884; padding: 12px 16px; overflow: auto; }\n aside h2 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; margin: 0 0 8px; opacity: 0.7; }\n #log { font: 12px ui-monospace, monospace; white-space: pre-wrap; margin: 0; }\n select, button { font: inherit; }\n</style>\n</head>\n<body>\n<header>\n <strong id=\"title\">Custom chart</strong>\n <code id=\"key\"></code>\n <label>Theme <select id=\"theme\"><option value=\"light\">light</option><option value=\"dark\">dark</option></select></label>\n <label>Size <select id=\"size\"><option value=\"600x320\">600 x 320</option><option value=\"900x420\">900 x 420</option><option value=\"320x240\">320 x 240</option></select></label>\n <button id=\"reload\">Rebuild and reload</button>\n</header>\n<main>\n <div id=\"stage\"><iframe id=\"frame\" sandbox=\"allow-scripts\" width=\"600\" height=\"320\" title=\"Custom chart\"></iframe></div>\n <aside><h2>Events</h2><pre id=\"log\">Waiting for ready...</pre></aside>\n</main>\n<script>\n(async () => {\n const log = document.getElementById('log');\n const frame = document.getElementById('frame');\n const themeSelect = document.getElementById('theme');\n const sizeSelect = document.getElementById('size');\n const say = (line) => { log.textContent = (line + '\\\\n' + log.textContent).slice(0, 8000); };\n const [manifest, bundle, sample, themes, css] = await Promise.all([\n fetch('/manifest.json').then((r) => r.json()),\n fetch('/bundle.js').then((r) => r.ok ? r.text() : r.text().then((t) => { throw new Error(t); })).catch((e) => { say('BUILD ERROR\\\\n' + e.message); return null; }),\n fetch('/sample-data.json').then((r) => r.json()),\n fetch('/themes.json').then((r) => r.json()),\n fetch('/index.css').then((r) => r.text()),\n ]);\n document.getElementById('title').textContent = manifest.name;\n document.getElementById('key').textContent = 'custom:' + manifest.id;\n if (!bundle) return;\n let revision = 0;\n const data = () => ({\n columns: sample.columns, rows: sample.rows,\n options: Object.assign({}, sample.defaults, sample.options || {}),\n theme: themes[themeSelect.value], language: 'en'\n });\n const send = () => frame.contentWindow.postMessage({ protocol: 'dbn-chart-sandbox', version: 1, channel: 'dev', type: 'data', revision: ++revision, data: data() }, '*');\n addEventListener('message', (event) => {\n if (event.source !== frame.contentWindow) return;\n const m = event.data || {};\n if (m.type === 'ready') { say('ready'); send(); return; }\n if (m.type === 'resize' && Number.isFinite(m.height)) frame.height = Math.max(80, Math.min(1200, m.height));\n say(m.type + ' ' + JSON.stringify(m, (k, v) => (k === 'protocol' || k === 'version' || k === 'channel' || k === 'type') ? undefined : v));\n });\n const boot = '(' + (function () {\n var channel = 'dev'; var revision = -1; var latest = null; var listener = null;\n var send = function (payload) { parent.postMessage(Object.assign({ protocol: 'dbn-chart-sandbox', version: 1, channel: channel }, payload), '*'); };\n window.dbnSandbox = Object.freeze({\n onData: function (cb) { listener = cb; send({ type: 'ready' }); if (latest) cb(latest); },\n click: function (rowIndex, columnId) { send({ type: 'click', revision: revision, rowIndex: rowIndex, columnId: columnId }); },\n filter: function (columnId, values) { send({ type: 'filter', revision: revision, columnId: columnId, values: values }); },\n resize: function (height) { send({ type: 'resize', height: height }); }\n });\n addEventListener('error', function (e) { send({ type: 'error', code: 'runtime', message: String(e.message || e) }); });\n addEventListener('message', function (event) {\n var m = event.data; if (!m || m.type !== 'data' || m.revision <= revision) return;\n revision = m.revision; latest = m.data; if (listener) listener(latest);\n });\n }).toString() + ')();';\n const child = '<!doctype html><html><head><meta charset=\"utf-8\"><style>html,body{margin:0;width:100%;height:100%;overflow:hidden}body{font:14px system-ui}#chart{width:100%;height:100%}</style><style>' + css.replace(/<\\\\/style/gi, '') + '</style></head><body><div id=\"chart\"></div><script>' + boot + '<\\\\/script><script>' + bundle.replace(/<\\\\/script/gi, '<\\\\\\\\/script') + '<\\\\/script></body></html>';\n const mount = () => { frame.srcdoc = child; };\n themeSelect.addEventListener('change', () => { if (revision > 0) send(); });\n sizeSelect.addEventListener('change', () => { const [w, h] = sizeSelect.value.split('x'); frame.width = w; frame.height = h; if (revision > 0) send(); });\n document.getElementById('reload').addEventListener('click', () => location.reload());\n mount();\n})();\n</script>\n</body>\n</html>\n`;\n\nexport async function startDevServer(options: DevServerOptions): Promise<{ port: number; close: () => void; server: Server }> {\n const server = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', 'http://127.0.0.1');\n const json = (status: number, body: unknown) => {\n res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8', 'Cache-Control': 'no-store' });\n res.end(JSON.stringify(body));\n };\n try {\n if (url.pathname === '/') {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8', 'Cache-Control': 'no-store' });\n res.end(PAGE);\n return;\n }\n if (url.pathname === '/bundle.js') {\n const result = await buildProject(options.dir, { write: false });\n if (!result.ok || !result.outputs) {\n res.writeHead(422, { 'Content-Type': 'text/plain; charset=utf-8', 'Cache-Control': 'no-store' });\n res.end(result.problems.map((p) => `${p.path || '/'} ${p.code} ${p.message}`).join('\\n'));\n return;\n }\n res.writeHead(200, { 'Content-Type': 'text/javascript; charset=utf-8', 'Cache-Control': 'no-store' });\n res.end(result.outputs.bundleJs);\n return;\n }\n const project = readProject(options.dir);\n const manifest = project.manifest as CustomChartManifest | undefined;\n if (url.pathname === '/manifest.json') {\n json(manifest ? 200 : 422, manifest ?? { problems: project.problems });\n return;\n }\n if (url.pathname === '/sample-data.json') {\n if (!manifest) {\n json(422, { problems: project.problems });\n return;\n }\n const sample = (project.sampleData as { columns?: unknown[]; rows?: unknown[][]; options?: unknown } | undefined) ?? generateSampleData(manifest);\n json(200, { ...sample, defaults: defaultOptions(manifest) });\n return;\n }\n if (url.pathname === '/index.css') {\n // The host injects bundleCss into the frame; this page plays the host.\n res.writeHead(200, { 'Content-Type': 'text/css; charset=utf-8', 'Cache-Control': 'no-store' });\n res.end(project.css ?? '');\n return;\n }\n if (url.pathname === '/themes.json') {\n json(200, { light: LIGHT_THEME, dark: DARK_THEME });\n return;\n }\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('not found');\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\n res.end((err as Error).message);\n }\n });\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(options.port, '127.0.0.1', () => resolve());\n });\n const address = server.address();\n const port = typeof address === 'object' && address ? address.port : options.port;\n return { port, server, close: () => server.close() };\n}\n"],"mappings":"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","names":["err","resolve"]}
1
+ {"version":3,"sources":["../src/cli/index.ts","../src/cli/dev-server.ts"],"sourcesContent":["import { existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs';\nimport { basename, join, resolve } from 'node:path';\nimport { createInterface } from 'node:readline';\nimport { DatabrainClient } from '../client/databrain-client.js';\nimport {\n apiProblems,\n createCustomChartsApi,\n planUpload,\n} from '../custom-chart/api.js';\nimport { buildProject, validateProject } from '../custom-chart/bundle.js';\nimport { scaffoldProject } from '../custom-chart/scaffold.js';\nimport type { Problem } from '../custom-chart/types.js';\nimport { DatabrainApiError } from '../utils/errors.js';\nimport { redactSecrets, registerSecret } from '../utils/logger.js';\nimport { MCP_SERVER_VERSION } from '../version.js';\nimport { startDevServer } from './dev-server.js';\n\n/**\n * The `databrain` bin (DAT-925). One command family today: custom-chart.\n * Output is for people: short lines, problems as `path code message`,\n * exit code 0 on success and 1 on any problem.\n */\n\nconst USAGE = `databrain ${MCP_SERVER_VERSION}\n\nUsage:\n databrain custom-chart init <dir> [--key <key>] [--name <name>] [--force]\n databrain custom-chart validate [dir]\n databrain custom-chart build [dir]\n databrain custom-chart upload [dir] [--publish] [--yes]\n databrain custom-chart dev [dir] [--port <port>]\n\nCommands:\n init Create a chart project from the template (manifest.json, chart.ts, chart.css, icon.svg, guide).\n validate Check manifest.json, icon.svg and chart.css against the rules. No build.\n build Compile chart.ts with esbuild and write dist/index.js, manifest.json, icon.svg, index.css, bundle.zip.\n upload Build, validate on the server, show the plan, then upload as a private chart or a preview version.\n Needs DATABRAIN_SERVICE_TOKEN (and DATABRAIN_API_URL for self hosted). --publish publishes it.\n dev Serve dist/index.js with sample-data.json in a local sandbox page for a quick look.\n\nOptions:\n --yes Skip the confirmation prompt on upload.\n --publish Publish the uploaded version right away.\n --force Let init write into a folder that is not empty.\n --help Show this help.\n --version Show the version.\n`;\n\ninterface ParsedArgs {\n positional: string[];\n flags: Record<string, string | boolean>;\n}\n\nfunction parseArgs(argv: string[]): ParsedArgs {\n const positional: string[] = [];\n const flags: Record<string, string | boolean> = {};\n for (let i = 0; i < argv.length; i++) {\n const arg = argv[i];\n if (arg.startsWith('--')) {\n const [name, inlineValue] = arg.slice(2).split('=', 2);\n if (inlineValue !== undefined) {\n flags[name] = inlineValue;\n } else if (\n ['key', 'name', 'port'].includes(name) &&\n i + 1 < argv.length &&\n !argv[i + 1].startsWith('--')\n ) {\n flags[name] = argv[++i];\n } else {\n flags[name] = true;\n }\n } else {\n positional.push(arg);\n }\n }\n return { positional, flags };\n}\n\n// The service token must never reach a terminal or a CI log, wherever it is\n// quoted from (a server error body that echoes the Authorization header, a\n// wrapped fetch error, a problem message). It is registered with the logger\n// in commandUpload; every line printed here is scrubbed the same way.\nconst out = (line: string): void => {\n process.stdout.write(`${redactSecrets(line)}\\n`);\n};\nconst err = (line: string): void => {\n process.stderr.write(`${redactSecrets(line)}\\n`);\n};\n\nexport function formatProblemLines(problems: Problem[]): string[] {\n return problems.map((p) => `${p.path || '/'} ${p.code} ${p.message}`);\n}\n\nfunction printProblems(problems: Problem[]): void {\n for (const line of formatProblemLines(problems)) err(line);\n}\n\nfunction keyFromDir(dir: string): string {\n const raw = basename(resolve(dir))\n .toLowerCase()\n .replace(/[^a-z0-9_-]+/g, '-')\n .replace(/^-+|-+$/g, '');\n const key =\n raw.length === 0 ? 'my-chart' : /^[a-z]/.test(raw) ? raw : `chart-${raw}`;\n return key.slice(0, 64);\n}\n\nfunction nameFromKey(key: string): string {\n const words = key.split(/[-_]+/).filter(Boolean);\n return words\n .map((word, index) =>\n index === 0 ? word[0].toUpperCase() + word.slice(1) : word\n )\n .join(' ');\n}\n\nfunction commandInit(args: ParsedArgs): number {\n const dir = args.positional[0];\n if (!dir) {\n err('init needs a folder: databrain custom-chart init <dir>');\n return 1;\n }\n const target = resolve(dir);\n if (\n existsSync(target) &&\n readdirSync(target).length > 0 &&\n args.flags.force !== true\n ) {\n err(`${target} is not empty. Pick another folder or pass --force.`);\n return 1;\n }\n const key =\n typeof args.flags.key === 'string' ? args.flags.key : keyFromDir(target);\n const name =\n typeof args.flags.name === 'string' ? args.flags.name : nameFromKey(key);\n const result = scaffoldProject({ key, name });\n if (!result.ok) {\n printProblems(result.problems);\n return 1;\n }\n mkdirSync(target, { recursive: true });\n for (const [file, content] of Object.entries(result.files)) {\n writeFileSync(join(target, file), content);\n }\n out(`Created chart project ${key} in ${target}`);\n for (const file of Object.keys(result.files)) out(` ${file}`);\n out('');\n out('Next:');\n out(` cd ${dir}`);\n out(' edit chart.ts (read AGENTS.md first)');\n out(' databrain custom-chart validate');\n out(' databrain custom-chart build');\n out(' databrain custom-chart upload');\n return 0;\n}\n\nfunction commandValidate(args: ParsedArgs): number {\n const dir = resolve(args.positional[0] ?? '.');\n const result = validateProject(dir);\n if (!result.ok) {\n err(\n `${result.problems.length} problem${result.problems.length === 1 ? '' : 's'} in ${dir}:`\n );\n printProblems(result.problems);\n return 1;\n }\n const manifest = result.project.manifest as {\n id: string;\n slots: unknown[];\n options: unknown[];\n };\n out(\n `Valid: custom:${manifest.id} (${manifest.slots.length} slots, ${manifest.options.length} options) in ${dir}`\n );\n return 0;\n}\n\nasync function commandBuild(args: ParsedArgs): Promise<number> {\n const dir = resolve(args.positional[0] ?? '.');\n const result = await buildProject(dir);\n if (!result.ok || !result.outputs) {\n err(\n `Build failed with ${result.problems.length} problem${result.problems.length === 1 ? '' : 's'}:`\n );\n printProblems(result.problems);\n return 1;\n }\n out(`Built custom:${result.outputs.manifest.id}`);\n for (const path of result.written) out(` ${path}`);\n out(` contentHash ${result.outputs.contentHash}`);\n out(\n ` size ${result.outputs.sizeBytes} bytes (bundle ${Buffer.byteLength(result.outputs.bundleJs, 'utf8')} of 2097152)`\n );\n return 0;\n}\n\nasync function confirm(question: string): Promise<boolean> {\n if (!process.stdin.isTTY) {\n err('stdin is not a terminal. Pass --yes to upload without a prompt.');\n return false;\n }\n const rl = createInterface({ input: process.stdin, output: process.stdout });\n const answer = await new Promise<string>((resolveAnswer) =>\n rl.question(question, resolveAnswer)\n );\n rl.close();\n return (\n answer.trim().toLowerCase() === 'y' || answer.trim().toLowerCase() === 'yes'\n );\n}\n\nasync function commandUpload(args: ParsedArgs): Promise<number> {\n const dir = resolve(args.positional[0] ?? '.');\n const serviceToken = process.env.DATABRAIN_SERVICE_TOKEN;\n if (!serviceToken) {\n err(\n 'DATABRAIN_SERVICE_TOKEN is not set. Create one in Settings > Service Tokens and export it, then try again.'\n );\n return 1;\n }\n registerSecret(serviceToken);\n const apiUrl =\n process.env.DATABRAIN_API_URL || 'https://api.usedatabrain.com';\n if (!process.env.DATABRAIN_API_URL)\n out(`DATABRAIN_API_URL is not set, using ${apiUrl}`);\n\n const built = await buildProject(dir);\n if (!built.ok || !built.outputs) {\n err('Build failed:');\n printProblems(built.problems);\n return 1;\n }\n const { manifest, bundleJs, bundleCss, iconSvg } = built.outputs;\n const key = manifest.id;\n out(\n `Built custom:${key} (${built.outputs.contentHash.slice(0, 12)}, ${built.outputs.sizeBytes} bytes)`\n );\n\n const client = new DatabrainClient({\n serviceToken,\n apiUrl,\n demoDomain: 'https://demo.usedatabrain.com',\n });\n const api = createCustomChartsApi(client);\n try {\n const validation = await api.validate({\n manifest,\n bundleJs,\n bundleCss,\n iconSvg,\n });\n if (!validation.ok) {\n err('The server refused the bundle:');\n printProblems(validation.problems);\n return 1;\n }\n out('Server validation: ok');\n const existing = (await api.list()).find((chart) => chart.key === key);\n const plan = planUpload(key, existing);\n out(`Plan: ${plan.summary}`);\n if (args.flags.publish === true)\n out(\n 'Then: publish that version (every dashboard using this key will render it).'\n );\n\n if (args.flags.yes !== true) {\n const go = await confirm('Continue? [y/N] ');\n if (!go) {\n out('Cancelled. Nothing was uploaded.');\n return 1;\n }\n }\n\n const uploaded = await api.upload({\n manifest,\n bundleJs,\n bundleCss,\n iconSvg,\n });\n const versionNumber = uploaded.version?.versionNumber ?? '?';\n if (uploaded.created === 'none')\n out(`This exact bundle is already v${versionNumber} of custom:${key}.`);\n else if (uploaded.created === 'chart')\n out(`Created custom:${key} (v${versionNumber}, private).`);\n else\n out(\n `Uploaded v${versionNumber} of custom:${key}. It is in preview until you publish it.`\n );\n\n if (args.flags.publish === true) {\n const published = await api.publish(key, uploaded.version?.id);\n out(\n `Published v${versionNumber} of custom:${key} (status ${published.chart?.status ?? 'published'}).`\n );\n } else if (uploaded.created !== 'none') {\n out(\n `Publish it with: databrain custom-chart upload --publish, the publish_custom_chart tool, or Settings > Developers > Custom charts.`\n );\n }\n return 0;\n } catch (error) {\n if (error instanceof DatabrainApiError) {\n err(\n `Error ${error.status || ''} ${error.code}: ${error.message}`\n .replace(/\\s+/g, ' ')\n .trim()\n );\n printProblems(apiProblems(error));\n return 1;\n }\n err(`Unexpected error: ${(error as Error).message}`);\n return 1;\n }\n}\n\nasync function commandDev(args: ParsedArgs): Promise<number> {\n const dir = resolve(args.positional[0] ?? '.');\n const port =\n typeof args.flags.port === 'string' ? Number(args.flags.port) : 4174;\n if (!Number.isInteger(port) || port < 1 || port > 65535) {\n err('--port must be a number between 1 and 65535.');\n return 1;\n }\n const built = await buildProject(dir);\n if (!built.ok) {\n err('Build failed:');\n printProblems(built.problems);\n return 1;\n }\n const server = await startDevServer({ dir, port });\n out(\n `Custom chart dev page: http://127.0.0.1:${server.port}/ (Ctrl+C to stop)`\n );\n out('The page rebuilds on every reload. Edit chart.ts, save, reload.');\n await new Promise<void>((resolveDone) => {\n const stop = () => {\n server.close();\n resolveDone();\n };\n process.once('SIGINT', stop);\n process.once('SIGTERM', stop);\n });\n return 0;\n}\n\nexport async function runCli(argv: string[]): Promise<number> {\n const args = parseArgs(argv);\n if (args.flags.version === true) {\n out(MCP_SERVER_VERSION);\n return 0;\n }\n const [family, command, ...rest] = args.positional;\n if (args.flags.help === true || !family) {\n out(USAGE);\n return family ? 0 : 1;\n }\n if (family !== 'custom-chart') {\n err(`Unknown command \"${family}\".`);\n out(USAGE);\n return 1;\n }\n const sub: ParsedArgs = { positional: rest, flags: args.flags };\n switch (command) {\n case 'init':\n return commandInit(sub);\n case 'validate':\n return commandValidate(sub);\n case 'build':\n return commandBuild(sub);\n case 'upload':\n return commandUpload(sub);\n case 'dev':\n return commandDev(sub);\n default:\n err(\n command\n ? `Unknown custom-chart command \"${command}\".`\n : 'custom-chart needs a command.'\n );\n out(USAGE);\n return 1;\n }\n}\n\nconst invokedDirectly =\n typeof process.argv[1] === 'string' &&\n /(^|[\\\\/])(cli\\.(js|mjs|ts)|databrain)$/.test(process.argv[1]);\nif (invokedDirectly) {\n runCli(process.argv.slice(2)).then(\n (code) => {\n process.exitCode = code;\n },\n (error: Error) => {\n err(`Unexpected error: ${error.message}`);\n process.exitCode = 1;\n }\n );\n}\n","import { createServer, type Server } from 'node:http';\nimport { buildProject, readProject } from '../custom-chart/bundle.js';\nimport type {\n CustomChartManifest,\n CustomChartOption,\n} from '../custom-chart/types.js';\n\n/**\n * `databrain custom-chart dev`: a local page that hosts dist/index.js the way\n * the product does, in a sandboxed frame that only sees the sandbox protocol.\n * It is a tiny copy of the plugin relay, enough to see the chart draw, click\n * and resize with sample-data.json. Like the product host it injects\n * chart.css into the frame; the bundle itself carries no css. It is not the\n * product sandbox: no CSP, no relay frame, no limits. Never point it at real\n * data.\n */\nexport interface DevServerOptions {\n dir: string;\n port: number;\n}\n\nconst LIGHT_THEME = {\n fontFamily: 'Inter, system-ui, sans-serif',\n fontSize: 12,\n textColor: '#1f2937',\n textSecondaryColor: '#6b7280',\n background: '#ffffff',\n surfaceColor: '#f9fafb',\n borderColor: '#e5e7eb',\n borderRadius: 6,\n primaryColor: '#3366cc',\n palette: [\n '#3366cc',\n '#dc3912',\n '#ff9900',\n '#109618',\n '#990099',\n '#0099c6',\n '#dd4477',\n '#66aa00',\n ],\n};\n\nconst DARK_THEME = {\n ...LIGHT_THEME,\n textColor: '#f3f4f6',\n textSecondaryColor: '#9ca3af',\n background: '#111827',\n surfaceColor: '#1f2937',\n borderColor: '#374151',\n primaryColor: '#60a5fa',\n palette: [\n '#60a5fa',\n '#f87171',\n '#fbbf24',\n '#34d399',\n '#c084fc',\n '#22d3ee',\n '#f472b6',\n '#a3e635',\n ],\n};\n\nfunction defaultOptions(\n manifest: CustomChartManifest\n): Record<string, string | number | boolean> {\n const options: Record<string, string | number | boolean> = {};\n for (const option of manifest.options as CustomChartOption[])\n options[option.id] = option.default;\n return options;\n}\n\n/** Deterministic sample data from the manifest slots when sample-data.json is absent. */\nfunction generateSampleData(manifest: CustomChartManifest): {\n columns: unknown[];\n rows: unknown[][];\n} {\n const labels = [\n 'North',\n 'South',\n 'East',\n 'West',\n 'Central',\n 'Coast',\n 'Island',\n 'Valley',\n ];\n const columns = manifest.slots.map((slot, index) => ({\n id: `${slot.id}_${index}`,\n label: slot.label,\n type: slot.types[0],\n filterable: slot.role === 'dimension',\n slotId: slot.id,\n }));\n const rows = labels.map((label, row) =>\n manifest.slots.map((slot, column) => {\n const type = slot.types[0];\n if (type === 'string') return `${label}${column > 0 ? ` ${column}` : ''}`;\n if (type === 'boolean') return (row + column) % 2 === 0;\n return Math.round(\n 1000 - row * 97 + column * 53 + ((row * 31 + column * 17) % 90)\n );\n })\n );\n return { columns, rows };\n}\n\nconst PAGE = `<!doctype html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Custom chart dev</title>\n<style>\n :root { color-scheme: light dark; }\n body { margin: 0; font: 14px system-ui, sans-serif; display: grid; grid-template-rows: auto 1fr; height: 100vh; }\n header { display: flex; gap: 12px; align-items: center; padding: 10px 16px; border-bottom: 1px solid #8884; }\n header code { font-size: 12px; opacity: 0.8; }\n main { display: grid; grid-template-columns: 1fr 320px; min-height: 0; }\n #stage { padding: 16px; display: flex; align-items: flex-start; justify-content: center; overflow: auto; }\n #frame { border: 1px solid #8886; border-radius: 8px; background: transparent; }\n aside { border-left: 1px solid #8884; padding: 12px 16px; overflow: auto; }\n aside h2 { font-size: 12px; text-transform: uppercase; letter-spacing: 0.04em; margin: 0 0 8px; opacity: 0.7; }\n #log { font: 12px ui-monospace, monospace; white-space: pre-wrap; margin: 0; }\n select, button { font: inherit; }\n</style>\n</head>\n<body>\n<header>\n <strong id=\"title\">Custom chart</strong>\n <code id=\"key\"></code>\n <label>Theme <select id=\"theme\"><option value=\"light\">light</option><option value=\"dark\">dark</option></select></label>\n <label>Size <select id=\"size\"><option value=\"600x320\">600 x 320</option><option value=\"900x420\">900 x 420</option><option value=\"320x240\">320 x 240</option></select></label>\n <button id=\"reload\">Rebuild and reload</button>\n</header>\n<main>\n <div id=\"stage\"><iframe id=\"frame\" sandbox=\"allow-scripts\" width=\"600\" height=\"320\" title=\"Custom chart\"></iframe></div>\n <aside><h2>Events</h2><pre id=\"log\">Waiting for ready...</pre></aside>\n</main>\n<script>\n(async () => {\n const log = document.getElementById('log');\n const frame = document.getElementById('frame');\n const themeSelect = document.getElementById('theme');\n const sizeSelect = document.getElementById('size');\n const say = (line) => { log.textContent = (line + '\\\\n' + log.textContent).slice(0, 8000); };\n const [manifest, bundle, sample, themes, css] = await Promise.all([\n fetch('/manifest.json').then((r) => r.json()),\n fetch('/bundle.js').then((r) => r.ok ? r.text() : r.text().then((t) => { throw new Error(t); })).catch((e) => { say('BUILD ERROR\\\\n' + e.message); return null; }),\n fetch('/sample-data.json').then((r) => r.json()),\n fetch('/themes.json').then((r) => r.json()),\n fetch('/index.css').then((r) => r.text()),\n ]);\n document.getElementById('title').textContent = manifest.name;\n document.getElementById('key').textContent = 'custom:' + manifest.id;\n if (!bundle) return;\n let revision = 0;\n const data = () => ({\n columns: sample.columns, rows: sample.rows,\n options: Object.assign({}, sample.defaults, sample.options || {}),\n theme: themes[themeSelect.value], language: 'en'\n });\n const send = () => frame.contentWindow.postMessage({ protocol: 'dbn-chart-sandbox', version: 1, channel: 'dev', type: 'data', revision: ++revision, data: data() }, '*');\n addEventListener('message', (event) => {\n if (event.source !== frame.contentWindow) return;\n const m = event.data || {};\n if (m.type === 'ready') { say('ready'); send(); return; }\n if (m.type === 'resize' && Number.isFinite(m.height)) frame.height = Math.max(80, Math.min(1200, m.height));\n say(m.type + ' ' + JSON.stringify(m, (k, v) => (k === 'protocol' || k === 'version' || k === 'channel' || k === 'type') ? undefined : v));\n });\n const boot = '(' + (function () {\n var channel = 'dev'; var revision = -1; var latest = null; var listener = null;\n var send = function (payload) { parent.postMessage(Object.assign({ protocol: 'dbn-chart-sandbox', version: 1, channel: channel }, payload), '*'); };\n window.dbnSandbox = Object.freeze({\n onData: function (cb) { listener = cb; send({ type: 'ready' }); if (latest) cb(latest); },\n click: function (rowIndex, columnId) { send({ type: 'click', revision: revision, rowIndex: rowIndex, columnId: columnId }); },\n filter: function (columnId, values) { send({ type: 'filter', revision: revision, columnId: columnId, values: values }); },\n resize: function (height) { send({ type: 'resize', height: height }); }\n });\n addEventListener('error', function (e) { send({ type: 'error', code: 'runtime', message: String(e.message || e) }); });\n addEventListener('message', function (event) {\n var m = event.data; if (!m || m.type !== 'data' || m.revision <= revision) return;\n revision = m.revision; latest = m.data; if (listener) listener(latest);\n });\n }).toString() + ')();';\n const child = '<!doctype html><html><head><meta charset=\"utf-8\"><style>html,body{margin:0;width:100%;height:100%;overflow:hidden}body{font:14px system-ui}#chart{width:100%;height:100%}</style><style>' + css.replace(/<\\\\/style/gi, '') + '</style></head><body><div id=\"chart\"></div><script>' + boot + '<\\\\/script><script>' + bundle.replace(/<\\\\/script/gi, '<\\\\\\\\/script') + '<\\\\/script></body></html>';\n const mount = () => { frame.srcdoc = child; };\n themeSelect.addEventListener('change', () => { if (revision > 0) send(); });\n sizeSelect.addEventListener('change', () => { const [w, h] = sizeSelect.value.split('x'); frame.width = w; frame.height = h; if (revision > 0) send(); });\n document.getElementById('reload').addEventListener('click', () => location.reload());\n mount();\n})();\n</script>\n</body>\n</html>\n`;\n\nexport async function startDevServer(\n options: DevServerOptions\n): Promise<{ port: number; close: () => void; server: Server }> {\n const server = createServer(async (req, res) => {\n const url = new URL(req.url ?? '/', 'http://127.0.0.1');\n const json = (status: number, body: unknown) => {\n res.writeHead(status, {\n 'Content-Type': 'application/json; charset=utf-8',\n 'Cache-Control': 'no-store',\n });\n res.end(JSON.stringify(body));\n };\n try {\n if (url.pathname === '/') {\n res.writeHead(200, {\n 'Content-Type': 'text/html; charset=utf-8',\n 'Cache-Control': 'no-store',\n });\n res.end(PAGE);\n return;\n }\n if (url.pathname === '/bundle.js') {\n const result = await buildProject(options.dir, { write: false });\n if (!result.ok || !result.outputs) {\n res.writeHead(422, {\n 'Content-Type': 'text/plain; charset=utf-8',\n 'Cache-Control': 'no-store',\n });\n res.end(\n result.problems\n .map((p) => `${p.path || '/'} ${p.code} ${p.message}`)\n .join('\\n')\n );\n return;\n }\n res.writeHead(200, {\n 'Content-Type': 'text/javascript; charset=utf-8',\n 'Cache-Control': 'no-store',\n });\n res.end(result.outputs.bundleJs);\n return;\n }\n const project = readProject(options.dir);\n const manifest = project.manifest as CustomChartManifest | undefined;\n if (url.pathname === '/manifest.json') {\n json(manifest ? 200 : 422, manifest ?? { problems: project.problems });\n return;\n }\n if (url.pathname === '/sample-data.json') {\n if (!manifest) {\n json(422, { problems: project.problems });\n return;\n }\n const sample =\n (project.sampleData as\n | { columns?: unknown[]; rows?: unknown[][]; options?: unknown }\n | undefined) ?? generateSampleData(manifest);\n json(200, { ...sample, defaults: defaultOptions(manifest) });\n return;\n }\n if (url.pathname === '/index.css') {\n // The host injects bundleCss into the frame; this page plays the host.\n res.writeHead(200, {\n 'Content-Type': 'text/css; charset=utf-8',\n 'Cache-Control': 'no-store',\n });\n res.end(project.css ?? '');\n return;\n }\n if (url.pathname === '/themes.json') {\n json(200, { light: LIGHT_THEME, dark: DARK_THEME });\n return;\n }\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('not found');\n } catch (err) {\n res.writeHead(500, { 'Content-Type': 'text/plain; charset=utf-8' });\n res.end((err as Error).message);\n }\n });\n await new Promise<void>((resolve, reject) => {\n server.once('error', reject);\n server.listen(options.port, '127.0.0.1', () => resolve());\n });\n const address = server.address();\n const port =\n typeof address === 'object' && address ? address.port : options.port;\n return { port, server, close: () => server.close() };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA,SAAS,YAAY,WAAW,aAAa,qBAAqB;AAClE,SAAS,UAAU,MAAM,eAAe;AACxC,SAAS,uBAAuB;;;ACFhC,SAAS,oBAAiC;AAqB1C,IAAM,cAAc;AAAA,EAClB,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,WAAW;AAAA,EACX,oBAAoB;AAAA,EACpB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,aAAa;AAAA,EACb,cAAc;AAAA,EACd,cAAc;AAAA,EACd,SAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,IAAM,aAAa;AAAA,EACjB,GAAG;AAAA,EACH,WAAW;AAAA,EACX,oBAAoB;AAAA,EACpB,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,aAAa;AAAA,EACb,cAAc;AAAA,EACd,SAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,SAAS,eACP,UAC2C;AAC3C,QAAM,UAAqD,CAAC;AAC5D,aAAW,UAAU,SAAS;AAC5B,YAAQ,OAAO,EAAE,IAAI,OAAO;AAC9B,SAAO;AACT;AAGA,SAAS,mBAAmB,UAG1B;AACA,QAAM,SAAS;AAAA,IACb;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,UAAU,SAAS,MAAM,IAAI,CAAC,MAAM,WAAW;AAAA,IACnD,IAAI,GAAG,KAAK,EAAE,IAAI,KAAK;AAAA,IACvB,OAAO,KAAK;AAAA,IACZ,MAAM,KAAK,MAAM,CAAC;AAAA,IAClB,YAAY,KAAK,SAAS;AAAA,IAC1B,QAAQ,KAAK;AAAA,EACf,EAAE;AACF,QAAM,OAAO,OAAO;AAAA,IAAI,CAAC,OAAO,QAC9B,SAAS,MAAM,IAAI,CAAC,MAAM,WAAW;AACnC,YAAM,OAAO,KAAK,MAAM,CAAC;AACzB,UAAI,SAAS,SAAU,QAAO,GAAG,KAAK,GAAG,SAAS,IAAI,IAAI,MAAM,KAAK,EAAE;AACvE,UAAI,SAAS,UAAW,SAAQ,MAAM,UAAU,MAAM;AACtD,aAAO,KAAK;AAAA,QACV,MAAO,MAAM,KAAK,SAAS,MAAO,MAAM,KAAK,SAAS,MAAM;AAAA,MAC9D;AAAA,IACF,CAAC;AAAA,EACH;AACA,SAAO,EAAE,SAAS,KAAK;AACzB;AAEA,IAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyFb,eAAsB,eACpB,SAC8D;AAC9D,QAAM,SAAS,aAAa,OAAO,KAAK,QAAQ;AAC9C,UAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,kBAAkB;AACtD,UAAM,OAAO,CAAC,QAAgB,SAAkB;AAC9C,UAAI,UAAU,QAAQ;AAAA,QACpB,gBAAgB;AAAA,QAChB,iBAAiB;AAAA,MACnB,CAAC;AACD,UAAI,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,IAC9B;AACA,QAAI;AACF,UAAI,IAAI,aAAa,KAAK;AACxB,YAAI,UAAU,KAAK;AAAA,UACjB,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,QACnB,CAAC;AACD,YAAI,IAAI,IAAI;AACZ;AAAA,MACF;AACA,UAAI,IAAI,aAAa,cAAc;AACjC,cAAM,SAAS,MAAM,aAAa,QAAQ,KAAK,EAAE,OAAO,MAAM,CAAC;AAC/D,YAAI,CAAC,OAAO,MAAM,CAAC,OAAO,SAAS;AACjC,cAAI,UAAU,KAAK;AAAA,YACjB,gBAAgB;AAAA,YAChB,iBAAiB;AAAA,UACnB,CAAC;AACD,cAAI;AAAA,YACF,OAAO,SACJ,IAAI,CAAC,MAAM,GAAG,EAAE,QAAQ,GAAG,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE,EACtD,KAAK,IAAI;AAAA,UACd;AACA;AAAA,QACF;AACA,YAAI,UAAU,KAAK;AAAA,UACjB,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,QACnB,CAAC;AACD,YAAI,IAAI,OAAO,QAAQ,QAAQ;AAC/B;AAAA,MACF;AACA,YAAM,UAAU,YAAY,QAAQ,GAAG;AACvC,YAAM,WAAW,QAAQ;AACzB,UAAI,IAAI,aAAa,kBAAkB;AACrC,aAAK,WAAW,MAAM,KAAK,YAAY,EAAE,UAAU,QAAQ,SAAS,CAAC;AACrE;AAAA,MACF;AACA,UAAI,IAAI,aAAa,qBAAqB;AACxC,YAAI,CAAC,UAAU;AACb,eAAK,KAAK,EAAE,UAAU,QAAQ,SAAS,CAAC;AACxC;AAAA,QACF;AACA,cAAM,SACH,QAAQ,cAES,mBAAmB,QAAQ;AAC/C,aAAK,KAAK,EAAE,GAAG,QAAQ,UAAU,eAAe,QAAQ,EAAE,CAAC;AAC3D;AAAA,MACF;AACA,UAAI,IAAI,aAAa,cAAc;AAEjC,YAAI,UAAU,KAAK;AAAA,UACjB,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,QACnB,CAAC;AACD,YAAI,IAAI,QAAQ,OAAO,EAAE;AACzB;AAAA,MACF;AACA,UAAI,IAAI,aAAa,gBAAgB;AACnC,aAAK,KAAK,EAAE,OAAO,aAAa,MAAM,WAAW,CAAC;AAClD;AAAA,MACF;AACA,UAAI,UAAU,KAAK,EAAE,gBAAgB,aAAa,CAAC;AACnD,UAAI,IAAI,WAAW;AAAA,IACrB,SAASA,MAAK;AACZ,UAAI,UAAU,KAAK,EAAE,gBAAgB,4BAA4B,CAAC;AAClE,UAAI,IAAKA,KAAc,OAAO;AAAA,IAChC;AAAA,EACF,CAAC;AACD,QAAM,IAAI,QAAc,CAACC,UAAS,WAAW;AAC3C,WAAO,KAAK,SAAS,MAAM;AAC3B,WAAO,OAAO,QAAQ,MAAM,aAAa,MAAMA,SAAQ,CAAC;AAAA,EAC1D,CAAC;AACD,QAAM,UAAU,OAAO,QAAQ;AAC/B,QAAM,OACJ,OAAO,YAAY,YAAY,UAAU,QAAQ,OAAO,QAAQ;AAClE,SAAO,EAAE,MAAM,QAAQ,OAAO,MAAM,OAAO,MAAM,EAAE;AACrD;;;ADrQA,IAAM,QAAQ,aAAa,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA8B7C,SAAS,UAAU,MAA4B;AAC7C,QAAM,aAAuB,CAAC;AAC9B,QAAM,QAA0C,CAAC;AACjD,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAM,MAAM,KAAK,CAAC;AAClB,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,YAAM,CAAC,MAAM,WAAW,IAAI,IAAI,MAAM,CAAC,EAAE,MAAM,KAAK,CAAC;AACrD,UAAI,gBAAgB,QAAW;AAC7B,cAAM,IAAI,IAAI;AAAA,MAChB,WACE,CAAC,OAAO,QAAQ,MAAM,EAAE,SAAS,IAAI,KACrC,IAAI,IAAI,KAAK,UACb,CAAC,KAAK,IAAI,CAAC,EAAE,WAAW,IAAI,GAC5B;AACA,cAAM,IAAI,IAAI,KAAK,EAAE,CAAC;AAAA,MACxB,OAAO;AACL,cAAM,IAAI,IAAI;AAAA,MAChB;AAAA,IACF,OAAO;AACL,iBAAW,KAAK,GAAG;AAAA,IACrB;AAAA,EACF;AACA,SAAO,EAAE,YAAY,MAAM;AAC7B;AAMA,IAAM,MAAM,CAAC,SAAuB;AAClC,UAAQ,OAAO,MAAM,GAAG,cAAc,IAAI,CAAC;AAAA,CAAI;AACjD;AACA,IAAM,MAAM,CAAC,SAAuB;AAClC,UAAQ,OAAO,MAAM,GAAG,cAAc,IAAI,CAAC;AAAA,CAAI;AACjD;AAEO,SAAS,mBAAmB,UAA+B;AAChE,SAAO,SAAS,IAAI,CAAC,MAAM,GAAG,EAAE,QAAQ,GAAG,KAAK,EAAE,IAAI,KAAK,EAAE,OAAO,EAAE;AACxE;AAEA,SAAS,cAAc,UAA2B;AAChD,aAAW,QAAQ,mBAAmB,QAAQ,EAAG,KAAI,IAAI;AAC3D;AAEA,SAAS,WAAW,KAAqB;AACvC,QAAM,MAAM,SAAS,QAAQ,GAAG,CAAC,EAC9B,YAAY,EACZ,QAAQ,iBAAiB,GAAG,EAC5B,QAAQ,YAAY,EAAE;AACzB,QAAM,MACJ,IAAI,WAAW,IAAI,aAAa,SAAS,KAAK,GAAG,IAAI,MAAM,SAAS,GAAG;AACzE,SAAO,IAAI,MAAM,GAAG,EAAE;AACxB;AAEA,SAAS,YAAY,KAAqB;AACxC,QAAM,QAAQ,IAAI,MAAM,OAAO,EAAE,OAAO,OAAO;AAC/C,SAAO,MACJ;AAAA,IAAI,CAAC,MAAM,UACV,UAAU,IAAI,KAAK,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,IAAI;AAAA,EACxD,EACC,KAAK,GAAG;AACb;AAEA,SAAS,YAAY,MAA0B;AAC7C,QAAM,MAAM,KAAK,WAAW,CAAC;AAC7B,MAAI,CAAC,KAAK;AACR,QAAI,wDAAwD;AAC5D,WAAO;AAAA,EACT;AACA,QAAM,SAAS,QAAQ,GAAG;AAC1B,MACE,WAAW,MAAM,KACjB,YAAY,MAAM,EAAE,SAAS,KAC7B,KAAK,MAAM,UAAU,MACrB;AACA,QAAI,GAAG,MAAM,qDAAqD;AAClE,WAAO;AAAA,EACT;AACA,QAAM,MACJ,OAAO,KAAK,MAAM,QAAQ,WAAW,KAAK,MAAM,MAAM,WAAW,MAAM;AACzE,QAAM,OACJ,OAAO,KAAK,MAAM,SAAS,WAAW,KAAK,MAAM,OAAO,YAAY,GAAG;AACzE,QAAM,SAAS,gBAAgB,EAAE,KAAK,KAAK,CAAC;AAC5C,MAAI,CAAC,OAAO,IAAI;AACd,kBAAc,OAAO,QAAQ;AAC7B,WAAO;AAAA,EACT;AACA,YAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AACrC,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,OAAO,KAAK,GAAG;AAC1D,kBAAc,KAAK,QAAQ,IAAI,GAAG,OAAO;AAAA,EAC3C;AACA,MAAI,yBAAyB,GAAG,OAAO,MAAM,EAAE;AAC/C,aAAW,QAAQ,OAAO,KAAK,OAAO,KAAK,EAAG,KAAI,KAAK,IAAI,EAAE;AAC7D,MAAI,EAAE;AACN,MAAI,OAAO;AACX,MAAI,QAAQ,GAAG,EAAE;AACjB,MAAI,wCAAwC;AAC5C,MAAI,mCAAmC;AACvC,MAAI,gCAAgC;AACpC,MAAI,iCAAiC;AACrC,SAAO;AACT;AAEA,SAAS,gBAAgB,MAA0B;AACjD,QAAM,MAAM,QAAQ,KAAK,WAAW,CAAC,KAAK,GAAG;AAC7C,QAAM,SAAS,gBAAgB,GAAG;AAClC,MAAI,CAAC,OAAO,IAAI;AACd;AAAA,MACE,GAAG,OAAO,SAAS,MAAM,WAAW,OAAO,SAAS,WAAW,IAAI,KAAK,GAAG,OAAO,GAAG;AAAA,IACvF;AACA,kBAAc,OAAO,QAAQ;AAC7B,WAAO;AAAA,EACT;AACA,QAAM,WAAW,OAAO,QAAQ;AAKhC;AAAA,IACE,iBAAiB,SAAS,EAAE,KAAK,SAAS,MAAM,MAAM,WAAW,SAAS,QAAQ,MAAM,gBAAgB,GAAG;AAAA,EAC7G;AACA,SAAO;AACT;AAEA,eAAe,aAAa,MAAmC;AAC7D,QAAM,MAAM,QAAQ,KAAK,WAAW,CAAC,KAAK,GAAG;AAC7C,QAAM,SAAS,MAAM,aAAa,GAAG;AACrC,MAAI,CAAC,OAAO,MAAM,CAAC,OAAO,SAAS;AACjC;AAAA,MACE,qBAAqB,OAAO,SAAS,MAAM,WAAW,OAAO,SAAS,WAAW,IAAI,KAAK,GAAG;AAAA,IAC/F;AACA,kBAAc,OAAO,QAAQ;AAC7B,WAAO;AAAA,EACT;AACA,MAAI,gBAAgB,OAAO,QAAQ,SAAS,EAAE,EAAE;AAChD,aAAW,QAAQ,OAAO,QAAS,KAAI,KAAK,IAAI,EAAE;AAClD,MAAI,iBAAiB,OAAO,QAAQ,WAAW,EAAE;AACjD;AAAA,IACE,UAAU,OAAO,QAAQ,SAAS,kBAAkB,OAAO,WAAW,OAAO,QAAQ,UAAU,MAAM,CAAC;AAAA,EACxG;AACA,SAAO;AACT;AAEA,eAAe,QAAQ,UAAoC;AACzD,MAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,QAAI,iEAAiE;AACrE,WAAO;AAAA,EACT;AACA,QAAM,KAAK,gBAAgB,EAAE,OAAO,QAAQ,OAAO,QAAQ,QAAQ,OAAO,CAAC;AAC3E,QAAM,SAAS,MAAM,IAAI;AAAA,IAAgB,CAAC,kBACxC,GAAG,SAAS,UAAU,aAAa;AAAA,EACrC;AACA,KAAG,MAAM;AACT,SACE,OAAO,KAAK,EAAE,YAAY,MAAM,OAAO,OAAO,KAAK,EAAE,YAAY,MAAM;AAE3E;AAEA,eAAe,cAAc,MAAmC;AAC9D,QAAM,MAAM,QAAQ,KAAK,WAAW,CAAC,KAAK,GAAG;AAC7C,QAAM,eAAe,QAAQ,IAAI;AACjC,MAAI,CAAC,cAAc;AACjB;AAAA,MACE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACA,iBAAe,YAAY;AAC3B,QAAM,SACJ,QAAQ,IAAI,qBAAqB;AACnC,MAAI,CAAC,QAAQ,IAAI;AACf,QAAI,uCAAuC,MAAM,EAAE;AAErD,QAAM,QAAQ,MAAM,aAAa,GAAG;AACpC,MAAI,CAAC,MAAM,MAAM,CAAC,MAAM,SAAS;AAC/B,QAAI,eAAe;AACnB,kBAAc,MAAM,QAAQ;AAC5B,WAAO;AAAA,EACT;AACA,QAAM,EAAE,UAAU,UAAU,WAAW,QAAQ,IAAI,MAAM;AACzD,QAAM,MAAM,SAAS;AACrB;AAAA,IACE,gBAAgB,GAAG,KAAK,MAAM,QAAQ,YAAY,MAAM,GAAG,EAAE,CAAC,KAAK,MAAM,QAAQ,SAAS;AAAA,EAC5F;AAEA,QAAM,SAAS,IAAI,gBAAgB;AAAA,IACjC;AAAA,IACA;AAAA,IACA,YAAY;AAAA,EACd,CAAC;AACD,QAAM,MAAM,sBAAsB,MAAM;AACxC,MAAI;AACF,UAAM,aAAa,MAAM,IAAI,SAAS;AAAA,MACpC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,QAAI,CAAC,WAAW,IAAI;AAClB,UAAI,gCAAgC;AACpC,oBAAc,WAAW,QAAQ;AACjC,aAAO;AAAA,IACT;AACA,QAAI,uBAAuB;AAC3B,UAAM,YAAY,MAAM,IAAI,KAAK,GAAG,KAAK,CAAC,UAAU,MAAM,QAAQ,GAAG;AACrE,UAAM,OAAO,WAAW,KAAK,QAAQ;AACrC,QAAI,SAAS,KAAK,OAAO,EAAE;AAC3B,QAAI,KAAK,MAAM,YAAY;AACzB;AAAA,QACE;AAAA,MACF;AAEF,QAAI,KAAK,MAAM,QAAQ,MAAM;AAC3B,YAAM,KAAK,MAAM,QAAQ,kBAAkB;AAC3C,UAAI,CAAC,IAAI;AACP,YAAI,kCAAkC;AACtC,eAAO;AAAA,MACT;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,IAAI,OAAO;AAAA,MAChC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AACD,UAAM,gBAAgB,SAAS,SAAS,iBAAiB;AACzD,QAAI,SAAS,YAAY;AACvB,UAAI,iCAAiC,aAAa,cAAc,GAAG,GAAG;AAAA,aAC/D,SAAS,YAAY;AAC5B,UAAI,kBAAkB,GAAG,MAAM,aAAa,aAAa;AAAA;AAEzD;AAAA,QACE,aAAa,aAAa,cAAc,GAAG;AAAA,MAC7C;AAEF,QAAI,KAAK,MAAM,YAAY,MAAM;AAC/B,YAAM,YAAY,MAAM,IAAI,QAAQ,KAAK,SAAS,SAAS,EAAE;AAC7D;AAAA,QACE,cAAc,aAAa,cAAc,GAAG,YAAY,UAAU,OAAO,UAAU,WAAW;AAAA,MAChG;AAAA,IACF,WAAW,SAAS,YAAY,QAAQ;AACtC;AAAA,QACE;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT,SAAS,OAAO;AACd,QAAI,iBAAiB,mBAAmB;AACtC;AAAA,QACE,SAAS,MAAM,UAAU,EAAE,IAAI,MAAM,IAAI,KAAK,MAAM,OAAO,GACxD,QAAQ,QAAQ,GAAG,EACnB,KAAK;AAAA,MACV;AACA,oBAAc,YAAY,KAAK,CAAC;AAChC,aAAO;AAAA,IACT;AACA,QAAI,qBAAsB,MAAgB,OAAO,EAAE;AACnD,WAAO;AAAA,EACT;AACF;AAEA,eAAe,WAAW,MAAmC;AAC3D,QAAM,MAAM,QAAQ,KAAK,WAAW,CAAC,KAAK,GAAG;AAC7C,QAAM,OACJ,OAAO,KAAK,MAAM,SAAS,WAAW,OAAO,KAAK,MAAM,IAAI,IAAI;AAClE,MAAI,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,OAAO;AACvD,QAAI,8CAA8C;AAClD,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,MAAM,aAAa,GAAG;AACpC,MAAI,CAAC,MAAM,IAAI;AACb,QAAI,eAAe;AACnB,kBAAc,MAAM,QAAQ;AAC5B,WAAO;AAAA,EACT;AACA,QAAM,SAAS,MAAM,eAAe,EAAE,KAAK,KAAK,CAAC;AACjD;AAAA,IACE,2CAA2C,OAAO,IAAI;AAAA,EACxD;AACA,MAAI,iEAAiE;AACrE,QAAM,IAAI,QAAc,CAAC,gBAAgB;AACvC,UAAM,OAAO,MAAM;AACjB,aAAO,MAAM;AACb,kBAAY;AAAA,IACd;AACA,YAAQ,KAAK,UAAU,IAAI;AAC3B,YAAQ,KAAK,WAAW,IAAI;AAAA,EAC9B,CAAC;AACD,SAAO;AACT;AAEA,eAAsB,OAAO,MAAiC;AAC5D,QAAM,OAAO,UAAU,IAAI;AAC3B,MAAI,KAAK,MAAM,YAAY,MAAM;AAC/B,QAAI,kBAAkB;AACtB,WAAO;AAAA,EACT;AACA,QAAM,CAAC,QAAQ,SAAS,GAAG,IAAI,IAAI,KAAK;AACxC,MAAI,KAAK,MAAM,SAAS,QAAQ,CAAC,QAAQ;AACvC,QAAI,KAAK;AACT,WAAO,SAAS,IAAI;AAAA,EACtB;AACA,MAAI,WAAW,gBAAgB;AAC7B,QAAI,oBAAoB,MAAM,IAAI;AAClC,QAAI,KAAK;AACT,WAAO;AAAA,EACT;AACA,QAAM,MAAkB,EAAE,YAAY,MAAM,OAAO,KAAK,MAAM;AAC9D,UAAQ,SAAS;AAAA,IACf,KAAK;AACH,aAAO,YAAY,GAAG;AAAA,IACxB,KAAK;AACH,aAAO,gBAAgB,GAAG;AAAA,IAC5B,KAAK;AACH,aAAO,aAAa,GAAG;AAAA,IACzB,KAAK;AACH,aAAO,cAAc,GAAG;AAAA,IAC1B,KAAK;AACH,aAAO,WAAW,GAAG;AAAA,IACvB;AACE;AAAA,QACE,UACI,iCAAiC,OAAO,OACxC;AAAA,MACN;AACA,UAAI,KAAK;AACT,aAAO;AAAA,EACX;AACF;AAEA,IAAM,kBACJ,OAAO,QAAQ,KAAK,CAAC,MAAM,YAC3B,yCAAyC,KAAK,QAAQ,KAAK,CAAC,CAAC;AAC/D,IAAI,iBAAiB;AACnB,SAAO,QAAQ,KAAK,MAAM,CAAC,CAAC,EAAE;AAAA,IAC5B,CAAC,SAAS;AACR,cAAQ,WAAW;AAAA,IACrB;AAAA,IACA,CAAC,UAAiB;AAChB,UAAI,qBAAqB,MAAM,OAAO,EAAE;AACxC,cAAQ,WAAW;AAAA,IACrB;AAAA,EACF;AACF;","names":["err","resolve"]}