@bitcobblers/wod-wiki-wql 0.35.2116 → 0.35.2119

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.
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { KNOWN_OUTPUT_TYPES, dimensionKeyOf, convertViaCatalog, systemDefaultUnit, MetricType, valueKindOf, normalizeFieldPath, fieldRefKey, normalizeFieldComponent } from '@bitcobblers/wod-wiki-core';
1
+ import { KNOWN_OUTPUT_TYPES, dimensionKeyOf, convertViaCatalog, systemDefaultUnit, MetricType, valueKindOf, normalizeFieldPath, validateNoteBlocks, fieldRefKey, normalizeFieldComponent } from '@bitcobblers/wod-wiki-core';
2
2
  export { SYSTEM_DEFAULT_OUTPUT_UNIT, UnitConversionError, convertViaCatalog, dimensionKeyOf, lookupUnit, systemDefaultUnit } from '@bitcobblers/wod-wiki-core';
3
3
  import { LRParser } from '@lezer/lr';
4
4
  import { LRLanguage, HighlightStyle, LanguageSupport, syntaxHighlighting } from '@codemirror/language';
@@ -653,10 +653,10 @@ function validateSourceFilter(filters) {
653
653
  if (val === "collection" || val === "collections") {
654
654
  return `source:${val} is retired \u2014 collections were renamed to feeds; use source:feeds or :feed{}.`;
655
655
  }
656
- if (WQL_SOURCE_VALUES.includes(val) || val === "feed" || val.startsWith("collection:")) {
656
+ if (WQL_SOURCE_VALUES.includes(val) || val === "feed" || val.startsWith("collection:") || val.startsWith("feed:")) {
657
657
  continue;
658
658
  }
659
- return `Unknown source "${val}". Try: ${WQL_SOURCE_VALUES.join(", ")} (or collection:<id>)`;
659
+ return `Unknown source "${val}". Try: ${WQL_SOURCE_VALUES.join(", ")} (or collection:<id>, feed:<id>)`;
660
660
  }
661
661
  }
662
662
  return void 0;
@@ -1143,9 +1143,7 @@ function findTargetAdvisories(query) {
1143
1143
  if (query.groupBy?.length) {
1144
1144
  const dimensions = wqlGroupingDimensions(target, "find");
1145
1145
  const unsupported = query.groupBy.filter((dim) => !dimensions.some((d) => d.toLowerCase() === dim.toLowerCase()));
1146
- if (target === "note" || target === "block") {
1147
- if (unsupported.length) advisories.push(`:${target} cannot group by ${unsupported.join(", ")}; grouped by tag instead. Valid alternatives: ${dimensions.join(", ")}.`);
1148
- } else if (target === "segment" || target === "event") {
1146
+ if (target === "note" || target === "block") ; else if (target === "segment" || target === "event") {
1149
1147
  const selected = query.pipes?.select?.map((column) => column.col);
1150
1148
  const unavailable = query.groupBy.filter((dim) => selected ? !selected.includes(dim) : !dimensions.includes(dim));
1151
1149
  if (unavailable.length) advisories.push(`:${target} groups only emitted table columns; ${unavailable.join(", ")} may be unassigned. Select each grouping column explicitly.`);
@@ -2591,8 +2589,8 @@ function normalizeSummaryFacts(logs, identity) {
2591
2589
  origin: identity.origin,
2592
2590
  pageId: identity.pageId,
2593
2591
  grain: "summary",
2594
- segmentId: identity.segmentId ?? "",
2595
- segmentVersion: identity.segmentVersion ?? 0,
2592
+ blockId: identity.blockId ?? "",
2593
+ blockVersion: identity.blockVersion ?? 0,
2596
2594
  resultId: identity.resultId,
2597
2595
  type: f.metricKey,
2598
2596
  value: f.value,
@@ -2644,8 +2642,8 @@ function toEventRows(logs, identity) {
2644
2642
  text: output.text,
2645
2643
  dialect: output.dialect,
2646
2644
  completionReason: output.completionReason,
2647
- segmentId: identity.segmentId,
2648
- segmentVersion: identity.segmentVersion
2645
+ blockId: identity.blockId,
2646
+ blockVersion: identity.blockVersion
2649
2647
  }));
2650
2648
  }
2651
2649
  function toSummaryEventRows(logs, identity) {
@@ -2692,8 +2690,8 @@ function toSummaryEventRows(logs, identity) {
2692
2690
  ...f.grade ? { grade: f.grade } : {}
2693
2691
  }
2694
2692
  }],
2695
- segmentId: identity.segmentId,
2696
- segmentVersion: identity.segmentVersion
2693
+ blockId: identity.blockId,
2694
+ blockVersion: identity.blockVersion
2697
2695
  }));
2698
2696
  }
2699
2697
  function projectEventToFacts(record) {
@@ -2712,8 +2710,8 @@ function projectEventToFacts(record) {
2712
2710
  origin: record.origin,
2713
2711
  pageId: record.pageId,
2714
2712
  grain: "summary",
2715
- segmentId: record.segmentId ?? "",
2716
- segmentVersion: record.segmentVersion ?? 0,
2713
+ blockId: record.blockId ?? "",
2714
+ blockVersion: record.blockVersion ?? 0,
2717
2715
  resultId: record.resultId,
2718
2716
  type: metricKey,
2719
2717
  value: m.value,
@@ -2771,8 +2769,8 @@ function projectEventToFacts(record) {
2771
2769
  origin: record.origin,
2772
2770
  pageId: record.pageId,
2773
2771
  grain: "event",
2774
- segmentId: record.segmentId ?? "",
2775
- segmentVersion: record.segmentVersion ?? 0,
2772
+ blockId: record.blockId ?? "",
2773
+ blockVersion: record.blockVersion ?? 0,
2776
2774
  resultId: record.resultId,
2777
2775
  type: metricKey,
2778
2776
  value: m.value,
@@ -2814,117 +2812,6 @@ function eventsToStoredLogs(events) {
2814
2812
  }));
2815
2813
  }
2816
2814
 
2817
- // src/dashboard/frontmatter.ts
2818
- var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
2819
- function unquote(value) {
2820
- return value.replace(
2821
- /^(['"])(.*)\1$/,
2822
- (_match, quote, inner) => quote === '"' ? inner.replace(/\\(["\\])/g, "$1") : inner
2823
- );
2824
- }
2825
- function parseFrontmatter(raw) {
2826
- const match = raw.match(FRONTMATTER_RE);
2827
- if (!match) return { meta: {}, body: raw };
2828
- return { meta: parseMetaLines(match[1].split(/\r?\n/)), body: raw.slice(match[0].length) };
2829
- }
2830
- function parseMetaLines(lines) {
2831
- const meta = {};
2832
- for (let i = 0; i < lines.length; i++) {
2833
- const keyMatch = lines[i].match(/^([A-Za-z][\w.-]*)\s*:(.*)$/);
2834
- if (!keyMatch) continue;
2835
- const key = keyMatch[1];
2836
- const rawVal = keyMatch[2].trim();
2837
- if (rawVal === "") {
2838
- const items = [];
2839
- while (i + 1 < lines.length) {
2840
- const itemMatch = lines[i + 1].match(/^\s+-\s+(.+)$/);
2841
- if (!itemMatch) break;
2842
- items.push(itemMatch[1].trim());
2843
- i++;
2844
- }
2845
- meta[key] = items.length > 0 ? items : "";
2846
- } else {
2847
- const wasQuoted = /^(['"])(.*)\1$/.test(rawVal);
2848
- const value = unquote(rawVal);
2849
- const num = Number(value);
2850
- meta[key] = !wasQuoted && value !== "" && !isNaN(num) ? num : value;
2851
- }
2852
- }
2853
- return meta;
2854
- }
2855
- function parseFrontmatterBody(innerContent) {
2856
- return parseMetaLines(innerContent.split(/\r?\n/));
2857
- }
2858
- function quoteYamlScalar(value) {
2859
- if (value === "") return '""';
2860
- const looksNumeric = !isNaN(Number(value));
2861
- const looksKeyword = /^(true|false|null|yes|no|on|off)$/i.test(value);
2862
- if (/[":'\n#{}[\\],&*?|<>=%!@`]/.test(value) || value !== value.trim() || value.startsWith("-") || looksNumeric || looksKeyword) {
2863
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
2864
- }
2865
- return value;
2866
- }
2867
- function serializeFrontmatter(meta) {
2868
- const lines = [];
2869
- for (const [key, value] of Object.entries(meta)) {
2870
- if (Array.isArray(value)) {
2871
- if (value.length === 0) {
2872
- lines.push(`${key}: ""`);
2873
- continue;
2874
- }
2875
- lines.push(`${key}:`);
2876
- for (const item of value) {
2877
- lines.push(` - ${quoteYamlScalar(item)}`);
2878
- }
2879
- } else if (typeof value === "number") {
2880
- lines.push(`${key}: ${value}`);
2881
- } else {
2882
- lines.push(`${key}: ${quoteYamlScalar(value)}`);
2883
- }
2884
- }
2885
- return lines.join("\n");
2886
- }
2887
- function stripFrontmatter(raw) {
2888
- return parseFrontmatter(raw).body;
2889
- }
2890
- function getScalar(meta, key) {
2891
- const value = meta[key];
2892
- return typeof value === "string" || typeof value === "number" ? value : void 0;
2893
- }
2894
- function getList(meta, key) {
2895
- const value = meta[key];
2896
- return Array.isArray(value) ? value : [];
2897
- }
2898
- function parseFrontmatterCategories(raw) {
2899
- return getList(parseFrontmatter(raw).meta, "category").map((c) => c.toLowerCase());
2900
- }
2901
- function extractFrontmatterTags(raw) {
2902
- const meta = FRONTMATTER_RE.test(raw) ? parseFrontmatter(raw).meta : parseFrontmatterBody(raw);
2903
- const tags = meta["tags"];
2904
- const list = Array.isArray(tags) ? tags : typeof tags === "string" && tags.trim() ? tags.trim().startsWith("[") && tags.trim().endsWith("]") ? tags.trim().slice(1, -1).split(",") : [tags] : [];
2905
- return [...new Set(list.map((tag) => tag.trim()).filter(Boolean))];
2906
- }
2907
- function parseFlatProperties(innerContent) {
2908
- const props = {};
2909
- for (const line of innerContent.split(/\r?\n/)) {
2910
- const match = line.match(/^([^:]+):\s*(.*)$/);
2911
- if (match) {
2912
- props[match[1].trim()] = match[2].trim();
2913
- }
2914
- }
2915
- return props;
2916
- }
2917
- function parseFrontmatterProps(lines) {
2918
- const props = {};
2919
- for (const line of lines) {
2920
- const match = line.match(/^([^:]+):\s*(.*)$/);
2921
- if (match) {
2922
- props[match[1].trim()] = match[2].trim();
2923
- }
2924
- }
2925
- return props;
2926
- }
2927
-
2928
2815
  // src/selection.ts
2929
2816
  function partitionKey(coverage, effortSlug) {
2930
2817
  const tags = coverage?.groupTags ? Object.entries(coverage.groupTags).sort(([a], [b]) => a < b ? -1 : 1).map(([k, v]) => `${k}=${v}`).join(",") : "";
@@ -3044,6 +2931,12 @@ function sourceMatches(item, kind) {
3044
2931
  if (kind === "playground") {
3045
2932
  return sourceId === "playground" || item.type === "playground";
3046
2933
  }
2934
+ if (kind.startsWith("feed:")) {
2935
+ const rest = kind.slice("feed:".length).replace(/^feeds\//, "");
2936
+ if (!rest || !sourceId?.startsWith("feed:")) return false;
2937
+ const idRest = sourceId.slice("feed:".length).replace(/^feeds\//, "");
2938
+ return idRest === rest || idRest.startsWith(`${rest}/`);
2939
+ }
3047
2940
  return sourceId === kind;
3048
2941
  }
3049
2942
  function applySourceFilter(items, filters) {
@@ -3398,7 +3291,6 @@ var QueryService = class {
3398
3291
  noteStore;
3399
3292
  blockStore;
3400
3293
  effortStore;
3401
- staticNoteStore;
3402
3294
  pageStore;
3403
3295
  relationStore;
3404
3296
  datasetStore;
@@ -3413,14 +3305,13 @@ var QueryService = class {
3413
3305
  noteTagsStore = {
3414
3306
  getAllFromIndex: async () => []
3415
3307
  };
3416
- constructor(storesOrEventStore, noteStore, blockStore, effortStore, staticNoteStore) {
3417
- if (storesOrEventStore && typeof storesOrEventStore === "object" && ("eventStore" in storesOrEventStore || "noteStore" in storesOrEventStore || "blockStore" in storesOrEventStore || "effortStore" in storesOrEventStore || "staticNoteStore" in storesOrEventStore || "pageStore" in storesOrEventStore || "relationStore" in storesOrEventStore || "datasetStore" in storesOrEventStore)) {
3308
+ constructor(storesOrEventStore, noteStore, blockStore, effortStore) {
3309
+ if (storesOrEventStore && typeof storesOrEventStore === "object" && ("eventStore" in storesOrEventStore || "noteStore" in storesOrEventStore || "blockStore" in storesOrEventStore || "effortStore" in storesOrEventStore || "pageStore" in storesOrEventStore || "relationStore" in storesOrEventStore || "datasetStore" in storesOrEventStore)) {
3418
3310
  const stores = storesOrEventStore;
3419
3311
  this.store = stores.eventStore ?? defaultEventStore;
3420
3312
  this.noteStore = stores.noteStore ?? defaultNoteStore;
3421
3313
  this.blockStore = stores.blockStore ?? defaultBlockStore;
3422
3314
  this.effortStore = stores.effortStore ?? defaultEffortStore;
3423
- this.staticNoteStore = stores.staticNoteStore;
3424
3315
  this.pageStore = stores.pageStore;
3425
3316
  this.relationStore = stores.relationStore;
3426
3317
  this.datasetStore = stores.datasetStore;
@@ -3432,7 +3323,6 @@ var QueryService = class {
3432
3323
  this.noteStore = noteStore ?? defaultNoteStore;
3433
3324
  this.blockStore = blockStore ?? defaultBlockStore;
3434
3325
  this.effortStore = effortStore ?? defaultEffortStore;
3435
- this.staticNoteStore = staticNoteStore;
3436
3326
  }
3437
3327
  }
3438
3328
  /** Windowed flat-fact fetch — the projected view over the event store. */
@@ -3752,14 +3642,11 @@ var QueryService = class {
3752
3642
  }
3753
3643
  const isCatalogHead = parsed.target === "note" && parsed.filters.some((f) => f.key === "type" && !f.negate && f.values.some((v) => v.value === "feed")) && (parsed.filters.some((f) => f.key === "source" && !f.negate && f.values.some((v) => v.value === "feed" || v.value === "feeds")) || parsed.sourceScope?.includes("feeds"));
3754
3644
  if (isCatalogHead) {
3755
- const notes2 = (await this.noteStore.getAllNotes()).concat(
3756
- this.staticNoteStore ? await this.staticNoteStore.getAllNotes() : []
3757
- );
3758
- return this.runFindCatalog(parsed, options2, notes2);
3645
+ return this.runFindCatalog(parsed, options2, await this.noteStore.getAllNotes());
3759
3646
  }
3760
3647
  const read = compileContentRead(parsed.filters, "note", parsed.sourceScope);
3761
- const paging = domainPaging(parsed, options2, read.residual || !!this.staticNoteStore);
3762
- const fetchedNotes = !this.staticNoteStore && (read.filters.length > 0 || read.selection.length > 0 || paging.paged) && this.noteStore.queryDomain ? await this.noteStore.queryDomain({
3648
+ const paging = domainPaging(parsed, options2, read.residual);
3649
+ const fetchedNotes = (read.filters.length > 0 || read.selection.length > 0 || paging.paged) && this.noteStore.queryDomain ? await this.noteStore.queryDomain({
3763
3650
  plan: "notes",
3764
3651
  selection: read.selection,
3765
3652
  ...read.filters.length ? { filters: read.filters } : {},
@@ -3771,11 +3658,6 @@ var QueryService = class {
3771
3658
  let notes = domainNotes ? domainNotes.rows : await this.noteStore.getAllNotes();
3772
3659
  const selectedFromDomain = domainNotes ? domainNotes.selectedCount : void 0;
3773
3660
  const notesPaged = !!domainNotes && paging.paged;
3774
- if (this.staticNoteStore) {
3775
- const staticRows = applyNoteSelectionStages(await this.staticNoteStore.getAllNotes(), parsed);
3776
- const known = new Set(notes.map((n) => n.id));
3777
- notes = notes.concat(staticRows.filter((n) => !known.has(n.id)));
3778
- }
3779
3661
  notes = applyNoteSelectionStages(notes, parsed);
3780
3662
  const selectedCount = selectedFromDomain ?? notes.length;
3781
3663
  const ctx = runContext(options2);
@@ -3784,16 +3666,13 @@ var QueryService = class {
3784
3666
  const matchingIds = /* @__PURE__ */ new Set();
3785
3667
  for (const v of filter.values) {
3786
3668
  const ids = await this.noteStore.getNoteIdsForTag(v.value);
3787
- const sIds = this.staticNoteStore ? await this.staticNoteStore.getNoteIdsForTag(v.value) : /* @__PURE__ */ new Set();
3788
3669
  ids.forEach((id) => matchingIds.add(id));
3789
- sIds.forEach((id) => matchingIds.add(id));
3790
3670
  }
3791
3671
  notes = notes.filter((n) => matchingIds.has(n.id));
3792
3672
  } else if (filter.key === "tags" && filter.negate) {
3793
3673
  for (const v of filter.values) {
3794
3674
  const ids = await this.noteStore.getNoteIdsForTag(v.value);
3795
- const sIds = this.staticNoteStore ? await this.staticNoteStore.getNoteIdsForTag(v.value) : /* @__PURE__ */ new Set();
3796
- notes = notes.filter((n) => !ids.has(n.id) && !sIds.has(n.id));
3675
+ notes = notes.filter((n) => !ids.has(n.id));
3797
3676
  }
3798
3677
  } else if (filter.key === "effort" && !filter.negate) {
3799
3678
  const matchingIds = /* @__PURE__ */ new Set();
@@ -3812,9 +3691,12 @@ var QueryService = class {
3812
3691
  }
3813
3692
  }
3814
3693
  for (const filter of parsed.filters) {
3815
- if (filter.key === "text" && !filter.negate) {
3694
+ if (filter.key === "text") {
3816
3695
  const search = filter.values.map((v) => v.value).join(" ").toLowerCase();
3817
- notes = notes.filter((n) => n.title.toLowerCase().includes(search));
3696
+ notes = notes.filter((n) => {
3697
+ const hit = n.title.toLowerCase().includes(search) || n.rawContent.toLowerCase().includes(search);
3698
+ return filter.negate ? !hit : hit;
3699
+ });
3818
3700
  }
3819
3701
  }
3820
3702
  for (const filter of parsed.filters) {
@@ -3911,6 +3793,26 @@ var QueryService = class {
3911
3793
  }
3912
3794
  return containers;
3913
3795
  }
3796
+ async hydrateBlocks(rows) {
3797
+ const ids = [...new Set(rows.map((row) => row.noteId))];
3798
+ if (ids.length === 0) return [];
3799
+ const notes = this.noteStore.getNotesByIds ? await this.noteStore.getNotesByIds(ids) : await this.noteStore.getAllNotes();
3800
+ const parents = /* @__PURE__ */ new Map();
3801
+ for (const note of notes) {
3802
+ if (!Number.isSafeInteger(note.sourceRevision) || note.sourceRevision < 1) continue;
3803
+ try {
3804
+ validateNoteBlocks(note.rawContent, note.blocks, note.sourceRevision);
3805
+ parents.set(note.id, note);
3806
+ } catch {
3807
+ }
3808
+ }
3809
+ return rows.flatMap((row) => {
3810
+ const note = parents.get(row.noteId);
3811
+ const block = note?.blocks[row.blockId];
3812
+ if (!note || !block || row.id !== `${note.id}:${block.id}` || block.id !== row.blockId || block.kind !== row.dataType || block.version !== row.blockVersion || block.sourceRevision !== row.sourceRevision || note.sourceRevision !== row.sourceRevision || block.from !== row.from || block.to !== row.to) return [];
3813
+ return [{ ...row, rawContent: note.rawContent.slice(block.from, block.to) }];
3814
+ });
3815
+ }
3914
3816
  /**
3915
3817
  * Execute a :block query against the derived block_index store.
3916
3818
  */
@@ -3926,17 +3828,20 @@ var QueryService = class {
3926
3828
  ...paging.limit !== void 0 ? { limit: paging.limit } : {}
3927
3829
  }) : void 0;
3928
3830
  const domainBlocks = fetchedBlocks && fetchedBlocks.plan === "blocks" ? fetchedBlocks : void 0;
3929
- let blocks = domainBlocks ? domainBlocks.rows : await this.blockStore.getAllBlocks();
3930
- const selectedFromDomain = domainBlocks ? domainBlocks.selectedCount : void 0;
3931
- const blocksPaged = !!domainBlocks && paging.paged;
3831
+ const candidates = domainBlocks ? domainBlocks.rows : await this.blockStore.getAllBlocks();
3832
+ let blocks = await this.hydrateBlocks(candidates);
3833
+ const invalidCandidates = blocks.length !== candidates.length;
3834
+ const selectedFromDomain = domainBlocks && !invalidCandidates ? domainBlocks.selectedCount : void 0;
3835
+ const blocksPaged = !!domainBlocks && paging.paged && !invalidCandidates;
3836
+ if (domainBlocks && invalidCandidates) blocks = await this.hydrateBlocks(await this.blockStore.getAllBlocks());
3932
3837
  blocks = applySourceFilter(blocks, parsed.filters);
3933
3838
  blocks = blocks.filter((b) => !b.sourceId || WQL_SOURCE_VALUES.some((k) => sourceMatches(b, k)));
3934
3839
  const selectedCount = selectedFromDomain ?? blocks.length;
3935
3840
  const ctx = runContext(options2);
3936
3841
  for (const filter of parsed.filters) {
3937
- if (filter.key === "text" && !filter.negate) {
3842
+ if (filter.key === "text") {
3938
3843
  const search = filter.values.map((v) => v.value).join(" ").toLowerCase();
3939
- blocks = blocks.filter((b) => b.rawContent.toLowerCase().includes(search));
3844
+ blocks = blocks.filter((b) => filter.negate !== b.rawContent.toLowerCase().includes(search));
3940
3845
  }
3941
3846
  }
3942
3847
  for (const filter of parsed.filters) {
@@ -3961,18 +3866,16 @@ var QueryService = class {
3961
3866
  const matchingNoteIds = /* @__PURE__ */ new Set();
3962
3867
  for (const v of filter.values) {
3963
3868
  const ids = await this.noteStore.getNoteIdsForTag(v.value);
3964
- const sIds = this.staticNoteStore ? await this.staticNoteStore.getNoteIdsForTag(v.value) : /* @__PURE__ */ new Set();
3965
3869
  ids.forEach((id) => matchingNoteIds.add(id));
3966
- sIds.forEach((id) => matchingNoteIds.add(id));
3967
3870
  }
3968
3871
  blocks = blocks.filter((b) => matchingNoteIds.has(b.noteId));
3969
3872
  } else if (filter.key === "effort" && !filter.negate) {
3970
3873
  const matchingBlockIds = /* @__PURE__ */ new Set();
3971
3874
  for (const v of filter.values) {
3972
3875
  const rows = await this.blockEffortsStore.getAllFromIndex("by-effort", v.value);
3973
- for (const r of rows) matchingBlockIds.add(r.blockContentId);
3876
+ for (const row of rows) matchingBlockIds.add(`${row.noteId}:${row.blockId}`);
3974
3877
  }
3975
- blocks = blocks.filter((b) => b.blockContentId && matchingBlockIds.has(b.blockContentId));
3878
+ blocks = blocks.filter((block) => matchingBlockIds.has(`${block.noteId}:${block.blockId}`));
3976
3879
  }
3977
3880
  }
3978
3881
  for (const filter of parsed.filters) {
@@ -3982,11 +3885,7 @@ var QueryService = class {
3982
3885
  }
3983
3886
  }
3984
3887
  if (parsed.window || options2.range) {
3985
- let allNotes = [];
3986
- allNotes = allNotes.concat(await this.noteStore.getAllNotes());
3987
- if (this.staticNoteStore) {
3988
- allNotes = allNotes.concat(await this.staticNoteStore.getAllNotes());
3989
- }
3888
+ const allNotes = await this.noteStore.getAllNotes();
3990
3889
  const noteTimeMap = new Map(allNotes.map((n) => [n.id, n.date ?? n.createdAt]));
3991
3890
  blocks = blocks.filter((b) => effectiveTimeWindow(noteTimeMap.get(b.noteId) ?? b.createdAt, parsed.window, options2.range, ctx));
3992
3891
  }
@@ -4364,7 +4263,7 @@ var QueryService = class {
4364
4263
  let values;
4365
4264
  try {
4366
4265
  values = members.map(
4367
- (m) => shouldConvert && targetUnit ? convertViaCatalog(m.value, m.unit ?? m.metricUnit, targetUnit) : m.value
4266
+ (m) => shouldConvert && targetUnit && (m.unit ?? m.metricUnit) !== void 0 ? convertViaCatalog(m.value, m.unit ?? m.metricUnit, targetUnit) : m.value
4368
4267
  );
4369
4268
  } catch (e) {
4370
4269
  error = e instanceof Error ? e.message : String(e);
@@ -4486,7 +4385,7 @@ var QueryService = class {
4486
4385
  }
4487
4386
  /** All content blocks — journal and seeded corpus in one store. */
4488
4387
  async allContentBlocks() {
4489
- return this.blockStore.getAllBlocks();
4388
+ return this.hydrateBlocks(await this.blockStore.getAllBlocks());
4490
4389
  }
4491
4390
  /** Map each note id to the wod blockContentIds it owns. */
4492
4391
  async noteContentMap(noteIds) {
@@ -4563,7 +4462,10 @@ var QueryService = class {
4563
4462
  type: "feed",
4564
4463
  sourceId: `page:collection:${cat}`,
4565
4464
  catalog: cat,
4566
- createdAt: n.createdAt ?? 0
4465
+ createdAt: n.createdAt ?? 0,
4466
+ rawContent: "",
4467
+ sourceRevision: 1,
4468
+ blocks: {}
4567
4469
  });
4568
4470
  existingCatIds.add(cat);
4569
4471
  }
@@ -4612,9 +4514,7 @@ var QueryService = class {
4612
4514
  const matchingIds = /* @__PURE__ */ new Set();
4613
4515
  for (const v of filter.values) {
4614
4516
  const ids = await this.noteStore.getNoteIdsForTag(v.value);
4615
- const sIds = this.staticNoteStore ? await this.staticNoteStore.getNoteIdsForTag(v.value) : /* @__PURE__ */ new Set();
4616
4517
  ids.forEach((id) => matchingIds.add(id));
4617
- sIds.forEach((id) => matchingIds.add(id));
4618
4518
  }
4619
4519
  matchingCatalogs = matchingCatalogs.filter((c) => {
4620
4520
  const catId = catalogOfItem(c) ?? c.id;
@@ -4639,7 +4539,7 @@ var QueryService = class {
4639
4539
  matchingCatalogs = matchingCatalogs.filter((c) => {
4640
4540
  const catId = catalogOfItem(c) ?? c.id;
4641
4541
  const members = membersByCat.get(catId) ?? [];
4642
- const hit = members.some((m) => m.title.toLowerCase().includes(search));
4542
+ const hit = members.some((m) => m.title.toLowerCase().includes(search) || m.rawContent.toLowerCase().includes(search));
4643
4543
  return filter.negate ? !hit : hit;
4644
4544
  });
4645
4545
  } else if (filter.key === "note") {
@@ -4679,56 +4579,6 @@ var QueryService = class {
4679
4579
  }
4680
4580
  };
4681
4581
 
4682
- // src/static.ts
4683
- function staticCatalogRoute(block) {
4684
- const sourceId = block.sourceId;
4685
- if (sourceId?.startsWith("page:collection:")) {
4686
- const catalog = sourceId.slice("page:collection:".length);
4687
- if (catalog) return { landing: true, catalog, sourceId };
4688
- } else if (sourceId?.startsWith("collection:")) {
4689
- const route = sourceId.slice("collection:".length);
4690
- if (route) {
4691
- const slash = route.indexOf("/");
4692
- return slash === -1 ? { landing: true, catalog: route, sourceId: `page:collection:${route}` } : { landing: false, catalog: route.slice(0, slash), sourceId };
4693
- }
4694
- } else if (sourceId?.startsWith("feed:")) {
4695
- const route = sourceId.slice("feed:".length);
4696
- if (route) {
4697
- const stem = route.startsWith("feeds/") ? route.slice("feeds/".length) : route;
4698
- return { landing: false, catalog: stem.split("/")[0], sourceId };
4699
- }
4700
- }
4701
- return { landing: false, catalog: catalogOfItem({ noteId: block.noteId, sourceId: block.sourceId }), sourceId };
4702
- }
4703
- function staticNotesFromBlocks(blocks) {
4704
- const map = /* @__PURE__ */ new Map();
4705
- for (const block of blocks) {
4706
- if (map.has(block.noteId)) continue;
4707
- const route = staticCatalogRoute(block);
4708
- map.set(block.noteId, {
4709
- id: block.noteId,
4710
- title: block.noteTitle,
4711
- createdAt: block.createdAt,
4712
- type: route.landing ? "feed" : "note",
4713
- sourceId: route.sourceId,
4714
- catalog: route.catalog
4715
- });
4716
- }
4717
- return Array.from(map.values());
4718
- }
4719
- function staticTagIndexFromBlocks(blocks) {
4720
- const index = /* @__PURE__ */ new Map();
4721
- for (const block of blocks) {
4722
- if (block.dataType !== "frontmatter") continue;
4723
- for (const tag of extractFrontmatterTags(block.rawContent)) {
4724
- const ids = index.get(tag);
4725
- if (ids) ids.add(block.noteId);
4726
- else index.set(tag, /* @__PURE__ */ new Set([block.noteId]));
4727
- }
4728
- }
4729
- return index;
4730
- }
4731
-
4732
4582
  // src/dashboard/model.ts
4733
4583
  var DASHBOARD_WIDGET_TYPES = [
4734
4584
  "table",
@@ -4917,6 +4767,117 @@ function buildDashboardDocument(sections, meta) {
4917
4767
  };
4918
4768
  }
4919
4769
 
4770
+ // src/dashboard/frontmatter.ts
4771
+ var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
4772
+ function unquote(value) {
4773
+ return value.replace(
4774
+ /^(['"])(.*)\1$/,
4775
+ (_match, quote, inner) => quote === '"' ? inner.replace(/\\(["\\])/g, "$1") : inner
4776
+ );
4777
+ }
4778
+ function parseFrontmatter(raw) {
4779
+ const match = raw.match(FRONTMATTER_RE);
4780
+ if (!match) return { meta: {}, body: raw };
4781
+ return { meta: parseMetaLines(match[1].split(/\r?\n/)), body: raw.slice(match[0].length) };
4782
+ }
4783
+ function parseMetaLines(lines) {
4784
+ const meta = {};
4785
+ for (let i = 0; i < lines.length; i++) {
4786
+ const keyMatch = lines[i].match(/^([A-Za-z][\w.-]*)\s*:(.*)$/);
4787
+ if (!keyMatch) continue;
4788
+ const key = keyMatch[1];
4789
+ const rawVal = keyMatch[2].trim();
4790
+ if (rawVal === "") {
4791
+ const items = [];
4792
+ while (i + 1 < lines.length) {
4793
+ const itemMatch = lines[i + 1].match(/^\s+-\s+(.+)$/);
4794
+ if (!itemMatch) break;
4795
+ items.push(itemMatch[1].trim());
4796
+ i++;
4797
+ }
4798
+ meta[key] = items.length > 0 ? items : "";
4799
+ } else {
4800
+ const wasQuoted = /^(['"])(.*)\1$/.test(rawVal);
4801
+ const value = unquote(rawVal);
4802
+ const num = Number(value);
4803
+ meta[key] = !wasQuoted && value !== "" && !isNaN(num) ? num : value;
4804
+ }
4805
+ }
4806
+ return meta;
4807
+ }
4808
+ function parseFrontmatterBody(innerContent) {
4809
+ return parseMetaLines(innerContent.split(/\r?\n/));
4810
+ }
4811
+ function quoteYamlScalar(value) {
4812
+ if (value === "") return '""';
4813
+ const looksNumeric = !isNaN(Number(value));
4814
+ const looksKeyword = /^(true|false|null|yes|no|on|off)$/i.test(value);
4815
+ if (/[":'\n#{}[\\],&*?|<>=%!@`]/.test(value) || value !== value.trim() || value.startsWith("-") || looksNumeric || looksKeyword) {
4816
+ return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
4817
+ }
4818
+ return value;
4819
+ }
4820
+ function serializeFrontmatter(meta) {
4821
+ const lines = [];
4822
+ for (const [key, value] of Object.entries(meta)) {
4823
+ if (Array.isArray(value)) {
4824
+ if (value.length === 0) {
4825
+ lines.push(`${key}: ""`);
4826
+ continue;
4827
+ }
4828
+ lines.push(`${key}:`);
4829
+ for (const item of value) {
4830
+ lines.push(` - ${quoteYamlScalar(item)}`);
4831
+ }
4832
+ } else if (typeof value === "number") {
4833
+ lines.push(`${key}: ${value}`);
4834
+ } else {
4835
+ lines.push(`${key}: ${quoteYamlScalar(value)}`);
4836
+ }
4837
+ }
4838
+ return lines.join("\n");
4839
+ }
4840
+ function stripFrontmatter(raw) {
4841
+ return parseFrontmatter(raw).body;
4842
+ }
4843
+ function getScalar(meta, key) {
4844
+ const value = meta[key];
4845
+ return typeof value === "string" || typeof value === "number" ? value : void 0;
4846
+ }
4847
+ function getList(meta, key) {
4848
+ const value = meta[key];
4849
+ return Array.isArray(value) ? value : [];
4850
+ }
4851
+ function parseFrontmatterCategories(raw) {
4852
+ return getList(parseFrontmatter(raw).meta, "category").map((c) => c.toLowerCase());
4853
+ }
4854
+ function extractFrontmatterTags(raw) {
4855
+ const meta = FRONTMATTER_RE.test(raw) ? parseFrontmatter(raw).meta : parseFrontmatterBody(raw);
4856
+ const tags = meta["tags"];
4857
+ const list = Array.isArray(tags) ? tags : typeof tags === "string" && tags.trim() ? tags.trim().startsWith("[") && tags.trim().endsWith("]") ? tags.trim().slice(1, -1).split(",") : [tags] : [];
4858
+ return [...new Set(list.map((tag) => tag.trim()).filter(Boolean))];
4859
+ }
4860
+ function parseFlatProperties(innerContent) {
4861
+ const props = {};
4862
+ for (const line of innerContent.split(/\r?\n/)) {
4863
+ const match = line.match(/^([^:]+):\s*(.*)$/);
4864
+ if (match) {
4865
+ props[match[1].trim()] = match[2].trim();
4866
+ }
4867
+ }
4868
+ return props;
4869
+ }
4870
+ function parseFrontmatterProps(lines) {
4871
+ const props = {};
4872
+ for (const line of lines) {
4873
+ const match = line.match(/^([^:]+):\s*(.*)$/);
4874
+ if (match) {
4875
+ props[match[1].trim()] = match[2].trim();
4876
+ }
4877
+ }
4878
+ return props;
4879
+ }
4880
+
4920
4881
  // src/dashboard/parser.ts
4921
4882
  function parseDashboardNote(rawContent) {
4922
4883
  const { meta } = parseFrontmatter(rawContent);
@@ -5121,6 +5082,44 @@ function appendWidget(raw, spec) {
5121
5082
  while (lines.length > 0 && lines[lines.length - 1] === "") lines.pop();
5122
5083
  return [...lines, "", ...group, ""].join("\n");
5123
5084
  }
5085
+ function widgetResult(raw, note, order) {
5086
+ let from = 0;
5087
+ while (from < raw.length && from < note.length && raw[from] === note[from]) from++;
5088
+ let to = raw.length;
5089
+ let nextTo = note.length;
5090
+ while (to > from && nextTo > from && raw[to - 1] === note[nextTo - 1]) {
5091
+ to--;
5092
+ nextTo--;
5093
+ }
5094
+ const queries = parseDashboardNote(raw).sections.filter((section) => section.type === "query");
5095
+ const nextQueries = parseDashboardNote(note).sections.filter((section) => section.type === "query");
5096
+ const oldOffsets = lineOffsets(raw);
5097
+ const nextOffsets = lineOffsets(note);
5098
+ const oldLines = raw.split("\n");
5099
+ const nextLines = note.split("\n");
5100
+ const retainedBlocks = [];
5101
+ for (const [nextIndex, oldIndex] of (order ?? queries.map((_, index) => index)).entries()) {
5102
+ if (oldIndex === null) continue;
5103
+ const block = queries[oldIndex];
5104
+ const next = nextQueries[nextIndex];
5105
+ if (!block || !next) throw new Error("Widget mutation lost its source lineage");
5106
+ retainedBlocks.push({
5107
+ from: oldOffsets[block.startLine],
5108
+ to: oldOffsets[block.endLine] + oldLines[block.endLine].replace(/\r$/, "").length,
5109
+ nextFrom: nextOffsets[next.startLine],
5110
+ nextTo: nextOffsets[next.endLine] + nextLines[next.endLine].replace(/\r$/, "").length
5111
+ });
5112
+ }
5113
+ return { ok: true, note, changes: raw === note ? [] : [{ from, to, insert: note.slice(from, nextTo) }], retainedBlocks };
5114
+ }
5115
+ function lineOffsets(raw) {
5116
+ let offset = 0;
5117
+ return raw.split("\n").map((line) => {
5118
+ const from = offset;
5119
+ offset += line.length + 1;
5120
+ return from;
5121
+ });
5122
+ }
5124
5123
  function updateWidget(raw, key, expectedBody, spec) {
5125
5124
  const { sections } = parseDashboardNote(raw);
5126
5125
  const found = findWidgetGroup(sections, key, expectedBody);
@@ -5128,7 +5127,7 @@ function updateWidget(raw, key, expectedBody, spec) {
5128
5127
  const { group } = found;
5129
5128
  const lines = raw.split("\n");
5130
5129
  lines.splice(group.startLine, group.endLine - group.startLine + 1, ...renderWidgetGroup(spec));
5131
- return { ok: true, note: lines.join("\n") };
5130
+ return widgetResult(raw, lines.join("\n"));
5132
5131
  }
5133
5132
  function duplicateWidget(raw, key, expectedBody) {
5134
5133
  const { sections } = parseDashboardNote(raw);
@@ -5138,7 +5137,9 @@ function duplicateWidget(raw, key, expectedBody) {
5138
5137
  const lines = raw.split("\n");
5139
5138
  const copy = lines.slice(group.startLine, group.endLine + 1);
5140
5139
  lines.splice(group.endLine + 1, 0, "", ...copy);
5141
- return { ok: true, note: lines.join("\n") };
5140
+ const order = sections.filter((section) => section.type === "query").map((_, index) => index);
5141
+ order.splice(group.widgetIndex + 1, 0, null);
5142
+ return widgetResult(raw, lines.join("\n"), order);
5142
5143
  }
5143
5144
  function removeWidget(raw, key, expectedBody) {
5144
5145
  const { sections } = parseDashboardNote(raw);
@@ -5150,7 +5151,9 @@ function removeWidget(raw, key, expectedBody) {
5150
5151
  if (group.startLine > 0 && group.startLine < lines.length && lines[group.startLine - 1] === "" && lines[group.startLine] === "") {
5151
5152
  lines.splice(group.startLine, 1);
5152
5153
  }
5153
- return { ok: true, note: lines.join("\n") };
5154
+ const order = sections.filter((section) => section.type === "query").map((_, index) => index);
5155
+ order.splice(group.widgetIndex, 1);
5156
+ return widgetResult(raw, lines.join("\n"), order);
5154
5157
  }
5155
5158
  function moveWidget(raw, key, expectedBody, delta) {
5156
5159
  const { sections } = parseDashboardNote(raw);
@@ -5159,7 +5162,7 @@ function moveWidget(raw, key, expectedBody, delta) {
5159
5162
  const { group } = found;
5160
5163
  const groups = widgetGroupRanges(sections);
5161
5164
  const neighbor = groups[group.widgetIndex + delta];
5162
- if (!neighbor) return { ok: true, note: raw };
5165
+ if (!neighbor) return widgetResult(raw, raw);
5163
5166
  const lines = raw.split("\n");
5164
5167
  const moving = lines.slice(group.startLine, group.endLine + 1);
5165
5168
  if (delta === -1) {
@@ -5171,7 +5174,10 @@ function moveWidget(raw, key, expectedBody, delta) {
5171
5174
  const insertAt = neighbor.endLine - shift + 1;
5172
5175
  lines.splice(insertAt, 0, ...moving);
5173
5176
  }
5174
- return { ok: true, note: lines.join("\n") };
5177
+ const order = groups.map((_, index) => index);
5178
+ order.splice(group.widgetIndex, 1);
5179
+ order.splice(group.widgetIndex + delta, 0, group.widgetIndex);
5180
+ return widgetResult(raw, lines.join("\n"), order);
5175
5181
  }
5176
5182
  function resizeWidget(raw, key, expectedBody, span) {
5177
5183
  if (span.spanCols != null && (span.spanCols < 1 || span.spanCols > DASHBOARD_GRID_MAX_COLS)) {
@@ -5193,7 +5199,7 @@ function resizeWidget(raw, key, expectedBody, span) {
5193
5199
  attributes: block.attributes,
5194
5200
  attributeOrder: block.attributeOrder
5195
5201
  });
5196
- return { ok: true, note: lines.join("\n") };
5202
+ return widgetResult(raw, lines.join("\n"));
5197
5203
  }
5198
5204
  function migrateLegacyDashboardBodies(raw) {
5199
5205
  let out = raw;
@@ -5214,15 +5220,15 @@ ${query}
5214
5220
  }
5215
5221
 
5216
5222
  // src/version.ts
5217
- var VERSION = "0.35.2116";
5218
- var GIT_SHA = "a4d411f";
5219
- var BUILD_TIME = "2026-10-12T00:14:24.795Z";
5223
+ var VERSION = "0.35.2119";
5224
+ var GIT_SHA = "e0eb840";
5225
+ var BUILD_TIME = "2026-10-13T06:24:52.520Z";
5220
5226
  var SEMVER = {
5221
- version: "0.35.2116",
5222
- gitSha: "a4d411f",
5223
- buildTime: "2026-10-12T00:14:24.795Z"
5227
+ version: "0.35.2119",
5228
+ gitSha: "e0eb840",
5229
+ buildTime: "2026-10-13T06:24:52.520Z"
5224
5230
  };
5225
5231
 
5226
- export { BUILD_TIME, CONTENT_GROUPING_DIMENSIONS, DASHBOARD_GRID_MAX_COLS, DASHBOARD_WIDGET_TYPES, DEFAULT_DASHBOARD_TITLE, DISCIPLINE_FACTORS, EFFORT_DISCIPLINES, GIT_SHA, PLANNED_WIDGET_TYPES, PageSourceRegistry, QueryDocumentRunner, QueryService, SEMVER, QueryDocumentRunner2 as SharedQueryDocumentRunner, UNASSIGNED, VERSION, WQL_AGGREGATORS, WQL_CALC_TARGETS, WQL_CHART_HEADS, WQL_COMPARISON_OPS, WQL_CONTENT_FILTER_KEYS, WQL_CONTENT_ONLY_KEYS, WQL_DISPLAY_UNITS, WQL_EFFORT_FILTER_KEYS, WQL_FIND_TARGETS, WQL_FUNCTION_HEADS, WQL_GRAINS, WQL_INTENSITY_TIERS, WQL_KEYWORDS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_NOTE_DEFAULT_SOURCES, WQL_RESULT_PLANES, WQL_ROLLUP_PERIODS, WQL_SOURCES, WQL_SOURCE_HEADS, WQL_SOURCE_HEAD_SCOPES, WQL_SOURCE_VALUES, WQL_STANDARD_DATASETS, WQL_TAG_KEYS, WQL_TYPED_TAG_KEYS, WQL_TYPE_HEADS, WQL_VIRTUAL_DIMS, allowedFilterTypesForTarget, appendSuffixes, appendWidget, buildDashboardDocument, buildDashboardScaffold, buildDrillDownQuery, captureContext, catalogOfItem, civilDateAdd, civilDateDiff, civilDateOf, civilDatesCoveredByRange, civilMonday, consumesRollupFacts, convertDisplay, createBuiltinFormulaEvaluator, dashboardSlug, defaultTokenValues, disciplineFactorFor, duplicateWidget, eventsToStoredLogs, extractDashboardTokens, extractFrontmatterTags, findTargetAdvisories, getList, getScalar, getUnitFamily, inRange, isAggregateQuery, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isPipelineQuery, isProposedMetric, migrateLegacyDashboardBodies, moveWidget, normalizeSummaryFacts, normalizeWql, parseDashboardNote, parseDocument, parseFlatProperties, parseFrontmatter, parseFrontmatterBody, parseFrontmatterCategories, parseFrontmatterProps, parseQuery, parseQueryWidgetSuffix, parseWqlSuffixes, projectEventToFacts, referencedTokens, removeWidget, renderWidgetGroup, resizeWidget, resolveCanonicalMetricKey, resolveOutputUnit, resolveWidgetType, resolveWindowRange, rowsParseError, serialize, serializeDocument, serializeFrontmatter, setDashboardTokenValue, sourceMatches, splitAtWhere, staticCatalogRoute, staticNotesFromBlocks, staticTagIndexFromBlocks, stripFrontmatter, substituteTokens2 as substituteTokens, substituteTokens as substituteTokensRaw, supportsWqlFilterKey, systemTimeZone, toEventRows, toSummaryEventRows, unknownTokensMessage, unknownWidgetTypeMessage, updateWidget, widgetBodyLine, widgetFenceTag, wql, wqlCompletion, wqlCompletionSource, wqlFilterKeys, wqlGroupingDimensions, wqlHighlightStyle, wqlLanguage, parser as wqlParser, wql_parser_terms_exports as wqlTerms, zonedNoon, zonedStartOfDay };
5232
+ export { BUILD_TIME, CONTENT_GROUPING_DIMENSIONS, DASHBOARD_GRID_MAX_COLS, DASHBOARD_WIDGET_TYPES, DEFAULT_DASHBOARD_TITLE, DISCIPLINE_FACTORS, EFFORT_DISCIPLINES, GIT_SHA, PLANNED_WIDGET_TYPES, PageSourceRegistry, QueryDocumentRunner, QueryService, SEMVER, QueryDocumentRunner2 as SharedQueryDocumentRunner, UNASSIGNED, VERSION, WQL_AGGREGATORS, WQL_CALC_TARGETS, WQL_CHART_HEADS, WQL_COMPARISON_OPS, WQL_CONTENT_FILTER_KEYS, WQL_CONTENT_ONLY_KEYS, WQL_DISPLAY_UNITS, WQL_EFFORT_FILTER_KEYS, WQL_FIND_TARGETS, WQL_FUNCTION_HEADS, WQL_GRAINS, WQL_INTENSITY_TIERS, WQL_KEYWORDS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_NOTE_DEFAULT_SOURCES, WQL_RESULT_PLANES, WQL_ROLLUP_PERIODS, WQL_SOURCES, WQL_SOURCE_HEADS, WQL_SOURCE_HEAD_SCOPES, WQL_SOURCE_VALUES, WQL_STANDARD_DATASETS, WQL_TAG_KEYS, WQL_TYPED_TAG_KEYS, WQL_TYPE_HEADS, WQL_VIRTUAL_DIMS, allowedFilterTypesForTarget, appendSuffixes, appendWidget, buildDashboardDocument, buildDashboardScaffold, buildDrillDownQuery, captureContext, catalogOfItem, civilDateAdd, civilDateDiff, civilDateOf, civilDatesCoveredByRange, civilMonday, consumesRollupFacts, convertDisplay, createBuiltinFormulaEvaluator, dashboardSlug, defaultTokenValues, disciplineFactorFor, duplicateWidget, eventsToStoredLogs, extractDashboardTokens, extractFrontmatterTags, findTargetAdvisories, getList, getScalar, getUnitFamily, inRange, isAggregateQuery, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isPipelineQuery, isProposedMetric, migrateLegacyDashboardBodies, moveWidget, normalizeSummaryFacts, normalizeWql, parseDashboardNote, parseDocument, parseFlatProperties, parseFrontmatter, parseFrontmatterBody, parseFrontmatterCategories, parseFrontmatterProps, parseQuery, parseQueryWidgetSuffix, parseWqlSuffixes, projectEventToFacts, referencedTokens, removeWidget, renderWidgetGroup, resizeWidget, resolveCanonicalMetricKey, resolveOutputUnit, resolveWidgetType, resolveWindowRange, rowsParseError, serialize, serializeDocument, serializeFrontmatter, setDashboardTokenValue, sourceMatches, splitAtWhere, stripFrontmatter, substituteTokens2 as substituteTokens, substituteTokens as substituteTokensRaw, supportsWqlFilterKey, systemTimeZone, toEventRows, toSummaryEventRows, unknownTokensMessage, unknownWidgetTypeMessage, updateWidget, widgetBodyLine, widgetFenceTag, wql, wqlCompletion, wqlCompletionSource, wqlFilterKeys, wqlGroupingDimensions, wqlHighlightStyle, wqlLanguage, parser as wqlParser, wql_parser_terms_exports as wqlTerms, zonedNoon, zonedStartOfDay };
5227
5233
  //# sourceMappingURL=index.mjs.map
5228
5234
  //# sourceMappingURL=index.mjs.map