@bitcobblers/wod-wiki-wql 0.9.40 → 0.10.42

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.d.cts CHANGED
@@ -376,6 +376,36 @@ declare function normalizeWql(raw: string): {
376
376
  advisories: string[];
377
377
  };
378
378
 
379
+ /**
380
+ * WQL serializer (C6 — one structured interface for code).
381
+ *
382
+ * The total serializer over the C5 discriminated query union: code holds the
383
+ * AST; strings live only at document edges (URL `?q=`, ```query``` fences,
384
+ * dashboard bodies). Properties (proven by tests/serialize.test.ts):
385
+ *
386
+ * 1. `serialize(parse(x)) === x` for canonical inputs (fixed-point text), and
387
+ * 2. `parse(serialize(a))` is structurally equal to `a` for every AST —
388
+ * equal on all query-structure fields; `raw` (provenance text) and
389
+ * `advisories` (parse-time deprecation notices) are intentionally not
390
+ * reproduced, since serialization emits modern canonical syntax.
391
+ *
392
+ * Errored ASTs serialize to their original `raw` text — a query that failed
393
+ * to parse has no well-defined structure to re-emit, and echoing the input
394
+ * keeps the function total.
395
+ *
396
+ * Round-trip equality holds for text-surface-representable ASTs. Three value
397
+ * shapes the grammar cannot express (or parses away) sit outside that
398
+ * contract — documented here rather than silently corrupted:
399
+ * - a `"` inside a filter value: the quoted token has no escape form;
400
+ * - a quoted value with `wildcard: true`: the parser forces wildcard=false
401
+ * on quoted atoms (extractFilters), so the flag cannot survive;
402
+ * - thresholds whose String() is exponential (>= 1e21): outside the join
403
+ * comparison regex's plain-decimal domain.
404
+ */
405
+
406
+ /** Serialize any parsed query to canonical WQL text. Total: never throws. */
407
+ declare function serialize(parsed: AnyParsedQuery): string;
408
+
379
409
  /**
380
410
  * Canonical discipline vocabulary — the single source of truth for effort
381
411
  * disciplines across the resolver, the TIS factor table, fact-row tags, the
@@ -1009,13 +1039,13 @@ declare function parseFrontmatterProps(lines: string[]): Record<string, string>;
1009
1039
  * Auto-generated build version metadata.
1010
1040
  * Do not edit directly; updated by scripts/stamp-version.ts
1011
1041
  */
1012
- declare const VERSION = "0.9.40";
1013
- declare const GIT_SHA = "2462ec9";
1014
- declare const BUILD_TIME = "2026-08-26T01:04:47.412Z";
1042
+ declare const VERSION = "0.10.42";
1043
+ declare const GIT_SHA = "79c6d18";
1044
+ declare const BUILD_TIME = "2026-08-26T04:44:54.356Z";
1015
1045
  declare const SEMVER: {
1016
- readonly version: "0.9.40";
1017
- readonly gitSha: "2462ec9";
1018
- readonly buildTime: "2026-08-26T01:04:47.412Z";
1046
+ readonly version: "0.10.42";
1047
+ readonly gitSha: "79c6d18";
1048
+ readonly buildTime: "2026-08-26T04:44:54.356Z";
1019
1049
  };
1020
1050
 
1021
- export { type Aggregator, type AnyParsedQuery, BUILD_TIME, type BlockQueryStore, type ComparisonOp, DASHBOARD_GRID_MAX_COLS, DASHBOARD_WIDGET_TYPES, DEFAULT_DASHBOARD_TITLE, DISCIPLINE_FACTORS, type DashboardDocument, type DashboardMeta, type DashboardParsedSection, type DashboardSectionInput, type DashboardToken, type DashboardWidget, type DashboardWidgetType, EFFORT_DISCIPLINES, type EffortDiscipline, type EffortQueryStore, type EventRowIdentity, type FindOptions, type FindPredicate, type FindQueryResult, GIT_SHA, type IEffort, KG_PER_LB, type LinkWidget, type MetricPredicate, type NoteQueryStore, PLANNED_WIDGET_TYPES, type ParsedAggregateQuery, type ParsedFindQuery, type ParsedFrontmatter, type ParsedRowsQuery, type ParsedWqlRollupSuffix, type ParsedWqlSuffixes, type ParsedWqlWindowSuffix, type QueryOptions, type QueryResult, QueryService, type QueryServiceStores, type QueryWidgetSuffix, type QueryWindow, type RowsQueryResult, type RowsRun, SEMVER, type Series, type SeriesPoint, type SummaryFactIdentity, type SummaryFactSourceOutput, type TagFilter, type TagValue, UNIT_FAMILIES, type UnifiedEventStore, type UnitFamily, type UnitFamilyDef, VERSION, WQL_AGGREGATORS, WQL_CALC_TARGETS, WQL_COMPARISON_OPS, WQL_CONTENT_FILTER_KEYS, WQL_DISPLAY_UNITS, WQL_FIND_TARGETS, WQL_GRAINS, WQL_INTENSITY_TIERS, WQL_KEYWORDS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_RESULT_PLANES, WQL_ROLLUP_PERIODS, WQL_ROWS_SCOPE_KEYS, WQL_ROWS_TARGETS, WQL_SOURCES, WQL_SOURCE_VALUES, WQL_TAG_KEYS, WQL_VIRTUAL_DIMS, type WqlAggregator, type WqlCalcTarget, type WqlComparisonOp, type WqlCompletionOptions, type WqlContentFilterKey, type WqlDisplayUnit, type WqlFindTarget, type WqlGrain, type WqlIntensityTier, type WqlKeyword, type WqlMetricAggregate, type WqlMetricFamily, type WqlResultPlane, type WqlRollupPeriod, type WqlRowsTarget, type WqlSource, type WqlSourceValue, type WqlTagKey, type WqlVirtualDim, buildDashboardDocument, buildDashboardScaffold, convert, dashboardSlug, defaultTokenValues, disciplineFactorFor, extractDashboardTokens, extractFrontmatterTags, getList, getScalar, getUnitFamily, isAggregateQuery, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isProposedMetric, isRowsQuery, normalizeSummaryFacts, normalizeWql, parseDashboardNote, parseFlatProperties, parseFrontmatter, parseFrontmatterBody, parseFrontmatterCategories, parseFrontmatterProps, parseQuery, parseQueryWidgetSuffix, parseWqlSuffixes, projectEventToFacts, referencedTokens, resolveCanonicalMetricKey, resolveDisplayUnit, resolveWidgetType, serializeFrontmatter, setDashboardTokenValue, splitAtWhere, splitWidgetBody, staticNotesFromBlocks, staticTagIndexFromBlocks, stripFrontmatter, substituteTokens, toEventRows, toSummaryEventRows, unknownTokensMessage, unknownWidgetTypeMessage, wql, wqlCompletion, wqlCompletionSource, wqlHighlightStyle, wqlLanguage, parser as wqlParser, wql_parser_terms as wqlTerms };
1051
+ export { type Aggregator, type AnyParsedQuery, BUILD_TIME, type BlockQueryStore, type ComparisonOp, DASHBOARD_GRID_MAX_COLS, DASHBOARD_WIDGET_TYPES, DEFAULT_DASHBOARD_TITLE, DISCIPLINE_FACTORS, type DashboardDocument, type DashboardMeta, type DashboardParsedSection, type DashboardSectionInput, type DashboardToken, type DashboardWidget, type DashboardWidgetType, EFFORT_DISCIPLINES, type EffortDiscipline, type EffortQueryStore, type EventRowIdentity, type FindOptions, type FindPredicate, type FindQueryResult, GIT_SHA, type IEffort, KG_PER_LB, type LinkWidget, type MetricPredicate, type NoteQueryStore, PLANNED_WIDGET_TYPES, type ParsedAggregateQuery, type ParsedFindQuery, type ParsedFrontmatter, type ParsedRowsQuery, type ParsedWqlRollupSuffix, type ParsedWqlSuffixes, type ParsedWqlWindowSuffix, type QueryOptions, type QueryResult, QueryService, type QueryServiceStores, type QueryWidgetSuffix, type QueryWindow, type RowsQueryResult, type RowsRun, SEMVER, type Series, type SeriesPoint, type SummaryFactIdentity, type SummaryFactSourceOutput, type TagFilter, type TagValue, UNIT_FAMILIES, type UnifiedEventStore, type UnitFamily, type UnitFamilyDef, VERSION, WQL_AGGREGATORS, WQL_CALC_TARGETS, WQL_COMPARISON_OPS, WQL_CONTENT_FILTER_KEYS, WQL_DISPLAY_UNITS, WQL_FIND_TARGETS, WQL_GRAINS, WQL_INTENSITY_TIERS, WQL_KEYWORDS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_RESULT_PLANES, WQL_ROLLUP_PERIODS, WQL_ROWS_SCOPE_KEYS, WQL_ROWS_TARGETS, WQL_SOURCES, WQL_SOURCE_VALUES, WQL_TAG_KEYS, WQL_VIRTUAL_DIMS, type WqlAggregator, type WqlCalcTarget, type WqlComparisonOp, type WqlCompletionOptions, type WqlContentFilterKey, type WqlDisplayUnit, type WqlFindTarget, type WqlGrain, type WqlIntensityTier, type WqlKeyword, type WqlMetricAggregate, type WqlMetricFamily, type WqlResultPlane, type WqlRollupPeriod, type WqlRowsTarget, type WqlSource, type WqlSourceValue, type WqlTagKey, type WqlVirtualDim, buildDashboardDocument, buildDashboardScaffold, convert, dashboardSlug, defaultTokenValues, disciplineFactorFor, extractDashboardTokens, extractFrontmatterTags, getList, getScalar, getUnitFamily, isAggregateQuery, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isProposedMetric, isRowsQuery, normalizeSummaryFacts, normalizeWql, parseDashboardNote, parseFlatProperties, parseFrontmatter, parseFrontmatterBody, parseFrontmatterCategories, parseFrontmatterProps, parseQuery, parseQueryWidgetSuffix, parseWqlSuffixes, projectEventToFacts, referencedTokens, resolveCanonicalMetricKey, resolveDisplayUnit, resolveWidgetType, serialize, serializeFrontmatter, setDashboardTokenValue, splitAtWhere, splitWidgetBody, staticNotesFromBlocks, staticTagIndexFromBlocks, stripFrontmatter, substituteTokens, toEventRows, toSummaryEventRows, unknownTokensMessage, unknownWidgetTypeMessage, wql, wqlCompletion, wqlCompletionSource, wqlHighlightStyle, wqlLanguage, parser as wqlParser, wql_parser_terms as wqlTerms };
package/dist/index.d.ts CHANGED
@@ -376,6 +376,36 @@ declare function normalizeWql(raw: string): {
376
376
  advisories: string[];
377
377
  };
378
378
 
379
+ /**
380
+ * WQL serializer (C6 — one structured interface for code).
381
+ *
382
+ * The total serializer over the C5 discriminated query union: code holds the
383
+ * AST; strings live only at document edges (URL `?q=`, ```query``` fences,
384
+ * dashboard bodies). Properties (proven by tests/serialize.test.ts):
385
+ *
386
+ * 1. `serialize(parse(x)) === x` for canonical inputs (fixed-point text), and
387
+ * 2. `parse(serialize(a))` is structurally equal to `a` for every AST —
388
+ * equal on all query-structure fields; `raw` (provenance text) and
389
+ * `advisories` (parse-time deprecation notices) are intentionally not
390
+ * reproduced, since serialization emits modern canonical syntax.
391
+ *
392
+ * Errored ASTs serialize to their original `raw` text — a query that failed
393
+ * to parse has no well-defined structure to re-emit, and echoing the input
394
+ * keeps the function total.
395
+ *
396
+ * Round-trip equality holds for text-surface-representable ASTs. Three value
397
+ * shapes the grammar cannot express (or parses away) sit outside that
398
+ * contract — documented here rather than silently corrupted:
399
+ * - a `"` inside a filter value: the quoted token has no escape form;
400
+ * - a quoted value with `wildcard: true`: the parser forces wildcard=false
401
+ * on quoted atoms (extractFilters), so the flag cannot survive;
402
+ * - thresholds whose String() is exponential (>= 1e21): outside the join
403
+ * comparison regex's plain-decimal domain.
404
+ */
405
+
406
+ /** Serialize any parsed query to canonical WQL text. Total: never throws. */
407
+ declare function serialize(parsed: AnyParsedQuery): string;
408
+
379
409
  /**
380
410
  * Canonical discipline vocabulary — the single source of truth for effort
381
411
  * disciplines across the resolver, the TIS factor table, fact-row tags, the
@@ -1009,13 +1039,13 @@ declare function parseFrontmatterProps(lines: string[]): Record<string, string>;
1009
1039
  * Auto-generated build version metadata.
1010
1040
  * Do not edit directly; updated by scripts/stamp-version.ts
1011
1041
  */
1012
- declare const VERSION = "0.9.40";
1013
- declare const GIT_SHA = "2462ec9";
1014
- declare const BUILD_TIME = "2026-08-26T01:04:47.412Z";
1042
+ declare const VERSION = "0.10.42";
1043
+ declare const GIT_SHA = "79c6d18";
1044
+ declare const BUILD_TIME = "2026-08-26T04:44:54.356Z";
1015
1045
  declare const SEMVER: {
1016
- readonly version: "0.9.40";
1017
- readonly gitSha: "2462ec9";
1018
- readonly buildTime: "2026-08-26T01:04:47.412Z";
1046
+ readonly version: "0.10.42";
1047
+ readonly gitSha: "79c6d18";
1048
+ readonly buildTime: "2026-08-26T04:44:54.356Z";
1019
1049
  };
1020
1050
 
1021
- export { type Aggregator, type AnyParsedQuery, BUILD_TIME, type BlockQueryStore, type ComparisonOp, DASHBOARD_GRID_MAX_COLS, DASHBOARD_WIDGET_TYPES, DEFAULT_DASHBOARD_TITLE, DISCIPLINE_FACTORS, type DashboardDocument, type DashboardMeta, type DashboardParsedSection, type DashboardSectionInput, type DashboardToken, type DashboardWidget, type DashboardWidgetType, EFFORT_DISCIPLINES, type EffortDiscipline, type EffortQueryStore, type EventRowIdentity, type FindOptions, type FindPredicate, type FindQueryResult, GIT_SHA, type IEffort, KG_PER_LB, type LinkWidget, type MetricPredicate, type NoteQueryStore, PLANNED_WIDGET_TYPES, type ParsedAggregateQuery, type ParsedFindQuery, type ParsedFrontmatter, type ParsedRowsQuery, type ParsedWqlRollupSuffix, type ParsedWqlSuffixes, type ParsedWqlWindowSuffix, type QueryOptions, type QueryResult, QueryService, type QueryServiceStores, type QueryWidgetSuffix, type QueryWindow, type RowsQueryResult, type RowsRun, SEMVER, type Series, type SeriesPoint, type SummaryFactIdentity, type SummaryFactSourceOutput, type TagFilter, type TagValue, UNIT_FAMILIES, type UnifiedEventStore, type UnitFamily, type UnitFamilyDef, VERSION, WQL_AGGREGATORS, WQL_CALC_TARGETS, WQL_COMPARISON_OPS, WQL_CONTENT_FILTER_KEYS, WQL_DISPLAY_UNITS, WQL_FIND_TARGETS, WQL_GRAINS, WQL_INTENSITY_TIERS, WQL_KEYWORDS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_RESULT_PLANES, WQL_ROLLUP_PERIODS, WQL_ROWS_SCOPE_KEYS, WQL_ROWS_TARGETS, WQL_SOURCES, WQL_SOURCE_VALUES, WQL_TAG_KEYS, WQL_VIRTUAL_DIMS, type WqlAggregator, type WqlCalcTarget, type WqlComparisonOp, type WqlCompletionOptions, type WqlContentFilterKey, type WqlDisplayUnit, type WqlFindTarget, type WqlGrain, type WqlIntensityTier, type WqlKeyword, type WqlMetricAggregate, type WqlMetricFamily, type WqlResultPlane, type WqlRollupPeriod, type WqlRowsTarget, type WqlSource, type WqlSourceValue, type WqlTagKey, type WqlVirtualDim, buildDashboardDocument, buildDashboardScaffold, convert, dashboardSlug, defaultTokenValues, disciplineFactorFor, extractDashboardTokens, extractFrontmatterTags, getList, getScalar, getUnitFamily, isAggregateQuery, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isProposedMetric, isRowsQuery, normalizeSummaryFacts, normalizeWql, parseDashboardNote, parseFlatProperties, parseFrontmatter, parseFrontmatterBody, parseFrontmatterCategories, parseFrontmatterProps, parseQuery, parseQueryWidgetSuffix, parseWqlSuffixes, projectEventToFacts, referencedTokens, resolveCanonicalMetricKey, resolveDisplayUnit, resolveWidgetType, serializeFrontmatter, setDashboardTokenValue, splitAtWhere, splitWidgetBody, staticNotesFromBlocks, staticTagIndexFromBlocks, stripFrontmatter, substituteTokens, toEventRows, toSummaryEventRows, unknownTokensMessage, unknownWidgetTypeMessage, wql, wqlCompletion, wqlCompletionSource, wqlHighlightStyle, wqlLanguage, parser as wqlParser, wql_parser_terms as wqlTerms };
1051
+ export { type Aggregator, type AnyParsedQuery, BUILD_TIME, type BlockQueryStore, type ComparisonOp, DASHBOARD_GRID_MAX_COLS, DASHBOARD_WIDGET_TYPES, DEFAULT_DASHBOARD_TITLE, DISCIPLINE_FACTORS, type DashboardDocument, type DashboardMeta, type DashboardParsedSection, type DashboardSectionInput, type DashboardToken, type DashboardWidget, type DashboardWidgetType, EFFORT_DISCIPLINES, type EffortDiscipline, type EffortQueryStore, type EventRowIdentity, type FindOptions, type FindPredicate, type FindQueryResult, GIT_SHA, type IEffort, KG_PER_LB, type LinkWidget, type MetricPredicate, type NoteQueryStore, PLANNED_WIDGET_TYPES, type ParsedAggregateQuery, type ParsedFindQuery, type ParsedFrontmatter, type ParsedRowsQuery, type ParsedWqlRollupSuffix, type ParsedWqlSuffixes, type ParsedWqlWindowSuffix, type QueryOptions, type QueryResult, QueryService, type QueryServiceStores, type QueryWidgetSuffix, type QueryWindow, type RowsQueryResult, type RowsRun, SEMVER, type Series, type SeriesPoint, type SummaryFactIdentity, type SummaryFactSourceOutput, type TagFilter, type TagValue, UNIT_FAMILIES, type UnifiedEventStore, type UnitFamily, type UnitFamilyDef, VERSION, WQL_AGGREGATORS, WQL_CALC_TARGETS, WQL_COMPARISON_OPS, WQL_CONTENT_FILTER_KEYS, WQL_DISPLAY_UNITS, WQL_FIND_TARGETS, WQL_GRAINS, WQL_INTENSITY_TIERS, WQL_KEYWORDS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_RESULT_PLANES, WQL_ROLLUP_PERIODS, WQL_ROWS_SCOPE_KEYS, WQL_ROWS_TARGETS, WQL_SOURCES, WQL_SOURCE_VALUES, WQL_TAG_KEYS, WQL_VIRTUAL_DIMS, type WqlAggregator, type WqlCalcTarget, type WqlComparisonOp, type WqlCompletionOptions, type WqlContentFilterKey, type WqlDisplayUnit, type WqlFindTarget, type WqlGrain, type WqlIntensityTier, type WqlKeyword, type WqlMetricAggregate, type WqlMetricFamily, type WqlResultPlane, type WqlRollupPeriod, type WqlRowsTarget, type WqlSource, type WqlSourceValue, type WqlTagKey, type WqlVirtualDim, buildDashboardDocument, buildDashboardScaffold, convert, dashboardSlug, defaultTokenValues, disciplineFactorFor, extractDashboardTokens, extractFrontmatterTags, getList, getScalar, getUnitFamily, isAggregateQuery, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isProposedMetric, isRowsQuery, normalizeSummaryFacts, normalizeWql, parseDashboardNote, parseFlatProperties, parseFrontmatter, parseFrontmatterBody, parseFrontmatterCategories, parseFrontmatterProps, parseQuery, parseQueryWidgetSuffix, parseWqlSuffixes, projectEventToFacts, referencedTokens, resolveCanonicalMetricKey, resolveDisplayUnit, resolveWidgetType, serialize, serializeFrontmatter, setDashboardTokenValue, splitAtWhere, splitWidgetBody, staticNotesFromBlocks, staticTagIndexFromBlocks, stripFrontmatter, substituteTokens, toEventRows, toSummaryEventRows, unknownTokensMessage, unknownWidgetTypeMessage, wql, wqlCompletion, wqlCompletionSource, wqlHighlightStyle, wqlLanguage, parser as wqlParser, wql_parser_terms as wqlTerms };
package/dist/index.mjs CHANGED
@@ -279,7 +279,10 @@ function parseJoinClause(where) {
279
279
  if (fp.window?.kind === "range") {
280
280
  return { error: "Range windows are not supported on join halves \u2014 use last <n>d|w" };
281
281
  }
282
- return { find: { target: fp.target, filters: fp.filters, last: fp.window?.kind === "relative" ? { size: fp.window.size, unit: fp.window.unit } : void 0 } };
282
+ return {
283
+ find: { target: fp.target, filters: fp.filters, last: fp.window?.kind === "relative" ? { size: fp.window.size, unit: fp.window.unit } : void 0 },
284
+ advisories: fp.advisories
285
+ };
283
286
  }
284
287
  const m = CMP_RE.exec(where.trim());
285
288
  if (!m) return { error: cannotParseJoin(where) };
@@ -340,6 +343,12 @@ function normalizeWql(raw) {
340
343
  head = `${head}{source:${scope}}`;
341
344
  }
342
345
  const parts = [head];
346
+ if (suffixes.groupBy) {
347
+ parts.push(`by {${suffixes.groupBy.join(", ")}}`);
348
+ }
349
+ if (suffixes.rollup) {
350
+ parts.push(`.rollup(${suffixes.rollup.raw})`);
351
+ }
343
352
  if (suffixes.window) {
344
353
  parts.push(suffixes.window.raw);
345
354
  }
@@ -361,7 +370,8 @@ function validateRowsFilters(filters) {
361
370
  (f) => !allowedKeys.has(f.key) || f.negate || f.values.some((v) => v.wildcard)
362
371
  );
363
372
  if (unsupported.length > 0) {
364
- return `Unsupported rows filter(s): ${unsupported.map((f) => (f.negate ? "!" : "") + f.key).join(", ")}. Rows queries support exact ${WQL_ROWS_SCOPE_KEYS.map((k) => `${k}:`).join(", ")} values.`;
373
+ const allowed = [...WQL_ROWS_SCOPE_KEYS, "source"];
374
+ return `Unsupported rows filter(s): ${unsupported.map((f) => (f.negate ? "!" : "") + f.key).join(", ")}. Rows queries support exact ${allowed.map((k) => `${k}:`).join(", ")} values.`;
365
375
  }
366
376
  if (!filters.some((f) => scopeKeys.has(f.key))) {
367
377
  return `Rows query needs a scope: ${WQL_ROWS_SCOPE_KEYS.map((k) => `${k}:`).join(", ")}.`;
@@ -377,7 +387,7 @@ function validateSourceFilter(filters) {
377
387
  if (validSources.has(val) || val === "collection" || val === "feed" || val.startsWith("collection:") || val.startsWith("feed:")) {
378
388
  continue;
379
389
  }
380
- return `Unknown source "${val}". Try: ${WQL_SOURCE_VALUES.join(", ")}`;
390
+ return `Unknown source "${val}". Try: ${WQL_SOURCE_VALUES.join(", ")} (or collection:<id>, feed:<id>)`;
381
391
  }
382
392
  }
383
393
  return void 0;
@@ -585,6 +595,9 @@ function parseAnalyticsQuery(raw) {
585
595
  base.error = join.error;
586
596
  return base;
587
597
  }
598
+ if (join.advisories?.length) {
599
+ base.advisories = [...base.advisories ?? [], ...join.advisories];
600
+ }
588
601
  if (!join.find) {
589
602
  base.error = `Cross-store join on an analytics query must be find:\u2026, got "${whereText}"`;
590
603
  return base;
@@ -680,6 +693,64 @@ function parseFindQuery(raw) {
680
693
  return result;
681
694
  }
682
695
 
696
+ // src/serialize.ts
697
+ function serializeValue(value) {
698
+ if (/^[a-zA-Z0-9_-]+(:[a-zA-Z0-9_-]+)?$/.test(value)) return value;
699
+ return `"${value}"`;
700
+ }
701
+ function serializeFilters(filters) {
702
+ return filters.map((f) => `${f.negate ? "!" : ""}${f.key}:${f.values.map((v) => serializeValue(v.value) + (v.wildcard ? "*" : "")).join("|")}`).join(",");
703
+ }
704
+ function serializeAggHead(agg, metric, filters) {
705
+ return `${agg}:${metric}{${serializeFilters(filters)}}`;
706
+ }
707
+ function serializeAggregateHead(a) {
708
+ return serializeAggHead(a.agg, a.metric, a.filters);
709
+ }
710
+ function serializeFindHalf(target, filters, last) {
711
+ const head = `find:${target}${filters.length ? `{${serializeFilters(filters)}}` : ""}`;
712
+ return last ? `${head} last ${last.size}${last.unit}` : head;
713
+ }
714
+ function serializeMetricHalf(j) {
715
+ return `${serializeAggHead(j.agg, j.metric, j.filters)} ${j.operator} ${j.threshold}`;
716
+ }
717
+ function serializeFindHead(f) {
718
+ return serializeFindHalf(f.target, f.filters);
719
+ }
720
+ function serializeRowsHead(r) {
721
+ return `rows:${r.outputType ?? "all"}{${serializeFilters(r.filters)}}`;
722
+ }
723
+ function serializeWindow(w) {
724
+ if (!w) return "";
725
+ if (w.kind === "relative") return `last ${w.size}${w.unit}`;
726
+ return w.end ? `from ${w.start} to ${w.end}` : `from ${w.start}`;
727
+ }
728
+ function serialize(parsed) {
729
+ if (parsed.error) return parsed.raw;
730
+ if (parsed.family === "aggregate") {
731
+ const a = parsed;
732
+ let text = serializeAggregateHead(a);
733
+ if (a.groupBy.length) text += ` by {${a.groupBy.join(", ")}}`;
734
+ if (a.rollup) text += `.rollup(${a.rollup.size}${a.rollup.unit})`;
735
+ if (a.displayUnit) text += ` in ${a.displayUnit}`;
736
+ const win = serializeWindow(a.window);
737
+ if (win) text += ` ${win}`;
738
+ if (a.join) text += ` where ${serializeFindHalf(a.join.target, a.join.filters, a.join.last)}`;
739
+ return text;
740
+ }
741
+ if (parsed.family === "find") {
742
+ const parts = [serializeFindHead(parsed), serializeWindow(parsed.window)];
743
+ if (parsed.join) parts.push(`where ${serializeMetricHalf(parsed.join)}`);
744
+ return parts.filter(Boolean).join(" ");
745
+ }
746
+ if (parsed.family === "rows") {
747
+ const win = serializeWindow(parsed.window);
748
+ return [serializeRowsHead(parsed), win].filter(Boolean).join(" ");
749
+ }
750
+ const unhandled = parsed;
751
+ return unhandled.raw ?? "";
752
+ }
753
+
683
754
  // src/disciplines.ts
684
755
  var EFFORT_DISCIPLINES = [
685
756
  "bodyweight",
@@ -1588,9 +1659,9 @@ var QueryService = class {
1588
1659
  if (this.staticNoteStore) {
1589
1660
  notes = notes.concat(await this.staticNoteStore.getAllNotes());
1590
1661
  }
1662
+ notes = applySourceFilter(notes, parsed.filters);
1591
1663
  const selectedCount = notes.length;
1592
1664
  const anchorNow = windowAnchor(notes, parsed, options2);
1593
- notes = applySourceFilter(notes, parsed.filters);
1594
1665
  for (const filter of parsed.filters) {
1595
1666
  if (filter.key === "tags" && !filter.negate) {
1596
1667
  const matchingIds = /* @__PURE__ */ new Set();
@@ -1650,9 +1721,9 @@ var QueryService = class {
1650
1721
  if (this.staticBlockStore) {
1651
1722
  blocks = blocks.concat(await this.staticBlockStore.getAllBlocks());
1652
1723
  }
1724
+ blocks = applySourceFilter(blocks, parsed.filters);
1653
1725
  const selectedCount = blocks.length;
1654
1726
  const anchorNow = windowAnchor(blocks, parsed, options2);
1655
- blocks = applySourceFilter(blocks, parsed.filters);
1656
1727
  for (const filter of parsed.filters) {
1657
1728
  if (filter.key === "text" && !filter.negate) {
1658
1729
  const search = filter.values.map((v) => v.value).join(" ").toLowerCase();
@@ -2249,15 +2320,15 @@ sum:$metric{} rollup:1w
2249
2320
  }
2250
2321
 
2251
2322
  // src/version.ts
2252
- var VERSION = "0.9.40";
2253
- var GIT_SHA = "2462ec9";
2254
- var BUILD_TIME = "2026-08-26T01:04:47.412Z";
2323
+ var VERSION = "0.10.42";
2324
+ var GIT_SHA = "79c6d18";
2325
+ var BUILD_TIME = "2026-08-26T04:44:54.356Z";
2255
2326
  var SEMVER = {
2256
- version: "0.9.40",
2257
- gitSha: "2462ec9",
2258
- buildTime: "2026-08-26T01:04:47.412Z"
2327
+ version: "0.10.42",
2328
+ gitSha: "79c6d18",
2329
+ buildTime: "2026-08-26T04:44:54.356Z"
2259
2330
  };
2260
2331
 
2261
- export { BUILD_TIME, DASHBOARD_GRID_MAX_COLS, DASHBOARD_WIDGET_TYPES, DEFAULT_DASHBOARD_TITLE, DISCIPLINE_FACTORS, EFFORT_DISCIPLINES, GIT_SHA, KG_PER_LB, PLANNED_WIDGET_TYPES, QueryService, SEMVER, UNIT_FAMILIES, VERSION, WQL_AGGREGATORS, WQL_CALC_TARGETS, WQL_COMPARISON_OPS, WQL_CONTENT_FILTER_KEYS, WQL_DISPLAY_UNITS, WQL_FIND_TARGETS, WQL_GRAINS, WQL_INTENSITY_TIERS, WQL_KEYWORDS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_RESULT_PLANES, WQL_ROLLUP_PERIODS, WQL_ROWS_SCOPE_KEYS, WQL_ROWS_TARGETS, WQL_SOURCES, WQL_SOURCE_VALUES, WQL_TAG_KEYS, WQL_VIRTUAL_DIMS, buildDashboardDocument, buildDashboardScaffold, convert, dashboardSlug, defaultTokenValues, disciplineFactorFor, extractDashboardTokens, extractFrontmatterTags, getList, getScalar, getUnitFamily, isAggregateQuery, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isProposedMetric, isRowsQuery, normalizeSummaryFacts, normalizeWql, parseDashboardNote, parseFlatProperties, parseFrontmatter, parseFrontmatterBody, parseFrontmatterCategories, parseFrontmatterProps, parseQuery, parseQueryWidgetSuffix, parseWqlSuffixes, projectEventToFacts, referencedTokens, resolveCanonicalMetricKey, resolveDisplayUnit, resolveWidgetType, serializeFrontmatter, setDashboardTokenValue, splitAtWhere, splitWidgetBody, staticNotesFromBlocks, staticTagIndexFromBlocks, stripFrontmatter, substituteTokens, toEventRows, toSummaryEventRows, unknownTokensMessage, unknownWidgetTypeMessage, wql, wqlCompletion, wqlCompletionSource, wqlHighlightStyle, wqlLanguage, parser as wqlParser, wql_parser_terms_exports as wqlTerms };
2332
+ export { BUILD_TIME, DASHBOARD_GRID_MAX_COLS, DASHBOARD_WIDGET_TYPES, DEFAULT_DASHBOARD_TITLE, DISCIPLINE_FACTORS, EFFORT_DISCIPLINES, GIT_SHA, KG_PER_LB, PLANNED_WIDGET_TYPES, QueryService, SEMVER, UNIT_FAMILIES, VERSION, WQL_AGGREGATORS, WQL_CALC_TARGETS, WQL_COMPARISON_OPS, WQL_CONTENT_FILTER_KEYS, WQL_DISPLAY_UNITS, WQL_FIND_TARGETS, WQL_GRAINS, WQL_INTENSITY_TIERS, WQL_KEYWORDS, WQL_METRIC_AGGREGATES, WQL_METRIC_FAMILIES, WQL_RESULT_PLANES, WQL_ROLLUP_PERIODS, WQL_ROWS_SCOPE_KEYS, WQL_ROWS_TARGETS, WQL_SOURCES, WQL_SOURCE_VALUES, WQL_TAG_KEYS, WQL_VIRTUAL_DIMS, buildDashboardDocument, buildDashboardScaffold, convert, dashboardSlug, defaultTokenValues, disciplineFactorFor, extractDashboardTokens, extractFrontmatterTags, getList, getScalar, getUnitFamily, isAggregateQuery, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isProposedMetric, isRowsQuery, normalizeSummaryFacts, normalizeWql, parseDashboardNote, parseFlatProperties, parseFrontmatter, parseFrontmatterBody, parseFrontmatterCategories, parseFrontmatterProps, parseQuery, parseQueryWidgetSuffix, parseWqlSuffixes, projectEventToFacts, referencedTokens, resolveCanonicalMetricKey, resolveDisplayUnit, resolveWidgetType, serialize, serializeFrontmatter, setDashboardTokenValue, splitAtWhere, splitWidgetBody, staticNotesFromBlocks, staticTagIndexFromBlocks, stripFrontmatter, substituteTokens, toEventRows, toSummaryEventRows, unknownTokensMessage, unknownWidgetTypeMessage, wql, wqlCompletion, wqlCompletionSource, wqlHighlightStyle, wqlLanguage, parser as wqlParser, wql_parser_terms_exports as wqlTerms };
2262
2333
  //# sourceMappingURL=index.mjs.map
2263
2334
  //# sourceMappingURL=index.mjs.map