@bitcobblers/wod-wiki-wql 0.6.31 → 0.6.36
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 +251 -102
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +90 -42
- package/dist/index.d.ts +90 -42
- package/dist/index.mjs +249 -103
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -55,7 +55,7 @@ var WQL_CALC_TARGETS = [
|
|
|
55
55
|
"calc.sends"
|
|
56
56
|
];
|
|
57
57
|
var WQL_INTENSITY_TIERS = ["low", "moderate", "high"];
|
|
58
|
-
var WQL_GRAINS = ["
|
|
58
|
+
var WQL_GRAINS = ["summary", "event"];
|
|
59
59
|
var WQL_FIND_TARGETS = ["note", "block", "effort"];
|
|
60
60
|
var WQL_SCOPES = ["journal", "collections", "feeds", "all"];
|
|
61
61
|
var WQL_CONTENT_FILTER_KEYS = ["type", "text", "has", "source", "catalog", ...WQL_TAG_KEYS];
|
|
@@ -316,9 +316,20 @@ function parseRowsQuery(raw) {
|
|
|
316
316
|
return result;
|
|
317
317
|
}
|
|
318
318
|
result.filters = extractFilters(tree.topNode, synthetic);
|
|
319
|
+
const grainError = retiredGrainRollup(result.filters);
|
|
320
|
+
if (grainError) {
|
|
321
|
+
result.error = grainError;
|
|
322
|
+
return result;
|
|
323
|
+
}
|
|
319
324
|
}
|
|
320
325
|
return result;
|
|
321
326
|
}
|
|
327
|
+
function retiredGrainRollup(filters) {
|
|
328
|
+
if (filters.some((f) => f.key === "grain" && f.values.some((v) => v.value === "rollup"))) {
|
|
329
|
+
return "grain:rollup is retired \u2014 rollup grains are never stored; compute them with the .rollup suffix";
|
|
330
|
+
}
|
|
331
|
+
return void 0;
|
|
332
|
+
}
|
|
322
333
|
function extractFilters(query, text) {
|
|
323
334
|
const out = [];
|
|
324
335
|
const filters = query.getChild(Filters);
|
|
@@ -387,6 +398,11 @@ function parseAnalyticsQuery(raw) {
|
|
|
387
398
|
base.agg = aggText;
|
|
388
399
|
base.metric = text.slice(metricNode.from, metricNode.to);
|
|
389
400
|
base.filters = extractFilters(query, text);
|
|
401
|
+
const grainError = retiredGrainRollup(base.filters);
|
|
402
|
+
if (grainError) {
|
|
403
|
+
base.error = grainError;
|
|
404
|
+
return base;
|
|
405
|
+
}
|
|
390
406
|
if (whereText) {
|
|
391
407
|
const join = parseJoinClause(whereText);
|
|
392
408
|
if (join.error) {
|
|
@@ -438,6 +454,11 @@ function parseFindQuery(raw) {
|
|
|
438
454
|
}
|
|
439
455
|
result.target = text.slice(metricNode.from, metricNode.to);
|
|
440
456
|
result.filters = extractFilters(query, text);
|
|
457
|
+
const findGrainError = retiredGrainRollup(result.filters);
|
|
458
|
+
if (findGrainError) {
|
|
459
|
+
result.error = findGrainError;
|
|
460
|
+
return result;
|
|
461
|
+
}
|
|
441
462
|
if (whereText) {
|
|
442
463
|
const join = parseJoinClause(whereText);
|
|
443
464
|
if (join.error) {
|
|
@@ -723,9 +744,8 @@ function readGroupTags(metadata) {
|
|
|
723
744
|
const entries = Object.entries(tags).filter((pair) => typeof pair[1] === "string" && pair[1].length > 0).sort(([a], [b]) => a < b ? -1 : 1);
|
|
724
745
|
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
725
746
|
}
|
|
726
|
-
function
|
|
727
|
-
const
|
|
728
|
-
const rowsByKey = /* @__PURE__ */ new Map();
|
|
747
|
+
function foldSummaryOutputs(logs) {
|
|
748
|
+
const folded = /* @__PURE__ */ new Map();
|
|
729
749
|
for (const output of logs) {
|
|
730
750
|
if (output.outputType !== "analytics") continue;
|
|
731
751
|
const label = output.metrics.find((m) => m.type === wodWikiCore.MetricType.Label);
|
|
@@ -740,32 +760,171 @@ function normalizeSummaryFacts(logs, identity) {
|
|
|
740
760
|
const grade = metadataString(value.metadata, "grade");
|
|
741
761
|
const groupTags = readGroupTags(value.metadata) ?? (effortSlug ? { effort: effortSlug } : void 0);
|
|
742
762
|
const rowKey = groupTags ? `${metricKey}:${Object.entries(groupTags).map(([k, v]) => `${k}=${v}`).join(":")}` : metricKey;
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
blockContentId: identity.blockContentId,
|
|
747
|
-
origin: identity.origin,
|
|
748
|
-
pageId: identity.pageId,
|
|
749
|
-
grain: "summary",
|
|
750
|
-
segmentId: identity.segmentId ?? "",
|
|
751
|
-
segmentVersion: identity.segmentVersion ?? 0,
|
|
752
|
-
resultId: identity.resultId,
|
|
753
|
-
type: metricKey,
|
|
763
|
+
folded.set(rowKey, {
|
|
764
|
+
projectionName,
|
|
765
|
+
metricKey,
|
|
754
766
|
value: value.value,
|
|
755
767
|
unit: value.unit,
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
...grade ? { grade } : {},
|
|
764
|
-
timestamp: identity.workoutTimestamp ?? output.timeSpan?.started ?? now,
|
|
765
|
-
createdAt: now
|
|
768
|
+
effortSlug,
|
|
769
|
+
discipline,
|
|
770
|
+
intensityTier,
|
|
771
|
+
grade,
|
|
772
|
+
groupTags,
|
|
773
|
+
rowKey,
|
|
774
|
+
started: output.timeSpan?.started
|
|
766
775
|
});
|
|
767
776
|
}
|
|
768
|
-
return
|
|
777
|
+
return folded;
|
|
778
|
+
}
|
|
779
|
+
function normalizeSummaryFacts(logs, identity) {
|
|
780
|
+
const now = Date.now();
|
|
781
|
+
return Array.from(foldSummaryOutputs(logs).values(), (f) => ({
|
|
782
|
+
id: `${identity.resultId}-${f.rowKey}-${now}`,
|
|
783
|
+
noteId: identity.noteId,
|
|
784
|
+
blockContentId: identity.blockContentId,
|
|
785
|
+
origin: identity.origin,
|
|
786
|
+
pageId: identity.pageId,
|
|
787
|
+
grain: "summary",
|
|
788
|
+
segmentId: identity.segmentId ?? "",
|
|
789
|
+
segmentVersion: identity.segmentVersion ?? 0,
|
|
790
|
+
resultId: identity.resultId,
|
|
791
|
+
type: f.metricKey,
|
|
792
|
+
value: f.value,
|
|
793
|
+
unit: f.unit,
|
|
794
|
+
label: f.projectionName,
|
|
795
|
+
metricKey: f.metricKey,
|
|
796
|
+
metricLabel: f.projectionName,
|
|
797
|
+
metricUnit: f.unit,
|
|
798
|
+
...f.effortSlug ? { effortSlug: f.effortSlug } : {},
|
|
799
|
+
...f.discipline ? { discipline: f.discipline } : {},
|
|
800
|
+
...f.intensityTier ? { intensityTier: f.intensityTier } : {},
|
|
801
|
+
...f.grade ? { grade: f.grade } : {},
|
|
802
|
+
timestamp: identity.workoutTimestamp ?? f.started ?? now,
|
|
803
|
+
createdAt: now
|
|
804
|
+
}));
|
|
805
|
+
}
|
|
806
|
+
function firstEffortSlug(metrics) {
|
|
807
|
+
const loose = metrics;
|
|
808
|
+
for (const m of loose) {
|
|
809
|
+
const slug = metadataString(m.metadata, "effortSlug");
|
|
810
|
+
if (slug) return slug;
|
|
811
|
+
}
|
|
812
|
+
return void 0;
|
|
813
|
+
}
|
|
814
|
+
function toEventRows(logs, identity) {
|
|
815
|
+
return logs.map((output, seq) => ({
|
|
816
|
+
id: `${identity.resultId}:${seq}`,
|
|
817
|
+
resultId: identity.resultId,
|
|
818
|
+
noteId: identity.noteId,
|
|
819
|
+
blockContentId: identity.blockContentId,
|
|
820
|
+
pageId: identity.pageId,
|
|
821
|
+
origin: identity.origin,
|
|
822
|
+
timestamp: identity.workoutTimestamp ?? output.timeSpan?.started ?? Date.now(),
|
|
823
|
+
grain: "event",
|
|
824
|
+
outputType: output.outputType ?? "segment",
|
|
825
|
+
effortSlug: firstEffortSlug(output.metrics),
|
|
826
|
+
metrics: output.metrics,
|
|
827
|
+
timeSpan: output.timeSpan?.started !== void 0 ? { started: output.timeSpan.started, ended: output.timeSpan.ended } : void 0,
|
|
828
|
+
sourceBlockKey: output.sourceBlockKey,
|
|
829
|
+
stackLevel: output.stackLevel,
|
|
830
|
+
completionReason: output.completionReason,
|
|
831
|
+
segmentId: identity.segmentId,
|
|
832
|
+
segmentVersion: identity.segmentVersion
|
|
833
|
+
}));
|
|
834
|
+
}
|
|
835
|
+
function toSummaryEventRows(logs, identity) {
|
|
836
|
+
const now = Date.now();
|
|
837
|
+
return Array.from(foldSummaryOutputs(logs).values(), (f) => ({
|
|
838
|
+
id: `${identity.resultId}:summary:${f.rowKey}`,
|
|
839
|
+
resultId: identity.resultId,
|
|
840
|
+
noteId: identity.noteId,
|
|
841
|
+
blockContentId: identity.blockContentId,
|
|
842
|
+
pageId: identity.pageId,
|
|
843
|
+
origin: identity.origin,
|
|
844
|
+
timestamp: identity.workoutTimestamp ?? f.started ?? now,
|
|
845
|
+
grain: "summary",
|
|
846
|
+
outputType: "analytics",
|
|
847
|
+
effortSlug: f.effortSlug,
|
|
848
|
+
metrics: [{
|
|
849
|
+
type: f.metricKey,
|
|
850
|
+
value: f.value,
|
|
851
|
+
...f.unit ? { unit: f.unit } : {},
|
|
852
|
+
metadata: {
|
|
853
|
+
canonicalKey: f.metricKey,
|
|
854
|
+
...f.effortSlug ? { effortSlug: f.effortSlug } : {},
|
|
855
|
+
...f.discipline ? { effortDiscipline: f.discipline } : {},
|
|
856
|
+
...f.intensityTier ? { effortIntensityTier: f.intensityTier } : {},
|
|
857
|
+
...f.groupTags ? { groupTags: f.groupTags } : {},
|
|
858
|
+
...f.grade ? { grade: f.grade } : {}
|
|
859
|
+
}
|
|
860
|
+
}],
|
|
861
|
+
segmentId: identity.segmentId,
|
|
862
|
+
segmentVersion: identity.segmentVersion
|
|
863
|
+
}));
|
|
864
|
+
}
|
|
865
|
+
function projectEventToFacts(record) {
|
|
866
|
+
const metrics = record.metrics;
|
|
867
|
+
if (record.grain === "summary") {
|
|
868
|
+
const m = metrics[0];
|
|
869
|
+
if (!m || typeof m.value !== "number") return [];
|
|
870
|
+
const metricKey = metadataString(m.metadata, "canonicalKey") ?? (m.type ?? "");
|
|
871
|
+
return [{
|
|
872
|
+
id: `${record.id}:0`,
|
|
873
|
+
noteId: record.noteId,
|
|
874
|
+
blockContentId: record.blockContentId,
|
|
875
|
+
origin: record.origin,
|
|
876
|
+
pageId: record.pageId,
|
|
877
|
+
grain: "summary",
|
|
878
|
+
segmentId: record.segmentId ?? "",
|
|
879
|
+
segmentVersion: record.segmentVersion ?? 0,
|
|
880
|
+
resultId: record.resultId,
|
|
881
|
+
type: metricKey,
|
|
882
|
+
value: m.value,
|
|
883
|
+
unit: m.unit,
|
|
884
|
+
label: metricKey,
|
|
885
|
+
metricKey,
|
|
886
|
+
metricLabel: metricKey,
|
|
887
|
+
metricUnit: m.unit,
|
|
888
|
+
effortSlug: metadataString(m.metadata, "effortSlug") ?? record.effortSlug,
|
|
889
|
+
discipline: metadataString(m.metadata, "effortDiscipline"),
|
|
890
|
+
intensityTier: metadataString(m.metadata, "effortIntensityTier"),
|
|
891
|
+
grade: metadataString(m.metadata, "grade"),
|
|
892
|
+
timestamp: record.timestamp,
|
|
893
|
+
createdAt: record.timestamp
|
|
894
|
+
}];
|
|
895
|
+
}
|
|
896
|
+
const label = metrics.find((m) => m.type === wodWikiCore.MetricType.Label);
|
|
897
|
+
const labelName = label ? String(label.value ?? label.image ?? "") : "";
|
|
898
|
+
const facts = [];
|
|
899
|
+
metrics.forEach((m) => {
|
|
900
|
+
if (m.type === wodWikiCore.MetricType.Label || typeof m.value !== "number") return;
|
|
901
|
+
const metricKey = metadataString(m.metadata, "canonicalKey") ?? (labelName ? resolveCanonicalMetricKey(labelName) : m.type ?? "metric");
|
|
902
|
+
const ordinal = facts.length;
|
|
903
|
+
facts.push({
|
|
904
|
+
id: `${record.id}:${ordinal}`,
|
|
905
|
+
noteId: record.noteId,
|
|
906
|
+
blockContentId: record.blockContentId,
|
|
907
|
+
origin: record.origin,
|
|
908
|
+
pageId: record.pageId,
|
|
909
|
+
grain: "event",
|
|
910
|
+
segmentId: record.segmentId ?? "",
|
|
911
|
+
segmentVersion: record.segmentVersion ?? 0,
|
|
912
|
+
resultId: record.resultId,
|
|
913
|
+
type: metricKey,
|
|
914
|
+
value: m.value,
|
|
915
|
+
unit: m.unit,
|
|
916
|
+
label: labelName || metricKey,
|
|
917
|
+
metricKey,
|
|
918
|
+
metricLabel: labelName || metricKey,
|
|
919
|
+
metricUnit: m.unit,
|
|
920
|
+
effortSlug: metadataString(m.metadata, "effortSlug") ?? record.effortSlug,
|
|
921
|
+
intensityTier: metadataString(m.metadata, "effortIntensityTier"),
|
|
922
|
+
grade: metadataString(m.metadata, "grade"),
|
|
923
|
+
timestamp: record.timestamp,
|
|
924
|
+
createdAt: record.timestamp
|
|
925
|
+
});
|
|
926
|
+
});
|
|
927
|
+
return facts;
|
|
769
928
|
}
|
|
770
929
|
|
|
771
930
|
// src/dashboard/frontmatter.ts
|
|
@@ -957,23 +1116,27 @@ function windowAnchor(selected, parsed, options2) {
|
|
|
957
1116
|
if (options2.anchor === "latest-activity" && parsed.last) return latestActivity(selected);
|
|
958
1117
|
return void 0;
|
|
959
1118
|
}
|
|
960
|
-
var
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
1119
|
+
var defaultEventStore = {
|
|
1120
|
+
getEventsByTimeRange: async () => [],
|
|
1121
|
+
getEventsByResult: async () => [],
|
|
1122
|
+
getEventsForNote: async () => [],
|
|
1123
|
+
getEventsByContent: async () => [],
|
|
1124
|
+
scanAll: async () => [],
|
|
1125
|
+
appendEvents: async () => {
|
|
1126
|
+
},
|
|
1127
|
+
finalizeSummaries: async () => {
|
|
1128
|
+
},
|
|
1129
|
+
deleteEvents: async () => {
|
|
1130
|
+
}
|
|
964
1131
|
};
|
|
965
1132
|
var defaultNoteStore = {
|
|
966
1133
|
getAllNotes: async () => [],
|
|
967
|
-
getNoteIdsForTag: async () => /* @__PURE__ */ new Set()
|
|
1134
|
+
getNoteIdsForTag: async () => /* @__PURE__ */ new Set(),
|
|
1135
|
+
getNoteTagLabels: async () => []
|
|
968
1136
|
};
|
|
969
1137
|
var defaultBlockStore = {
|
|
970
1138
|
getAllBlocks: async () => []
|
|
971
1139
|
};
|
|
972
|
-
var defaultResultStore = {
|
|
973
|
-
getResultsByContentId: async () => [],
|
|
974
|
-
getResultById: async () => void 0,
|
|
975
|
-
getResultsForNote: async () => []
|
|
976
|
-
};
|
|
977
1140
|
var defaultEffortStore = {
|
|
978
1141
|
getAllEfforts: async () => []
|
|
979
1142
|
};
|
|
@@ -1085,32 +1248,31 @@ var QueryService = class {
|
|
|
1085
1248
|
store;
|
|
1086
1249
|
noteStore;
|
|
1087
1250
|
blockStore;
|
|
1088
|
-
resultStore;
|
|
1089
1251
|
effortStore;
|
|
1090
1252
|
staticNoteStore;
|
|
1091
1253
|
staticBlockStore;
|
|
1092
|
-
constructor(
|
|
1093
|
-
if (
|
|
1094
|
-
const stores =
|
|
1095
|
-
this.store = stores.
|
|
1254
|
+
constructor(storesOrEventStore, noteStore, blockStore, effortStore, staticNoteStore, staticBlockStore) {
|
|
1255
|
+
if (storesOrEventStore && typeof storesOrEventStore === "object" && ("eventStore" in storesOrEventStore || "noteStore" in storesOrEventStore || "blockStore" in storesOrEventStore || "effortStore" in storesOrEventStore || "staticNoteStore" in storesOrEventStore || "staticBlockStore" in storesOrEventStore)) {
|
|
1256
|
+
const stores = storesOrEventStore;
|
|
1257
|
+
this.store = stores.eventStore ?? defaultEventStore;
|
|
1096
1258
|
this.noteStore = stores.noteStore ?? defaultNoteStore;
|
|
1097
1259
|
this.blockStore = stores.blockStore ?? defaultBlockStore;
|
|
1098
|
-
this.resultStore = stores.resultStore ?? defaultResultStore;
|
|
1099
1260
|
this.effortStore = stores.effortStore ?? defaultEffortStore;
|
|
1100
1261
|
this.staticNoteStore = stores.staticNoteStore;
|
|
1101
1262
|
this.staticBlockStore = stores.staticBlockStore;
|
|
1102
1263
|
} else {
|
|
1103
|
-
this.store =
|
|
1264
|
+
this.store = storesOrEventStore ?? defaultEventStore;
|
|
1104
1265
|
this.noteStore = noteStore ?? defaultNoteStore;
|
|
1105
1266
|
this.blockStore = blockStore ?? defaultBlockStore;
|
|
1106
|
-
this.resultStore = resultStore ?? defaultResultStore;
|
|
1107
1267
|
this.effortStore = effortStore ?? defaultEffortStore;
|
|
1108
1268
|
this.staticNoteStore = staticNoteStore;
|
|
1109
1269
|
this.staticBlockStore = staticBlockStore;
|
|
1110
1270
|
}
|
|
1111
1271
|
}
|
|
1272
|
+
/** Windowed flat-fact fetch — the projected view over the event store. */
|
|
1112
1273
|
async getFactsByTimeRange(start, end) {
|
|
1113
|
-
|
|
1274
|
+
const rows = await this.store.getEventsByTimeRange(start, end);
|
|
1275
|
+
return rows.flatMap(projectEventToFacts);
|
|
1114
1276
|
}
|
|
1115
1277
|
async runQuery(raw, options2 = {}) {
|
|
1116
1278
|
const parsed = parseQuery(raw);
|
|
@@ -1134,8 +1296,8 @@ var QueryService = class {
|
|
|
1134
1296
|
}
|
|
1135
1297
|
/**
|
|
1136
1298
|
* Execute a rows query (rows:{…}, #949) — the session results table plane.
|
|
1137
|
-
*
|
|
1138
|
-
*
|
|
1299
|
+
* Reads event rows directly over the unified store (ticket 003): no
|
|
1300
|
+
* WorkoutResult blob parsing; outputType narrowing hits the promoted column.
|
|
1139
1301
|
*/
|
|
1140
1302
|
async runRows(parsed, options2 = {}) {
|
|
1141
1303
|
const empty = { parsed, runs: [] };
|
|
@@ -1157,28 +1319,30 @@ var QueryService = class {
|
|
|
1157
1319
|
if (resultIds.length + blockIds.length + noteIds.length === 0) {
|
|
1158
1320
|
return { ...empty, error: "Rows query needs a scope: result:, block:, or note:." };
|
|
1159
1321
|
}
|
|
1160
|
-
const
|
|
1161
|
-
|
|
1162
|
-
const
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
}
|
|
1168
|
-
for (const
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
let
|
|
1322
|
+
const byResult = /* @__PURE__ */ new Map();
|
|
1323
|
+
const collect = (rows) => {
|
|
1324
|
+
for (const row of rows) {
|
|
1325
|
+
const bucket = byResult.get(row.resultId);
|
|
1326
|
+
if (bucket) bucket.push(row);
|
|
1327
|
+
else byResult.set(row.resultId, [row]);
|
|
1328
|
+
}
|
|
1329
|
+
};
|
|
1330
|
+
for (const id of resultIds) collect(await this.store.getEventsByResult(id));
|
|
1331
|
+
for (const blockContentId of blockIds) collect(await this.store.getEventsByContent(blockContentId));
|
|
1332
|
+
for (const noteId of noteIds) collect(await this.store.getEventsForNote(noteId));
|
|
1333
|
+
let groups = [...byResult.entries()].filter(([, rows]) => rows.length > 0);
|
|
1172
1334
|
if (parsed.last) {
|
|
1173
|
-
|
|
1174
|
-
(
|
|
1335
|
+
groups = groups.filter(
|
|
1336
|
+
([, rows]) => effectiveTimeWindow(rows[0].timestamp, parsed.last, void 0, options2.anchorNow)
|
|
1175
1337
|
);
|
|
1176
1338
|
}
|
|
1177
|
-
|
|
1178
|
-
const runs =
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1339
|
+
groups.sort((a, b) => b[1][0].timestamp - a[1][0].timestamp);
|
|
1340
|
+
const runs = groups.map(([resultId, rows]) => ({
|
|
1341
|
+
resultId,
|
|
1342
|
+
noteId: rows[0].noteId,
|
|
1343
|
+
timestamp: rows[0].timestamp,
|
|
1344
|
+
events: parsed.outputType ? rows.filter((row) => row.outputType === parsed.outputType) : rows
|
|
1345
|
+
})).filter((run) => run.events.length > 0);
|
|
1182
1346
|
return { parsed, runs };
|
|
1183
1347
|
}
|
|
1184
1348
|
/**
|
|
@@ -1367,14 +1531,11 @@ var QueryService = class {
|
|
|
1367
1531
|
};
|
|
1368
1532
|
if (parsed.error) return empty;
|
|
1369
1533
|
if (parsed.join) return this.runJoined(parsed, options2);
|
|
1370
|
-
const
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
const inRange = new Set((await this.store.getFactsByTimeRange(start, end)).map((row) => row.id));
|
|
1376
|
-
candidates = candidates.filter((row) => inRange.has(row.id));
|
|
1377
|
-
}
|
|
1534
|
+
const windowed = options2.rangeStart !== void 0 || options2.rangeEnd !== void 0;
|
|
1535
|
+
const start = options2.rangeStart ?? 0;
|
|
1536
|
+
const end = options2.rangeEnd ?? Number.MAX_SAFE_INTEGER;
|
|
1537
|
+
const eventRows = windowed ? await this.store.getEventsByTimeRange(start, end) : await this.store.scanAll();
|
|
1538
|
+
const candidates = eventRows.flatMap(projectEventToFacts).filter((row) => row.metricKey === parsed.metric);
|
|
1378
1539
|
const touchesTags = parsed.filters.some((f) => f.key === "tags") || parsed.groupBy.includes("tags");
|
|
1379
1540
|
const noteTags = await this.loadNoteTags(candidates, touchesTags);
|
|
1380
1541
|
const matched = this.applyEffortScope(
|
|
@@ -1518,29 +1679,14 @@ var QueryService = class {
|
|
|
1518
1679
|
}
|
|
1519
1680
|
return matched.some((r) => r.effortSlug === void 0) ? matched.filter((r) => r.effortSlug === void 0) : matched;
|
|
1520
1681
|
}
|
|
1521
|
-
/**
|
|
1522
|
-
*
|
|
1523
|
-
*
|
|
1682
|
+
/** Summary facts for one Canonical Metric Key across the given content ids —
|
|
1683
|
+
* the cross-store join source. Reads finalize-written summary rows straight
|
|
1684
|
+
* off the content index (ticket 003: the store is authoritative; the old
|
|
1685
|
+
* freshness re-derivation is moot). One fact row per result × rowKey. */
|
|
1524
1686
|
async deriveMetricFacts(contentIds, metricKey) {
|
|
1525
|
-
const out = [];
|
|
1526
1687
|
const ids = [...new Set(contentIds)];
|
|
1527
|
-
await Promise.all(ids.map(
|
|
1528
|
-
|
|
1529
|
-
for (const result of results) {
|
|
1530
|
-
const facts = normalizeSummaryFacts(result.data.logs ?? [], {
|
|
1531
|
-
noteId: result.noteId,
|
|
1532
|
-
resultId: result.id,
|
|
1533
|
-
segmentId: result.segmentId,
|
|
1534
|
-
segmentVersion: result.segmentVersion,
|
|
1535
|
-
blockContentId,
|
|
1536
|
-
origin: result.origin,
|
|
1537
|
-
pageId: result.pageId,
|
|
1538
|
-
workoutTimestamp: result.createdAt
|
|
1539
|
-
});
|
|
1540
|
-
for (const f of facts) if (f.metricKey === metricKey) out.push(f);
|
|
1541
|
-
}
|
|
1542
|
-
}));
|
|
1543
|
-
return out;
|
|
1688
|
+
const rows = await Promise.all(ids.map((blockContentId) => this.store.getEventsByContent(blockContentId)));
|
|
1689
|
+
return rows.flat().filter((row) => row.grain === "summary").flatMap(projectEventToFacts).filter((f) => f.metricKey === metricKey);
|
|
1544
1690
|
}
|
|
1545
1691
|
/** All content blocks across the journal + static corpus. */
|
|
1546
1692
|
async allContentBlocks() {
|
|
@@ -1580,7 +1726,7 @@ var QueryService = class {
|
|
|
1580
1726
|
const noteTags = /* @__PURE__ */ new Map();
|
|
1581
1727
|
if (!touchesTags) return noteTags;
|
|
1582
1728
|
const noteIds = [...new Set(rows.map((r) => r.noteId))];
|
|
1583
|
-
await Promise.all(noteIds.map(async (id) => noteTags.set(id, await this.
|
|
1729
|
+
await Promise.all(noteIds.map(async (id) => noteTags.set(id, await this.noteStore.getNoteTagLabels(id))));
|
|
1584
1730
|
return noteTags;
|
|
1585
1731
|
}
|
|
1586
1732
|
};
|
|
@@ -1880,13 +2026,13 @@ sum:$metric{} rollup:1w
|
|
|
1880
2026
|
}
|
|
1881
2027
|
|
|
1882
2028
|
// src/version.ts
|
|
1883
|
-
var VERSION = "0.6.
|
|
1884
|
-
var GIT_SHA = "
|
|
1885
|
-
var BUILD_TIME = "2026-08-
|
|
2029
|
+
var VERSION = "0.6.36";
|
|
2030
|
+
var GIT_SHA = "c5ad2b0";
|
|
2031
|
+
var BUILD_TIME = "2026-08-24T20:14:33.951Z";
|
|
1886
2032
|
var SEMVER = {
|
|
1887
|
-
version: "0.6.
|
|
1888
|
-
gitSha: "
|
|
1889
|
-
buildTime: "2026-08-
|
|
2033
|
+
version: "0.6.36",
|
|
2034
|
+
gitSha: "c5ad2b0",
|
|
2035
|
+
buildTime: "2026-08-24T20:14:33.951Z"
|
|
1890
2036
|
};
|
|
1891
2037
|
|
|
1892
2038
|
exports.BUILD_TIME = BUILD_TIME;
|
|
@@ -1945,6 +2091,7 @@ exports.parseFrontmatterProps = parseFrontmatterProps;
|
|
|
1945
2091
|
exports.parseQuery = parseQuery;
|
|
1946
2092
|
exports.parseQueryWidgetSuffix = parseQueryWidgetSuffix;
|
|
1947
2093
|
exports.parseWqlSuffixes = parseWqlSuffixes;
|
|
2094
|
+
exports.projectEventToFacts = projectEventToFacts;
|
|
1948
2095
|
exports.referencedTokens = referencedTokens;
|
|
1949
2096
|
exports.resolveCanonicalMetricKey = resolveCanonicalMetricKey;
|
|
1950
2097
|
exports.resolveDisplayUnit = resolveDisplayUnit;
|
|
@@ -1957,6 +2104,8 @@ exports.staticNotesFromBlocks = staticNotesFromBlocks;
|
|
|
1957
2104
|
exports.staticTagIndexFromBlocks = staticTagIndexFromBlocks;
|
|
1958
2105
|
exports.stripFrontmatter = stripFrontmatter;
|
|
1959
2106
|
exports.substituteTokens = substituteTokens;
|
|
2107
|
+
exports.toEventRows = toEventRows;
|
|
2108
|
+
exports.toSummaryEventRows = toSummaryEventRows;
|
|
1960
2109
|
exports.unknownTokensMessage = unknownTokensMessage;
|
|
1961
2110
|
exports.unknownWidgetTypeMessage = unknownWidgetTypeMessage;
|
|
1962
2111
|
exports.wql = wql;
|