@bitcobblers/wod-wiki-wql 0.7.38 → 0.9.40
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 +343 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +90 -37
- package/dist/index.d.ts +90 -37
- package/dist/index.mjs +339 -140
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
|
+
import { KNOWN_OUTPUT_TYPES, MetricType } from '@bitcobblers/wod-wiki-core';
|
|
1
2
|
import { LRParser } from '@lezer/lr';
|
|
2
3
|
import { LRLanguage, HighlightStyle, LanguageSupport, syntaxHighlighting, syntaxTree } from '@codemirror/language';
|
|
3
4
|
import { autocompletion, snippetCompletion } from '@codemirror/autocomplete';
|
|
4
5
|
import { styleTags, tags } from '@lezer/highlight';
|
|
5
|
-
import { MetricType } from '@bitcobblers/wod-wiki-core';
|
|
6
6
|
|
|
7
7
|
var __defProp = Object.defineProperty;
|
|
8
8
|
var __export = (target, all) => {
|
|
9
9
|
for (var name in all)
|
|
10
10
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
11
|
};
|
|
12
|
-
|
|
13
|
-
// src/vocabulary.ts
|
|
14
12
|
var WQL_METRIC_FAMILIES = ["reps", "distance", "resistance", "elapsed", "power", "pace"];
|
|
15
13
|
var WQL_METRIC_AGGREGATES = ["totalVolume", "totalDistance", "tis", "sessionLoad"];
|
|
16
14
|
var WQL_AGGREGATORS = ["sum", "avg", "min", "max", "count", "last", "delta"];
|
|
@@ -55,7 +53,10 @@ var WQL_CALC_TARGETS = [
|
|
|
55
53
|
var WQL_INTENSITY_TIERS = ["low", "moderate", "high"];
|
|
56
54
|
var WQL_GRAINS = ["summary", "event"];
|
|
57
55
|
var WQL_FIND_TARGETS = ["note", "block", "effort"];
|
|
58
|
-
var
|
|
56
|
+
var WQL_SOURCE_VALUES = ["journal", "collections", "feeds", "all"];
|
|
57
|
+
var WQL_RESULT_PLANES = KNOWN_OUTPUT_TYPES;
|
|
58
|
+
var WQL_ROWS_TARGETS = [...WQL_FIND_TARGETS, ...WQL_RESULT_PLANES, "all"];
|
|
59
|
+
var WQL_ROWS_SCOPE_KEYS = ["result", "block", "note"];
|
|
59
60
|
var WQL_CONTENT_FILTER_KEYS = ["type", "text", "has", "source", "catalog", ...WQL_TAG_KEYS];
|
|
60
61
|
var WQL_SOURCES = ["journal", "collections", "feeds", "notes", "blocks", "efforts", "metrics"];
|
|
61
62
|
var WQL_ROLLUP_PERIODS = ["1d", "1w"];
|
|
@@ -151,6 +152,7 @@ var DISPLAY_UNIT_RE = /\s+in\s+([a-zA-Z0-9_-]+)\s*$/;
|
|
|
151
152
|
var ROLLUP_RE = /\.rollup\((\d+)?([a-zA-Z]*)\)\s*$/;
|
|
152
153
|
var BY_RE = /\s+by\s+\{([^}]*)\}\s*$/;
|
|
153
154
|
var LAST_RE = /\s+last\s+(\d+)([dw])\s*$/i;
|
|
155
|
+
var FROM_TO_RE = /\s+from\s+(\d{4}-\d{2}-\d{2})(?:\s+to\s+(\d{4}-\d{2}-\d{2}))?\s*$/i;
|
|
154
156
|
var IN_SCOPE_RE = /\s+in\s+(\w+)\s*$/;
|
|
155
157
|
function parseWqlSuffixes(raw) {
|
|
156
158
|
const { primary, where } = splitAtWhere(raw);
|
|
@@ -158,8 +160,8 @@ function parseWqlSuffixes(raw) {
|
|
|
158
160
|
let displayUnit;
|
|
159
161
|
let rollup;
|
|
160
162
|
let groupBy;
|
|
161
|
-
let
|
|
162
|
-
let
|
|
163
|
+
let window;
|
|
164
|
+
let legacyScope;
|
|
163
165
|
const conflicts = [];
|
|
164
166
|
const isFind = text.startsWith("find:");
|
|
165
167
|
const isRows = /^rows(?=[:{]|\s|$)/.test(text);
|
|
@@ -178,18 +180,40 @@ function parseWqlSuffixes(raw) {
|
|
|
178
180
|
);
|
|
179
181
|
}
|
|
180
182
|
};
|
|
183
|
+
const froms = stripRepeated(FROM_TO_RE);
|
|
184
|
+
const lasts = stripRepeated(LAST_RE);
|
|
185
|
+
{
|
|
186
|
+
const windows = [
|
|
187
|
+
...froms.map((m) => ({
|
|
188
|
+
kind: "range",
|
|
189
|
+
start: m[1],
|
|
190
|
+
end: m[2],
|
|
191
|
+
raw: m[0].trim(),
|
|
192
|
+
at: m.index
|
|
193
|
+
})),
|
|
194
|
+
...lasts.map((m) => ({
|
|
195
|
+
kind: "relative",
|
|
196
|
+
size: parseInt(m[1], 10),
|
|
197
|
+
unit: m[2].toLowerCase(),
|
|
198
|
+
raw: m[0].trim(),
|
|
199
|
+
at: m.index
|
|
200
|
+
}))
|
|
201
|
+
].sort((a, b) => a.at - b.at);
|
|
202
|
+
if (windows.length > 1) {
|
|
203
|
+
conflicts.push(
|
|
204
|
+
`Duplicate 'window' clause: '${windows[0].raw}' conflicts with '${windows[windows.length - 1].raw}'`
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
if (windows.length === 1) {
|
|
208
|
+
const w = windows[0];
|
|
209
|
+
window = w.kind === "range" ? { kind: "range", start: w.start, end: w.end, raw: w.raw } : { kind: "relative", size: w.size, unit: w.unit, raw: w.raw };
|
|
210
|
+
}
|
|
211
|
+
}
|
|
181
212
|
if (isFind || isRows) {
|
|
182
|
-
const
|
|
183
|
-
conflictFrom("
|
|
184
|
-
if (
|
|
185
|
-
|
|
186
|
-
last = { size: parseInt(m[1], 10), unit: m[2].toLowerCase(), raw: m[0].trim() };
|
|
187
|
-
}
|
|
188
|
-
if (isFind) {
|
|
189
|
-
const scopes = stripRepeated(IN_SCOPE_RE);
|
|
190
|
-
conflictFrom("scope", scopes);
|
|
191
|
-
if (scopes.length) scope = scopes[scopes.length - 1][1];
|
|
192
|
-
} else {
|
|
213
|
+
const scopes = stripRepeated(IN_SCOPE_RE);
|
|
214
|
+
conflictFrom("scope", scopes);
|
|
215
|
+
if (scopes.length) legacyScope = scopes[scopes.length - 1][1];
|
|
216
|
+
if (isRows) {
|
|
193
217
|
const rollups = stripRepeated(ROLLUP_RE);
|
|
194
218
|
conflictFrom(".rollup", rollups);
|
|
195
219
|
if (rollups.length) {
|
|
@@ -223,8 +247,8 @@ function parseWqlSuffixes(raw) {
|
|
|
223
247
|
displayUnit,
|
|
224
248
|
rollup,
|
|
225
249
|
groupBy,
|
|
226
|
-
|
|
227
|
-
|
|
250
|
+
window,
|
|
251
|
+
legacyScope,
|
|
228
252
|
conflicts: conflicts.length ? conflicts : void 0,
|
|
229
253
|
primaryText: text
|
|
230
254
|
};
|
|
@@ -252,7 +276,10 @@ function parseJoinClause(where) {
|
|
|
252
276
|
if (where.trimStart().startsWith("find:")) {
|
|
253
277
|
const fp = parseFindQuery(where);
|
|
254
278
|
if (fp.error) return { error: fp.error };
|
|
255
|
-
|
|
279
|
+
if (fp.window?.kind === "range") {
|
|
280
|
+
return { error: "Range windows are not supported on join halves \u2014 use last <n>d|w" };
|
|
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 } };
|
|
256
283
|
}
|
|
257
284
|
const m = CMP_RE.exec(where.trim());
|
|
258
285
|
if (!m) return { error: cannotParseJoin(where) };
|
|
@@ -269,27 +296,112 @@ function parseJoinClause(where) {
|
|
|
269
296
|
};
|
|
270
297
|
}
|
|
271
298
|
function parseQuery(raw) {
|
|
272
|
-
const
|
|
299
|
+
const norm = normalizeWql(raw);
|
|
300
|
+
const trimmed = norm.query.trimStart();
|
|
301
|
+
let result;
|
|
273
302
|
if (trimmed.startsWith("find:")) {
|
|
274
|
-
|
|
303
|
+
result = parseFindQuery(norm.query);
|
|
304
|
+
} else if (/^rows(?=[:{]|\s|$)/.test(trimmed)) {
|
|
305
|
+
result = parseRowsQuery(norm.query);
|
|
306
|
+
} else {
|
|
307
|
+
result = parseAnalyticsQuery(norm.query);
|
|
308
|
+
}
|
|
309
|
+
if (norm.advisories.length) {
|
|
310
|
+
result.advisories = [...result.advisories ?? [], ...norm.advisories];
|
|
311
|
+
}
|
|
312
|
+
result.raw = raw;
|
|
313
|
+
return result;
|
|
314
|
+
}
|
|
315
|
+
function normalizeWql(raw) {
|
|
316
|
+
const advisories = [];
|
|
317
|
+
let text = raw.trim();
|
|
318
|
+
if (/^rows:?\s*[{]/.test(text)) {
|
|
319
|
+
text = text.replace(/^rows:?\s*[{]/, "rows:all{");
|
|
320
|
+
advisories.push("Bare 'rows:{...}' syntax is deprecated; use 'rows:all{...}' instead.");
|
|
275
321
|
}
|
|
276
|
-
|
|
277
|
-
|
|
322
|
+
const { primary, where } = splitAtWhere(text);
|
|
323
|
+
const isFind = primary.startsWith("find:");
|
|
324
|
+
const isRows = /^rows(?=[:{]|\s|$)/.test(primary);
|
|
325
|
+
if (isFind || isRows) {
|
|
326
|
+
const suffixes = parseWqlSuffixes(primary);
|
|
327
|
+
if (suffixes.legacyScope && !suffixes.conflicts?.length) {
|
|
328
|
+
advisories.push("Legacy 'in <scope>' syntax is deprecated; use 'source:<scope>' filter instead.");
|
|
329
|
+
const scope = suffixes.legacyScope;
|
|
330
|
+
let head = suffixes.primaryText.trim();
|
|
331
|
+
const braceOpen = head.indexOf("{");
|
|
332
|
+
const braceClose = head.lastIndexOf("}");
|
|
333
|
+
if (braceOpen !== -1 && braceClose !== -1 && braceClose > braceOpen) {
|
|
334
|
+
const beforeBrace = head.slice(0, braceOpen + 1);
|
|
335
|
+
const inside = head.slice(braceOpen + 1, braceClose).trim();
|
|
336
|
+
const afterBrace = head.slice(braceClose);
|
|
337
|
+
const newInside = inside ? `${inside},source:${scope}` : `source:${scope}`;
|
|
338
|
+
head = `${beforeBrace}${newInside}${afterBrace}`;
|
|
339
|
+
} else {
|
|
340
|
+
head = `${head}{source:${scope}}`;
|
|
341
|
+
}
|
|
342
|
+
const parts = [head];
|
|
343
|
+
if (suffixes.window) {
|
|
344
|
+
parts.push(suffixes.window.raw);
|
|
345
|
+
}
|
|
346
|
+
if (where) {
|
|
347
|
+
parts.push(`where ${where}`);
|
|
348
|
+
}
|
|
349
|
+
text = parts.join(" ");
|
|
350
|
+
}
|
|
278
351
|
}
|
|
279
|
-
return
|
|
352
|
+
return { query: text, advisories };
|
|
280
353
|
}
|
|
281
354
|
function cannotParseRows(text) {
|
|
282
|
-
return `Cannot parse "${text}". Expected rows:{result:\u2026|block:\u2026|note:\u2026} or rows:segment{\u2026} last 8w`;
|
|
355
|
+
return `Cannot parse "${text}". Expected rows:all{result:\u2026|block:\u2026|note:\u2026}, rows:<plane>{\u2026}, or rows:segment{\u2026} last 8w`;
|
|
356
|
+
}
|
|
357
|
+
function validateRowsFilters(filters) {
|
|
358
|
+
const scopeKeys = new Set(WQL_ROWS_SCOPE_KEYS);
|
|
359
|
+
const allowedKeys = /* @__PURE__ */ new Set([...WQL_ROWS_SCOPE_KEYS, "source"]);
|
|
360
|
+
const unsupported = filters.filter(
|
|
361
|
+
(f) => !allowedKeys.has(f.key) || f.negate || f.values.some((v) => v.wildcard)
|
|
362
|
+
);
|
|
363
|
+
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.`;
|
|
365
|
+
}
|
|
366
|
+
if (!filters.some((f) => scopeKeys.has(f.key))) {
|
|
367
|
+
return `Rows query needs a scope: ${WQL_ROWS_SCOPE_KEYS.map((k) => `${k}:`).join(", ")}.`;
|
|
368
|
+
}
|
|
369
|
+
return void 0;
|
|
370
|
+
}
|
|
371
|
+
function validateSourceFilter(filters) {
|
|
372
|
+
const validSources = new Set(WQL_SOURCE_VALUES);
|
|
373
|
+
for (const f of filters) {
|
|
374
|
+
if (f.key !== "source") continue;
|
|
375
|
+
for (const v of f.values) {
|
|
376
|
+
const val = v.value;
|
|
377
|
+
if (validSources.has(val) || val === "collection" || val === "feed" || val.startsWith("collection:") || val.startsWith("feed:")) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
return `Unknown source "${val}". Try: ${WQL_SOURCE_VALUES.join(", ")}`;
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return void 0;
|
|
283
384
|
}
|
|
385
|
+
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}.';
|
|
284
386
|
function parseRowsQuery(raw) {
|
|
285
387
|
const suffixes = parseWqlSuffixes(raw);
|
|
286
|
-
const { where: whereText,
|
|
388
|
+
const { where: whereText, window: windowSuffix, legacyScope, groupBy, rollup, primaryText } = suffixes;
|
|
389
|
+
const win = toQueryWindow(windowSuffix);
|
|
390
|
+
const advisories = [];
|
|
391
|
+
if (legacyScope) {
|
|
392
|
+
advisories.push("Legacy 'in <scope>' syntax is deprecated; use 'source:<scope>' filter instead.");
|
|
393
|
+
}
|
|
287
394
|
const result = {
|
|
288
|
-
raw,
|
|
289
395
|
family: "rows",
|
|
396
|
+
raw,
|
|
290
397
|
filters: [],
|
|
291
|
-
|
|
398
|
+
window: win.window,
|
|
399
|
+
...advisories.length ? { advisories } : {}
|
|
292
400
|
};
|
|
401
|
+
if (win.error) {
|
|
402
|
+
result.error = win.error;
|
|
403
|
+
return result;
|
|
404
|
+
}
|
|
293
405
|
if (suffixes.conflicts?.length) {
|
|
294
406
|
result.error = suffixes.conflicts.join("; ");
|
|
295
407
|
return result;
|
|
@@ -299,44 +411,84 @@ function parseRowsQuery(raw) {
|
|
|
299
411
|
return result;
|
|
300
412
|
}
|
|
301
413
|
const text = primaryText.trim();
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
} else {
|
|
414
|
+
if (/^rows:?\s*[{]?$/.test(text) || /^rows:?\s*[{]/.test(text)) {
|
|
415
|
+
result.error = BARE_ROWS_RETIRED;
|
|
416
|
+
return result;
|
|
417
|
+
}
|
|
418
|
+
const tree = parser.parse(text);
|
|
419
|
+
let syntaxError = false;
|
|
420
|
+
tree.iterate({ enter(node) {
|
|
421
|
+
if (node.type.isError) syntaxError = true;
|
|
422
|
+
} });
|
|
423
|
+
if (syntaxError) {
|
|
313
424
|
result.error = cannotParseRows(text);
|
|
314
425
|
return result;
|
|
315
426
|
}
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
result.
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
427
|
+
const query = tree.topNode;
|
|
428
|
+
const head = query.getChild(Head);
|
|
429
|
+
const aggNode = head?.getChild(Aggregator);
|
|
430
|
+
const metricNode = head?.getChild(Metric);
|
|
431
|
+
if (!head || !aggNode || !metricNode) {
|
|
432
|
+
result.error = BARE_ROWS_RETIRED;
|
|
433
|
+
return result;
|
|
434
|
+
}
|
|
435
|
+
const aggText = text.slice(aggNode.from, aggNode.to);
|
|
436
|
+
if (aggText !== "rows") {
|
|
437
|
+
result.error = cannotParseRows(text);
|
|
438
|
+
return result;
|
|
439
|
+
}
|
|
440
|
+
const target = text.slice(metricNode.from, metricNode.to);
|
|
441
|
+
if (!WQL_ROWS_TARGETS.includes(target)) {
|
|
442
|
+
result.error = `Unknown rows target "${target}". Try: ${WQL_ROWS_TARGETS.join(", ")}`;
|
|
443
|
+
return result;
|
|
444
|
+
}
|
|
445
|
+
if (target !== "all") result.outputType = target;
|
|
446
|
+
result.filters = extractFilters(query, text);
|
|
447
|
+
if (legacyScope) {
|
|
448
|
+
result.filters.push({
|
|
449
|
+
key: "source",
|
|
450
|
+
negate: false,
|
|
451
|
+
values: [{ value: legacyScope, wildcard: false }]
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
const sourceError = validateSourceFilter(result.filters);
|
|
455
|
+
if (sourceError) {
|
|
456
|
+
result.error = sourceError;
|
|
457
|
+
return result;
|
|
458
|
+
}
|
|
459
|
+
const grainError = retiredGrainRollup(result.filters);
|
|
460
|
+
if (grainError) {
|
|
461
|
+
result.error = grainError;
|
|
462
|
+
return result;
|
|
463
|
+
}
|
|
464
|
+
const filterError = validateRowsFilters(result.filters);
|
|
465
|
+
if (filterError) {
|
|
466
|
+
result.error = filterError;
|
|
467
|
+
return result;
|
|
337
468
|
}
|
|
338
469
|
return result;
|
|
339
470
|
}
|
|
471
|
+
function isCivilDate(s) {
|
|
472
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
|
|
473
|
+
if (!m) return false;
|
|
474
|
+
const y = Number(m[1]);
|
|
475
|
+
const mo = Number(m[2]);
|
|
476
|
+
const d = Number(m[3]);
|
|
477
|
+
const dt = new Date(y, mo - 1, d);
|
|
478
|
+
return dt.getFullYear() === y && dt.getMonth() === mo - 1 && dt.getDate() === d;
|
|
479
|
+
}
|
|
480
|
+
function toQueryWindow(w) {
|
|
481
|
+
if (!w) return {};
|
|
482
|
+
if (w.kind === "relative") {
|
|
483
|
+
return { window: { kind: "relative", size: w.size, unit: w.unit } };
|
|
484
|
+
}
|
|
485
|
+
for (const d of [w.start, w.end]) {
|
|
486
|
+
if (d !== void 0 && !isCivilDate(d)) {
|
|
487
|
+
return { error: `Invalid window date "${d}" \u2014 expected a real calendar date YYYY-MM-DD` };
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return { window: { kind: "range", start: w.start, end: w.end } };
|
|
491
|
+
}
|
|
340
492
|
function retiredGrainRollup(filters) {
|
|
341
493
|
if (filters.some((f) => f.key === "grain" && f.values.some((v) => v.value === "rollup"))) {
|
|
342
494
|
return "grain:rollup is retired \u2014 rollup grains are never stored; compute them with the .rollup suffix";
|
|
@@ -372,7 +524,8 @@ function extractFilters(query, text) {
|
|
|
372
524
|
}
|
|
373
525
|
function parseAnalyticsQuery(raw) {
|
|
374
526
|
const suffixes = parseWqlSuffixes(raw);
|
|
375
|
-
const { where: whereText, displayUnit, groupBy, rollup, primaryText: text } = suffixes;
|
|
527
|
+
const { where: whereText, displayUnit, groupBy, rollup, window: windowSuffix, primaryText: text } = suffixes;
|
|
528
|
+
const win = toQueryWindow(windowSuffix);
|
|
376
529
|
const base = {
|
|
377
530
|
family: "aggregate",
|
|
378
531
|
raw,
|
|
@@ -381,8 +534,13 @@ function parseAnalyticsQuery(raw) {
|
|
|
381
534
|
filters: [],
|
|
382
535
|
groupBy: groupBy ?? [],
|
|
383
536
|
displayUnit,
|
|
384
|
-
rollup: rollup ? { size: rollup.size, unit: rollup.unit } : void 0
|
|
537
|
+
rollup: rollup ? { size: rollup.size, unit: rollup.unit } : void 0,
|
|
538
|
+
window: win.window
|
|
385
539
|
};
|
|
540
|
+
if (win.error) {
|
|
541
|
+
base.error = win.error;
|
|
542
|
+
return base;
|
|
543
|
+
}
|
|
386
544
|
if (suffixes.conflicts?.length) {
|
|
387
545
|
base.error = suffixes.conflicts.join("; ");
|
|
388
546
|
return base;
|
|
@@ -436,19 +594,28 @@ function parseAnalyticsQuery(raw) {
|
|
|
436
594
|
return base;
|
|
437
595
|
}
|
|
438
596
|
function cannotParseFind(text) {
|
|
439
|
-
return `Cannot parse "${text}". Expected find:target{filters}
|
|
597
|
+
return `Cannot parse "${text}". Expected find:target{filters} last 8w`;
|
|
440
598
|
}
|
|
441
599
|
function parseFindQuery(raw) {
|
|
442
600
|
const suffixes = parseWqlSuffixes(raw);
|
|
443
|
-
const { where: whereText,
|
|
601
|
+
const { where: whereText, window: windowSuffix, legacyScope, primaryText: text } = suffixes;
|
|
602
|
+
const win = toQueryWindow(windowSuffix);
|
|
603
|
+
const advisories = [];
|
|
604
|
+
if (legacyScope) {
|
|
605
|
+
advisories.push("Legacy 'in <scope>' syntax is deprecated; use 'source:<scope>' filter instead.");
|
|
606
|
+
}
|
|
444
607
|
const result = {
|
|
445
608
|
family: "find",
|
|
446
609
|
raw,
|
|
447
610
|
target: "",
|
|
448
611
|
filters: [],
|
|
449
|
-
|
|
450
|
-
|
|
612
|
+
window: win.window,
|
|
613
|
+
...advisories.length ? { advisories } : {}
|
|
451
614
|
};
|
|
615
|
+
if (win.error) {
|
|
616
|
+
result.error = win.error;
|
|
617
|
+
return result;
|
|
618
|
+
}
|
|
452
619
|
if (suffixes.conflicts?.length) {
|
|
453
620
|
result.error = suffixes.conflicts.join("; ");
|
|
454
621
|
return result;
|
|
@@ -476,7 +643,23 @@ function parseFindQuery(raw) {
|
|
|
476
643
|
return result;
|
|
477
644
|
}
|
|
478
645
|
result.target = text.slice(metricNode.from, metricNode.to);
|
|
646
|
+
if (!WQL_FIND_TARGETS.includes(result.target)) {
|
|
647
|
+
result.error = `Unknown find target "${result.target}". Try: ${WQL_FIND_TARGETS.join(", ")}`;
|
|
648
|
+
return result;
|
|
649
|
+
}
|
|
479
650
|
result.filters = extractFilters(query, text);
|
|
651
|
+
if (legacyScope) {
|
|
652
|
+
result.filters.push({
|
|
653
|
+
key: "source",
|
|
654
|
+
negate: false,
|
|
655
|
+
values: [{ value: legacyScope, wildcard: false }]
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
const sourceError = validateSourceFilter(result.filters);
|
|
659
|
+
if (sourceError) {
|
|
660
|
+
result.error = sourceError;
|
|
661
|
+
return result;
|
|
662
|
+
}
|
|
480
663
|
const findGrainError = retiredGrainRollup(result.filters);
|
|
481
664
|
if (findGrainError) {
|
|
482
665
|
result.error = findGrainError;
|
|
@@ -601,6 +784,8 @@ function wqlCompletionSource(options_ = {}) {
|
|
|
601
784
|
return options(WQL_GRAINS);
|
|
602
785
|
case "metric":
|
|
603
786
|
return metricOptions();
|
|
787
|
+
case "source":
|
|
788
|
+
return options(WQL_SOURCE_VALUES);
|
|
604
789
|
default:
|
|
605
790
|
return null;
|
|
606
791
|
}
|
|
@@ -1093,8 +1278,12 @@ function staticTagIndexFromBlocks(blocks) {
|
|
|
1093
1278
|
|
|
1094
1279
|
// src/QueryService.ts
|
|
1095
1280
|
var DAY = 864e5;
|
|
1281
|
+
var ROWS_CONTENT_PLANES = new Set(WQL_FIND_TARGETS);
|
|
1096
1282
|
function localDateString(ts) {
|
|
1097
|
-
|
|
1283
|
+
const d = new Date(ts);
|
|
1284
|
+
const mm = String(d.getMonth() + 1).padStart(2, "0");
|
|
1285
|
+
const dd = String(d.getDate()).padStart(2, "0");
|
|
1286
|
+
return `${d.getFullYear()}-${mm}-${dd}`;
|
|
1098
1287
|
}
|
|
1099
1288
|
function catalogOfItem(item) {
|
|
1100
1289
|
if (item.catalog) return item.catalog;
|
|
@@ -1104,9 +1293,13 @@ function catalogOfItem(item) {
|
|
|
1104
1293
|
return clean.split("/")[0];
|
|
1105
1294
|
}
|
|
1106
1295
|
function sourceMatches(sourceId, kind) {
|
|
1296
|
+
if (kind === "all") return true;
|
|
1107
1297
|
if (kind === "journal") return !sourceId || sourceId === "journal";
|
|
1108
|
-
if (kind === "collection" || kind === "
|
|
1109
|
-
return !!sourceId && sourceId.startsWith(
|
|
1298
|
+
if (kind === "collection" || kind === "collections") {
|
|
1299
|
+
return !!sourceId && sourceId.startsWith("collection:");
|
|
1300
|
+
}
|
|
1301
|
+
if (kind === "feed" || kind === "feeds") {
|
|
1302
|
+
return !!sourceId && sourceId.startsWith("feed:");
|
|
1110
1303
|
}
|
|
1111
1304
|
return sourceId === kind;
|
|
1112
1305
|
}
|
|
@@ -1121,12 +1314,26 @@ function applySourceFilter(items, filters) {
|
|
|
1121
1314
|
}
|
|
1122
1315
|
return items;
|
|
1123
1316
|
}
|
|
1124
|
-
function
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1317
|
+
function civilMidnight(iso) {
|
|
1318
|
+
const [y, m, d] = iso.split("-").map(Number);
|
|
1319
|
+
return new Date(y, m - 1, d).getTime();
|
|
1320
|
+
}
|
|
1321
|
+
function nextCivilMidnight(iso) {
|
|
1322
|
+
const [y, m, d] = iso.split("-").map(Number);
|
|
1323
|
+
return new Date(y, m - 1, d + 1).getTime();
|
|
1324
|
+
}
|
|
1325
|
+
function windowRange(w, anchorNow) {
|
|
1326
|
+
if (!w) return void 0;
|
|
1327
|
+
if (w.kind === "relative") {
|
|
1328
|
+
return { start: (anchorNow ?? Date.now()) - w.size * (w.unit === "w" ? 7 : 1) * DAY, end: Number.MAX_SAFE_INTEGER };
|
|
1129
1329
|
}
|
|
1330
|
+
const start = civilMidnight(w.start);
|
|
1331
|
+
const end = w.end !== void 0 ? nextCivilMidnight(w.end) - 1 : Number.MAX_SAFE_INTEGER;
|
|
1332
|
+
return { start, end };
|
|
1333
|
+
}
|
|
1334
|
+
function effectiveTimeWindow(createdAt, window, range, anchorNow) {
|
|
1335
|
+
const resolved = range ?? windowRange(window, anchorNow);
|
|
1336
|
+
if (resolved) return createdAt >= resolved.start && createdAt <= resolved.end;
|
|
1130
1337
|
return true;
|
|
1131
1338
|
}
|
|
1132
1339
|
function latestActivity(rows) {
|
|
@@ -1136,7 +1343,7 @@ function latestActivity(rows) {
|
|
|
1136
1343
|
}
|
|
1137
1344
|
function windowAnchor(selected, parsed, options2) {
|
|
1138
1345
|
if (options2.anchorNow !== void 0) return options2.anchorNow;
|
|
1139
|
-
if (options2.anchor === "latest-activity" && parsed.
|
|
1346
|
+
if (options2.anchor === "latest-activity" && parsed.window?.kind === "relative") return latestActivity(selected);
|
|
1140
1347
|
return void 0;
|
|
1141
1348
|
}
|
|
1142
1349
|
var defaultEventStore = {
|
|
@@ -1206,9 +1413,11 @@ function matchesFilters(row, filters, noteTags) {
|
|
|
1206
1413
|
const negate = group[0].negate;
|
|
1207
1414
|
const raw = factTagValue(row, key, noteTags);
|
|
1208
1415
|
const rowValues = Array.isArray(raw) ? raw : raw !== void 0 ? [raw] : [];
|
|
1209
|
-
const hit =
|
|
1210
|
-
(
|
|
1211
|
-
(
|
|
1416
|
+
const hit = rowValues.some(
|
|
1417
|
+
(value) => group.some(
|
|
1418
|
+
(f) => f.values.some(
|
|
1419
|
+
(a) => a.wildcard ? value.startsWith(a.value) : value === a.value
|
|
1420
|
+
)
|
|
1212
1421
|
)
|
|
1213
1422
|
);
|
|
1214
1423
|
return negate ? !hit : hit;
|
|
@@ -1218,8 +1427,8 @@ function dimValue(row, dim, noteTags) {
|
|
|
1218
1427
|
if (dim === "day") return localDateString(row.timestamp);
|
|
1219
1428
|
if (dim === "week") {
|
|
1220
1429
|
const d = new Date(row.timestamp);
|
|
1221
|
-
const monday = new Date(
|
|
1222
|
-
return
|
|
1430
|
+
const monday = new Date(d.getFullYear(), d.getMonth(), d.getDate() - (d.getDay() + 6) % 7);
|
|
1431
|
+
return localDateString(monday.getTime());
|
|
1223
1432
|
}
|
|
1224
1433
|
if (dim === "session") return row.resultId;
|
|
1225
1434
|
const raw = factTagValue(row, dim, noteTags);
|
|
@@ -1318,29 +1527,20 @@ var QueryService = class {
|
|
|
1318
1527
|
return this.run(parsed, options2);
|
|
1319
1528
|
}
|
|
1320
1529
|
/**
|
|
1321
|
-
* Execute a rows query (rows
|
|
1322
|
-
*
|
|
1323
|
-
*
|
|
1530
|
+
* Execute a rows query (rows:<target>{…}, #949/C4) — the session results
|
|
1531
|
+
* table plane. Filter rules are validated at parse; this executes only.
|
|
1532
|
+
* Reads event rows directly over the unified store: outputType narrowing
|
|
1533
|
+
* hits the promoted column; content-plane targets scope by content.
|
|
1324
1534
|
*/
|
|
1325
1535
|
async runRows(parsed, options2 = {}) {
|
|
1326
1536
|
const empty = { parsed, runs: [] };
|
|
1327
1537
|
if (parsed.error) return { ...empty, error: parsed.error };
|
|
1328
|
-
const ROWS_SCOPE_KEYS = /* @__PURE__ */ new Set(["result", "block", "note"]);
|
|
1329
|
-
const unsupported = parsed.filters.filter(
|
|
1330
|
-
(f) => !ROWS_SCOPE_KEYS.has(f.key) || f.negate || f.values.some((v) => v.wildcard)
|
|
1331
|
-
);
|
|
1332
|
-
if (unsupported.length > 0) {
|
|
1333
|
-
return {
|
|
1334
|
-
...empty,
|
|
1335
|
-
error: `Unsupported rows filter(s): ${unsupported.map((f) => (f.negate ? "!" : "") + f.key).join(", ")}. Rows queries support exact result:, block:, note: values.`
|
|
1336
|
-
};
|
|
1337
|
-
}
|
|
1338
1538
|
const scopeValues = (key) => parsed.filters.filter((f) => f.key === key).flatMap((f) => f.values.map((v) => v.value));
|
|
1339
1539
|
const resultIds = scopeValues("result");
|
|
1340
1540
|
const blockIds = scopeValues("block");
|
|
1341
1541
|
const noteIds = scopeValues("note");
|
|
1342
1542
|
if (resultIds.length + blockIds.length + noteIds.length === 0) {
|
|
1343
|
-
return { ...empty,
|
|
1543
|
+
return { ...empty, runs: [] };
|
|
1344
1544
|
}
|
|
1345
1545
|
const byResult = /* @__PURE__ */ new Map();
|
|
1346
1546
|
const collect = (rows) => {
|
|
@@ -1354,9 +1554,9 @@ var QueryService = class {
|
|
|
1354
1554
|
for (const blockContentId of blockIds) collect(await this.store.getEventsByContent(blockContentId));
|
|
1355
1555
|
for (const noteId of noteIds) collect(await this.store.getEventsForNote(noteId));
|
|
1356
1556
|
let groups = [...byResult.entries()].filter(([, rows]) => rows.length > 0);
|
|
1357
|
-
if (parsed.
|
|
1557
|
+
if (parsed.window) {
|
|
1358
1558
|
groups = groups.filter(
|
|
1359
|
-
([, rows]) => effectiveTimeWindow(rows[0].timestamp, parsed.
|
|
1559
|
+
([, rows]) => effectiveTimeWindow(rows[0].timestamp, parsed.window, void 0, options2.anchorNow)
|
|
1360
1560
|
);
|
|
1361
1561
|
}
|
|
1362
1562
|
groups.sort((a, b) => b[1][0].timestamp - a[1][0].timestamp);
|
|
@@ -1364,7 +1564,7 @@ var QueryService = class {
|
|
|
1364
1564
|
resultId,
|
|
1365
1565
|
noteId: rows[0].noteId,
|
|
1366
1566
|
timestamp: rows[0].timestamp,
|
|
1367
|
-
events: parsed.outputType ? rows.filter((row) => row.outputType === parsed.outputType) : rows
|
|
1567
|
+
events: parsed.outputType && !ROWS_CONTENT_PLANES.has(parsed.outputType) ? rows.filter((row) => row.outputType === parsed.outputType) : rows
|
|
1368
1568
|
})).filter((run) => run.events.length > 0);
|
|
1369
1569
|
return { parsed, runs };
|
|
1370
1570
|
}
|
|
@@ -1384,15 +1584,9 @@ var QueryService = class {
|
|
|
1384
1584
|
return this.runFindEffort(parsed);
|
|
1385
1585
|
}
|
|
1386
1586
|
let notes = [];
|
|
1387
|
-
|
|
1388
|
-
if (
|
|
1389
|
-
notes = notes.concat(await this.
|
|
1390
|
-
}
|
|
1391
|
-
if (scope === "collections" || scope === "feeds" || scope === "all") {
|
|
1392
|
-
let sNotes = this.staticNoteStore ? await this.staticNoteStore.getAllNotes() : [];
|
|
1393
|
-
if (scope === "collections") sNotes = sNotes.filter((n) => n.sourceId?.startsWith("collection:"));
|
|
1394
|
-
if (scope === "feeds") sNotes = sNotes.filter((n) => n.sourceId?.startsWith("feed:"));
|
|
1395
|
-
notes = notes.concat(sNotes);
|
|
1587
|
+
notes = notes.concat(await this.noteStore.getAllNotes());
|
|
1588
|
+
if (this.staticNoteStore) {
|
|
1589
|
+
notes = notes.concat(await this.staticNoteStore.getAllNotes());
|
|
1396
1590
|
}
|
|
1397
1591
|
const selectedCount = notes.length;
|
|
1398
1592
|
const anchorNow = windowAnchor(notes, parsed, options2);
|
|
@@ -1438,8 +1632,8 @@ var QueryService = class {
|
|
|
1438
1632
|
});
|
|
1439
1633
|
}
|
|
1440
1634
|
}
|
|
1441
|
-
if (parsed.
|
|
1442
|
-
notes = notes.filter((n) => effectiveTimeWindow(n.createdAt, parsed.
|
|
1635
|
+
if (parsed.window || options2.range) {
|
|
1636
|
+
notes = notes.filter((n) => effectiveTimeWindow(n.createdAt, parsed.window, options2.range, anchorNow));
|
|
1443
1637
|
}
|
|
1444
1638
|
if (parsed.join) {
|
|
1445
1639
|
const joined = await this.applyMetricJoin(parsed, notes, []);
|
|
@@ -1452,15 +1646,9 @@ var QueryService = class {
|
|
|
1452
1646
|
*/
|
|
1453
1647
|
async runFindBlock(parsed, options2 = {}) {
|
|
1454
1648
|
let blocks = [];
|
|
1455
|
-
|
|
1456
|
-
if (
|
|
1457
|
-
blocks = blocks.concat(await this.
|
|
1458
|
-
}
|
|
1459
|
-
if (scope === "collections" || scope === "feeds" || scope === "all") {
|
|
1460
|
-
let sBlocks = this.staticBlockStore ? await this.staticBlockStore.getAllBlocks() : [];
|
|
1461
|
-
if (scope === "collections") sBlocks = sBlocks.filter((b) => b.sourceId?.startsWith("collection:"));
|
|
1462
|
-
if (scope === "feeds") sBlocks = sBlocks.filter((b) => b.sourceId?.startsWith("feed:"));
|
|
1463
|
-
blocks = blocks.concat(sBlocks);
|
|
1649
|
+
blocks = blocks.concat(await this.blockStore.getAllBlocks());
|
|
1650
|
+
if (this.staticBlockStore) {
|
|
1651
|
+
blocks = blocks.concat(await this.staticBlockStore.getAllBlocks());
|
|
1464
1652
|
}
|
|
1465
1653
|
const selectedCount = blocks.length;
|
|
1466
1654
|
const anchorNow = windowAnchor(blocks, parsed, options2);
|
|
@@ -1500,8 +1688,8 @@ var QueryService = class {
|
|
|
1500
1688
|
blocks = blocks.filter((b) => matchingNoteIds.has(b.noteId));
|
|
1501
1689
|
}
|
|
1502
1690
|
}
|
|
1503
|
-
if (parsed.
|
|
1504
|
-
blocks = blocks.filter((b) => effectiveTimeWindow(b.createdAt, parsed.
|
|
1691
|
+
if (parsed.window || options2.range) {
|
|
1692
|
+
blocks = blocks.filter((b) => effectiveTimeWindow(b.createdAt, parsed.window, options2.range, anchorNow));
|
|
1505
1693
|
}
|
|
1506
1694
|
if (parsed.join) {
|
|
1507
1695
|
const joined = await this.applyMetricJoin(parsed, [], blocks);
|
|
@@ -1554,10 +1742,8 @@ var QueryService = class {
|
|
|
1554
1742
|
};
|
|
1555
1743
|
if (parsed.error) return empty;
|
|
1556
1744
|
if (parsed.join) return this.runJoined(parsed, options2);
|
|
1557
|
-
const
|
|
1558
|
-
const
|
|
1559
|
-
const end = options2.rangeEnd ?? Number.MAX_SAFE_INTEGER;
|
|
1560
|
-
const eventRows = windowed ? await this.store.getEventsByTimeRange(start, end) : await this.store.scanAll();
|
|
1745
|
+
const range = options2.rangeStart !== void 0 || options2.rangeEnd !== void 0 ? { start: options2.rangeStart ?? 0, end: options2.rangeEnd ?? Number.MAX_SAFE_INTEGER } : windowRange(parsed.window);
|
|
1746
|
+
const eventRows = range ? await this.store.getEventsByTimeRange(range.start, range.end) : await this.store.scanAll();
|
|
1561
1747
|
const candidates = eventRows.flatMap(projectEventToFacts).filter((row) => row.metricKey === parsed.metric);
|
|
1562
1748
|
const touchesTags = parsed.filters.some((f) => f.key === "tags") || parsed.groupBy.includes("tags");
|
|
1563
1749
|
const noteTags = await this.loadNoteTags(candidates, touchesTags);
|
|
@@ -1575,8 +1761,24 @@ var QueryService = class {
|
|
|
1575
1761
|
const timeDim = parsed.groupBy.find((d) => d === "day" || d === "week");
|
|
1576
1762
|
const tagDims = parsed.groupBy.filter((d) => d !== "day" && d !== "week");
|
|
1577
1763
|
const bucketMs = timeDim ? (timeDim === "week" ? 7 : 1) * DAY : parsed.rollup ? parsed.rollup.size * (parsed.rollup.unit === "w" ? 7 : 1) * DAY : null;
|
|
1578
|
-
const
|
|
1764
|
+
const civilDay = (ts) => {
|
|
1765
|
+
const d = new Date(ts);
|
|
1766
|
+
return Math.floor(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()) / DAY);
|
|
1767
|
+
};
|
|
1768
|
+
const bucketKey = (ts) => {
|
|
1769
|
+
if (timeDim === "day") return civilDay(ts);
|
|
1770
|
+
if (timeDim === "week") {
|
|
1771
|
+
const d = new Date(ts);
|
|
1772
|
+
return civilDay(ts) - (d.getDay() + 6) % 7;
|
|
1773
|
+
}
|
|
1774
|
+
return bucketMs ? Math.floor(ts / bucketMs) : 0;
|
|
1775
|
+
};
|
|
1579
1776
|
const bucketCount = bucketMs ? new Set(matched.map((p) => bucketKey(p.timestamp))).size : matched.length ? 1 : 0;
|
|
1777
|
+
const civilBucketInstant = (anchor, dim) => {
|
|
1778
|
+
const d = new Date(anchor);
|
|
1779
|
+
const back = dim === "week" ? (d.getDay() + 6) % 7 : 0;
|
|
1780
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate() - back, 12).getTime();
|
|
1781
|
+
};
|
|
1580
1782
|
const { unit: targetUnit, convert: shouldConvert } = resolveDisplayUnit(matched, {
|
|
1581
1783
|
directive: parsed.displayUnit,
|
|
1582
1784
|
preferred: options2.preferredUnit
|
|
@@ -1601,7 +1803,7 @@ var QueryService = class {
|
|
|
1601
1803
|
(m) => toDisplayValue(m.value, m.unit ?? m.metricUnit, shouldConvert ? targetUnit : void 0)
|
|
1602
1804
|
);
|
|
1603
1805
|
return {
|
|
1604
|
-
ts: bucketMs ? b * bucketMs + bucketMs / 2 : Math.min(...members.map((m) => m.timestamp)),
|
|
1806
|
+
ts: timeDim ? civilBucketInstant(members[0].timestamp, timeDim) : bucketMs ? b * bucketMs + bucketMs / 2 : Math.min(...members.map((m) => m.timestamp)),
|
|
1605
1807
|
value: Math.round(aggregate(values, parsed.agg, members, shouldConvert ? targetUnit : void 0) * 100) / 100
|
|
1606
1808
|
};
|
|
1607
1809
|
});
|
|
@@ -1635,17 +1837,14 @@ var QueryService = class {
|
|
|
1635
1837
|
raw: "",
|
|
1636
1838
|
target: join.target,
|
|
1637
1839
|
filters: join.filters,
|
|
1638
|
-
|
|
1639
|
-
last: join.last
|
|
1840
|
+
window: join.last ? { kind: "relative", size: join.last.size, unit: join.last.unit } : void 0
|
|
1640
1841
|
});
|
|
1641
1842
|
const contentIds = await this.contentIdsFromFindResult(findResult);
|
|
1642
1843
|
if (contentIds.size === 0) return empty;
|
|
1643
1844
|
let facts = await this.deriveMetricFacts(contentIds, parsed.metric);
|
|
1644
|
-
|
|
1645
|
-
if (
|
|
1646
|
-
|
|
1647
|
-
const end = options2.rangeEnd ?? Number.MAX_SAFE_INTEGER;
|
|
1648
|
-
facts = facts.filter((f) => f.timestamp >= start && f.timestamp <= end);
|
|
1845
|
+
const joinRange = options2.rangeStart !== void 0 || options2.rangeEnd !== void 0 ? { start: options2.rangeStart ?? 0, end: options2.rangeEnd ?? Number.MAX_SAFE_INTEGER } : windowRange(parsed.window);
|
|
1846
|
+
if (joinRange) {
|
|
1847
|
+
facts = facts.filter((f) => f.timestamp >= joinRange.start && f.timestamp <= joinRange.end);
|
|
1649
1848
|
}
|
|
1650
1849
|
const touchesTags = parsed.filters.some((f) => f.key === "tags") || parsed.groupBy.includes("tags");
|
|
1651
1850
|
const noteTags = await this.loadNoteTags(facts, touchesTags);
|
|
@@ -2050,15 +2249,15 @@ sum:$metric{} rollup:1w
|
|
|
2050
2249
|
}
|
|
2051
2250
|
|
|
2052
2251
|
// src/version.ts
|
|
2053
|
-
var VERSION = "0.
|
|
2054
|
-
var GIT_SHA = "
|
|
2055
|
-
var BUILD_TIME = "2026-08-
|
|
2252
|
+
var VERSION = "0.9.40";
|
|
2253
|
+
var GIT_SHA = "2462ec9";
|
|
2254
|
+
var BUILD_TIME = "2026-08-26T01:04:47.412Z";
|
|
2056
2255
|
var SEMVER = {
|
|
2057
|
-
version: "0.
|
|
2058
|
-
gitSha: "
|
|
2059
|
-
buildTime: "2026-08-
|
|
2256
|
+
version: "0.9.40",
|
|
2257
|
+
gitSha: "2462ec9",
|
|
2258
|
+
buildTime: "2026-08-26T01:04:47.412Z"
|
|
2060
2259
|
};
|
|
2061
2260
|
|
|
2062
|
-
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,
|
|
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 };
|
|
2063
2262
|
//# sourceMappingURL=index.mjs.map
|
|
2064
2263
|
//# sourceMappingURL=index.mjs.map
|