@malloydata/malloyyo 0.2.22 → 0.2.23

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 (2) hide show
  1. package/dist/index.js +73 -10
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -7,19 +7,80 @@ import { resolve as resolve2 } from "node:path";
7
7
  // src/config.ts
8
8
  import { readFileSync, existsSync } from "node:fs";
9
9
  import { join } from "node:path";
10
+ var KNOWN_KEYS = /* @__PURE__ */ new Set(["analytics", "targets"]);
11
+ function isTarget(v) {
12
+ return typeof v === "object" && v !== null && typeof v.url === "string";
13
+ }
14
+ var warned = /* @__PURE__ */ new Set();
15
+ function warnOnce(key, msg) {
16
+ if (warned.has(key)) return;
17
+ warned.add(key);
18
+ console.warn(msg);
19
+ }
20
+ function parseMalloyyoConfig(raw) {
21
+ const declared = raw.targets;
22
+ const targets = typeof declared === "object" && declared !== null ? { ...declared } : {};
23
+ const legacy = [];
24
+ const unknown = [];
25
+ for (const [k, v] of Object.entries(raw)) {
26
+ if (KNOWN_KEYS.has(k)) continue;
27
+ if (isTarget(v)) {
28
+ if (!(k in targets)) targets[k] = v;
29
+ legacy.push(k);
30
+ } else {
31
+ unknown.push(k);
32
+ }
33
+ }
34
+ if (legacy.length) {
35
+ warnOnce(
36
+ "legacy-targets",
37
+ `malloy-config.json: publish target(s) ${legacy.map((t) => `"${t}"`).join(", ")} are at the top of the "malloyyo" block. Move them under "targets":
38
+ "malloyyo": { "targets": { ${legacy.map((t) => `"${t}": { \u2026 }`).join(", ")} } }
39
+ The old shape still works for now.`
40
+ );
41
+ }
42
+ if (unknown.length) {
43
+ warnOnce(
44
+ "unknown-keys",
45
+ `malloy-config.json: ignoring unknown key(s) in the "malloyyo" block: ${unknown.map((k) => `"${k}"`).join(", ")}. Known keys: ${[...KNOWN_KEYS].join(", ")}.`
46
+ );
47
+ }
48
+ const analytics = raw.analytics;
49
+ return {
50
+ analytics: typeof analytics === "string" && analytics ? analytics : void 0,
51
+ targets
52
+ };
53
+ }
10
54
  function readTargetMap(dir) {
55
+ const raw = readMalloyyoBlock(dir);
56
+ if (raw) return parseMalloyyoConfig(raw).targets;
57
+ throw new Error(
58
+ `No \`malloyyo\` config found in ${dir} (looked for a "malloyyo" block in malloy-config.json, then malloyyo.json).`
59
+ );
60
+ }
61
+ function readMalloyyoBlock(dir) {
11
62
  const malloyConfig = join(dir, "malloy-config.json");
12
63
  if (existsSync(malloyConfig)) {
13
- const json = JSON.parse(readFileSync(malloyConfig, "utf8"));
14
- if (json.malloyyo && typeof json.malloyyo === "object") return json.malloyyo;
64
+ try {
65
+ const json = JSON.parse(readFileSync(malloyConfig, "utf8"));
66
+ if (json.malloyyo && typeof json.malloyyo === "object") return json.malloyyo;
67
+ } catch {
68
+ }
15
69
  }
16
70
  const standalone = join(dir, "malloyyo.json");
17
71
  if (existsSync(standalone)) {
18
- return JSON.parse(readFileSync(standalone, "utf8"));
72
+ try {
73
+ return JSON.parse(readFileSync(standalone, "utf8"));
74
+ } catch {
75
+ }
19
76
  }
20
- throw new Error(
21
- `No \`malloyyo\` config found in ${dir} (looked for a "malloyyo" block in malloy-config.json, then malloyyo.json).`
22
- );
77
+ return null;
78
+ }
79
+ function readSiteConfig(dir) {
80
+ const raw = readMalloyyoBlock(dir);
81
+ if (!raw) return {};
82
+ const { analytics } = parseMalloyyoConfig(raw);
83
+ return analytics ? { analytics } : {};
23
84
  }
24
85
  var normalizeUrl = (u) => u.replace(/\/+$/, "");
25
86
  function resolveTarget(dir, name) {
@@ -3366,6 +3427,7 @@ async function bundleDashboards(opts = {}) {
3366
3427
  const outDir = path7.resolve(root, opts.out ?? "docs");
3367
3428
  const title = opts.title ?? path7.basename(root);
3368
3429
  const target = opts.target ?? "pages";
3430
+ const analytics = opts.analytics ?? readSiteConfig(root).analytics;
3369
3431
  const cleanUrls = target === "vercel";
3370
3432
  const selfHostDuckdb = opts.duckdb === "bundled";
3371
3433
  const runner = await makeRunner(root);
@@ -3502,9 +3564,9 @@ boot(Dashboard);
3502
3564
  if (!got.ok) throw new Error(`dashboard ${d.name}: ${got.error}`);
3503
3565
  specs = got.givens;
3504
3566
  }
3505
- fs6.writeFileSync(path7.join(outDir, `${d.name}.html`), page(d, dashboards, title, specs, tileSpecs, cleanUrls, opts.analytics));
3567
+ fs6.writeFileSync(path7.join(outDir, `${d.name}.html`), page(d, dashboards, title, specs, tileSpecs, cleanUrls, analytics));
3506
3568
  }
3507
- fs6.writeFileSync(path7.join(outDir, "index.html"), indexPage(dashboards, title, !!landing, cleanUrls, opts.analytics));
3569
+ fs6.writeFileSync(path7.join(outDir, "index.html"), indexPage(dashboards, title, !!landing, cleanUrls, analytics));
3508
3570
  if (landing) {
3509
3571
  await esbuild3.build({
3510
3572
  stdin: {
@@ -3542,6 +3604,7 @@ bundled ${dashboards.length} dashboard(s) \u2192 ${path7.relative(process.cwd(),
3542
3604
  selfHostDuckdb ? ` duckdb ${duck.length} assets (self-hosted)` : ` duckdb jsDelivr CDN (nothing copied)`
3543
3605
  );
3544
3606
  console.log(` model ${Object.keys(modelFiles).length} .malloy files inlined`);
3607
+ if (analytics) console.log(` analytics ${analytics}`);
3545
3608
  if (copiedData.length) {
3546
3609
  const mb = copiedData.reduce((a, r) => a + fs6.statSync(path7.join(root, r)).size, 0) / 1048576;
3547
3610
  console.log(` data ${copiedData.length} file(s) copied, ${mb.toFixed(1)} MB (same-origin)`);
@@ -3677,7 +3740,7 @@ async function launchCmd(mode, opts) {
3677
3740
  }
3678
3741
 
3679
3742
  // package.json
3680
- var version = "0.2.22";
3743
+ var version = "0.2.23";
3681
3744
 
3682
3745
  // src/index.ts
3683
3746
  function shortSha(sha) {
@@ -3784,7 +3847,7 @@ program.command("author").option("-C, --root <dir>", "project root (default: cur
3784
3847
  program.command("test").option("-C, --root <dir>", "project root (default: current directory)").description("launch Claude wired ONLY to the explore surface \u2014 the claude.ai web preview").action(async (opts) => {
3785
3848
  await launchCmd("test", opts);
3786
3849
  });
3787
- program.command("dashboard").argument("<action>", "action to run (dev | bundle)").option("-C, --root <dir>", "project root (default: current directory)").option("-p, --port <port>", "port to serve on (dev)", "4173").option("-o, --out <dir>", "output directory (bundle)", "docs").option("--title <title>", "site title (bundle; default: project directory name)").option("--target <target>", "deploy target: pages | vercel (bundle)", "pages").option("--duckdb <source>", "DuckDB binaries: cdn | bundled (bundle)", "cdn").option("--analytics <id>", "Google Analytics 4 Measurement ID, e.g. G-XXXXXXXXXX (bundle)").option("--no-serve", "bundle only; don't serve the result (bundle)").description("preview dashboards locally (dev), or build a static site from them (bundle)").action(
3850
+ program.command("dashboard").argument("<action>", "action to run (dev | bundle)").option("-C, --root <dir>", "project root (default: current directory)").option("-p, --port <port>", "port to serve on (dev)", "4173").option("-o, --out <dir>", "output directory (bundle)", "docs").option("--title <title>", "site title (bundle; default: project directory name)").option("--target <target>", "deploy target: pages | vercel (bundle)", "pages").option("--duckdb <source>", "DuckDB binaries: cdn | bundled (bundle)", "cdn").option("--analytics <id>", "GA4 Measurement ID, overriding malloyyo.analytics in malloy-config.json (bundle)").option("--no-serve", "bundle only; don't serve the result (bundle)").description("preview dashboards locally (dev), or build a static site from them (bundle)").action(
3788
3851
  async (action, opts) => {
3789
3852
  if (action === "dev") {
3790
3853
  await serveDashboard({ root: opts.root, port: Number(opts.port) });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@malloydata/malloyyo",
3
- "version": "0.2.22",
3
+ "version": "0.2.23",
4
4
  "description": "Publish Malloy models to a Malloyyo instance",
5
5
  "license": "MIT",
6
6
  "repository": {