@bitcobblers/wod-wiki-wql 0.7.37 → 0.8.39
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 +89 -61
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +46 -19
- package/dist/index.d.ts +46 -19
- package/dist/index.mjs +86 -62
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var wodWikiCore = require('@bitcobblers/wod-wiki-core');
|
|
3
4
|
var lr = require('@lezer/lr');
|
|
4
5
|
var language = require('@codemirror/language');
|
|
5
6
|
var autocomplete = require('@codemirror/autocomplete');
|
|
6
7
|
var highlight = require('@lezer/highlight');
|
|
7
|
-
var wodWikiCore = require('@bitcobblers/wod-wiki-core');
|
|
8
8
|
|
|
9
9
|
var __defProp = Object.defineProperty;
|
|
10
10
|
var __export = (target, all) => {
|
|
11
11
|
for (var name in all)
|
|
12
12
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
13
13
|
};
|
|
14
|
-
|
|
15
|
-
// src/vocabulary.ts
|
|
16
14
|
var WQL_METRIC_FAMILIES = ["reps", "distance", "resistance", "elapsed", "power", "pace"];
|
|
17
15
|
var WQL_METRIC_AGGREGATES = ["totalVolume", "totalDistance", "tis", "sessionLoad"];
|
|
18
16
|
var WQL_AGGREGATORS = ["sum", "avg", "min", "max", "count", "last", "delta"];
|
|
@@ -58,6 +56,9 @@ var WQL_INTENSITY_TIERS = ["low", "moderate", "high"];
|
|
|
58
56
|
var WQL_GRAINS = ["summary", "event"];
|
|
59
57
|
var WQL_FIND_TARGETS = ["note", "block", "effort"];
|
|
60
58
|
var WQL_SCOPES = ["journal", "collections", "feeds", "all"];
|
|
59
|
+
var WQL_RESULT_PLANES = wodWikiCore.KNOWN_OUTPUT_TYPES;
|
|
60
|
+
var WQL_ROWS_TARGETS = [...WQL_FIND_TARGETS, ...WQL_RESULT_PLANES, "all"];
|
|
61
|
+
var WQL_ROWS_SCOPE_KEYS = ["result", "block", "note"];
|
|
61
62
|
var WQL_CONTENT_FILTER_KEYS = ["type", "text", "has", "source", "catalog", ...WQL_TAG_KEYS];
|
|
62
63
|
var WQL_SOURCES = ["journal", "collections", "feeds", "notes", "blocks", "efforts", "metrics"];
|
|
63
64
|
var WQL_ROLLUP_PERIODS = ["1d", "1w"];
|
|
@@ -234,11 +235,14 @@ function parseWqlSuffixes(raw) {
|
|
|
234
235
|
|
|
235
236
|
// src/wql.ts
|
|
236
237
|
function isFindQuery(parsed) {
|
|
237
|
-
return "
|
|
238
|
+
return parsed.family === "find";
|
|
238
239
|
}
|
|
239
240
|
function isRowsQuery(parsed) {
|
|
240
241
|
return parsed.family === "rows";
|
|
241
242
|
}
|
|
243
|
+
function isAggregateQuery(parsed) {
|
|
244
|
+
return parsed.family === "aggregate";
|
|
245
|
+
}
|
|
242
246
|
var AGGS = WQL_AGGREGATORS;
|
|
243
247
|
function cannotParse(text) {
|
|
244
248
|
return `Cannot parse "${text}". Expected agg:metric{filters} by {dims} .rollup(period)`;
|
|
@@ -278,14 +282,28 @@ function parseQuery(raw) {
|
|
|
278
282
|
return parseAnalyticsQuery(raw);
|
|
279
283
|
}
|
|
280
284
|
function cannotParseRows(text) {
|
|
281
|
-
return `Cannot parse "${text}". Expected rows:{result:\u2026|block:\u2026|note:\u2026} or rows:segment{\u2026} last 8w`;
|
|
285
|
+
return `Cannot parse "${text}". Expected rows:all{result:\u2026|block:\u2026|note:\u2026}, rows:<plane>{\u2026}, or rows:segment{\u2026} last 8w`;
|
|
282
286
|
}
|
|
287
|
+
function validateRowsFilters(filters) {
|
|
288
|
+
const scopeKeys = new Set(WQL_ROWS_SCOPE_KEYS);
|
|
289
|
+
const unsupported = filters.filter(
|
|
290
|
+
(f) => !scopeKeys.has(f.key) || f.negate || f.values.some((v) => v.wildcard)
|
|
291
|
+
);
|
|
292
|
+
if (unsupported.length > 0) {
|
|
293
|
+
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.`;
|
|
294
|
+
}
|
|
295
|
+
if (!filters.some((f) => scopeKeys.has(f.key))) {
|
|
296
|
+
return `Rows query needs a scope: ${WQL_ROWS_SCOPE_KEYS.map((k) => `${k}:`).join(", ")}.`;
|
|
297
|
+
}
|
|
298
|
+
return void 0;
|
|
299
|
+
}
|
|
300
|
+
var BARE_ROWS_RETIRED = 'Bare "rows:" is retired \u2014 name a target: rows:all{\u2026} for every output type, or a plane like rows:segment{\u2026}.';
|
|
283
301
|
function parseRowsQuery(raw) {
|
|
284
302
|
const suffixes = parseWqlSuffixes(raw);
|
|
285
303
|
const { where: whereText, last, groupBy, rollup, primaryText } = suffixes;
|
|
286
304
|
const result = {
|
|
287
|
-
raw,
|
|
288
305
|
family: "rows",
|
|
306
|
+
raw,
|
|
289
307
|
filters: [],
|
|
290
308
|
last: last ? { size: last.size, unit: last.unit } : void 0
|
|
291
309
|
};
|
|
@@ -298,41 +316,48 @@ function parseRowsQuery(raw) {
|
|
|
298
316
|
return result;
|
|
299
317
|
}
|
|
300
318
|
const text = primaryText.trim();
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
} else {
|
|
319
|
+
if (/^rows:?\s*[{]?$/.test(text) || /^rows:?\s*[{]/.test(text)) {
|
|
320
|
+
result.error = BARE_ROWS_RETIRED;
|
|
321
|
+
return result;
|
|
322
|
+
}
|
|
323
|
+
const tree = parser.parse(text);
|
|
324
|
+
let syntaxError = false;
|
|
325
|
+
tree.iterate({ enter(node) {
|
|
326
|
+
if (node.type.isError) syntaxError = true;
|
|
327
|
+
} });
|
|
328
|
+
if (syntaxError) {
|
|
312
329
|
result.error = cannotParseRows(text);
|
|
313
330
|
return result;
|
|
314
331
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
result.
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
332
|
+
const query = tree.topNode;
|
|
333
|
+
const head = query.getChild(Head);
|
|
334
|
+
const aggNode = head?.getChild(Aggregator);
|
|
335
|
+
const metricNode = head?.getChild(Metric);
|
|
336
|
+
if (!head || !aggNode || !metricNode) {
|
|
337
|
+
result.error = BARE_ROWS_RETIRED;
|
|
338
|
+
return result;
|
|
339
|
+
}
|
|
340
|
+
const aggText = text.slice(aggNode.from, aggNode.to);
|
|
341
|
+
if (aggText !== "rows") {
|
|
342
|
+
result.error = cannotParseRows(text);
|
|
343
|
+
return result;
|
|
344
|
+
}
|
|
345
|
+
const target = text.slice(metricNode.from, metricNode.to);
|
|
346
|
+
if (!WQL_ROWS_TARGETS.includes(target)) {
|
|
347
|
+
result.error = `Unknown rows target "${target}". Try: ${WQL_ROWS_TARGETS.join(", ")}`;
|
|
348
|
+
return result;
|
|
349
|
+
}
|
|
350
|
+
if (target !== "all") result.outputType = target;
|
|
351
|
+
result.filters = extractFilters(query, text);
|
|
352
|
+
const grainError = retiredGrainRollup(result.filters);
|
|
353
|
+
if (grainError) {
|
|
354
|
+
result.error = grainError;
|
|
355
|
+
return result;
|
|
356
|
+
}
|
|
357
|
+
const filterError = validateRowsFilters(result.filters);
|
|
358
|
+
if (filterError) {
|
|
359
|
+
result.error = filterError;
|
|
360
|
+
return result;
|
|
336
361
|
}
|
|
337
362
|
return result;
|
|
338
363
|
}
|
|
@@ -373,6 +398,7 @@ function parseAnalyticsQuery(raw) {
|
|
|
373
398
|
const suffixes = parseWqlSuffixes(raw);
|
|
374
399
|
const { where: whereText, displayUnit, groupBy, rollup, primaryText: text } = suffixes;
|
|
375
400
|
const base = {
|
|
401
|
+
family: "aggregate",
|
|
376
402
|
raw,
|
|
377
403
|
agg: "sum",
|
|
378
404
|
metric: "",
|
|
@@ -440,6 +466,7 @@ function parseFindQuery(raw) {
|
|
|
440
466
|
const suffixes = parseWqlSuffixes(raw);
|
|
441
467
|
const { where: whereText, last, scope, primaryText: text } = suffixes;
|
|
442
468
|
const result = {
|
|
469
|
+
family: "find",
|
|
443
470
|
raw,
|
|
444
471
|
target: "",
|
|
445
472
|
filters: [],
|
|
@@ -473,6 +500,10 @@ function parseFindQuery(raw) {
|
|
|
473
500
|
return result;
|
|
474
501
|
}
|
|
475
502
|
result.target = text.slice(metricNode.from, metricNode.to);
|
|
503
|
+
if (!WQL_FIND_TARGETS.includes(result.target)) {
|
|
504
|
+
result.error = `Unknown find target "${result.target}". Try: ${WQL_FIND_TARGETS.join(", ")}`;
|
|
505
|
+
return result;
|
|
506
|
+
}
|
|
476
507
|
result.filters = extractFilters(query, text);
|
|
477
508
|
const findGrainError = retiredGrainRollup(result.filters);
|
|
478
509
|
if (findGrainError) {
|
|
@@ -1090,6 +1121,7 @@ function staticTagIndexFromBlocks(blocks) {
|
|
|
1090
1121
|
|
|
1091
1122
|
// src/QueryService.ts
|
|
1092
1123
|
var DAY = 864e5;
|
|
1124
|
+
var ROWS_CONTENT_PLANES = new Set(WQL_FIND_TARGETS);
|
|
1093
1125
|
function localDateString(ts) {
|
|
1094
1126
|
return new Date(ts).toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
1095
1127
|
}
|
|
@@ -1298,7 +1330,7 @@ var QueryService = class {
|
|
|
1298
1330
|
const parsed = parseQuery(raw);
|
|
1299
1331
|
if (isFindQuery(parsed)) {
|
|
1300
1332
|
return {
|
|
1301
|
-
parsed: { raw, agg: "count", metric: parsed.target, filters: [], groupBy: [] },
|
|
1333
|
+
parsed: { family: "aggregate", raw, agg: "count", metric: parsed.target, filters: [], groupBy: [] },
|
|
1302
1334
|
series: [],
|
|
1303
1335
|
stages: { selected: 0, buckets: 0, aggregated: 0, groups: 0 },
|
|
1304
1336
|
matched: []
|
|
@@ -1306,7 +1338,7 @@ var QueryService = class {
|
|
|
1306
1338
|
}
|
|
1307
1339
|
if (isRowsQuery(parsed)) {
|
|
1308
1340
|
return {
|
|
1309
|
-
parsed: { raw, agg: "count", metric: "rows", filters: [], groupBy: [] },
|
|
1341
|
+
parsed: { family: "aggregate", raw, agg: "count", metric: "rows", filters: [], groupBy: [] },
|
|
1310
1342
|
series: [],
|
|
1311
1343
|
stages: { selected: 0, buckets: 0, aggregated: 0, groups: 0 },
|
|
1312
1344
|
matched: []
|
|
@@ -1315,29 +1347,20 @@ var QueryService = class {
|
|
|
1315
1347
|
return this.run(parsed, options2);
|
|
1316
1348
|
}
|
|
1317
1349
|
/**
|
|
1318
|
-
* Execute a rows query (rows
|
|
1319
|
-
*
|
|
1320
|
-
*
|
|
1350
|
+
* Execute a rows query (rows:<target>{…}, #949/C4) — the session results
|
|
1351
|
+
* table plane. Filter rules are validated at parse; this executes only.
|
|
1352
|
+
* Reads event rows directly over the unified store: outputType narrowing
|
|
1353
|
+
* hits the promoted column; content-plane targets scope by content.
|
|
1321
1354
|
*/
|
|
1322
1355
|
async runRows(parsed, options2 = {}) {
|
|
1323
1356
|
const empty = { parsed, runs: [] };
|
|
1324
1357
|
if (parsed.error) return { ...empty, error: parsed.error };
|
|
1325
|
-
const ROWS_SCOPE_KEYS = /* @__PURE__ */ new Set(["result", "block", "note"]);
|
|
1326
|
-
const unsupported = parsed.filters.filter(
|
|
1327
|
-
(f) => !ROWS_SCOPE_KEYS.has(f.key) || f.negate || f.values.some((v) => v.wildcard)
|
|
1328
|
-
);
|
|
1329
|
-
if (unsupported.length > 0) {
|
|
1330
|
-
return {
|
|
1331
|
-
...empty,
|
|
1332
|
-
error: `Unsupported rows filter(s): ${unsupported.map((f) => (f.negate ? "!" : "") + f.key).join(", ")}. Rows queries support exact result:, block:, note: values.`
|
|
1333
|
-
};
|
|
1334
|
-
}
|
|
1335
1358
|
const scopeValues = (key) => parsed.filters.filter((f) => f.key === key).flatMap((f) => f.values.map((v) => v.value));
|
|
1336
1359
|
const resultIds = scopeValues("result");
|
|
1337
1360
|
const blockIds = scopeValues("block");
|
|
1338
1361
|
const noteIds = scopeValues("note");
|
|
1339
1362
|
if (resultIds.length + blockIds.length + noteIds.length === 0) {
|
|
1340
|
-
return { ...empty,
|
|
1363
|
+
return { ...empty, runs: [] };
|
|
1341
1364
|
}
|
|
1342
1365
|
const byResult = /* @__PURE__ */ new Map();
|
|
1343
1366
|
const collect = (rows) => {
|
|
@@ -1361,7 +1384,7 @@ var QueryService = class {
|
|
|
1361
1384
|
resultId,
|
|
1362
1385
|
noteId: rows[0].noteId,
|
|
1363
1386
|
timestamp: rows[0].timestamp,
|
|
1364
|
-
events: parsed.outputType ? rows.filter((row) => row.outputType === parsed.outputType) : rows
|
|
1387
|
+
events: parsed.outputType && !ROWS_CONTENT_PLANES.has(parsed.outputType) ? rows.filter((row) => row.outputType === parsed.outputType) : rows
|
|
1365
1388
|
})).filter((run) => run.events.length > 0);
|
|
1366
1389
|
return { parsed, runs };
|
|
1367
1390
|
}
|
|
@@ -1628,6 +1651,7 @@ var QueryService = class {
|
|
|
1628
1651
|
};
|
|
1629
1652
|
const join = parsed.join;
|
|
1630
1653
|
const findResult = await this.runFind({
|
|
1654
|
+
family: "find",
|
|
1631
1655
|
raw: "",
|
|
1632
1656
|
target: join.target,
|
|
1633
1657
|
filters: join.filters,
|
|
@@ -2046,13 +2070,13 @@ sum:$metric{} rollup:1w
|
|
|
2046
2070
|
}
|
|
2047
2071
|
|
|
2048
2072
|
// src/version.ts
|
|
2049
|
-
var VERSION = "0.
|
|
2050
|
-
var GIT_SHA = "
|
|
2051
|
-
var BUILD_TIME = "2026-08-
|
|
2073
|
+
var VERSION = "0.8.39";
|
|
2074
|
+
var GIT_SHA = "3c19185";
|
|
2075
|
+
var BUILD_TIME = "2026-08-26T00:07:31.934Z";
|
|
2052
2076
|
var SEMVER = {
|
|
2053
|
-
version: "0.
|
|
2054
|
-
gitSha: "
|
|
2055
|
-
buildTime: "2026-08-
|
|
2077
|
+
version: "0.8.39",
|
|
2078
|
+
gitSha: "3c19185",
|
|
2079
|
+
buildTime: "2026-08-26T00:07:31.934Z"
|
|
2056
2080
|
};
|
|
2057
2081
|
|
|
2058
2082
|
exports.BUILD_TIME = BUILD_TIME;
|
|
@@ -2079,7 +2103,10 @@ exports.WQL_INTENSITY_TIERS = WQL_INTENSITY_TIERS;
|
|
|
2079
2103
|
exports.WQL_KEYWORDS = WQL_KEYWORDS;
|
|
2080
2104
|
exports.WQL_METRIC_AGGREGATES = WQL_METRIC_AGGREGATES;
|
|
2081
2105
|
exports.WQL_METRIC_FAMILIES = WQL_METRIC_FAMILIES;
|
|
2106
|
+
exports.WQL_RESULT_PLANES = WQL_RESULT_PLANES;
|
|
2082
2107
|
exports.WQL_ROLLUP_PERIODS = WQL_ROLLUP_PERIODS;
|
|
2108
|
+
exports.WQL_ROWS_SCOPE_KEYS = WQL_ROWS_SCOPE_KEYS;
|
|
2109
|
+
exports.WQL_ROWS_TARGETS = WQL_ROWS_TARGETS;
|
|
2083
2110
|
exports.WQL_SCOPES = WQL_SCOPES;
|
|
2084
2111
|
exports.WQL_SOURCES = WQL_SOURCES;
|
|
2085
2112
|
exports.WQL_TAG_KEYS = WQL_TAG_KEYS;
|
|
@@ -2095,6 +2122,7 @@ exports.extractFrontmatterTags = extractFrontmatterTags;
|
|
|
2095
2122
|
exports.getList = getList;
|
|
2096
2123
|
exports.getScalar = getScalar;
|
|
2097
2124
|
exports.getUnitFamily = getUnitFamily;
|
|
2125
|
+
exports.isAggregateQuery = isAggregateQuery;
|
|
2098
2126
|
exports.isDashboardMeta = isDashboardMeta;
|
|
2099
2127
|
exports.isDashboardWidgetType = isDashboardWidgetType;
|
|
2100
2128
|
exports.isEffortDiscipline = isEffortDiscipline;
|