@kernhq/module-tracker 0.6.0 → 0.7.1

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.
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Formula fields: an expression over the same issue's own values.
3
+ *
4
+ * Deliberately narrow. A formula reads the issue it is on and nothing else — no rollups over
5
+ * children, no references to other issues. That removes the dependency graph and the recompute
6
+ * fan-out entirely, which is the difference between a slice of work and a quarter of it: a value is
7
+ * computed when the issue is written, and nothing else can ever invalidate it.
8
+ *
9
+ * The KQL lexer is not reused. It has no arithmetic and its tokens carry query meanings (`~`, `in`,
10
+ * field kinds), so sharing it would mean teaching one lexer two languages for the sake of a hundred
11
+ * lines.
12
+ *
13
+ * A field is named the way it is named everywhere else: `{estimate}` for a system field,
14
+ * `{cf.story_points}` for a custom one.
15
+ */
16
+ export type FormulaValue = number | string | boolean | null;
17
+ export interface FormulaProblem {
18
+ message: string;
19
+ /** index into the source, for pointing at the mistake */
20
+ at: number;
21
+ }
22
+ /** The fields a formula reads, whether or not it parses cleanly. */
23
+ export declare function formulaReferences(source: string): string[];
24
+ /** Is this a formula the evaluator can run? Returns every problem, not just the first. */
25
+ export declare function validateFormula(source: string): {
26
+ ok: boolean;
27
+ problems: FormulaProblem[];
28
+ };
29
+ /**
30
+ * Run a formula. Returns `null` for anything it cannot compute — a missing value, a division by
31
+ * zero, a date that will not parse — rather than throwing or inventing a zero.
32
+ */
33
+ export declare function runFormula(source: string, read: (name: string) => FormulaValue): FormulaValue;
34
+ //# sourceMappingURL=formula.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formula.d.ts","sourceRoot":"","sources":["../../src/server/formula.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAA;AAE3D,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,yDAAyD;IACzD,EAAE,EAAE,MAAM,CAAA;CACX;AA6MD,oEAAoE;AACpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAE1D;AAED,0FAA0F;AAC1F,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;CAAE,CAG3F;AAgHD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,YAAY,GAAG,YAAY,CAQ7F"}
@@ -0,0 +1,350 @@
1
+ /**
2
+ * Formula fields: an expression over the same issue's own values.
3
+ *
4
+ * Deliberately narrow. A formula reads the issue it is on and nothing else — no rollups over
5
+ * children, no references to other issues. That removes the dependency graph and the recompute
6
+ * fan-out entirely, which is the difference between a slice of work and a quarter of it: a value is
7
+ * computed when the issue is written, and nothing else can ever invalidate it.
8
+ *
9
+ * The KQL lexer is not reused. It has no arithmetic and its tokens carry query meanings (`~`, `in`,
10
+ * field kinds), so sharing it would mean teaching one lexer two languages for the sake of a hundred
11
+ * lines.
12
+ *
13
+ * A field is named the way it is named everywhere else: `{estimate}` for a system field,
14
+ * `{cf.story_points}` for a custom one.
15
+ */
16
+ const OPERATORS = ['<=', '>=', '!=', '==', '+', '-', '*', '/', '%', '(', ')', ',', '<', '>'];
17
+ function tokenize(source) {
18
+ const tokens = [];
19
+ const problems = [];
20
+ let i = 0;
21
+ while (i < source.length) {
22
+ const c = source[i];
23
+ if (/\s/.test(c)) {
24
+ i++;
25
+ continue;
26
+ }
27
+ const at = i;
28
+ if (c === '{') {
29
+ const end = source.indexOf('}', i);
30
+ if (end === -1) {
31
+ problems.push({ message: 'A field reference is missing its closing brace', at });
32
+ break;
33
+ }
34
+ tokens.push({ kind: 'field', name: source.slice(i + 1, end).trim(), at });
35
+ i = end + 1;
36
+ continue;
37
+ }
38
+ if (c === '"' || c === "'") {
39
+ const end = source.indexOf(c, i + 1);
40
+ if (end === -1) {
41
+ problems.push({ message: 'A piece of text is missing its closing quote', at });
42
+ break;
43
+ }
44
+ tokens.push({ kind: 'string', value: source.slice(i + 1, end), at });
45
+ i = end + 1;
46
+ continue;
47
+ }
48
+ if (/[0-9]/.test(c)) {
49
+ let j = i;
50
+ while (j < source.length && /[0-9._]/.test(source[j]))
51
+ j++;
52
+ const raw = source.slice(i, j).replace(/_/g, '');
53
+ const value = Number(raw);
54
+ if (Number.isNaN(value))
55
+ problems.push({ message: `"${raw}" is not a number`, at });
56
+ tokens.push({ kind: 'number', value: Number.isNaN(value) ? 0 : value, at });
57
+ i = j;
58
+ continue;
59
+ }
60
+ if (/[a-zA-Z_]/.test(c)) {
61
+ let j = i;
62
+ while (j < source.length && /[a-zA-Z0-9_]/.test(source[j]))
63
+ j++;
64
+ tokens.push({ kind: 'name', value: source.slice(i, j), at });
65
+ i = j;
66
+ continue;
67
+ }
68
+ const op = OPERATORS.find((o) => source.startsWith(o, i));
69
+ if (op) {
70
+ tokens.push({ kind: 'op', value: op, at });
71
+ i += op.length;
72
+ continue;
73
+ }
74
+ problems.push({ message: `"${c}" does not mean anything here`, at });
75
+ i++;
76
+ }
77
+ return { tokens, problems };
78
+ }
79
+ /** Binding power per operator: comparison loosest, then `+ -`, then `* / %`. */
80
+ const BINDING = {
81
+ '<': 1,
82
+ '>': 1,
83
+ '<=': 1,
84
+ '>=': 1,
85
+ '==': 1,
86
+ '!=': 1,
87
+ '+': 2,
88
+ '-': 2,
89
+ '*': 3,
90
+ '/': 3,
91
+ '%': 3,
92
+ };
93
+ /** The functions a formula may call, with how many arguments each takes. */
94
+ const FUNCTIONS = {
95
+ abs: { min: 1, max: 1 },
96
+ round: { min: 1, max: 2 },
97
+ min: { min: 1, max: 8 },
98
+ max: { min: 1, max: 8 },
99
+ coalesce: { min: 1, max: 8 },
100
+ daysbetween: { min: 2, max: 2 },
101
+ if: { min: 3, max: 3 },
102
+ concat: { min: 1, max: 8 },
103
+ length: { min: 1, max: 1 },
104
+ };
105
+ function parse(source) {
106
+ const { tokens, problems } = tokenize(source);
107
+ const fields = [];
108
+ let pos = 0;
109
+ const peek = () => tokens[pos];
110
+ const fail = (message, at) => {
111
+ problems.push({ message, at });
112
+ };
113
+ function primary() {
114
+ const token = peek();
115
+ if (!token) {
116
+ fail('The formula stops before it finishes', source.length);
117
+ return null;
118
+ }
119
+ pos++;
120
+ if (token.kind === 'number')
121
+ return { type: 'number', value: token.value };
122
+ if (token.kind === 'string')
123
+ return { type: 'string', value: token.value };
124
+ if (token.kind === 'field') {
125
+ if (!token.name) {
126
+ fail('A field reference has no name', token.at);
127
+ return null;
128
+ }
129
+ fields.push(token.name);
130
+ return { type: 'field', name: token.name };
131
+ }
132
+ if (token.kind === 'name') {
133
+ const name = token.value.toLowerCase();
134
+ const next = peek();
135
+ if (!next || next.kind !== 'op' || next.value !== '(') {
136
+ if (name === 'true')
137
+ return { type: 'number', value: 1 };
138
+ if (name === 'false')
139
+ return { type: 'number', value: 0 };
140
+ fail(`"${token.value}" is not a function. Did you mean {${token.value}}?`, token.at);
141
+ return null;
142
+ }
143
+ pos++; // the '('
144
+ const args = [];
145
+ if (peek()?.kind === 'op' && peek().value === ')')
146
+ pos++;
147
+ else {
148
+ for (;;) {
149
+ const arg = expression(0);
150
+ if (!arg)
151
+ return null;
152
+ args.push(arg);
153
+ const sep = peek();
154
+ if (sep?.kind === 'op' && sep.value === ',') {
155
+ pos++;
156
+ continue;
157
+ }
158
+ if (sep?.kind === 'op' && sep.value === ')') {
159
+ pos++;
160
+ break;
161
+ }
162
+ fail('Expected a comma or a closing bracket', sep?.at ?? source.length);
163
+ return null;
164
+ }
165
+ }
166
+ const spec = FUNCTIONS[name];
167
+ if (!spec)
168
+ fail(`There is no function called "${token.value}"`, token.at);
169
+ else if (args.length < spec.min || args.length > spec.max)
170
+ fail(`"${token.value}" does not take ${args.length} argument(s)`, token.at);
171
+ return { type: 'call', name, args, at: token.at };
172
+ }
173
+ if (token.value === '(') {
174
+ const inner = expression(0);
175
+ const close = peek();
176
+ if (close?.kind === 'op' && close.value === ')')
177
+ pos++;
178
+ else
179
+ fail('A bracket is never closed', token.at);
180
+ return inner;
181
+ }
182
+ if (token.value === '-') {
183
+ const operand = expression(4);
184
+ return operand ? { type: 'unary', op: '-', operand } : null;
185
+ }
186
+ fail(`"${token.value}" cannot start a value`, token.at);
187
+ return null;
188
+ }
189
+ function expression(minBinding) {
190
+ let left = primary();
191
+ if (!left)
192
+ return null;
193
+ for (;;) {
194
+ const token = peek();
195
+ if (!token || token.kind !== 'op')
196
+ break;
197
+ const binding = BINDING[token.value];
198
+ if (binding === undefined || binding < minBinding)
199
+ break;
200
+ pos++;
201
+ const right = expression(binding + 1);
202
+ if (!right)
203
+ return null;
204
+ left = { type: 'binary', op: token.value, left, right };
205
+ }
206
+ return left;
207
+ }
208
+ const ast = expression(0);
209
+ if (ast && pos < tokens.length)
210
+ fail('There is something extra after the formula', tokens[pos].at);
211
+ return { ast: problems.length ? null : ast, problems, fields };
212
+ }
213
+ /** The fields a formula reads, whether or not it parses cleanly. */
214
+ export function formulaReferences(source) {
215
+ return [...new Set(parse(source).fields)];
216
+ }
217
+ /** Is this a formula the evaluator can run? Returns every problem, not just the first. */
218
+ export function validateFormula(source) {
219
+ const { problems } = parse(source);
220
+ return { ok: problems.length === 0, problems };
221
+ }
222
+ const asNumber = (value) => {
223
+ if (typeof value === 'number')
224
+ return value;
225
+ if (typeof value === 'boolean')
226
+ return value ? 1 : 0;
227
+ if (typeof value === 'string' && value.trim() !== '') {
228
+ const n = Number(value);
229
+ return Number.isNaN(n) ? null : n;
230
+ }
231
+ return null;
232
+ };
233
+ const asDate = (value) => {
234
+ if (typeof value !== 'string')
235
+ return null;
236
+ const t = Date.parse(value);
237
+ return Number.isNaN(t) ? null : t;
238
+ };
239
+ const DAY = 86_400_000;
240
+ function evaluate(node, read) {
241
+ switch (node.type) {
242
+ case 'number':
243
+ return node.value;
244
+ case 'string':
245
+ return node.value;
246
+ case 'field':
247
+ return read(node.name);
248
+ case 'unary': {
249
+ const n = asNumber(evaluate(node.operand, read));
250
+ return n === null ? null : -n;
251
+ }
252
+ case 'binary': {
253
+ const left = evaluate(node.left, read);
254
+ const right = evaluate(node.right, read);
255
+ if (['==', '!='].includes(node.op)) {
256
+ const same = JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
257
+ return node.op === '==' ? same : !same;
258
+ }
259
+ if (node.op === '+' && (typeof left === 'string' || typeof right === 'string'))
260
+ return `${left ?? ''}${right ?? ''}`;
261
+ const a = asNumber(left);
262
+ const b = asNumber(right);
263
+ // A missing value makes the whole expression empty rather than zero: a story with no estimate
264
+ // has no doubled estimate either, and pretending it is 0 would put it top of a sort.
265
+ if (a === null || b === null)
266
+ return null;
267
+ switch (node.op) {
268
+ case '+':
269
+ return a + b;
270
+ case '-':
271
+ return a - b;
272
+ case '*':
273
+ return a * b;
274
+ case '/':
275
+ return b === 0 ? null : a / b;
276
+ case '%':
277
+ return b === 0 ? null : a % b;
278
+ case '<':
279
+ return a < b;
280
+ case '>':
281
+ return a > b;
282
+ case '<=':
283
+ return a <= b;
284
+ case '>=':
285
+ return a >= b;
286
+ default:
287
+ return null;
288
+ }
289
+ }
290
+ case 'call': {
291
+ const args = node.args.map((a) => evaluate(a, read));
292
+ switch (node.name) {
293
+ case 'abs': {
294
+ const n = asNumber(args[0] ?? null);
295
+ return n === null ? null : Math.abs(n);
296
+ }
297
+ case 'round': {
298
+ const n = asNumber(args[0] ?? null);
299
+ if (n === null)
300
+ return null;
301
+ const places = asNumber(args[1] ?? 0) ?? 0;
302
+ const factor = 10 ** Math.max(0, Math.min(6, Math.trunc(places)));
303
+ return Math.round(n * factor) / factor;
304
+ }
305
+ case 'min':
306
+ case 'max': {
307
+ const numbers = args.map(asNumber).filter((n) => n !== null);
308
+ if (!numbers.length)
309
+ return null;
310
+ return node.name === 'min' ? Math.min(...numbers) : Math.max(...numbers);
311
+ }
312
+ case 'coalesce':
313
+ return args.find((a) => a !== null && a !== '') ?? null;
314
+ case 'daysbetween': {
315
+ const from = asDate(args[0] ?? null);
316
+ const to = asDate(args[1] ?? null);
317
+ if (from === null || to === null)
318
+ return null;
319
+ return Math.round((to - from) / DAY);
320
+ }
321
+ case 'if':
322
+ return args[0] ? (args[1] ?? null) : (args[2] ?? null);
323
+ case 'concat':
324
+ return args.map((a) => (a === null ? '' : String(a))).join('');
325
+ case 'length': {
326
+ const value = args[0];
327
+ return value === null || value === undefined ? null : String(value).length;
328
+ }
329
+ default:
330
+ return null;
331
+ }
332
+ }
333
+ }
334
+ }
335
+ /**
336
+ * Run a formula. Returns `null` for anything it cannot compute — a missing value, a division by
337
+ * zero, a date that will not parse — rather than throwing or inventing a zero.
338
+ */
339
+ export function runFormula(source, read) {
340
+ const { ast } = parse(source);
341
+ if (!ast)
342
+ return null;
343
+ try {
344
+ return evaluate(ast, read);
345
+ }
346
+ catch {
347
+ return null;
348
+ }
349
+ }
350
+ //# sourceMappingURL=formula.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formula.js","sourceRoot":"","sources":["../../src/server/formula.ts"],"names":[],"mappings":"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"}
@@ -52,6 +52,17 @@ export declare class ConfigService {
52
52
  }): Promise<FieldDef[]>;
53
53
  /** Fields visible across a set of projects (KQL autocomplete over a multi-project view). */
54
54
  fieldsForProjects(tx: Tx, workspaceId: string, projectIds: string[]): Promise<FieldDef[]>;
55
+ /**
56
+ * Check a field's configuration before it is stored.
57
+ *
58
+ * Two things are compiled here rather than at value-check time, because both are supplied by an
59
+ * administrator and both would otherwise fail on every write to the project instead of on the one
60
+ * save that introduced them: a text `pattern`, and a `formula`.
61
+ *
62
+ * A formula that reaches itself is refused. Since a formula reads only its own issue, a cycle is
63
+ * a closed walk over the fields it names — no graph over rows, just over definitions.
64
+ */
65
+ private assertFieldConfigValid;
55
66
  createField(tx: Tx, workspaceId: string, input: UpsertFieldDef): Promise<FieldDef>;
56
67
  updateField(tx: Tx, workspaceId: string, id: string, patch: Partial<Omit<UpsertFieldDef, 'key' | 'type'>>): Promise<FieldDef>;
57
68
  archiveField(tx: Tx, workspaceId: string, id: string, archived: boolean): Promise<FieldDef>;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/server/services/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/server/services/config.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@ import { KernError, uuidv7 } from '@kernhq/kernel';
2
2
  import { builtinRegistry, createWorkflowFromTemplate, sortedStatuses, validateDefinition, workflowTemplates, } from '@kernhq/workflow';
3
3
  import { and, asc, eq, inArray, isNull, or, sql } from 'drizzle-orm';
4
4
  import { HierarchyRules, ProjectTemplateBody, } from '../../contract/models.js';
5
+ import { formulaReferences, validateFormula } from '../formula.js';
5
6
  import { fieldDefs, hierarchyRules, issues, labels, projects, typeSchemes, views, workflowSchemes, workflows, workItemTypes, } from '../schema.js';
6
7
  import { projectTemplateBody } from '../seeds/templates.js';
7
8
  import { toFieldDef, toTypeScheme, toWorkflow, toWorkflowScheme, toWorkItemType, } from './db.js';
@@ -252,6 +253,57 @@ export class ConfigService {
252
253
  seen.set(f.id, f);
253
254
  return [...seen.values()];
254
255
  }
256
+ /**
257
+ * Check a field's configuration before it is stored.
258
+ *
259
+ * Two things are compiled here rather than at value-check time, because both are supplied by an
260
+ * administrator and both would otherwise fail on every write to the project instead of on the one
261
+ * save that introduced them: a text `pattern`, and a `formula`.
262
+ *
263
+ * A formula that reaches itself is refused. Since a formula reads only its own issue, a cycle is
264
+ * a closed walk over the fields it names — no graph over rows, just over definitions.
265
+ */
266
+ async assertFieldConfigValid(tx, workspaceId, field) {
267
+ const config = field.config ?? {};
268
+ if (config.pattern)
269
+ try {
270
+ new RegExp(config.pattern);
271
+ }
272
+ catch {
273
+ throw KernError.badRequest('That is not a valid pattern', { field: 'config.pattern' });
274
+ }
275
+ if (field.type !== 'formula')
276
+ return;
277
+ const formula = config.formula;
278
+ if (!formula?.trim())
279
+ throw KernError.badRequest('A calculated field needs a formula', { field: 'config.formula' });
280
+ const checked = validateFormula(formula);
281
+ if (!checked.ok)
282
+ throw KernError.badRequest(checked.problems[0]?.message ?? 'That formula cannot be read', {
283
+ field: 'config.formula',
284
+ problems: checked.problems,
285
+ });
286
+ const byKey = new Map((await this.listFields(tx, workspaceId, {})).map((f) => [f.key, f]));
287
+ const seen = new Set();
288
+ const walk = (key, source) => {
289
+ if (seen.has(key))
290
+ return;
291
+ seen.add(key);
292
+ for (const reference of formulaReferences(source)) {
293
+ if (!reference.startsWith('cf.'))
294
+ continue;
295
+ const name = reference.slice(3);
296
+ if (name === field.key)
297
+ throw KernError.badRequest('That formula would end up calculating itself', {
298
+ field: 'config.formula',
299
+ });
300
+ const referenced = byKey.get(name);
301
+ if (referenced?.type === 'formula' && referenced.config.formula)
302
+ walk(name, referenced.config.formula);
303
+ }
304
+ };
305
+ walk(field.key, formula);
306
+ }
255
307
  async createField(tx, workspaceId, input) {
256
308
  const [clash] = await tx
257
309
  .select({ id: fieldDefs.id })
@@ -264,6 +316,7 @@ export class ConfigService {
264
316
  .limit(1);
265
317
  if (clash)
266
318
  throw KernError.conflict(`Field key "${input.key}" is already used`, 'tracker.field.key_taken');
319
+ await this.assertFieldConfigValid(tx, workspaceId, input);
267
320
  const [row] = await tx
268
321
  .insert(fieldDefs)
269
322
  .values({
@@ -287,6 +340,22 @@ export class ConfigService {
287
340
  return toFieldDef(row);
288
341
  }
289
342
  async updateField(tx, workspaceId, id, patch) {
343
+ // The same checks as on create: an edit is the other way a bad pattern or a self-referring
344
+ // formula gets in, and it would then fail on every write to the project rather than here.
345
+ if (patch.config) {
346
+ const [existing] = await tx
347
+ .select({ key: fieldDefs.key, type: fieldDefs.type })
348
+ .from(fieldDefs)
349
+ .where(and(eq(fieldDefs.workspaceId, workspaceId), eq(fieldDefs.id, id)))
350
+ .limit(1);
351
+ if (!existing)
352
+ throw KernError.notFound('Field');
353
+ await this.assertFieldConfigValid(tx, workspaceId, {
354
+ key: existing.key,
355
+ type: existing.type,
356
+ config: patch.config,
357
+ });
358
+ }
290
359
  const [row] = await tx
291
360
  .update(fieldDefs)
292
361
  .set({