@bitcobblers/wod-wiki-wql 0.6.32 → 0.7.37
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 +309 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +92 -42
- package/dist/index.d.ts +92 -42
- package/dist/index.mjs +307 -141
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -53,7 +53,7 @@ var WQL_CALC_TARGETS = [
|
|
|
53
53
|
"calc.sends"
|
|
54
54
|
];
|
|
55
55
|
var WQL_INTENSITY_TIERS = ["low", "moderate", "high"];
|
|
56
|
-
var WQL_GRAINS = ["
|
|
56
|
+
var WQL_GRAINS = ["summary", "event"];
|
|
57
57
|
var WQL_FIND_TARGETS = ["note", "block", "effort"];
|
|
58
58
|
var WQL_SCOPES = ["journal", "collections", "feeds", "all"];
|
|
59
59
|
var WQL_CONTENT_FILTER_KEYS = ["type", "text", "has", "source", "catalog", ...WQL_TAG_KEYS];
|
|
@@ -160,55 +160,62 @@ function parseWqlSuffixes(raw) {
|
|
|
160
160
|
let groupBy;
|
|
161
161
|
let last;
|
|
162
162
|
let scope;
|
|
163
|
+
const conflicts = [];
|
|
163
164
|
const isFind = text.startsWith("find:");
|
|
164
165
|
const isRows = /^rows(?=[:{]|\s|$)/.test(text);
|
|
166
|
+
const stripRepeated = (re) => {
|
|
167
|
+
const matches = [];
|
|
168
|
+
for (let m = re.exec(text); m; m = re.exec(text)) {
|
|
169
|
+
matches.unshift(m);
|
|
170
|
+
text = text.slice(0, m.index).trim();
|
|
171
|
+
}
|
|
172
|
+
return matches;
|
|
173
|
+
};
|
|
174
|
+
const conflictFrom = (label, ms) => {
|
|
175
|
+
if (ms.length > 1) {
|
|
176
|
+
conflicts.push(
|
|
177
|
+
`Duplicate '${label}' clause: '${ms[0][0].trim()}' conflicts with '${ms[ms.length - 1][0].trim()}'`
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
};
|
|
165
181
|
if (isFind || isRows) {
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
raw: lastMatch[0].trim()
|
|
172
|
-
};
|
|
173
|
-
text = text.slice(0, lastMatch.index).trim();
|
|
182
|
+
const lasts = stripRepeated(LAST_RE);
|
|
183
|
+
conflictFrom("window", lasts);
|
|
184
|
+
if (lasts.length) {
|
|
185
|
+
const m = lasts[lasts.length - 1];
|
|
186
|
+
last = { size: parseInt(m[1], 10), unit: m[2].toLowerCase(), raw: m[0].trim() };
|
|
174
187
|
}
|
|
175
188
|
if (isFind) {
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
text = text.slice(0, scopeMatch.index).trim();
|
|
180
|
-
}
|
|
189
|
+
const scopes = stripRepeated(IN_SCOPE_RE);
|
|
190
|
+
conflictFrom("scope", scopes);
|
|
191
|
+
if (scopes.length) scope = scopes[scopes.length - 1][1];
|
|
181
192
|
} else {
|
|
182
|
-
const
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
193
|
+
const rollups = stripRepeated(ROLLUP_RE);
|
|
194
|
+
conflictFrom(".rollup", rollups);
|
|
195
|
+
if (rollups.length) {
|
|
196
|
+
const m = rollups[rollups.length - 1];
|
|
197
|
+
rollup = { size: m[1] ? parseInt(m[1], 10) : 1, unit: m[2] || "", raw: m[1] + m[2] };
|
|
187
198
|
}
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
199
|
+
const bys = stripRepeated(BY_RE);
|
|
200
|
+
conflictFrom("by", bys);
|
|
201
|
+
if (bys.length) {
|
|
202
|
+
groupBy = bys[bys.length - 1][1].split(",").map((d) => d.trim()).filter(Boolean);
|
|
192
203
|
}
|
|
193
204
|
}
|
|
194
205
|
} else {
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const size = rollupMatch[1] ? parseInt(rollupMatch[1], 10) : 1;
|
|
204
|
-
const unit = rollupMatch[2] || "";
|
|
205
|
-
rollup = { size, unit, raw: rawRollup };
|
|
206
|
-
text = text.slice(0, rollupMatch.index).trim();
|
|
206
|
+
const units = stripRepeated(DISPLAY_UNIT_RE);
|
|
207
|
+
conflictFrom("display-unit", units);
|
|
208
|
+
if (units.length) displayUnit = units[units.length - 1][1];
|
|
209
|
+
const rollups = stripRepeated(ROLLUP_RE);
|
|
210
|
+
conflictFrom(".rollup", rollups);
|
|
211
|
+
if (rollups.length) {
|
|
212
|
+
const m = rollups[rollups.length - 1];
|
|
213
|
+
rollup = { size: m[1] ? parseInt(m[1], 10) : 1, unit: m[2] || "", raw: m[1] + m[2] };
|
|
207
214
|
}
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
215
|
+
const bys = stripRepeated(BY_RE);
|
|
216
|
+
conflictFrom("by", bys);
|
|
217
|
+
if (bys.length) {
|
|
218
|
+
groupBy = bys[bys.length - 1][1].split(",").map((d) => d.trim()).filter(Boolean);
|
|
212
219
|
}
|
|
213
220
|
}
|
|
214
221
|
return {
|
|
@@ -218,6 +225,7 @@ function parseWqlSuffixes(raw) {
|
|
|
218
225
|
groupBy,
|
|
219
226
|
last,
|
|
220
227
|
scope,
|
|
228
|
+
conflicts: conflicts.length ? conflicts : void 0,
|
|
221
229
|
primaryText: text
|
|
222
230
|
};
|
|
223
231
|
}
|
|
@@ -279,6 +287,10 @@ function parseRowsQuery(raw) {
|
|
|
279
287
|
filters: [],
|
|
280
288
|
last: last ? { size: last.size, unit: last.unit } : void 0
|
|
281
289
|
};
|
|
290
|
+
if (suffixes.conflicts?.length) {
|
|
291
|
+
result.error = suffixes.conflicts.join("; ");
|
|
292
|
+
return result;
|
|
293
|
+
}
|
|
282
294
|
if (whereText || groupBy || rollup) {
|
|
283
295
|
result.error = `Rows queries return raw statements \u2014 no where / by / rollup. Got "${primaryText.trim()}"`;
|
|
284
296
|
return result;
|
|
@@ -314,9 +326,20 @@ function parseRowsQuery(raw) {
|
|
|
314
326
|
return result;
|
|
315
327
|
}
|
|
316
328
|
result.filters = extractFilters(tree.topNode, synthetic);
|
|
329
|
+
const grainError = retiredGrainRollup(result.filters);
|
|
330
|
+
if (grainError) {
|
|
331
|
+
result.error = grainError;
|
|
332
|
+
return result;
|
|
333
|
+
}
|
|
317
334
|
}
|
|
318
335
|
return result;
|
|
319
336
|
}
|
|
337
|
+
function retiredGrainRollup(filters) {
|
|
338
|
+
if (filters.some((f) => f.key === "grain" && f.values.some((v) => v.value === "rollup"))) {
|
|
339
|
+
return "grain:rollup is retired \u2014 rollup grains are never stored; compute them with the .rollup suffix";
|
|
340
|
+
}
|
|
341
|
+
return void 0;
|
|
342
|
+
}
|
|
320
343
|
function extractFilters(query, text) {
|
|
321
344
|
const out = [];
|
|
322
345
|
const filters = query.getChild(Filters);
|
|
@@ -356,6 +379,10 @@ function parseAnalyticsQuery(raw) {
|
|
|
356
379
|
displayUnit,
|
|
357
380
|
rollup: rollup ? { size: rollup.size, unit: rollup.unit } : void 0
|
|
358
381
|
};
|
|
382
|
+
if (suffixes.conflicts?.length) {
|
|
383
|
+
base.error = suffixes.conflicts.join("; ");
|
|
384
|
+
return base;
|
|
385
|
+
}
|
|
359
386
|
if (rollup && rollup.unit !== "d" && rollup.unit !== "w") {
|
|
360
387
|
base.error = cannotParse(text);
|
|
361
388
|
return base;
|
|
@@ -385,6 +412,11 @@ function parseAnalyticsQuery(raw) {
|
|
|
385
412
|
base.agg = aggText;
|
|
386
413
|
base.metric = text.slice(metricNode.from, metricNode.to);
|
|
387
414
|
base.filters = extractFilters(query, text);
|
|
415
|
+
const grainError = retiredGrainRollup(base.filters);
|
|
416
|
+
if (grainError) {
|
|
417
|
+
base.error = grainError;
|
|
418
|
+
return base;
|
|
419
|
+
}
|
|
388
420
|
if (whereText) {
|
|
389
421
|
const join = parseJoinClause(whereText);
|
|
390
422
|
if (join.error) {
|
|
@@ -412,6 +444,10 @@ function parseFindQuery(raw) {
|
|
|
412
444
|
scope,
|
|
413
445
|
last: last ? { size: last.size, unit: last.unit } : void 0
|
|
414
446
|
};
|
|
447
|
+
if (suffixes.conflicts?.length) {
|
|
448
|
+
result.error = suffixes.conflicts.join("; ");
|
|
449
|
+
return result;
|
|
450
|
+
}
|
|
415
451
|
const tree = parser.parse(text);
|
|
416
452
|
let syntaxError = false;
|
|
417
453
|
tree.iterate({ enter(node) {
|
|
@@ -436,6 +472,11 @@ function parseFindQuery(raw) {
|
|
|
436
472
|
}
|
|
437
473
|
result.target = text.slice(metricNode.from, metricNode.to);
|
|
438
474
|
result.filters = extractFilters(query, text);
|
|
475
|
+
const findGrainError = retiredGrainRollup(result.filters);
|
|
476
|
+
if (findGrainError) {
|
|
477
|
+
result.error = findGrainError;
|
|
478
|
+
return result;
|
|
479
|
+
}
|
|
439
480
|
if (whereText) {
|
|
440
481
|
const join = parseJoinClause(whereText);
|
|
441
482
|
if (join.error) {
|
|
@@ -721,9 +762,8 @@ function readGroupTags(metadata) {
|
|
|
721
762
|
const entries = Object.entries(tags).filter((pair) => typeof pair[1] === "string" && pair[1].length > 0).sort(([a], [b]) => a < b ? -1 : 1);
|
|
722
763
|
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
723
764
|
}
|
|
724
|
-
function
|
|
725
|
-
const
|
|
726
|
-
const rowsByKey = /* @__PURE__ */ new Map();
|
|
765
|
+
function foldSummaryOutputs(logs) {
|
|
766
|
+
const folded = /* @__PURE__ */ new Map();
|
|
727
767
|
for (const output of logs) {
|
|
728
768
|
if (output.outputType !== "analytics") continue;
|
|
729
769
|
const label = output.metrics.find((m) => m.type === MetricType.Label);
|
|
@@ -738,32 +778,171 @@ function normalizeSummaryFacts(logs, identity) {
|
|
|
738
778
|
const grade = metadataString(value.metadata, "grade");
|
|
739
779
|
const groupTags = readGroupTags(value.metadata) ?? (effortSlug ? { effort: effortSlug } : void 0);
|
|
740
780
|
const rowKey = groupTags ? `${metricKey}:${Object.entries(groupTags).map(([k, v]) => `${k}=${v}`).join(":")}` : metricKey;
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
blockContentId: identity.blockContentId,
|
|
745
|
-
origin: identity.origin,
|
|
746
|
-
pageId: identity.pageId,
|
|
747
|
-
grain: "summary",
|
|
748
|
-
segmentId: identity.segmentId ?? "",
|
|
749
|
-
segmentVersion: identity.segmentVersion ?? 0,
|
|
750
|
-
resultId: identity.resultId,
|
|
751
|
-
type: metricKey,
|
|
781
|
+
folded.set(rowKey, {
|
|
782
|
+
projectionName,
|
|
783
|
+
metricKey,
|
|
752
784
|
value: value.value,
|
|
753
785
|
unit: value.unit,
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
...grade ? { grade } : {},
|
|
762
|
-
timestamp: identity.workoutTimestamp ?? output.timeSpan?.started ?? now,
|
|
763
|
-
createdAt: now
|
|
786
|
+
effortSlug,
|
|
787
|
+
discipline,
|
|
788
|
+
intensityTier,
|
|
789
|
+
grade,
|
|
790
|
+
groupTags,
|
|
791
|
+
rowKey,
|
|
792
|
+
started: output.timeSpan?.started
|
|
764
793
|
});
|
|
765
794
|
}
|
|
766
|
-
return
|
|
795
|
+
return folded;
|
|
796
|
+
}
|
|
797
|
+
function normalizeSummaryFacts(logs, identity) {
|
|
798
|
+
const now = Date.now();
|
|
799
|
+
return Array.from(foldSummaryOutputs(logs).values(), (f) => ({
|
|
800
|
+
id: `${identity.resultId}-${f.rowKey}-${now}`,
|
|
801
|
+
noteId: identity.noteId,
|
|
802
|
+
blockContentId: identity.blockContentId,
|
|
803
|
+
origin: identity.origin,
|
|
804
|
+
pageId: identity.pageId,
|
|
805
|
+
grain: "summary",
|
|
806
|
+
segmentId: identity.segmentId ?? "",
|
|
807
|
+
segmentVersion: identity.segmentVersion ?? 0,
|
|
808
|
+
resultId: identity.resultId,
|
|
809
|
+
type: f.metricKey,
|
|
810
|
+
value: f.value,
|
|
811
|
+
unit: f.unit,
|
|
812
|
+
label: f.projectionName,
|
|
813
|
+
metricKey: f.metricKey,
|
|
814
|
+
metricLabel: f.projectionName,
|
|
815
|
+
metricUnit: f.unit,
|
|
816
|
+
...f.effortSlug ? { effortSlug: f.effortSlug } : {},
|
|
817
|
+
...f.discipline ? { discipline: f.discipline } : {},
|
|
818
|
+
...f.intensityTier ? { intensityTier: f.intensityTier } : {},
|
|
819
|
+
...f.grade ? { grade: f.grade } : {},
|
|
820
|
+
timestamp: identity.workoutTimestamp ?? f.started ?? now,
|
|
821
|
+
createdAt: now
|
|
822
|
+
}));
|
|
823
|
+
}
|
|
824
|
+
function firstEffortSlug(metrics) {
|
|
825
|
+
const loose = metrics;
|
|
826
|
+
for (const m of loose) {
|
|
827
|
+
const slug = metadataString(m.metadata, "effortSlug");
|
|
828
|
+
if (slug) return slug;
|
|
829
|
+
}
|
|
830
|
+
return void 0;
|
|
831
|
+
}
|
|
832
|
+
function toEventRows(logs, identity) {
|
|
833
|
+
return logs.map((output, seq) => ({
|
|
834
|
+
id: `${identity.resultId}:${seq}`,
|
|
835
|
+
resultId: identity.resultId,
|
|
836
|
+
noteId: identity.noteId,
|
|
837
|
+
blockContentId: identity.blockContentId,
|
|
838
|
+
pageId: identity.pageId,
|
|
839
|
+
origin: identity.origin,
|
|
840
|
+
timestamp: identity.workoutTimestamp ?? output.timeSpan?.started ?? Date.now(),
|
|
841
|
+
grain: "event",
|
|
842
|
+
outputType: output.outputType ?? "segment",
|
|
843
|
+
effortSlug: firstEffortSlug(output.metrics),
|
|
844
|
+
metrics: output.metrics,
|
|
845
|
+
timeSpan: output.timeSpan?.started !== void 0 ? { started: output.timeSpan.started, ended: output.timeSpan.ended } : void 0,
|
|
846
|
+
sourceBlockKey: output.sourceBlockKey,
|
|
847
|
+
stackLevel: output.stackLevel,
|
|
848
|
+
completionReason: output.completionReason,
|
|
849
|
+
segmentId: identity.segmentId,
|
|
850
|
+
segmentVersion: identity.segmentVersion
|
|
851
|
+
}));
|
|
852
|
+
}
|
|
853
|
+
function toSummaryEventRows(logs, identity) {
|
|
854
|
+
const now = Date.now();
|
|
855
|
+
return Array.from(foldSummaryOutputs(logs).values(), (f) => ({
|
|
856
|
+
id: `${identity.resultId}:summary:${f.rowKey}`,
|
|
857
|
+
resultId: identity.resultId,
|
|
858
|
+
noteId: identity.noteId,
|
|
859
|
+
blockContentId: identity.blockContentId,
|
|
860
|
+
pageId: identity.pageId,
|
|
861
|
+
origin: identity.origin,
|
|
862
|
+
timestamp: identity.workoutTimestamp ?? f.started ?? now,
|
|
863
|
+
grain: "summary",
|
|
864
|
+
outputType: "analytics",
|
|
865
|
+
effortSlug: f.effortSlug,
|
|
866
|
+
metrics: [{
|
|
867
|
+
type: f.metricKey,
|
|
868
|
+
value: f.value,
|
|
869
|
+
...f.unit ? { unit: f.unit } : {},
|
|
870
|
+
metadata: {
|
|
871
|
+
canonicalKey: f.metricKey,
|
|
872
|
+
...f.effortSlug ? { effortSlug: f.effortSlug } : {},
|
|
873
|
+
...f.discipline ? { effortDiscipline: f.discipline } : {},
|
|
874
|
+
...f.intensityTier ? { effortIntensityTier: f.intensityTier } : {},
|
|
875
|
+
...f.groupTags ? { groupTags: f.groupTags } : {},
|
|
876
|
+
...f.grade ? { grade: f.grade } : {}
|
|
877
|
+
}
|
|
878
|
+
}],
|
|
879
|
+
segmentId: identity.segmentId,
|
|
880
|
+
segmentVersion: identity.segmentVersion
|
|
881
|
+
}));
|
|
882
|
+
}
|
|
883
|
+
function projectEventToFacts(record) {
|
|
884
|
+
const metrics = record.metrics;
|
|
885
|
+
if (record.grain === "summary") {
|
|
886
|
+
const m = metrics[0];
|
|
887
|
+
if (!m || typeof m.value !== "number") return [];
|
|
888
|
+
const metricKey = metadataString(m.metadata, "canonicalKey") ?? (m.type ?? "");
|
|
889
|
+
return [{
|
|
890
|
+
id: `${record.id}:0`,
|
|
891
|
+
noteId: record.noteId,
|
|
892
|
+
blockContentId: record.blockContentId,
|
|
893
|
+
origin: record.origin,
|
|
894
|
+
pageId: record.pageId,
|
|
895
|
+
grain: "summary",
|
|
896
|
+
segmentId: record.segmentId ?? "",
|
|
897
|
+
segmentVersion: record.segmentVersion ?? 0,
|
|
898
|
+
resultId: record.resultId,
|
|
899
|
+
type: metricKey,
|
|
900
|
+
value: m.value,
|
|
901
|
+
unit: m.unit,
|
|
902
|
+
label: metricKey,
|
|
903
|
+
metricKey,
|
|
904
|
+
metricLabel: metricKey,
|
|
905
|
+
metricUnit: m.unit,
|
|
906
|
+
effortSlug: metadataString(m.metadata, "effortSlug") ?? record.effortSlug,
|
|
907
|
+
discipline: metadataString(m.metadata, "effortDiscipline"),
|
|
908
|
+
intensityTier: metadataString(m.metadata, "effortIntensityTier"),
|
|
909
|
+
grade: metadataString(m.metadata, "grade"),
|
|
910
|
+
timestamp: record.timestamp,
|
|
911
|
+
createdAt: record.timestamp
|
|
912
|
+
}];
|
|
913
|
+
}
|
|
914
|
+
const label = metrics.find((m) => m.type === MetricType.Label);
|
|
915
|
+
const labelName = label ? String(label.value ?? label.image ?? "") : "";
|
|
916
|
+
const facts = [];
|
|
917
|
+
metrics.forEach((m) => {
|
|
918
|
+
if (m.type === MetricType.Label || typeof m.value !== "number") return;
|
|
919
|
+
const metricKey = metadataString(m.metadata, "canonicalKey") ?? (labelName ? resolveCanonicalMetricKey(labelName) : m.type ?? "metric");
|
|
920
|
+
const ordinal = facts.length;
|
|
921
|
+
facts.push({
|
|
922
|
+
id: `${record.id}:${ordinal}`,
|
|
923
|
+
noteId: record.noteId,
|
|
924
|
+
blockContentId: record.blockContentId,
|
|
925
|
+
origin: record.origin,
|
|
926
|
+
pageId: record.pageId,
|
|
927
|
+
grain: "event",
|
|
928
|
+
segmentId: record.segmentId ?? "",
|
|
929
|
+
segmentVersion: record.segmentVersion ?? 0,
|
|
930
|
+
resultId: record.resultId,
|
|
931
|
+
type: metricKey,
|
|
932
|
+
value: m.value,
|
|
933
|
+
unit: m.unit,
|
|
934
|
+
label: labelName || metricKey,
|
|
935
|
+
metricKey,
|
|
936
|
+
metricLabel: labelName || metricKey,
|
|
937
|
+
metricUnit: m.unit,
|
|
938
|
+
effortSlug: metadataString(m.metadata, "effortSlug") ?? record.effortSlug,
|
|
939
|
+
intensityTier: metadataString(m.metadata, "effortIntensityTier"),
|
|
940
|
+
grade: metadataString(m.metadata, "grade"),
|
|
941
|
+
timestamp: record.timestamp,
|
|
942
|
+
createdAt: record.timestamp
|
|
943
|
+
});
|
|
944
|
+
});
|
|
945
|
+
return facts;
|
|
767
946
|
}
|
|
768
947
|
|
|
769
948
|
// src/dashboard/frontmatter.ts
|
|
@@ -955,23 +1134,27 @@ function windowAnchor(selected, parsed, options2) {
|
|
|
955
1134
|
if (options2.anchor === "latest-activity" && parsed.last) return latestActivity(selected);
|
|
956
1135
|
return void 0;
|
|
957
1136
|
}
|
|
958
|
-
var
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
1137
|
+
var defaultEventStore = {
|
|
1138
|
+
getEventsByTimeRange: async () => [],
|
|
1139
|
+
getEventsByResult: async () => [],
|
|
1140
|
+
getEventsForNote: async () => [],
|
|
1141
|
+
getEventsByContent: async () => [],
|
|
1142
|
+
scanAll: async () => [],
|
|
1143
|
+
appendEvents: async () => {
|
|
1144
|
+
},
|
|
1145
|
+
finalizeSummaries: async () => {
|
|
1146
|
+
},
|
|
1147
|
+
deleteEvents: async () => {
|
|
1148
|
+
}
|
|
962
1149
|
};
|
|
963
1150
|
var defaultNoteStore = {
|
|
964
1151
|
getAllNotes: async () => [],
|
|
965
|
-
getNoteIdsForTag: async () => /* @__PURE__ */ new Set()
|
|
1152
|
+
getNoteIdsForTag: async () => /* @__PURE__ */ new Set(),
|
|
1153
|
+
getNoteTagLabels: async () => []
|
|
966
1154
|
};
|
|
967
1155
|
var defaultBlockStore = {
|
|
968
1156
|
getAllBlocks: async () => []
|
|
969
1157
|
};
|
|
970
|
-
var defaultResultStore = {
|
|
971
|
-
getResultsByContentId: async () => [],
|
|
972
|
-
getResultById: async () => void 0,
|
|
973
|
-
getResultsForNote: async () => []
|
|
974
|
-
};
|
|
975
1158
|
var defaultEffortStore = {
|
|
976
1159
|
getAllEfforts: async () => []
|
|
977
1160
|
};
|
|
@@ -1083,32 +1266,31 @@ var QueryService = class {
|
|
|
1083
1266
|
store;
|
|
1084
1267
|
noteStore;
|
|
1085
1268
|
blockStore;
|
|
1086
|
-
resultStore;
|
|
1087
1269
|
effortStore;
|
|
1088
1270
|
staticNoteStore;
|
|
1089
1271
|
staticBlockStore;
|
|
1090
|
-
constructor(
|
|
1091
|
-
if (
|
|
1092
|
-
const stores =
|
|
1093
|
-
this.store = stores.
|
|
1272
|
+
constructor(storesOrEventStore, noteStore, blockStore, effortStore, staticNoteStore, staticBlockStore) {
|
|
1273
|
+
if (storesOrEventStore && typeof storesOrEventStore === "object" && ("eventStore" in storesOrEventStore || "noteStore" in storesOrEventStore || "blockStore" in storesOrEventStore || "effortStore" in storesOrEventStore || "staticNoteStore" in storesOrEventStore || "staticBlockStore" in storesOrEventStore)) {
|
|
1274
|
+
const stores = storesOrEventStore;
|
|
1275
|
+
this.store = stores.eventStore ?? defaultEventStore;
|
|
1094
1276
|
this.noteStore = stores.noteStore ?? defaultNoteStore;
|
|
1095
1277
|
this.blockStore = stores.blockStore ?? defaultBlockStore;
|
|
1096
|
-
this.resultStore = stores.resultStore ?? defaultResultStore;
|
|
1097
1278
|
this.effortStore = stores.effortStore ?? defaultEffortStore;
|
|
1098
1279
|
this.staticNoteStore = stores.staticNoteStore;
|
|
1099
1280
|
this.staticBlockStore = stores.staticBlockStore;
|
|
1100
1281
|
} else {
|
|
1101
|
-
this.store =
|
|
1282
|
+
this.store = storesOrEventStore ?? defaultEventStore;
|
|
1102
1283
|
this.noteStore = noteStore ?? defaultNoteStore;
|
|
1103
1284
|
this.blockStore = blockStore ?? defaultBlockStore;
|
|
1104
|
-
this.resultStore = resultStore ?? defaultResultStore;
|
|
1105
1285
|
this.effortStore = effortStore ?? defaultEffortStore;
|
|
1106
1286
|
this.staticNoteStore = staticNoteStore;
|
|
1107
1287
|
this.staticBlockStore = staticBlockStore;
|
|
1108
1288
|
}
|
|
1109
1289
|
}
|
|
1290
|
+
/** Windowed flat-fact fetch — the projected view over the event store. */
|
|
1110
1291
|
async getFactsByTimeRange(start, end) {
|
|
1111
|
-
|
|
1292
|
+
const rows = await this.store.getEventsByTimeRange(start, end);
|
|
1293
|
+
return rows.flatMap(projectEventToFacts);
|
|
1112
1294
|
}
|
|
1113
1295
|
async runQuery(raw, options2 = {}) {
|
|
1114
1296
|
const parsed = parseQuery(raw);
|
|
@@ -1132,8 +1314,8 @@ var QueryService = class {
|
|
|
1132
1314
|
}
|
|
1133
1315
|
/**
|
|
1134
1316
|
* Execute a rows query (rows:{…}, #949) — the session results table plane.
|
|
1135
|
-
*
|
|
1136
|
-
*
|
|
1317
|
+
* Reads event rows directly over the unified store (ticket 003): no
|
|
1318
|
+
* WorkoutResult blob parsing; outputType narrowing hits the promoted column.
|
|
1137
1319
|
*/
|
|
1138
1320
|
async runRows(parsed, options2 = {}) {
|
|
1139
1321
|
const empty = { parsed, runs: [] };
|
|
@@ -1155,28 +1337,30 @@ var QueryService = class {
|
|
|
1155
1337
|
if (resultIds.length + blockIds.length + noteIds.length === 0) {
|
|
1156
1338
|
return { ...empty, error: "Rows query needs a scope: result:, block:, or note:." };
|
|
1157
1339
|
}
|
|
1158
|
-
const
|
|
1159
|
-
|
|
1160
|
-
const
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
}
|
|
1166
|
-
for (const
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
let
|
|
1340
|
+
const byResult = /* @__PURE__ */ new Map();
|
|
1341
|
+
const collect = (rows) => {
|
|
1342
|
+
for (const row of rows) {
|
|
1343
|
+
const bucket = byResult.get(row.resultId);
|
|
1344
|
+
if (bucket) bucket.push(row);
|
|
1345
|
+
else byResult.set(row.resultId, [row]);
|
|
1346
|
+
}
|
|
1347
|
+
};
|
|
1348
|
+
for (const id of resultIds) collect(await this.store.getEventsByResult(id));
|
|
1349
|
+
for (const blockContentId of blockIds) collect(await this.store.getEventsByContent(blockContentId));
|
|
1350
|
+
for (const noteId of noteIds) collect(await this.store.getEventsForNote(noteId));
|
|
1351
|
+
let groups = [...byResult.entries()].filter(([, rows]) => rows.length > 0);
|
|
1170
1352
|
if (parsed.last) {
|
|
1171
|
-
|
|
1172
|
-
(
|
|
1353
|
+
groups = groups.filter(
|
|
1354
|
+
([, rows]) => effectiveTimeWindow(rows[0].timestamp, parsed.last, void 0, options2.anchorNow)
|
|
1173
1355
|
);
|
|
1174
1356
|
}
|
|
1175
|
-
|
|
1176
|
-
const runs =
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1357
|
+
groups.sort((a, b) => b[1][0].timestamp - a[1][0].timestamp);
|
|
1358
|
+
const runs = groups.map(([resultId, rows]) => ({
|
|
1359
|
+
resultId,
|
|
1360
|
+
noteId: rows[0].noteId,
|
|
1361
|
+
timestamp: rows[0].timestamp,
|
|
1362
|
+
events: parsed.outputType ? rows.filter((row) => row.outputType === parsed.outputType) : rows
|
|
1363
|
+
})).filter((run) => run.events.length > 0);
|
|
1180
1364
|
return { parsed, runs };
|
|
1181
1365
|
}
|
|
1182
1366
|
/**
|
|
@@ -1365,14 +1549,11 @@ var QueryService = class {
|
|
|
1365
1549
|
};
|
|
1366
1550
|
if (parsed.error) return empty;
|
|
1367
1551
|
if (parsed.join) return this.runJoined(parsed, options2);
|
|
1368
|
-
const
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
const inRange = new Set((await this.store.getFactsByTimeRange(start, end)).map((row) => row.id));
|
|
1374
|
-
candidates = candidates.filter((row) => inRange.has(row.id));
|
|
1375
|
-
}
|
|
1552
|
+
const windowed = options2.rangeStart !== void 0 || options2.rangeEnd !== void 0;
|
|
1553
|
+
const start = options2.rangeStart ?? 0;
|
|
1554
|
+
const end = options2.rangeEnd ?? Number.MAX_SAFE_INTEGER;
|
|
1555
|
+
const eventRows = windowed ? await this.store.getEventsByTimeRange(start, end) : await this.store.scanAll();
|
|
1556
|
+
const candidates = eventRows.flatMap(projectEventToFacts).filter((row) => row.metricKey === parsed.metric);
|
|
1376
1557
|
const touchesTags = parsed.filters.some((f) => f.key === "tags") || parsed.groupBy.includes("tags");
|
|
1377
1558
|
const noteTags = await this.loadNoteTags(candidates, touchesTags);
|
|
1378
1559
|
const matched = this.applyEffortScope(
|
|
@@ -1516,29 +1697,14 @@ var QueryService = class {
|
|
|
1516
1697
|
}
|
|
1517
1698
|
return matched.some((r) => r.effortSlug === void 0) ? matched.filter((r) => r.effortSlug === void 0) : matched;
|
|
1518
1699
|
}
|
|
1519
|
-
/**
|
|
1520
|
-
*
|
|
1521
|
-
*
|
|
1700
|
+
/** Summary facts for one Canonical Metric Key across the given content ids —
|
|
1701
|
+
* the cross-store join source. Reads finalize-written summary rows straight
|
|
1702
|
+
* off the content index (ticket 003: the store is authoritative; the old
|
|
1703
|
+
* freshness re-derivation is moot). One fact row per result × rowKey. */
|
|
1522
1704
|
async deriveMetricFacts(contentIds, metricKey) {
|
|
1523
|
-
const out = [];
|
|
1524
1705
|
const ids = [...new Set(contentIds)];
|
|
1525
|
-
await Promise.all(ids.map(
|
|
1526
|
-
|
|
1527
|
-
for (const result of results) {
|
|
1528
|
-
const facts = normalizeSummaryFacts(result.data.logs ?? [], {
|
|
1529
|
-
noteId: result.noteId,
|
|
1530
|
-
resultId: result.id,
|
|
1531
|
-
segmentId: result.segmentId,
|
|
1532
|
-
segmentVersion: result.segmentVersion,
|
|
1533
|
-
blockContentId,
|
|
1534
|
-
origin: result.origin,
|
|
1535
|
-
pageId: result.pageId,
|
|
1536
|
-
workoutTimestamp: result.createdAt
|
|
1537
|
-
});
|
|
1538
|
-
for (const f of facts) if (f.metricKey === metricKey) out.push(f);
|
|
1539
|
-
}
|
|
1540
|
-
}));
|
|
1541
|
-
return out;
|
|
1706
|
+
const rows = await Promise.all(ids.map((blockContentId) => this.store.getEventsByContent(blockContentId)));
|
|
1707
|
+
return rows.flat().filter((row) => row.grain === "summary").flatMap(projectEventToFacts).filter((f) => f.metricKey === metricKey);
|
|
1542
1708
|
}
|
|
1543
1709
|
/** All content blocks across the journal + static corpus. */
|
|
1544
1710
|
async allContentBlocks() {
|
|
@@ -1578,7 +1744,7 @@ var QueryService = class {
|
|
|
1578
1744
|
const noteTags = /* @__PURE__ */ new Map();
|
|
1579
1745
|
if (!touchesTags) return noteTags;
|
|
1580
1746
|
const noteIds = [...new Set(rows.map((r) => r.noteId))];
|
|
1581
|
-
await Promise.all(noteIds.map(async (id) => noteTags.set(id, await this.
|
|
1747
|
+
await Promise.all(noteIds.map(async (id) => noteTags.set(id, await this.noteStore.getNoteTagLabels(id))));
|
|
1582
1748
|
return noteTags;
|
|
1583
1749
|
}
|
|
1584
1750
|
};
|
|
@@ -1878,15 +2044,15 @@ sum:$metric{} rollup:1w
|
|
|
1878
2044
|
}
|
|
1879
2045
|
|
|
1880
2046
|
// src/version.ts
|
|
1881
|
-
var VERSION = "0.
|
|
1882
|
-
var GIT_SHA = "
|
|
1883
|
-
var BUILD_TIME = "2026-08-
|
|
2047
|
+
var VERSION = "0.7.37";
|
|
2048
|
+
var GIT_SHA = "713c593";
|
|
2049
|
+
var BUILD_TIME = "2026-08-25T00:18:25.714Z";
|
|
1884
2050
|
var SEMVER = {
|
|
1885
|
-
version: "0.
|
|
1886
|
-
gitSha: "
|
|
1887
|
-
buildTime: "2026-08-
|
|
2051
|
+
version: "0.7.37",
|
|
2052
|
+
gitSha: "713c593",
|
|
2053
|
+
buildTime: "2026-08-25T00:18:25.714Z"
|
|
1888
2054
|
};
|
|
1889
2055
|
|
|
1890
|
-
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_ROLLUP_PERIODS, WQL_SCOPES, WQL_SOURCES, WQL_TAG_KEYS, WQL_VIRTUAL_DIMS, buildDashboardDocument, buildDashboardScaffold, convert, dashboardSlug, defaultTokenValues, disciplineFactorFor, extractDashboardTokens, extractFrontmatterTags, getList, getScalar, getUnitFamily, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isProposedMetric, isRowsQuery, normalizeSummaryFacts, parseDashboardNote, parseFlatProperties, parseFrontmatter, parseFrontmatterBody, parseFrontmatterCategories, parseFrontmatterProps, parseQuery, parseQueryWidgetSuffix, parseWqlSuffixes, referencedTokens, resolveCanonicalMetricKey, resolveDisplayUnit, resolveWidgetType, serializeFrontmatter, setDashboardTokenValue, splitAtWhere, splitWidgetBody, staticNotesFromBlocks, staticTagIndexFromBlocks, stripFrontmatter, substituteTokens, unknownTokensMessage, unknownWidgetTypeMessage, wql, wqlCompletion, wqlCompletionSource, wqlHighlightStyle, wqlLanguage, parser as wqlParser, wql_parser_terms_exports as wqlTerms };
|
|
2056
|
+
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_ROLLUP_PERIODS, WQL_SCOPES, WQL_SOURCES, WQL_TAG_KEYS, WQL_VIRTUAL_DIMS, buildDashboardDocument, buildDashboardScaffold, convert, dashboardSlug, defaultTokenValues, disciplineFactorFor, extractDashboardTokens, extractFrontmatterTags, getList, getScalar, getUnitFamily, isDashboardMeta, isDashboardWidgetType, isEffortDiscipline, isFindQuery, isProposedMetric, isRowsQuery, normalizeSummaryFacts, 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 };
|
|
1891
2057
|
//# sourceMappingURL=index.mjs.map
|
|
1892
2058
|
//# sourceMappingURL=index.mjs.map
|