@bitcobblers/wod-wiki-wql 0.37.2140 → 0.39.2142

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.cjs CHANGED
@@ -31,7 +31,7 @@ var WQL_TAG_KEYS = [
31
31
  "result",
32
32
  "tags"
33
33
  ];
34
- var WQL_CONTENT_ONLY_KEYS = ["type", "text", "has", "source", "catalog"];
34
+ var WQL_CONTENT_ONLY_KEYS = ["type", "text", "has", "source", "catalog", "notebook"];
35
35
  var WQL_EFFORT_FILTER_KEYS = ["effort", "discipline", "intensity", "origin", "text"];
36
36
  var WQL_VIRTUAL_DIMS = ["day", "week", "session", "round"];
37
37
  var WQL_CALC_TARGETS = [
@@ -63,12 +63,15 @@ var WQL_FIND_TARGETS = ["note", "block", "effort", "session", "segment", "event"
63
63
  var WQL_SOURCE_VALUES = ["journal", "feeds", "guides", "playground", "dashboards", "efforts", "equipment"];
64
64
  var WQL_SOURCE_HEADS = [
65
65
  "note",
66
+ "notes",
66
67
  "block",
67
68
  "effort",
68
69
  "session",
69
70
  "segment",
70
71
  "event",
71
72
  "journal",
73
+ "notebook",
74
+ "notebooks",
72
75
  "feed",
73
76
  "feeds",
74
77
  "catalog",
@@ -78,6 +81,8 @@ var WQL_SOURCE_HEADS = [
78
81
  ];
79
82
  var WQL_SOURCE_HEAD_SCOPES = {
80
83
  journal: "journal",
84
+ notebook: "feeds",
85
+ notebooks: "feeds",
81
86
  feed: "feeds",
82
87
  feeds: "feeds",
83
88
  catalog: "feeds",
@@ -92,7 +97,7 @@ var WQL_FUNCTION_HEADS = WQL_AGGREGATORS;
92
97
  var WQL_CHART_HEADS = ["timeseries", "bar", "table", "donut", "toplist", "value"];
93
98
  var WQL_STANDARD_DATASETS = ["@session", "@today"];
94
99
  var WQL_RESULT_PLANES = wodWikiCore.KNOWN_OUTPUT_TYPES;
95
- var WQL_CONTENT_FILTER_KEYS = ["type", "text", "has", "source", "catalog", ...WQL_TAG_KEYS];
100
+ var WQL_CONTENT_FILTER_KEYS = ["type", "text", "has", "source", "catalog", "notebook", ...WQL_TAG_KEYS];
96
101
  var WQL_SOURCES = ["note", "block", "effort", "session", "segment", "event"];
97
102
  var WQL_ROLLUP_PERIODS = ["2w", "4w"];
98
103
  var WQL_DISPLAY_UNITS = ["kg", "lb"];
@@ -114,7 +119,7 @@ var WQL_KEYWORDS = [
114
119
  ];
115
120
 
116
121
  // src/capabilities.ts
117
- var CONTENT_GROUPING_DIMENSIONS = ["date", "day", "week", "month", "year", "discipline", "origin", "source", "kind", "type", "tag"];
122
+ var CONTENT_GROUPING_DIMENSIONS = ["date", "day", "week", "month", "year", "discipline", "origin", "source", "notebook", "kind", "type", "tag"];
118
123
  var STRUCTURAL_TYPES = { time: true, groupby: true, rollup: true, unit: true, where: true, agg: true };
119
124
  var FACT_KEYS = WQL_TAG_KEYS.filter((key) => key !== "metric");
120
125
  var TABLE_KEYS = WQL_TAG_KEYS.filter((key) => key !== "tags");
@@ -129,8 +134,8 @@ var AGGREGATE_TYPES = /* @__PURE__ */ new Set([
129
134
  "metric"
130
135
  ]);
131
136
  var TARGET_TYPES = {
132
- note: /* @__PURE__ */ new Set(["text", "catalog", "tag", "effort", ...WQL_TYPED_TAG_KEYS, "type", "page", "source", "note", "time", "groupby", "where"]),
133
- block: /* @__PURE__ */ new Set(["text", "catalog", "tag", "effort", "type", "source", "note", "time", "groupby", "where"]),
137
+ note: /* @__PURE__ */ new Set(["text", "catalog", "notebook", "tag", "effort", ...WQL_TYPED_TAG_KEYS, "type", "page", "source", "note", "time", "groupby", "where"]),
138
+ block: /* @__PURE__ */ new Set(["text", "catalog", "notebook", "tag", "effort", "type", "source", "note", "time", "groupby", "where"]),
134
139
  effort: /* @__PURE__ */ new Set([...WQL_EFFORT_FILTER_KEYS, "groupby"]),
135
140
  session: /* @__PURE__ */ new Set(["result", "block", "note", "plane", "time", "groupby"]),
136
141
  segment: /* @__PURE__ */ new Set([...TABLE_KEYS, "time", "groupby", "unit"]),
@@ -598,9 +603,12 @@ function parseQuery(raw) {
598
603
  }
599
604
  return parseSingleQuery(raw);
600
605
  }
606
+ function normalizeNotebookFilterText(raw) {
607
+ return raw.replace(/\bnotebook:notebook\/([a-zA-Z0-9_-]+)/g, 'notebook:"notebook/$1"');
608
+ }
601
609
  function normalizeWql(raw) {
602
610
  const advisories = [];
603
- let text = raw.trim();
611
+ let text = normalizeNotebookFilterText(raw.trim());
604
612
  const { primary, where } = splitAtWhere(text);
605
613
  const isFind = primary.startsWith("find:");
606
614
  if (isFind) {
@@ -654,7 +662,7 @@ function validateSourceFilter(filters) {
654
662
  if (val === "collection" || val === "collections") {
655
663
  return `source:${val} is retired \u2014 collections were renamed to feeds; use source:feeds or :feed{}.`;
656
664
  }
657
- if (WQL_SOURCE_VALUES.includes(val) || val === "feed" || val.startsWith("collection:") || val.startsWith("feed:")) {
665
+ if (WQL_SOURCE_VALUES.includes(val) || val === "feed" || val === "notebook" || val === "notebooks" || val.startsWith("collection:") || val.startsWith("feed:") || val.startsWith("notebook:") || val.startsWith("notebook/")) {
658
666
  continue;
659
667
  }
660
668
  return `Unknown source "${val}". Try: ${WQL_SOURCE_VALUES.join(", ")} (or collection:<id>, feed:<id>)`;
@@ -870,7 +878,8 @@ function cannotParseFind(text) {
870
878
  return `Cannot parse "${text}". Expected :source{key:value, !key:value}; filters are optional. Optional suffixes include by {dimension}, last <n>d or last <n>w, from YYYY-MM-DD [to YYYY-MM-DD], where <aggregator>:<metric>{filters} <operator> <number>, and | order by <column> | limit <n>. Support depends on the target.`;
871
879
  }
872
880
  function parseFindQuery(raw, opts) {
873
- const { text: rawNoPipes, pipes } = extractPipes(raw);
881
+ const normalizedRaw = normalizeNotebookFilterText(raw);
882
+ const { text: rawNoPipes, pipes } = extractPipes(normalizedRaw);
874
883
  const suffixes = parseWqlSuffixes(rawNoPipes);
875
884
  const { where: whereText, window: windowSuffix, legacyScope, groupBy, displayUnit, primaryText: text } = suffixes;
876
885
  const win = toQueryWindow(windowSuffix);
@@ -939,7 +948,7 @@ function parseFindQuery(raw, opts) {
939
948
  if (scope || typeScope) {
940
949
  result.target = "note";
941
950
  } else {
942
- result.target = headName;
951
+ result.target = headName === "notes" ? "note" : headName;
943
952
  if (result.target === "page") {
944
953
  result.error = "find:page is retired \u2014 page-ness is handled by type: (e.g. :note{source:guides} or type:feed).";
945
954
  return result;
@@ -963,7 +972,7 @@ function parseFindQuery(raw, opts) {
963
972
  negate: false,
964
973
  values: [{ value: scope, wildcard: false }]
965
974
  });
966
- if (headName === "catalog" || headName === "catalogs") {
975
+ if (headName === "catalog" || headName === "catalogs" || headName === "notebook" || headName === "notebooks") {
967
976
  result.filters.push({
968
977
  key: "type",
969
978
  negate: false,
@@ -1499,7 +1508,7 @@ function headApply(o, colonTyped) {
1499
1508
  return { ...o, apply: `${colonTyped ? "" : ":"}${o.label}{` };
1500
1509
  }
1501
1510
  var LEGACY_HEAD_OPTIONS = WQL_AGGREGATORS.map((label) => ({ label, type: "keyword" }));
1502
- var NOTE_COLUMNS = ["title", "date", "createdAt", "type", "sourceId", "catalog"];
1511
+ var NOTE_COLUMNS = ["title", "date", "createdAt", "type", "sourceId", "catalog", "notebookId"];
1503
1512
  var BLOCK_COLUMNS = ["noteTitle", "dataType", "position", "createdAt", "noteId", "sourceId"];
1504
1513
  var EFFORT_COLUMNS = ["slug", "label", "registrySource"];
1505
1514
  var SESSION_COLUMNS = ["duration", "startTime", "origin"];
@@ -1526,14 +1535,18 @@ function resolveColonHead(name) {
1526
1535
  const n = name.toLowerCase();
1527
1536
  if (WQL_FUNCTION_HEADS.includes(n)) return { family: "aggregate" };
1528
1537
  if (WQL_CHART_HEADS.includes(n)) return { family: "find" };
1529
- let source = n;
1530
- if (!WQL_SOURCE_HEADS.includes(source)) {
1531
- const partial = source ? WQL_SOURCE_HEADS.filter((t2) => t2.startsWith(source)) : [];
1532
- if (partial.length === 1) source = partial[0];
1538
+ const headTarget = (head) => {
1539
+ if (head === "notes") return "note";
1540
+ const scoped = WQL_SOURCE_HEAD_SCOPES[head] || WQL_TYPE_HEADS[head];
1541
+ return scoped ? "note" : head;
1542
+ };
1543
+ if (WQL_SOURCE_HEADS.includes(n)) {
1544
+ return { family: "find", target: headTarget(n) };
1533
1545
  }
1534
- if (WQL_SOURCE_HEADS.includes(source)) {
1535
- const scoped = WQL_SOURCE_HEAD_SCOPES[source] || WQL_TYPE_HEADS[source];
1536
- return { family: "find", target: scoped ? "note" : source };
1546
+ const partial = n ? WQL_SOURCE_HEADS.filter((t2) => t2.startsWith(n)) : [];
1547
+ const targets = [...new Set(partial.map(headTarget))];
1548
+ if (targets.length === 1) {
1549
+ return { family: "find", target: targets[0] };
1537
1550
  }
1538
1551
  return { family: "find" };
1539
1552
  }
@@ -2899,8 +2912,6 @@ function dedupeById(facts) {
2899
2912
  }
2900
2913
  return out;
2901
2914
  }
2902
-
2903
- // src/QueryService.ts
2904
2915
  var NOTE_UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2905
2916
  function catalogOfItem(item) {
2906
2917
  if (item.catalog) return item.catalog;
@@ -2912,6 +2923,25 @@ function catalogOfItem(item) {
2912
2923
  if (!isCollectionOrFeed && !clean.includes("/")) return void 0;
2913
2924
  return clean.split("/")[0];
2914
2925
  }
2926
+ function notebookOfItem(item) {
2927
+ if (item.notebookId && item.notebookId.trim()) {
2928
+ return wodWikiCore.toNotebookId(item.notebookId);
2929
+ }
2930
+ if (item.tags) {
2931
+ for (const tag of item.tags) {
2932
+ if (tag.startsWith("notebook:") || tag.startsWith("notebook/")) {
2933
+ const slug = wodWikiCore.notebookSlugFromId(tag);
2934
+ if (slug) return wodWikiCore.toNotebookId(slug);
2935
+ }
2936
+ }
2937
+ }
2938
+ if (sourceMatches(item, "playground")) return "notebook/playground";
2939
+ if (sourceMatches(item, "guides")) return "notebook/guides";
2940
+ const cat = catalogOfItem(item);
2941
+ if (cat) return wodWikiCore.toNotebookId(cat);
2942
+ if (sourceMatches(item, "journal")) return "notebook/journal";
2943
+ return void 0;
2944
+ }
2915
2945
  function sourceMatches(item, kind) {
2916
2946
  const sourceId = item.sourceId;
2917
2947
  if (kind === "all") return !sourceId || WQL_SOURCE_VALUES.some((k) => sourceMatches(item, k));
@@ -2920,7 +2950,7 @@ function sourceMatches(item, kind) {
2920
2950
  if (sourceId && sourceId !== "journal" && !NOTE_UUID_RE.test(sourceId) && !/^journal\/\d{4}-\d{2}-\d{2}$/.test(sourceId)) return false;
2921
2951
  return item.type !== "dashboard" && item.type !== "effort" && item.type !== "equipment" && item.seedOrigin !== "seed" && item.seedChunkId === void 0 && !item.catalog && !(!!item.sourcePath && item.sourcePath.startsWith("markdown/"));
2922
2952
  }
2923
- if (kind === "feed" || kind === "feeds") {
2953
+ if (kind === "feed" || kind === "feeds" || kind === "notebook" || kind === "notebooks") {
2924
2954
  return !!sourceId && (sourceId.startsWith("collection:") || sourceId.startsWith("page:collection:"));
2925
2955
  }
2926
2956
  if (kind === "page" || kind === "pages") {
@@ -2938,6 +2968,9 @@ function sourceMatches(item, kind) {
2938
2968
  const idRest = sourceId.slice("feed:".length).replace(/^feeds\//, "");
2939
2969
  return idRest === rest || idRest.startsWith(`${rest}/`);
2940
2970
  }
2971
+ if (kind.startsWith("notebook:") || kind.startsWith("notebook/")) {
2972
+ return notebookOfItem(item) === wodWikiCore.toNotebookId(kind);
2973
+ }
2941
2974
  return sourceId === kind;
2942
2975
  }
2943
2976
  function applySourceFilter(items, filters) {
@@ -2951,6 +2984,19 @@ function applySourceFilter(items, filters) {
2951
2984
  }
2952
2985
  return items;
2953
2986
  }
2987
+ function applyNotebookFilter(items, filters) {
2988
+ for (const filter of filters) {
2989
+ if (filter.key !== "notebook") continue;
2990
+ const wanted = new Set(filter.values.map((v) => wodWikiCore.toNotebookId(v.value)));
2991
+ items = items.filter((item) => {
2992
+ const nb = notebookOfItem(item);
2993
+ if (!nb) return filter.negate;
2994
+ const hit = wanted.has(nb);
2995
+ return filter.negate ? !hit : hit;
2996
+ });
2997
+ }
2998
+ return items;
2999
+ }
2954
3000
  var DOMAIN_SOURCE_KINDS = {
2955
3001
  feed: true,
2956
3002
  feeds: true,
@@ -3641,7 +3687,7 @@ var QueryService = class {
3641
3687
  if (parsed.target === "segment" || parsed.target === "event") {
3642
3688
  return this.runFindTable(parsed, options2);
3643
3689
  }
3644
- 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"));
3690
+ 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" || v.value === "notebook" || v.value === "notebooks")) || parsed.sourceScope?.includes("feeds") || parsed.sourceScope?.includes("notebooks"));
3645
3691
  if (isCatalogHead) {
3646
3692
  return this.runFindCatalog(parsed, options2, await this.noteStore.getAllNotes());
3647
3693
  }
@@ -3724,6 +3770,7 @@ var QueryService = class {
3724
3770
  });
3725
3771
  }
3726
3772
  }
3773
+ notes = applyNotebookFilter(notes, parsed.filters);
3727
3774
  for (const filter of parsed.filters) {
3728
3775
  if (filter.key === "note") {
3729
3776
  const wanted = new Set(filter.values.map((v) => v.value));
@@ -3862,6 +3909,7 @@ var QueryService = class {
3862
3909
  });
3863
3910
  }
3864
3911
  }
3912
+ blocks = applyNotebookFilter(blocks, parsed.filters);
3865
3913
  for (const filter of parsed.filters) {
3866
3914
  if (filter.key === "tags" && !filter.negate) {
3867
3915
  const matchingNoteIds = /* @__PURE__ */ new Set();
@@ -4488,14 +4536,14 @@ var QueryService = class {
4488
4536
  }
4489
4537
  }
4490
4538
  const criteriaFilters = parsed.filters.filter(
4491
- (f) => !(f.key === "source" && !f.negate && f.values.some((v) => v.value === "feeds" || v.value === "feed")) && !(f.key === "type" && !f.negate && f.values.some((v) => v.value === "feed"))
4539
+ (f) => !(f.key === "source" && !f.negate && f.values.some((v) => v.value === "feeds" || v.value === "feed" || v.value === "notebooks" || v.value === "notebook")) && !(f.key === "type" && !f.negate && f.values.some((v) => v.value === "feed"))
4492
4540
  );
4493
4541
  let matchingCatalogs = [...catalogNotes];
4494
4542
  for (const filter of criteriaFilters) {
4495
- if (filter.key === "catalog") {
4496
- const wanted = new Set(filter.values.map((v) => v.value));
4543
+ if (filter.key === "catalog" || filter.key === "notebook") {
4544
+ const wanted = new Set(filter.values.map((v) => wodWikiCore.notebookSlugFromId(v.value)));
4497
4545
  matchingCatalogs = matchingCatalogs.filter((c) => {
4498
- const catId = catalogOfItem(c) ?? c.id;
4546
+ const catId = wodWikiCore.notebookSlugFromId(catalogOfItem(c) ?? c.id);
4499
4547
  const hit = wanted.has(catId);
4500
4548
  return filter.negate ? !hit : hit;
4501
4549
  });
@@ -5221,15 +5269,19 @@ ${query}
5221
5269
  }
5222
5270
 
5223
5271
  // src/version.ts
5224
- var VERSION = "0.37.2140";
5225
- var GIT_SHA = "bcf7960";
5226
- var BUILD_TIME = "2026-10-18T21:43:29.081Z";
5272
+ var VERSION = "0.39.2142";
5273
+ var GIT_SHA = "fce2c7d";
5274
+ var BUILD_TIME = "2026-10-19T23:06:12.684Z";
5227
5275
  var SEMVER = {
5228
- version: "0.37.2140",
5229
- gitSha: "bcf7960",
5230
- buildTime: "2026-10-18T21:43:29.081Z"
5276
+ version: "0.39.2142",
5277
+ gitSha: "fce2c7d",
5278
+ buildTime: "2026-10-19T23:06:12.684Z"
5231
5279
  };
5232
5280
 
5281
+ Object.defineProperty(exports, "DEFAULT_NOTEBOOK_SLUGS", {
5282
+ enumerable: true,
5283
+ get: function () { return wodWikiCore.DEFAULT_NOTEBOOK_SLUGS; }
5284
+ });
5233
5285
  Object.defineProperty(exports, "SYSTEM_DEFAULT_OUTPUT_UNIT", {
5234
5286
  enumerable: true,
5235
5287
  get: function () { return wodWikiCore.SYSTEM_DEFAULT_OUTPUT_UNIT; }
@@ -5246,14 +5298,26 @@ Object.defineProperty(exports, "dimensionKeyOf", {
5246
5298
  enumerable: true,
5247
5299
  get: function () { return wodWikiCore.dimensionKeyOf; }
5248
5300
  });
5301
+ Object.defineProperty(exports, "isNoteEditable", {
5302
+ enumerable: true,
5303
+ get: function () { return wodWikiCore.isNoteEditable; }
5304
+ });
5249
5305
  Object.defineProperty(exports, "lookupUnit", {
5250
5306
  enumerable: true,
5251
5307
  get: function () { return wodWikiCore.lookupUnit; }
5252
5308
  });
5309
+ Object.defineProperty(exports, "notebookSlugFromId", {
5310
+ enumerable: true,
5311
+ get: function () { return wodWikiCore.notebookSlugFromId; }
5312
+ });
5253
5313
  Object.defineProperty(exports, "systemDefaultUnit", {
5254
5314
  enumerable: true,
5255
5315
  get: function () { return wodWikiCore.systemDefaultUnit; }
5256
5316
  });
5317
+ Object.defineProperty(exports, "toNotebookId", {
5318
+ enumerable: true,
5319
+ get: function () { return wodWikiCore.toNotebookId; }
5320
+ });
5257
5321
  exports.BUILD_TIME = BUILD_TIME;
5258
5322
  exports.CONTENT_GROUPING_DIMENSIONS = CONTENT_GROUPING_DIMENSIONS;
5259
5323
  exports.DASHBOARD_GRID_MAX_COLS = DASHBOARD_GRID_MAX_COLS;
@@ -5336,6 +5400,7 @@ exports.migrateLegacyDashboardBodies = migrateLegacyDashboardBodies;
5336
5400
  exports.moveWidget = moveWidget;
5337
5401
  exports.normalizeSummaryFacts = normalizeSummaryFacts;
5338
5402
  exports.normalizeWql = normalizeWql;
5403
+ exports.notebookOfItem = notebookOfItem;
5339
5404
  exports.parseDashboardNote = parseDashboardNote;
5340
5405
  exports.parseDocument = parseDocument;
5341
5406
  exports.parseFlatProperties = parseFlatProperties;