blixify-ui-web 1.2.181 → 1.2.183

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.
Files changed (39) hide show
  1. package/lib/components/data/dataTemplate/activityChanges.d.ts.map +1 -1
  2. package/lib/components/data/dataTemplate/activityChanges.js +1 -0
  3. package/lib/components/data/dataTemplate/activityChanges.js.map +1 -1
  4. package/lib/components/data/dataTemplate/index.d.ts +1 -0
  5. package/lib/components/data/dataTemplate/index.d.ts.map +1 -1
  6. package/lib/components/data/dataTemplate/index.js +664 -419
  7. package/lib/components/data/dataTemplate/index.js.map +1 -1
  8. package/lib/components/data/dataTemplate/model.d.ts +11 -2
  9. package/lib/components/data/dataTemplate/model.d.ts.map +1 -1
  10. package/lib/components/data/flexFilter/index.d.ts.map +1 -1
  11. package/lib/components/data/flexFilter/index.js +41 -14
  12. package/lib/components/data/flexFilter/index.js.map +1 -1
  13. package/lib/components/data/formula/builder.d.ts +19 -0
  14. package/lib/components/data/formula/builder.d.ts.map +1 -0
  15. package/lib/components/data/formula/builder.js +189 -0
  16. package/lib/components/data/formula/builder.js.map +1 -0
  17. package/lib/components/data/formula/functions.d.ts +22 -0
  18. package/lib/components/data/formula/functions.d.ts.map +1 -0
  19. package/lib/components/data/formula/functions.js +773 -0
  20. package/lib/components/data/formula/functions.js.map +1 -0
  21. package/lib/components/data/formula/index.d.ts +75 -0
  22. package/lib/components/data/formula/index.d.ts.map +1 -0
  23. package/lib/components/data/formula/index.js +801 -0
  24. package/lib/components/data/formula/index.js.map +1 -0
  25. package/lib/components/data/listModule.d.ts.map +1 -1
  26. package/lib/components/data/listModule.js +7 -1
  27. package/lib/components/data/listModule.js.map +1 -1
  28. package/lib/components/data/readModule.d.ts.map +1 -1
  29. package/lib/components/data/readModule.js +25 -2
  30. package/lib/components/data/readModule.js.map +1 -1
  31. package/lib/components/data/utils.d.ts.map +1 -1
  32. package/lib/components/data/utils.js +4 -0
  33. package/lib/components/data/utils.js.map +1 -1
  34. package/lib/components/display/newTable/index.d.ts +1 -0
  35. package/lib/components/display/newTable/index.d.ts.map +1 -1
  36. package/lib/components/display/newTable/index.js +85 -30
  37. package/lib/components/display/newTable/index.js.map +1 -1
  38. package/lib/tail.css +2 -2
  39. package/package.json +1 -1
@@ -0,0 +1,801 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.handleMatchFormulaQuery = exports.handleCompareFormulaResults = exports.handleIsFormulaEmpty = exports.handleFormatFormulaValue = exports.handleEvaluateFormulaRow = exports.handleEvaluateFormula = exports.handleValidateFormula = exports.handleCompileFormula = exports.handleFormulaToStorage = exports.handleGetFormulaDisplay = exports.handleFormulaToDisplay = exports.handleGetFormulaColumns = exports.handleFindFormulaColumn = exports.handleFormulaEquals = exports.FORMULA_MAX_LENGTH = exports.FORMULA_INCOMPATIBLE_TYPES = void 0;
18
+ var expr_eval_1 = require("expr-eval");
19
+ var functions_1 = require("./functions");
20
+ __exportStar(require("./functions"), exports);
21
+ // INFO: column types a formula can read — monday leaves files, links and
22
+ // locations out of formulas, and so do we
23
+ exports.FORMULA_INCOMPATIBLE_TYPES = [
24
+ "password",
25
+ "image",
26
+ "file",
27
+ "multipleImage",
28
+ "multipleFile",
29
+ "signature",
30
+ "canvas",
31
+ "object",
32
+ "listObject",
33
+ "address",
34
+ "listAddress",
35
+ "ganttchart",
36
+ ];
37
+ var LABEL_TYPES = [
38
+ "reference",
39
+ "listReference",
40
+ "referenceSelection",
41
+ "person",
42
+ "listPerson",
43
+ "roles",
44
+ ];
45
+ var FUNCTION_NAMES = new Set(functions_1.FORMULA_FUNCTIONS.filter(function (each) { return !each.constant; }).map(function (each) { return each.name; }));
46
+ var CONSTANT_NAMES = new Set(Object.keys(functions_1.FORMULA_CONSTANTS));
47
+ // INFO: null-prototype tables throughout — expr-eval resolves names with
48
+ // `in`, so a plain object would answer for constructor, toString and the rest
49
+ // of Object.prototype
50
+ var handleOwnOnly = function (source, keys) {
51
+ var table = Object.create(null);
52
+ (keys !== null && keys !== void 0 ? keys : Object.keys(source)).forEach(function (each) {
53
+ if (Object.prototype.hasOwnProperty.call(source, each))
54
+ table[each] = source[each];
55
+ });
56
+ return table;
57
+ };
58
+ var HARDENED_OPTIONS = {
59
+ allowMemberAccess: false,
60
+ operators: handleOwnOnly({
61
+ assignment: false,
62
+ fndef: false,
63
+ array: false,
64
+ in: false,
65
+ }),
66
+ };
67
+ // INFO: the operators a translated formula can contain — everything else the
68
+ // stock parser knows (sqrt, not, length, in, =, [ …) is not there to reach
69
+ var FORMULA_UNARY_OPS = ["-", "+"];
70
+ var FORMULA_BINARY_OPS = [
71
+ "+",
72
+ "-",
73
+ "*",
74
+ "/",
75
+ "%",
76
+ "^",
77
+ "||",
78
+ "==",
79
+ "!=",
80
+ ">",
81
+ "<",
82
+ ">=",
83
+ "<=",
84
+ ];
85
+ // INFO: the longest formula a column can hold — monday's own formula limit
86
+ exports.FORMULA_MAX_LENGTH = 10000;
87
+ // INFO: text a formula can build stops at FORMULA_MAX_TEXT. Every text function
88
+ // stops at it and so does every result, so no formula (or chain of formula
89
+ // columns) can hand every row an unbounded string.
90
+ var handleClampText = function (value) {
91
+ return typeof value === "string" && value.length > functions_1.FORMULA_MAX_TEXT
92
+ ? value.slice(0, functions_1.FORMULA_MAX_TEXT)
93
+ : value;
94
+ };
95
+ var handleCreateParser = function () {
96
+ var _a;
97
+ var parser = new expr_eval_1.Parser(HARDENED_OPTIONS);
98
+ var functions = Object.create(null);
99
+ functions_1.FORMULA_FUNCTIONS.forEach(function (each) {
100
+ var fn = each.fn;
101
+ if (fn)
102
+ functions[each.name] = function () {
103
+ var args = [];
104
+ for (var _i = 0; _i < arguments.length; _i++) {
105
+ args[_i] = arguments[_i];
106
+ }
107
+ return handleClampText(fn.apply(void 0, args));
108
+ };
109
+ });
110
+ parser.functions = functions;
111
+ parser.unaryOps = handleOwnOnly(parser.unaryOps, FORMULA_UNARY_OPS);
112
+ parser.binaryOps = handleOwnOnly(parser.binaryOps, FORMULA_BINARY_OPS);
113
+ parser.ternaryOps = handleOwnOnly((_a = parser.ternaryOps) !== null && _a !== void 0 ? _a : {}, ["?"]);
114
+ parser.consts = Object.assign(Object.create(null), functions_1.FORMULA_CONSTANTS, {
115
+ true: true,
116
+ false: false,
117
+ });
118
+ return parser;
119
+ };
120
+ var formulaParser = handleCreateParser();
121
+ // INFO: a math column a formula reads is worked out exactly as the math column
122
+ // itself is in the table (listModule): the stock parser over the raw fields,
123
+ // 0 for an absent one. Same parser, same values — nothing new is exposed.
124
+ var mathParser = new expr_eval_1.Parser();
125
+ // INFO: monday's = compares a number column with "5" or an empty cell with 0
126
+ // as equal values, where expr-eval's == is ===. Numbers compare as numbers,
127
+ // anything else as text (case-sensitive, as monday documents).
128
+ var handleIsNumberLike = function (value) {
129
+ return typeof value === "number" ||
130
+ typeof value === "boolean" ||
131
+ (typeof value === "string" &&
132
+ value.trim() !== "" &&
133
+ Number.isFinite(Number(value)));
134
+ };
135
+ var handleIsEmptyValue = function (value) {
136
+ return value === "" || value === null || value === undefined;
137
+ };
138
+ var handleFormulaEquals = function (a, b) {
139
+ if (a === b)
140
+ return true;
141
+ if (handleIsEmptyValue(a) && handleIsEmptyValue(b))
142
+ return true;
143
+ var aNumeric = typeof a === "number" || typeof a === "boolean";
144
+ var bNumeric = typeof b === "number" || typeof b === "boolean";
145
+ // INFO: against a number, an empty cell is 0 and a numeric text is its number
146
+ if ((aNumeric && (handleIsNumberLike(b) || handleIsEmptyValue(b))) ||
147
+ (bNumeric && (handleIsNumberLike(a) || handleIsEmptyValue(a))) ||
148
+ (handleIsNumberLike(a) && handleIsNumberLike(b)))
149
+ return (Number(handleIsEmptyValue(a) ? 0 : a) ===
150
+ Number(handleIsEmptyValue(b) ? 0 : b));
151
+ return (0, functions_1.handleToFormulaText)(a) === (0, functions_1.handleToFormulaText)(b);
152
+ };
153
+ exports.handleFormulaEquals = handleFormulaEquals;
154
+ formulaParser.binaryOps["=="] = exports.handleFormulaEquals;
155
+ formulaParser.binaryOps["!="] = function (a, b) {
156
+ return !(0, exports.handleFormulaEquals)(a, b);
157
+ };
158
+ //=====================================================================================
159
+ //SECTION: Column references
160
+ //=====================================================================================
161
+ var handleFindFormulaColumn = function (reference, schema) {
162
+ var _a, _b, _c;
163
+ var target = reference.trim();
164
+ var lowered = target.toLowerCase();
165
+ return ((_c = (_b = (_a = schema.find(function (each) { return each.id === target; })) !== null && _a !== void 0 ? _a : schema.find(function (each) { return each.name === target; })) !== null && _b !== void 0 ? _b : schema.find(function (each) { var _a; return ((_a = each.name) !== null && _a !== void 0 ? _a : "").toLowerCase() === lowered; })) !== null && _c !== void 0 ? _c : schema.find(function (each) { return each.id.toLowerCase() === lowered; }));
166
+ };
167
+ exports.handleFindFormulaColumn = handleFindFormulaColumn;
168
+ // INFO: columns the builder offers — everything a formula can read except the
169
+ // column being edited, which would only ever reference itself
170
+ var handleGetFormulaColumns = function (schema, excludeId) {
171
+ return schema.filter(function (each) {
172
+ return each.id !== excludeId &&
173
+ each.id !== "_id" &&
174
+ !exports.FORMULA_INCOMPATIBLE_TYPES.includes(each.type);
175
+ });
176
+ };
177
+ exports.handleGetFormulaColumns = handleGetFormulaColumns;
178
+ var QUOTES = {
179
+ '"': '"',
180
+ "'": "'",
181
+ "\u201C": "\u201D",
182
+ "\u2018": "\u2019",
183
+ };
184
+ // INFO: walks a formula once, handing string literals and {references} to
185
+ // callbacks and copying everything else — every rewrite below shares it, so
186
+ // none of them can touch the inside of a string by accident
187
+ var handleWalkFormula = function (source, handlers) {
188
+ var output = "";
189
+ var text = "";
190
+ var index = 0;
191
+ var handleFlushText = function () {
192
+ if (text)
193
+ output += handlers.onText(text, index - text.length);
194
+ text = "";
195
+ };
196
+ while (index < source.length) {
197
+ var char = source[index];
198
+ if (QUOTES[char]) {
199
+ handleFlushText();
200
+ var closers = [QUOTES[char], char === "\u201C" ? '"' : char];
201
+ var end = index + 1;
202
+ while (end < source.length && !closers.includes(source[end]))
203
+ end += 1;
204
+ if (end >= source.length)
205
+ throw new Error("Missing a closing quote");
206
+ output += handlers.onString(source.slice(index + 1, end), char);
207
+ index = end + 1;
208
+ continue;
209
+ }
210
+ if (char === "{") {
211
+ handleFlushText();
212
+ var end = source.indexOf("}", index);
213
+ if (end < 0)
214
+ throw new Error("Missing a closing }");
215
+ output += handlers.onReference(source.slice(index + 1, end));
216
+ index = end + 1;
217
+ continue;
218
+ }
219
+ text += char;
220
+ index += 1;
221
+ }
222
+ handleFlushText();
223
+ return output;
224
+ };
225
+ var handleRewriteBraces = function (expression, handleMap) {
226
+ try {
227
+ return handleWalkFormula(expression, {
228
+ onString: function (content, quote) { var _a; return quote + content + ((_a = QUOTES[quote]) !== null && _a !== void 0 ? _a : quote); },
229
+ onReference: function (reference) { return "{".concat(handleMap(reference), "}"); },
230
+ onText: function (text) { return text; },
231
+ });
232
+ }
233
+ catch (err) {
234
+ return expression;
235
+ }
236
+ };
237
+ /**
238
+ * Stored → shown: `{budgetAmount}` becomes `{Budget}`.
239
+ */
240
+ var handleFormulaToDisplay = function (expression, schema) {
241
+ if (!expression)
242
+ return "";
243
+ return handleRewriteBraces(expression, function (reference) {
244
+ var _a;
245
+ var column = schema.find(function (each) { return each.id === reference.trim(); });
246
+ if (!column)
247
+ return reference;
248
+ // INFO: a name is shown only when saving it finds this same column again.
249
+ // A name shared with another column, or equal to another column's id,
250
+ // would be saved as that other column — it is shown by id instead.
251
+ var name = (_a = column.name) === null || _a === void 0 ? void 0 : _a.trim();
252
+ if (name && (0, exports.handleFindFormulaColumn)(name, schema) === column)
253
+ return name;
254
+ return column.id;
255
+ });
256
+ };
257
+ exports.handleFormulaToDisplay = handleFormulaToDisplay;
258
+ // INFO: what the builder opens with for an existing formula column
259
+ var handleGetFormulaDisplay = function (column, schema) { return (0, exports.handleFormulaToDisplay)(column === null || column === void 0 ? void 0 : column.formulaExpression, schema); };
260
+ exports.handleGetFormulaDisplay = handleGetFormulaDisplay;
261
+ /**
262
+ * Shown → stored: `{Budget}` becomes `{budgetAmount}`, so renaming a column
263
+ * never breaks the formulas that read it. Unknown names are kept for the
264
+ * validator to report.
265
+ */
266
+ var handleFormulaToStorage = function (expression, schema) {
267
+ return handleRewriteBraces(expression, function (reference) {
268
+ var column = (0, exports.handleFindFormulaColumn)(reference, schema);
269
+ return column ? column.id : reference;
270
+ });
271
+ };
272
+ exports.handleFormulaToStorage = handleFormulaToStorage;
273
+ //=====================================================================================
274
+ //SECTION: Compile
275
+ //=====================================================================================
276
+ var handleTranslateFormula = function (expression, schema) {
277
+ var variables = Object.create(null);
278
+ var literals = Object.create(null);
279
+ var columnVariables = Object.create(null);
280
+ var source = handleWalkFormula(expression, {
281
+ // INFO: text is handed to the parser as a variable, never as a quoted
282
+ // literal — expr-eval's own string rules (backslash escapes) can then
283
+ // never disagree with the scanner about where a string ends, so no part of
284
+ // a string can be read as code
285
+ onString: function (content) {
286
+ var variable = "__s".concat(Object.keys(literals).length);
287
+ literals[variable] = content;
288
+ return " ".concat(variable, " ");
289
+ },
290
+ onReference: function (reference) {
291
+ var column = (0, exports.handleFindFormulaColumn)(reference, schema);
292
+ if (!column)
293
+ throw new Error("Unknown column {".concat(reference.trim(), "}"));
294
+ if (exports.FORMULA_INCOMPATIBLE_TYPES.includes(column.type))
295
+ throw new Error("{".concat(column.name, "} cannot be used in a formula"));
296
+ var variable = columnVariables[column.id];
297
+ if (!variable) {
298
+ variable = "__c".concat(Object.keys(variables).length);
299
+ columnVariables[column.id] = variable;
300
+ variables[variable] = column.id;
301
+ }
302
+ return " ".concat(variable, " ");
303
+ },
304
+ onText: function (text) {
305
+ var _a;
306
+ var output = "";
307
+ var index = 0;
308
+ while (index < text.length) {
309
+ var char = text[index];
310
+ var next = text[index + 1];
311
+ if (char === "}")
312
+ throw new Error("Unexpected }");
313
+ if (char === "[" || char === "]" || char === ";")
314
+ throw new Error("\"".concat(char, "\" is not supported in a formula"));
315
+ if (char === "<" && next === ">") {
316
+ output += "!=";
317
+ index += 2;
318
+ continue;
319
+ }
320
+ if (char === "=") {
321
+ if (next === "=") {
322
+ output += "==";
323
+ index += 2;
324
+ continue;
325
+ }
326
+ // INFO: monday's = compares; <=, >= and != keep their own =
327
+ var previous = text[index - 1];
328
+ output +=
329
+ previous === "<" || previous === ">" || previous === "!"
330
+ ? "="
331
+ : "==";
332
+ index += 1;
333
+ continue;
334
+ }
335
+ if (char === "&") {
336
+ output += " || ";
337
+ index += 1;
338
+ continue;
339
+ }
340
+ var numberMatch = /^(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?/.exec(text.slice(index));
341
+ if (numberMatch && !/[A-Za-z0-9_]/.test((_a = text[index - 1]) !== null && _a !== void 0 ? _a : "")) {
342
+ output += numberMatch[0];
343
+ index += numberMatch[0].length;
344
+ continue;
345
+ }
346
+ var wordMatch = /^[A-Za-z_][A-Za-z0-9_]*/.exec(text.slice(index));
347
+ if (wordMatch) {
348
+ var word = wordMatch[0];
349
+ var upper = word.toUpperCase();
350
+ index += word.length;
351
+ if (CONSTANT_NAMES.has(upper)) {
352
+ output += upper;
353
+ // INFO: monday writes PI() and TRUE alike — a constant called
354
+ // with no arguments is the constant
355
+ var call = /^\s*\(\s*\)/.exec(text.slice(index));
356
+ if (call)
357
+ index += call[0].length;
358
+ }
359
+ else if (FUNCTION_NAMES.has(upper)) {
360
+ output += upper;
361
+ }
362
+ else {
363
+ throw new Error("Unknown name \"".concat(word, "\" \u2014 wrap column names in { }"));
364
+ }
365
+ continue;
366
+ }
367
+ output += char;
368
+ index += 1;
369
+ }
370
+ return output;
371
+ },
372
+ });
373
+ return { source: source, variables: variables, literals: literals };
374
+ };
375
+ // INFO: operators that bind looser than & in monday/Excel — comparisons and
376
+ // the ternary. & itself sits just above them, below + and -.
377
+ var LOOSER_THAN_CONCAT = ["==", "!=", "<=", ">=", "<", ">", "?", ":"];
378
+ var handleTokenizeTranslated = function (source) {
379
+ var tokens = [];
380
+ var index = 0;
381
+ var text = "";
382
+ var handleFlush = function () {
383
+ if (text)
384
+ tokens.push({ kind: "text", value: text });
385
+ text = "";
386
+ };
387
+ while (index < source.length) {
388
+ var char = source[index];
389
+ var pair = source.slice(index, index + 2);
390
+ if (["||", "==", "!=", "<=", ">="].includes(pair)) {
391
+ handleFlush();
392
+ tokens.push({ kind: "op", value: pair });
393
+ index += 2;
394
+ continue;
395
+ }
396
+ if (["<", ">", "?", ":"].includes(char)) {
397
+ handleFlush();
398
+ tokens.push({ kind: "op", value: char });
399
+ index += 1;
400
+ continue;
401
+ }
402
+ if (char === "(" || char === ")" || char === ",") {
403
+ handleFlush();
404
+ tokens.push({
405
+ kind: char === "(" ? "open" : char === ")" ? "close" : "comma",
406
+ value: char,
407
+ });
408
+ index += 1;
409
+ continue;
410
+ }
411
+ text += char;
412
+ index += 1;
413
+ }
414
+ handleFlush();
415
+ return tokens;
416
+ };
417
+ var handleNestTokens = function (tokens) {
418
+ var root = [];
419
+ var stack = [root];
420
+ tokens.forEach(function (each) {
421
+ var current = stack[stack.length - 1];
422
+ if (each.kind === "open") {
423
+ var group = { kind: "group", items: [] };
424
+ current.push(group);
425
+ stack.push(group.items);
426
+ }
427
+ else if (each.kind === "close") {
428
+ // INFO: an unmatched ) is left for the parser to report
429
+ if (stack.length > 1)
430
+ stack.pop();
431
+ else
432
+ current.push(each);
433
+ }
434
+ else
435
+ current.push(each);
436
+ });
437
+ return root;
438
+ };
439
+ var handleRenderConcatNodes = function (nodes) {
440
+ var handleRenderNode = function (node) {
441
+ return node.kind === "group"
442
+ ? "(".concat(handleRenderConcatNodes(node.items), ")")
443
+ : node.value;
444
+ };
445
+ var handleRenderOperand = function (operand) {
446
+ var parts = [[]];
447
+ operand.forEach(function (each) {
448
+ if (each.kind === "op" && each.value === "||")
449
+ parts.push([]);
450
+ else
451
+ parts[parts.length - 1].push(each);
452
+ });
453
+ var rendered = parts.map(function (each) { return each.map(handleRenderNode).join(""); });
454
+ return parts.length > 1
455
+ ? " CONCATENATE(".concat(rendered.map(function (each) { return "(".concat(each, ")"); }).join(", "), ") ")
456
+ : rendered[0];
457
+ };
458
+ // INFO: split on commas, then on operators looser than &, so each & chain
459
+ // is gathered whole and nothing that binds tighter is left outside it
460
+ var segments = [[]];
461
+ var separators = [];
462
+ nodes.forEach(function (each) {
463
+ if (each.kind === "comma" ||
464
+ (each.kind === "op" && LOOSER_THAN_CONCAT.includes(each.value))) {
465
+ separators.push(each.value);
466
+ segments.push([]);
467
+ }
468
+ else
469
+ segments[segments.length - 1].push(each);
470
+ });
471
+ return segments
472
+ .map(function (each, index) {
473
+ return handleRenderOperand(each) +
474
+ (index < separators.length ? " ".concat(separators[index], " ") : "");
475
+ })
476
+ .join("");
477
+ };
478
+ /**
479
+ * INFO: `&` binds looser than + and - in monday, but expr-eval reads its
480
+ * stand-in `||` at the level of + and -, so `"Total: " & {a} + 1` would
481
+ * become NaN. Each & chain is rewritten into one CONCATENATE call, which gives
482
+ * it monday's precedence: below arithmetic, above comparisons.
483
+ */
484
+ var handleLowerConcatenation = function (source) {
485
+ if (!handleTokenizeTranslated(source).some(function (each) { return each.value === "||"; }))
486
+ return source;
487
+ return handleRenderConcatNodes(handleNestTokens(handleTokenizeTranslated(source)));
488
+ };
489
+ var handleCheckSymbols = function (expression, allowed) {
490
+ var blocked = expression
491
+ .symbols()
492
+ .find(function (eachSymbol) { return !allowed(eachSymbol); });
493
+ if (blocked)
494
+ throw new Error("\"".concat(blocked, "\" is not allowed in a formula"));
495
+ };
496
+ var compileCache = new Map();
497
+ var handleCompileFormula = function (expression, schema) {
498
+ if (!expression || !expression.trim())
499
+ return { variables: {}, error: "The formula is empty" };
500
+ if (expression.length > exports.FORMULA_MAX_LENGTH)
501
+ return {
502
+ variables: {},
503
+ error: "A formula can be up to ".concat(exports.FORMULA_MAX_LENGTH, " characters"),
504
+ };
505
+ var cacheKey = "".concat(expression, "\0").concat(schema
506
+ .map(function (each) { return "".concat(each.id, "\u0001").concat(each.name, "\u0001").concat(each.type); })
507
+ .join("\u0002"));
508
+ var cached = compileCache.get(cacheKey);
509
+ if (cached)
510
+ return cached;
511
+ var compiled;
512
+ try {
513
+ var _a = handleTranslateFormula(expression, schema), source = _a.source, variables_1 = _a.variables, literals_1 = _a.literals;
514
+ var parsed = formulaParser.parse(handleLowerConcatenation(source));
515
+ var handleIsOwn_1 = function (table, key) {
516
+ return Object.prototype.hasOwnProperty.call(table, key);
517
+ };
518
+ handleCheckSymbols(parsed, function (symbol) {
519
+ return FUNCTION_NAMES.has(symbol) ||
520
+ handleIsOwn_1(variables_1, symbol) ||
521
+ handleIsOwn_1(literals_1, symbol);
522
+ });
523
+ compiled = { expression: parsed, variables: variables_1, literals: literals_1 };
524
+ }
525
+ catch (err) {
526
+ compiled = { variables: {}, error: handleCleanParseError(err === null || err === void 0 ? void 0 : err.message) };
527
+ }
528
+ if (compileCache.size > 500)
529
+ compileCache.clear();
530
+ compileCache.set(cacheKey, compiled);
531
+ return compiled;
532
+ };
533
+ exports.handleCompileFormula = handleCompileFormula;
534
+ // INFO: expr-eval reports positions in the translated source, which the user
535
+ // never sees — keep the reason, drop the position
536
+ var handleCleanParseError = function (message) {
537
+ if (!message)
538
+ return "Illegal formula";
539
+ return message.replace(/\s*\[?\s*at position \d+\s*\]?/gi, "").trim();
540
+ };
541
+ var handleValidateFormula = function (expression, schema) { var _a; return (_a = (0, exports.handleCompileFormula)(expression, schema).error) !== null && _a !== void 0 ? _a : ""; };
542
+ exports.handleValidateFormula = handleValidateFormula;
543
+ //=====================================================================================
544
+ //SECTION: Evaluate
545
+ //=====================================================================================
546
+ var handleIsPrimitive = function (value) {
547
+ return typeof value === "string" ||
548
+ typeof value === "number" ||
549
+ typeof value === "boolean";
550
+ };
551
+ var handleResolveDate = function (value, column) {
552
+ if (value === "" || value === null || value === undefined)
553
+ return "";
554
+ var source = typeof value === "object" && !(value instanceof Date) && (value === null || value === void 0 ? void 0 : value._seconds)
555
+ ? new Date(value._seconds * 1000)
556
+ : value;
557
+ var parsed = (0, functions_1.handleToFormulaDate)(source);
558
+ if (!parsed)
559
+ return "";
560
+ if (column.hideShowDate)
561
+ return parsed.format("HH:mm");
562
+ if (column.hideShowTime)
563
+ return parsed.format("YYYY-MM-DD");
564
+ return (0, functions_1.handleFormatFormulaDate)(parsed);
565
+ };
566
+ var handleResolveListValue = function (value) {
567
+ if (Array.isArray(value))
568
+ return value
569
+ .map(function (each) {
570
+ var _a, _b;
571
+ return handleIsPrimitive(each)
572
+ ? String(each)
573
+ : ((_b = (_a = each === null || each === void 0 ? void 0 : each.label) !== null && _a !== void 0 ? _a : each === null || each === void 0 ? void 0 : each.name) !== null && _b !== void 0 ? _b : "");
574
+ })
575
+ .filter(Boolean)
576
+ .join(", ");
577
+ return handleIsPrimitive(value) ? value : "";
578
+ };
579
+ // INFO: the math column's own evaluation, as listModule runs it, returned as
580
+ // a number for the formula reading it
581
+ var handleEvaluateMathColumn = function (column, rawRow) {
582
+ var _a;
583
+ try {
584
+ var expr = mathParser.parse((_a = column.mathExpression) !== null && _a !== void 0 ? _a : "");
585
+ var variableKeys_1 = {};
586
+ expr.variables().forEach(function (eachVariable) {
587
+ var _a;
588
+ variableKeys_1[eachVariable] = (_a = rawRow === null || rawRow === void 0 ? void 0 : rawRow[eachVariable]) !== null && _a !== void 0 ? _a : 0;
589
+ });
590
+ return Number(expr.evaluate(variableKeys_1));
591
+ }
592
+ catch (err) {
593
+ throw new Error("{".concat(column.name || column.id, "} has an error"));
594
+ }
595
+ };
596
+ var handleResolveColumnValue = function (column, rawRow, displayRow, schema, memo, visiting) {
597
+ if (column.type === "math")
598
+ return handleEvaluateMathColumn(column, rawRow);
599
+ if (column.type === "formula") {
600
+ var nested = handleEvaluateColumn(column, rawRow, displayRow, schema, memo, visiting);
601
+ if (nested.error)
602
+ throw new Error(nested.error);
603
+ return nested.value;
604
+ }
605
+ var raw = rawRow === null || rawRow === void 0 ? void 0 : rawRow[column.id];
606
+ switch (column.type) {
607
+ case "number": {
608
+ if (raw === "" || raw === null || raw === undefined)
609
+ return "";
610
+ var numberValue = Number(raw);
611
+ return Number.isFinite(numberValue) ? numberValue : "";
612
+ }
613
+ case "boolean":
614
+ return raw === true || raw === "true";
615
+ case "date":
616
+ return handleResolveDate(raw, column);
617
+ case "multipleList":
618
+ return handleResolveListValue(raw);
619
+ default:
620
+ break;
621
+ }
622
+ // INFO: a reference or person stores an id; the label the table already
623
+ // resolved is what a formula should compare against, as monday reads labels
624
+ if (LABEL_TYPES.includes(column.type)) {
625
+ var shown = displayRow === null || displayRow === void 0 ? void 0 : displayRow[column.id];
626
+ if (handleIsPrimitive(shown))
627
+ return shown === " - " ? "" : shown;
628
+ // INFO: a reference list is shown as an array of labels, " - " standing
629
+ // in for none — the labels are joined, never the stored ids
630
+ if (Array.isArray(shown))
631
+ return handleResolveListValue(shown.filter(function (each) { return each !== " - " && handleIsPrimitive(each); }));
632
+ return handleResolveListValue(raw);
633
+ }
634
+ if (raw === null || raw === undefined)
635
+ return "";
636
+ return handleIsPrimitive(raw) ? raw : "";
637
+ };
638
+ var handleEvaluateColumn = function (column, rawRow, displayRow, schema, memo, visiting) {
639
+ var _a;
640
+ var memoised = memo.get(column.id);
641
+ if (memoised)
642
+ return memoised;
643
+ if (visiting.has(column.id))
644
+ return { value: "", error: "Circular reference" };
645
+ var compiled = (0, exports.handleCompileFormula)(column.formulaExpression, schema);
646
+ if (compiled.error || !compiled.expression) {
647
+ var result_1 = { value: "", error: compiled.error };
648
+ memo.set(column.id, result_1);
649
+ return result_1;
650
+ }
651
+ visiting.add(column.id);
652
+ var result;
653
+ try {
654
+ var values_1 = Object.create(null);
655
+ Object.entries((_a = compiled.literals) !== null && _a !== void 0 ? _a : {}).forEach(function (_a) {
656
+ var variable = _a[0], text = _a[1];
657
+ values_1[variable] = text;
658
+ });
659
+ Object.entries(compiled.variables).forEach(function (_a) {
660
+ var variable = _a[0], columnId = _a[1];
661
+ var referenced = schema.find(function (each) { return each.id === columnId; });
662
+ values_1[variable] = referenced
663
+ ? handleResolveColumnValue(referenced, rawRow, displayRow, schema, memo, visiting)
664
+ : "";
665
+ });
666
+ result = { value: handleClampText(compiled.expression.evaluate(values_1)) };
667
+ if (typeof result.value === "function" || typeof result.value === "object")
668
+ result = { value: "", error: "Illegal formula" };
669
+ }
670
+ catch (err) {
671
+ result = { value: "", error: handleCleanParseError(err === null || err === void 0 ? void 0 : err.message) };
672
+ }
673
+ visiting.delete(column.id);
674
+ memo.set(column.id, result);
675
+ return result;
676
+ };
677
+ /**
678
+ * Evaluates one formula column for a row. `rawRow` is the stored document;
679
+ * `displayRow` is the same row as the table shows it, where reference and
680
+ * person labels are already resolved.
681
+ */
682
+ var handleEvaluateFormula = function (column, rawRow, displayRow, schema) {
683
+ return handleEvaluateColumn(column, rawRow, displayRow, schema, new Map(), new Set());
684
+ };
685
+ exports.handleEvaluateFormula = handleEvaluateFormula;
686
+ // INFO: every formula column of a row, sharing one memo so a formula read by
687
+ // several others is worked out once
688
+ var handleEvaluateFormulaRow = function (rawRow, displayRow, schema) {
689
+ var memo = new Map();
690
+ var results = {};
691
+ schema.forEach(function (each) {
692
+ if (each.type !== "formula")
693
+ return;
694
+ results[each.id] = handleEvaluateColumn(each, rawRow, displayRow, schema, memo, new Set());
695
+ });
696
+ return results;
697
+ };
698
+ exports.handleEvaluateFormulaRow = handleEvaluateFormulaRow;
699
+ var handleFormatFormulaValue = function (result) {
700
+ if (result.error)
701
+ return "Error";
702
+ var value = result.value;
703
+ if (value === null || value === undefined)
704
+ return "";
705
+ if (typeof value === "number") {
706
+ if (Number.isNaN(value))
707
+ return "NaN";
708
+ if (!Number.isFinite(value))
709
+ return value > 0 ? "∞" : "-∞";
710
+ // INFO: shown as computed, to ten places — ROUND and TEXT are how a
711
+ // formula asks for fewer, and a fixed two would undo ROUND({a}, 4)
712
+ return value.toLocaleString("en-US", {
713
+ maximumFractionDigits: 10,
714
+ useGrouping: false,
715
+ });
716
+ }
717
+ if (typeof value === "boolean")
718
+ return value ? "true" : "false";
719
+ return (0, functions_1.handleToFormulaText)(value);
720
+ };
721
+ exports.handleFormatFormulaValue = handleFormatFormulaValue;
722
+ //=====================================================================================
723
+ //SECTION: Sort & filter — monday sorts and filters a formula column on its
724
+ // computed value, so these run on the evaluated rows
725
+ //=====================================================================================
726
+ var handleIsFormulaEmpty = function (result) {
727
+ return !result ||
728
+ !!result.error ||
729
+ result.value === "" ||
730
+ result.value === null ||
731
+ result.value === undefined ||
732
+ (typeof result.value === "number" && Number.isNaN(result.value));
733
+ };
734
+ exports.handleIsFormulaEmpty = handleIsFormulaEmpty;
735
+ var handleAsNumber = function (value) {
736
+ if (typeof value === "number")
737
+ return value;
738
+ if (typeof value === "boolean")
739
+ return value ? 1 : 0;
740
+ if (typeof value === "string" && value.trim() !== "") {
741
+ var numberValue = Number(value);
742
+ if (Number.isFinite(numberValue))
743
+ return numberValue;
744
+ }
745
+ return undefined;
746
+ };
747
+ var handleSortValue = function (result) { return result.value; };
748
+ // INFO: empty and errored cells are kept for the caller to place last
749
+ var handleCompareFormulaResults = function (a, b) {
750
+ var aValue = handleSortValue(a);
751
+ var bValue = handleSortValue(b);
752
+ var aNumber = handleAsNumber(aValue);
753
+ var bNumber = handleAsNumber(bValue);
754
+ if (aNumber !== undefined && bNumber !== undefined)
755
+ return aNumber - bNumber;
756
+ return (0, functions_1.handleToFormulaText)(aValue).localeCompare((0, functions_1.handleToFormulaText)(bValue), undefined, { numeric: true, sensitivity: "base" });
757
+ };
758
+ exports.handleCompareFormulaResults = handleCompareFormulaResults;
759
+ var handleCompareToFilter = function (result, filterValue) {
760
+ var value = handleSortValue(result);
761
+ var valueNumber = handleAsNumber(value);
762
+ var filterNumber = handleAsNumber(filterValue);
763
+ if (valueNumber !== undefined && filterNumber !== undefined)
764
+ return valueNumber - filterNumber;
765
+ return (0, functions_1.handleToFormulaText)(value).localeCompare((0, functions_1.handleToFormulaText)(filterValue), undefined, { numeric: true, sensitivity: "base" });
766
+ };
767
+ var handleEqualsFilter = function (result, filterValue) {
768
+ return handleCompareToFilter(result, filterValue) === 0 ||
769
+ (0, exports.handleFormatFormulaValue)(result).toLowerCase() ===
770
+ (0, functions_1.handleToFormulaText)(filterValue).trim().toLowerCase();
771
+ };
772
+ /**
773
+ * Applies one flex-filter condition (as produced by renderFlexFilterConditions)
774
+ * to a formula cell.
775
+ */
776
+ var handleMatchFormulaQuery = function (result, query) {
777
+ var empty = (0, exports.handleIsFormulaEmpty)(result);
778
+ switch (query.type) {
779
+ case "exists":
780
+ return query.value === false ? empty : !empty;
781
+ case "=":
782
+ return !empty && handleEqualsFilter(result, query.value);
783
+ case "!=":
784
+ return empty || !handleEqualsFilter(result, query.value);
785
+ case ">":
786
+ return !empty && handleCompareToFilter(result, query.value) > 0;
787
+ case "<":
788
+ return !empty && handleCompareToFilter(result, query.value) < 0;
789
+ case "><": {
790
+ if (empty || !Array.isArray(query.value))
791
+ return false;
792
+ var _a = query.value, start = _a[0], end = _a[1];
793
+ return (handleCompareToFilter(result, start) >= 0 &&
794
+ handleCompareToFilter(result, end) <= 0);
795
+ }
796
+ default:
797
+ return true;
798
+ }
799
+ };
800
+ exports.handleMatchFormulaQuery = handleMatchFormulaQuery;
801
+ //# sourceMappingURL=index.js.map