@lotics/app-sdk 0.115.2 → 0.115.4
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.js +298 -122
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -716,19 +716,12 @@ function setKey(key, answer) {
|
|
|
716
716
|
// src/written.ts
|
|
717
717
|
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
718
718
|
|
|
719
|
-
// ../shared/src/add_operator.ts
|
|
720
|
-
function addOrConcat(left, right, addNumbers) {
|
|
721
|
-
if (typeof left === "string" || typeof right === "string") {
|
|
722
|
-
return String(left ?? "") + String(right ?? "");
|
|
723
|
-
}
|
|
724
|
-
return addNumbers();
|
|
725
|
-
}
|
|
726
|
-
|
|
727
719
|
// ../shared/src/expression_limits.ts
|
|
728
720
|
var MAX_RESULT_LENGTH = 1e5;
|
|
729
721
|
var MAX_STRING_LENGTH = 1e7;
|
|
730
722
|
var MAX_RANDOM_LENGTH = 1e3;
|
|
731
723
|
var MAX_RUN_BUILT_BYTES = 512 * 1024 * 1024;
|
|
724
|
+
var MAX_IN_PLACE_BYTES = 1024 * 1024;
|
|
732
725
|
var MAX_PERSISTED_JSON_LENGTH = 64 * 1024 * 1024;
|
|
733
726
|
var ExpressionLimitError = class extends Error {
|
|
734
727
|
constructor(message2) {
|
|
@@ -808,21 +801,54 @@ function escapedLength(text2) {
|
|
|
808
801
|
function isLowSurrogate(code) {
|
|
809
802
|
return code >= 56320 && code <= 57343;
|
|
810
803
|
}
|
|
804
|
+
function textOf(value) {
|
|
805
|
+
if (!Array.isArray(value)) return ownText(value);
|
|
806
|
+
const parts = [];
|
|
807
|
+
walkJoined(value, (text2) => {
|
|
808
|
+
parts.push(text2);
|
|
809
|
+
return true;
|
|
810
|
+
});
|
|
811
|
+
return parts.join("");
|
|
812
|
+
}
|
|
811
813
|
function textLengthUpTo(value, max3) {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
let length2 = Math.max(0, value.length - 1);
|
|
819
|
-
for (let index = 0; index < value.length && length2 <= max3; index++) {
|
|
820
|
-
const element = value[index];
|
|
821
|
-
if (element != null) length2 += textLength(element, max3 - length2, joining);
|
|
822
|
-
}
|
|
823
|
-
joining.delete(value);
|
|
814
|
+
if (!Array.isArray(value)) return ownText(value).length;
|
|
815
|
+
let length2 = 0;
|
|
816
|
+
walkJoined(value, (text2) => {
|
|
817
|
+
length2 += text2.length;
|
|
818
|
+
return length2 <= max3;
|
|
819
|
+
});
|
|
824
820
|
return length2;
|
|
825
821
|
}
|
|
822
|
+
function ownText(value) {
|
|
823
|
+
if (typeof value === "string") return value;
|
|
824
|
+
if (value instanceof Date) return Date.prototype.toString.call(value);
|
|
825
|
+
if (typeof value === "object" && value !== null) return Object.prototype.toString.call(value);
|
|
826
|
+
return String(value);
|
|
827
|
+
}
|
|
828
|
+
function walkJoined(array2, write2) {
|
|
829
|
+
const joining = /* @__PURE__ */ new Set([array2]);
|
|
830
|
+
const stack = [{ array: array2, at: 0 }];
|
|
831
|
+
while (stack.length > 0) {
|
|
832
|
+
const frame2 = stack[stack.length - 1];
|
|
833
|
+
if (frame2.at >= frame2.array.length) {
|
|
834
|
+
joining.delete(frame2.array);
|
|
835
|
+
stack.pop();
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
if (frame2.at > 0 && !write2(",")) return;
|
|
839
|
+
const element = frame2.array[frame2.at];
|
|
840
|
+
frame2.at += 1;
|
|
841
|
+
if (element === null || element === void 0) continue;
|
|
842
|
+
if (Array.isArray(element)) {
|
|
843
|
+
if (!joining.has(element)) {
|
|
844
|
+
joining.add(element);
|
|
845
|
+
stack.push({ array: element, at: 0 });
|
|
846
|
+
}
|
|
847
|
+
continue;
|
|
848
|
+
}
|
|
849
|
+
if (!write2(ownText(element))) return;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
826
852
|
function jsonPreview(value, max3) {
|
|
827
853
|
if (typeof value === "string") {
|
|
828
854
|
const text2 = JSON.stringify(value.slice(0, max3));
|
|
@@ -832,6 +858,14 @@ function jsonPreview(value, max3) {
|
|
|
832
858
|
return Array.isArray(value) ? `[\u2026 ${value.length} items]` : "{\u2026}";
|
|
833
859
|
}
|
|
834
860
|
|
|
861
|
+
// ../shared/src/add_operator.ts
|
|
862
|
+
function addOrConcat(left, right, addNumbers) {
|
|
863
|
+
if (typeof left === "string" || typeof right === "string") {
|
|
864
|
+
return textOf(left ?? "") + textOf(right ?? "");
|
|
865
|
+
}
|
|
866
|
+
return addNumbers();
|
|
867
|
+
}
|
|
868
|
+
|
|
835
869
|
// ../../node_modules/jexpr/lib/constants.js
|
|
836
870
|
var KEYWORDS = ["this"];
|
|
837
871
|
var UNARY_OPERATORS = ["+", "-", "!"];
|
|
@@ -1691,6 +1725,16 @@ __export(expression_array_exports, {
|
|
|
1691
1725
|
unique: () => unique,
|
|
1692
1726
|
uniqueBy: () => uniqueBy
|
|
1693
1727
|
});
|
|
1728
|
+
|
|
1729
|
+
// ../shared/src/own_property.ts
|
|
1730
|
+
function ownMember(value, key) {
|
|
1731
|
+
return Object.hasOwn(value, key) ? Reflect.get(value, key) : void 0;
|
|
1732
|
+
}
|
|
1733
|
+
function defineOwn(target, key, value) {
|
|
1734
|
+
Object.defineProperty(target, key, { value, writable: true, enumerable: true, configurable: true });
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
// ../shared/src/expression_array.ts
|
|
1694
1738
|
function getField(obj, field) {
|
|
1695
1739
|
if (obj == null) return void 0;
|
|
1696
1740
|
const parts = field.split(".");
|
|
@@ -1698,10 +1742,17 @@ function getField(obj, field) {
|
|
|
1698
1742
|
for (const part of parts) {
|
|
1699
1743
|
if (value == null) return void 0;
|
|
1700
1744
|
if (typeof value !== "object") return void 0;
|
|
1701
|
-
value = value
|
|
1745
|
+
value = ownMember(value, part);
|
|
1702
1746
|
}
|
|
1703
1747
|
return value;
|
|
1704
1748
|
}
|
|
1749
|
+
function countInto(result, key) {
|
|
1750
|
+
defineOwn(result, key, (Object.hasOwn(result, key) ? result[key] : 0) + 1);
|
|
1751
|
+
}
|
|
1752
|
+
function groupInto(result, key, item) {
|
|
1753
|
+
if (Object.hasOwn(result, key)) result[key].push(item);
|
|
1754
|
+
else defineOwn(result, key, [item]);
|
|
1755
|
+
}
|
|
1705
1756
|
function compareValues(a, b) {
|
|
1706
1757
|
if (a == null && b == null) return 0;
|
|
1707
1758
|
if (a == null) return 1;
|
|
@@ -1863,7 +1914,7 @@ function countBy(arr, fieldOrCb) {
|
|
|
1863
1914
|
const result2 = {};
|
|
1864
1915
|
for (const val of keys2) {
|
|
1865
1916
|
const key = val == null ? "null" : String(val);
|
|
1866
|
-
result2
|
|
1917
|
+
countInto(result2, key);
|
|
1867
1918
|
}
|
|
1868
1919
|
return result2;
|
|
1869
1920
|
});
|
|
@@ -1876,7 +1927,7 @@ function countBy(arr, fieldOrCb) {
|
|
|
1876
1927
|
for (const item of arr) {
|
|
1877
1928
|
const val = getField(item, field);
|
|
1878
1929
|
const key = val == null ? "null" : String(val);
|
|
1879
|
-
result
|
|
1930
|
+
countInto(result, key);
|
|
1880
1931
|
}
|
|
1881
1932
|
return result;
|
|
1882
1933
|
}
|
|
@@ -1996,7 +2047,7 @@ function groupBy(arr, fieldOrCb) {
|
|
|
1996
2047
|
const result2 = {};
|
|
1997
2048
|
for (let i = 0; i < arr.length; i++) {
|
|
1998
2049
|
const key = keys2[i] == null ? "null" : String(keys2[i]);
|
|
1999
|
-
(result2
|
|
2050
|
+
groupInto(result2, key, arr[i]);
|
|
2000
2051
|
}
|
|
2001
2052
|
return result2;
|
|
2002
2053
|
});
|
|
@@ -2009,10 +2060,7 @@ function groupBy(arr, fieldOrCb) {
|
|
|
2009
2060
|
for (const item of arr) {
|
|
2010
2061
|
const val = getField(item, field);
|
|
2011
2062
|
const key = val == null ? "null" : String(val);
|
|
2012
|
-
|
|
2013
|
-
result[key] = [];
|
|
2014
|
-
}
|
|
2015
|
-
result[key].push(item);
|
|
2063
|
+
groupInto(result, key, item);
|
|
2016
2064
|
}
|
|
2017
2065
|
return result;
|
|
2018
2066
|
}
|
|
@@ -2946,7 +2994,7 @@ function getNestedValue(obj, path) {
|
|
|
2946
2994
|
for (const part of parts) {
|
|
2947
2995
|
if (value == null) return void 0;
|
|
2948
2996
|
if (typeof value !== "object") return void 0;
|
|
2949
|
-
value = value
|
|
2997
|
+
value = ownMember(value, part);
|
|
2950
2998
|
}
|
|
2951
2999
|
return value;
|
|
2952
3000
|
}
|
|
@@ -3002,9 +3050,7 @@ function pick(obj, fields) {
|
|
|
3002
3050
|
const objRecord = obj;
|
|
3003
3051
|
for (const field of fields) {
|
|
3004
3052
|
const fieldStr = String(field);
|
|
3005
|
-
if (fieldStr
|
|
3006
|
-
result[fieldStr] = objRecord[fieldStr];
|
|
3007
|
-
}
|
|
3053
|
+
if (Object.hasOwn(objRecord, fieldStr)) defineOwn(result, fieldStr, objRecord[fieldStr]);
|
|
3008
3054
|
}
|
|
3009
3055
|
return result;
|
|
3010
3056
|
}
|
|
@@ -3022,10 +3068,8 @@ function omit(obj, fields) {
|
|
|
3022
3068
|
const result = {};
|
|
3023
3069
|
const objRecord = obj;
|
|
3024
3070
|
const fieldsSet = new Set(fields.map(String));
|
|
3025
|
-
for (const key
|
|
3026
|
-
if (!fieldsSet.has(key))
|
|
3027
|
-
result[key] = objRecord[key];
|
|
3028
|
-
}
|
|
3071
|
+
for (const key of Object.keys(objRecord)) {
|
|
3072
|
+
if (!fieldsSet.has(key)) defineOwn(result, key, objRecord[key]);
|
|
3029
3073
|
}
|
|
3030
3074
|
return result;
|
|
3031
3075
|
}
|
|
@@ -3153,7 +3197,7 @@ function toString(val) {
|
|
|
3153
3197
|
if (typeof val !== "string" && textLengthUpTo(val, MAX_STRING_LENGTH) > MAX_STRING_LENGTH) {
|
|
3154
3198
|
throw new ExpressionLimitError(`toString: result too long (max ${MAX_STRING_LENGTH} characters)`);
|
|
3155
3199
|
}
|
|
3156
|
-
return
|
|
3200
|
+
return textOf(val);
|
|
3157
3201
|
}
|
|
3158
3202
|
function isNull(val) {
|
|
3159
3203
|
return val === null || val === void 0;
|
|
@@ -27341,6 +27385,12 @@ var WorkflowExpressionBudgetError = class extends Error {
|
|
|
27341
27385
|
}
|
|
27342
27386
|
budget;
|
|
27343
27387
|
};
|
|
27388
|
+
var ExpressionNotCheapError = class extends Error {
|
|
27389
|
+
constructor() {
|
|
27390
|
+
super(`The expression walks or builds more than ${MAX_IN_PLACE_BYTES / 1024 / 1024}MB at once, past what an evaluation in place may.`);
|
|
27391
|
+
this.name = "ExpressionNotCheapError";
|
|
27392
|
+
}
|
|
27393
|
+
};
|
|
27344
27394
|
function budgetMessage(budget) {
|
|
27345
27395
|
switch (budget.exceeded) {
|
|
27346
27396
|
case "bytes":
|
|
@@ -27388,6 +27438,66 @@ function builtSize(value) {
|
|
|
27388
27438
|
if (typeof value === "object" && value !== null) return OBJECT_BYTES + Object.keys(value).length * SLOT_BYTES;
|
|
27389
27439
|
return 0;
|
|
27390
27440
|
}
|
|
27441
|
+
var LONGEST_NUMBER_TEXT = 24;
|
|
27442
|
+
function numberTextLength(value) {
|
|
27443
|
+
if (!Number.isSafeInteger(value)) return LONGEST_NUMBER_TEXT;
|
|
27444
|
+
let length2 = value < 0 ? 2 : 1;
|
|
27445
|
+
for (let rest = Math.abs(value); rest >= 10; rest = Math.floor(rest / 10)) length2 += 1;
|
|
27446
|
+
return length2;
|
|
27447
|
+
}
|
|
27448
|
+
function expandedSize(value, max3) {
|
|
27449
|
+
let bytes = 0;
|
|
27450
|
+
const pending = [value];
|
|
27451
|
+
while (pending.length > 0 && bytes <= max3) {
|
|
27452
|
+
const member = pending.pop();
|
|
27453
|
+
if (typeof member === "string") bytes += member.length * CHAR_BYTES;
|
|
27454
|
+
else if (typeof member === "number") bytes += numberTextLength(member) * CHAR_BYTES;
|
|
27455
|
+
else if (typeof member === "boolean") bytes += (member ? 4 : 5) * CHAR_BYTES;
|
|
27456
|
+
else if (typeof member === "bigint") bytes += String(member).length * CHAR_BYTES;
|
|
27457
|
+
else if (typeof member !== "object" || member === null) continue;
|
|
27458
|
+
else if (member instanceof Map) {
|
|
27459
|
+
bytes += OBJECT_BYTES + member.size * 2 * SLOT_BYTES;
|
|
27460
|
+
if (bytes <= max3) for (const [key, held2] of member) pending.push(key, held2);
|
|
27461
|
+
} else if (member instanceof Set) {
|
|
27462
|
+
bytes += OBJECT_BYTES + member.size * SLOT_BYTES;
|
|
27463
|
+
if (bytes <= max3) for (const held2 of member) pending.push(held2);
|
|
27464
|
+
} else if (Array.isArray(member)) {
|
|
27465
|
+
bytes += OBJECT_BYTES + member.length * SLOT_BYTES;
|
|
27466
|
+
if (bytes <= max3) for (let at2 = 0; at2 < member.length; at2++) pending.push(member[at2]);
|
|
27467
|
+
} else {
|
|
27468
|
+
const known = ownKeyBytes.get(member);
|
|
27469
|
+
if (known !== void 0 && bytes + known > max3) {
|
|
27470
|
+
bytes += known;
|
|
27471
|
+
continue;
|
|
27472
|
+
}
|
|
27473
|
+
const keys2 = Object.keys(member);
|
|
27474
|
+
let own = OBJECT_BYTES + keys2.length * SLOT_BYTES;
|
|
27475
|
+
for (const key of keys2) own += key.length * CHAR_BYTES;
|
|
27476
|
+
ownKeyBytes.set(member, own);
|
|
27477
|
+
bytes += own;
|
|
27478
|
+
if (bytes <= max3) for (const key of keys2) pending.push(Reflect.get(member, key));
|
|
27479
|
+
}
|
|
27480
|
+
}
|
|
27481
|
+
return bytes;
|
|
27482
|
+
}
|
|
27483
|
+
var ownKeyBytes = /* @__PURE__ */ new WeakMap();
|
|
27484
|
+
var OBJECT_TEXT_LENGTH = 64;
|
|
27485
|
+
function writtenSize(value, max3) {
|
|
27486
|
+
let bytes = 0;
|
|
27487
|
+
const pending = [value];
|
|
27488
|
+
while (pending.length > 0 && bytes <= max3) {
|
|
27489
|
+
const member = pending.pop();
|
|
27490
|
+
if (typeof member === "string") bytes += member.length * CHAR_BYTES;
|
|
27491
|
+
else if (typeof member === "number") bytes += numberTextLength(member) * CHAR_BYTES;
|
|
27492
|
+
else if (typeof member === "boolean") bytes += (member ? 4 : 5) * CHAR_BYTES;
|
|
27493
|
+
else if (typeof member === "bigint") bytes += String(member).length * CHAR_BYTES;
|
|
27494
|
+
else if (Array.isArray(member)) {
|
|
27495
|
+
bytes += OBJECT_BYTES + member.length * SLOT_BYTES;
|
|
27496
|
+
if (bytes <= max3) for (let at2 = 0; at2 < member.length; at2++) pending.push(member[at2]);
|
|
27497
|
+
} else if (typeof member === "object" && member !== null) bytes += OBJECT_TEXT_LENGTH * CHAR_BYTES;
|
|
27498
|
+
}
|
|
27499
|
+
return bytes;
|
|
27500
|
+
}
|
|
27391
27501
|
var PARSED_NODE_BYTES = 40;
|
|
27392
27502
|
var OPEN_BRACKET = "[".charCodeAt(0);
|
|
27393
27503
|
var OPEN_BRACE = "{".charCodeAt(0);
|
|
@@ -27401,6 +27511,22 @@ function parsedSize(text2) {
|
|
|
27401
27511
|
}
|
|
27402
27512
|
return text2.length * CHAR_BYTES + nodes * PARSED_NODE_BYTES;
|
|
27403
27513
|
}
|
|
27514
|
+
function assertCheap(budget, ...values2) {
|
|
27515
|
+
if (!budget.bounded) return;
|
|
27516
|
+
let bytes = 0;
|
|
27517
|
+
for (const value of values2) {
|
|
27518
|
+
bytes += writtenSize(value, MAX_IN_PLACE_BYTES - bytes);
|
|
27519
|
+
if (bytes > MAX_IN_PLACE_BYTES) throw new ExpressionNotCheapError();
|
|
27520
|
+
}
|
|
27521
|
+
}
|
|
27522
|
+
function charge(ctx, bytes) {
|
|
27523
|
+
const budget = ctx.evaluation_budget;
|
|
27524
|
+
assertUnsettled(budget);
|
|
27525
|
+
if (Date.now() > ctx.run_budget.deadline_ms) throw new WorkflowTimeBudgetError(ctx.run_budget.subject, ctx.run_budget.budget_ms);
|
|
27526
|
+
if (budget.bounded && budget.built + bytes > MAX_IN_PLACE_BYTES) throw new ExpressionNotCheapError();
|
|
27527
|
+
budget.built += bytes;
|
|
27528
|
+
chargeBuilt(ctx.run_budget, bytes);
|
|
27529
|
+
}
|
|
27404
27530
|
function callbackWorkers() {
|
|
27405
27531
|
let free = LINK_FETCH_CONCURRENCY - 1;
|
|
27406
27532
|
return {
|
|
@@ -27414,10 +27540,16 @@ function callbackWorkers() {
|
|
|
27414
27540
|
}
|
|
27415
27541
|
};
|
|
27416
27542
|
}
|
|
27417
|
-
function evaluateWorkflowExpression(expr2, ctx) {
|
|
27418
|
-
const budget = { workers: callbackWorkers(), settled: false };
|
|
27543
|
+
function evaluateWorkflowExpression(expr2, ctx, options = {}) {
|
|
27544
|
+
const budget = { workers: callbackWorkers(), bounded: options.bounded === true, built: 0, settled: false };
|
|
27419
27545
|
return evaluateExpression(expr2, { ...ctx, evaluation_budget: budget }).finally(() => {
|
|
27420
27546
|
budget.settled = true;
|
|
27547
|
+
}).then((answer) => {
|
|
27548
|
+
if (budget.bounded && expandedSize(answer, MAX_IN_PLACE_BYTES) > MAX_IN_PLACE_BYTES) throw new ExpressionNotCheapError();
|
|
27549
|
+
return answer;
|
|
27550
|
+
}).catch((error51) => {
|
|
27551
|
+
if (budget.bounded && ctx.run_budget.host === "shared") ctx.run_budget.built_bytes -= budget.built;
|
|
27552
|
+
throw error51;
|
|
27421
27553
|
});
|
|
27422
27554
|
}
|
|
27423
27555
|
async function evaluateExpression(expr2, ctx) {
|
|
@@ -27443,15 +27575,13 @@ async function evaluateExpression(expr2, ctx) {
|
|
|
27443
27575
|
return evaluateLambda(expr2.params, expr2.body, ctx, []);
|
|
27444
27576
|
case "array_literal": {
|
|
27445
27577
|
const elements = await Promise.all(expr2.elements.map((el) => evaluateExpression(el, ctx)));
|
|
27446
|
-
|
|
27578
|
+
charge(ctx, builtSize(elements));
|
|
27447
27579
|
return elements;
|
|
27448
27580
|
}
|
|
27449
27581
|
case "object_literal": {
|
|
27450
27582
|
const out = {};
|
|
27451
|
-
for (const entry of expr2.entries)
|
|
27452
|
-
|
|
27453
|
-
}
|
|
27454
|
-
chargeBuilt(ctx.run_budget, builtSize(out));
|
|
27583
|
+
for (const entry of expr2.entries) defineOwn(out, entry.key, await evaluateExpression(entry.value, ctx));
|
|
27584
|
+
charge(ctx, builtSize(out));
|
|
27455
27585
|
return out;
|
|
27456
27586
|
}
|
|
27457
27587
|
default:
|
|
@@ -27472,9 +27602,7 @@ function assertUnsettled(budget) {
|
|
|
27472
27602
|
function evaluateLambda(params, body, ctx, items) {
|
|
27473
27603
|
const call = async (...args) => {
|
|
27474
27604
|
const frame2 = {};
|
|
27475
|
-
for (let i = 0; i < params.length; i++)
|
|
27476
|
-
frame2[params[i]] = args[i];
|
|
27477
|
-
}
|
|
27605
|
+
for (let i = 0; i < params.length; i++) defineOwn(frame2, params[i], args[i]);
|
|
27478
27606
|
const stack = ctx.lambda_params ?? [];
|
|
27479
27607
|
const newStack = [...stack, frame2];
|
|
27480
27608
|
const innerCtx = {
|
|
@@ -27542,16 +27670,14 @@ function resolveReadRoot(source, ctx) {
|
|
|
27542
27670
|
case "foreach_index":
|
|
27543
27671
|
return resolveForeachFrame(ctx, void 0, "foreach_index").index;
|
|
27544
27672
|
case "step_output": {
|
|
27545
|
-
if (!(source.step_id
|
|
27673
|
+
if (!Object.hasOwn(ctx.step_outputs, source.step_id)) {
|
|
27546
27674
|
throw new WorkflowEvalError(
|
|
27547
27675
|
`Read from step_output "${source.step_id}", but no such step has run`,
|
|
27548
27676
|
{ kind: "read", at: "step_output", extra: { step_id: source.step_id } }
|
|
27549
27677
|
);
|
|
27550
27678
|
}
|
|
27551
27679
|
const stored = ctx.step_outputs[source.step_id];
|
|
27552
|
-
if (stored && typeof stored === "object" && "output"
|
|
27553
|
-
return stored.output;
|
|
27554
|
-
}
|
|
27680
|
+
if (stored && typeof stored === "object" && Object.hasOwn(stored, "output")) return ownMember(stored, "output");
|
|
27555
27681
|
return stored;
|
|
27556
27682
|
}
|
|
27557
27683
|
case "runtime":
|
|
@@ -27561,7 +27687,7 @@ function resolveReadRoot(source, ctx) {
|
|
|
27561
27687
|
if (stack !== void 0) {
|
|
27562
27688
|
for (let i = stack.length - 1; i >= 0; i--) {
|
|
27563
27689
|
const frame2 = stack[i];
|
|
27564
|
-
if (source.name
|
|
27690
|
+
if (Object.hasOwn(frame2, source.name)) return frame2[source.name];
|
|
27565
27691
|
}
|
|
27566
27692
|
}
|
|
27567
27693
|
throw new WorkflowEvalError(
|
|
@@ -27574,7 +27700,7 @@ function resolveReadRoot(source, ctx) {
|
|
|
27574
27700
|
if (stack !== void 0) {
|
|
27575
27701
|
for (let i = stack.length - 1; i >= 0; i--) {
|
|
27576
27702
|
const frame2 = stack[i];
|
|
27577
|
-
if (source.name
|
|
27703
|
+
if (Object.hasOwn(frame2, source.name)) return frame2[source.name];
|
|
27578
27704
|
}
|
|
27579
27705
|
}
|
|
27580
27706
|
throw new WorkflowEvalError(
|
|
@@ -27676,63 +27802,74 @@ async function coerceFieldDisplay(value, field, ctx) {
|
|
|
27676
27802
|
if (value === null || value === void 0) return value;
|
|
27677
27803
|
switch (field.type) {
|
|
27678
27804
|
case "select":
|
|
27679
|
-
return coerceSelectDisplay(value, field.options);
|
|
27805
|
+
return coerceSelectDisplay(value, field.options, ctx);
|
|
27680
27806
|
// One of its own options, named as a select's is.
|
|
27681
27807
|
case "formula":
|
|
27682
|
-
return field.formula.options === void 0 ? value : coerceSelectDisplay(value, field.formula.options);
|
|
27808
|
+
return field.formula.options === void 0 ? value : coerceSelectDisplay(value, field.formula.options, ctx);
|
|
27683
27809
|
case "select_record_link":
|
|
27684
27810
|
return coerceRecordLinkDisplay(value, field, ctx);
|
|
27685
27811
|
case "select_member":
|
|
27686
27812
|
return coerceMemberDisplay(value, ctx);
|
|
27687
27813
|
case "lookup":
|
|
27688
|
-
return field.lookup_field_options ? coerceOptionKeysDeep(value, field.lookup_field_options) : value;
|
|
27814
|
+
return field.lookup_field_options ? coerceOptionKeysDeep(value, field.lookup_field_options, ctx) : value;
|
|
27689
27815
|
default:
|
|
27690
27816
|
return value;
|
|
27691
27817
|
}
|
|
27692
27818
|
}
|
|
27693
|
-
function coerceSelectDisplay(value, options) {
|
|
27819
|
+
function coerceSelectDisplay(value, options, ctx) {
|
|
27694
27820
|
const optionMap = new Map(options.map((o) => [o.key, o.name]));
|
|
27695
27821
|
const resolve = (key) => {
|
|
27696
27822
|
if (typeof key !== "string") return "";
|
|
27697
27823
|
return optionMap.get(key) ?? key;
|
|
27698
27824
|
};
|
|
27699
|
-
if (Array.isArray(value)) return value
|
|
27700
|
-
|
|
27825
|
+
if (!Array.isArray(value)) return resolve(value);
|
|
27826
|
+
assertCheap(ctx.evaluation_budget, value);
|
|
27827
|
+
const names = value.map(resolve);
|
|
27828
|
+
charge(ctx, builtSize(names));
|
|
27829
|
+
return names;
|
|
27701
27830
|
}
|
|
27702
|
-
function coerceOptionKeysDeep(value, options) {
|
|
27831
|
+
function coerceOptionKeysDeep(value, options, ctx) {
|
|
27832
|
+
assertCheap(ctx.evaluation_budget, value);
|
|
27703
27833
|
const optionMap = new Map(options.map((o) => [o.key, o.name]));
|
|
27704
27834
|
const resolve = (v) => {
|
|
27705
|
-
if (Array.isArray(v))
|
|
27835
|
+
if (Array.isArray(v)) {
|
|
27836
|
+
const resolved = v.map(resolve);
|
|
27837
|
+
charge(ctx, builtSize(resolved));
|
|
27838
|
+
return resolved;
|
|
27839
|
+
}
|
|
27706
27840
|
if (typeof v === "string") return optionMap.get(v) ?? v;
|
|
27707
27841
|
return v;
|
|
27708
27842
|
};
|
|
27709
27843
|
return resolve(value);
|
|
27710
27844
|
}
|
|
27711
27845
|
async function coerceMemberDisplay(value, ctx) {
|
|
27846
|
+
if (Array.isArray(value)) assertCheap(ctx.evaluation_budget, value);
|
|
27712
27847
|
const ids = Array.isArray(value) ? value.filter((v) => typeof v === "string") : typeof value === "string" ? [value] : [];
|
|
27713
27848
|
if (ids.length === 0) return Array.isArray(value) ? [] : "";
|
|
27714
27849
|
const nameMap = await ctx.member_lookup(ids);
|
|
27715
27850
|
const names = new Set(nameMap.values());
|
|
27716
27851
|
const resolve = (id) => nameMap.get(id) ?? (names.has(id) ? id : "");
|
|
27717
|
-
|
|
27852
|
+
if (!Array.isArray(value)) return resolve(ids[0]);
|
|
27853
|
+
const shown = value.map((v) => resolve(textOf(v)));
|
|
27854
|
+
charge(ctx, builtSize(shown));
|
|
27855
|
+
return shown;
|
|
27718
27856
|
}
|
|
27719
27857
|
async function coerceRecordLinkDisplay(value, field, ctx) {
|
|
27720
27858
|
if (!Array.isArray(value)) return value;
|
|
27859
|
+
assertCheap(ctx.evaluation_budget, value);
|
|
27721
27860
|
const displayFieldKeys = field.display_field_keys ?? [];
|
|
27722
|
-
|
|
27723
|
-
value.map(
|
|
27724
|
-
|
|
27725
|
-
|
|
27726
|
-
if (!data) return "";
|
|
27727
|
-
if (displayFieldKeys.length === 0) {
|
|
27728
|
-
return "";
|
|
27729
|
-
}
|
|
27730
|
-
return displayFieldKeys.map((key) => {
|
|
27731
|
-
const v = data[key];
|
|
27732
|
-
return v === null || v === void 0 ? "" : String(v);
|
|
27733
|
-
}).filter((s) => s !== "").join(" ");
|
|
27734
|
-
})
|
|
27861
|
+
const rows = await fetchRecordsBounded(
|
|
27862
|
+
value.map((id) => typeof id === "string" ? id : null),
|
|
27863
|
+
`Showing "${field.key}"`,
|
|
27864
|
+
ctx
|
|
27735
27865
|
);
|
|
27866
|
+
const shown = rows.map((row2) => row2 === null ? [] : displayFieldKeys.map((key) => row2[key]));
|
|
27867
|
+
assertCheap(ctx.evaluation_budget, shown);
|
|
27868
|
+
const texts = shown.map(
|
|
27869
|
+
(values2) => values2.filter((v) => v !== null && v !== void 0).map(textOf).filter((text2) => text2 !== "").join(" ")
|
|
27870
|
+
);
|
|
27871
|
+
charge(ctx, texts.reduce((bytes, text2) => bytes + builtSize(text2), builtSize(texts)));
|
|
27872
|
+
return texts;
|
|
27736
27873
|
}
|
|
27737
27874
|
function advanceTable(segment, currentTable, ctx) {
|
|
27738
27875
|
if (segment.at === "linked" && currentTable) {
|
|
@@ -27762,7 +27899,7 @@ async function walkSegment(value, segment, ctx) {
|
|
|
27762
27899
|
return void 0;
|
|
27763
27900
|
}
|
|
27764
27901
|
if (typeof value !== "object") return void 0;
|
|
27765
|
-
return value
|
|
27902
|
+
return ownMember(value, segment.key);
|
|
27766
27903
|
}
|
|
27767
27904
|
case "index": {
|
|
27768
27905
|
if (value === null || value === void 0) return void 0;
|
|
@@ -27772,7 +27909,7 @@ async function walkSegment(value, segment, ctx) {
|
|
|
27772
27909
|
}
|
|
27773
27910
|
if (typeof value === "object") {
|
|
27774
27911
|
const key = typeof segment.index === "number" ? String(segment.index) : await resolveObjectKeyExpression(segment.index, ctx);
|
|
27775
|
-
return value
|
|
27912
|
+
return ownMember(value, key);
|
|
27776
27913
|
}
|
|
27777
27914
|
throw new WorkflowEvalError(
|
|
27778
27915
|
`Cannot index ${typeof value} \u2014 only an array or an object can be read by index.`,
|
|
@@ -27790,9 +27927,8 @@ async function resolveObjectKeyExpression(expr2, ctx) {
|
|
|
27790
27927
|
throw new WorkflowEvalError(
|
|
27791
27928
|
// Bounded: the value is whatever the expression produced — a whole record,
|
|
27792
27929
|
// a page of rows — and the message goes into a persisted execution row and
|
|
27793
|
-
// an author-facing error.
|
|
27794
|
-
|
|
27795
|
-
`Computed object key must evaluate to a string, got ${value === null ? "null" : typeof value}: ${jsonPreview(value, VALUE_PREVIEW_LENGTH)}`,
|
|
27930
|
+
// an author-facing error.
|
|
27931
|
+
`Computed object key must evaluate to a string, got ${describeValue(value)}`,
|
|
27796
27932
|
{ kind: "read", at: "index" }
|
|
27797
27933
|
);
|
|
27798
27934
|
}
|
|
@@ -27801,7 +27937,7 @@ async function resolveIndexExpression(expr2, ctx, context) {
|
|
|
27801
27937
|
const value = await evaluateExpression(expr2, ctx);
|
|
27802
27938
|
if (typeof value !== "number" || !Number.isInteger(value) || value < 0) {
|
|
27803
27939
|
throw new WorkflowEvalError(
|
|
27804
|
-
`Computed ${context} must evaluate to a non-negative integer, got ${
|
|
27940
|
+
`Computed ${context} must evaluate to a non-negative integer, got ${describeValue(value)}`,
|
|
27805
27941
|
{ kind: "read", at: "index" }
|
|
27806
27942
|
);
|
|
27807
27943
|
}
|
|
@@ -27815,17 +27951,17 @@ async function walkLinked(value, segment, ctx) {
|
|
|
27815
27951
|
{ kind: "read", at: "linked", extra: { via: segment.via } }
|
|
27816
27952
|
);
|
|
27817
27953
|
}
|
|
27818
|
-
const
|
|
27819
|
-
const ids = extractLinkIds(linkValue, segment.via);
|
|
27954
|
+
const ids = linkIds(ownMember(value, segment.via), segment.via);
|
|
27820
27955
|
if (segment.index === "each") {
|
|
27821
|
-
|
|
27956
|
+
assertCheap(ctx.evaluation_budget, ids);
|
|
27957
|
+
return fetchRecordsBounded(ids.map((id) => assertLinkId(id, segment.via)), `linked(...) on "${segment.via}"`, ctx);
|
|
27822
27958
|
}
|
|
27823
27959
|
const idx = typeof segment.index === "number" ? segment.index : await resolveIndexExpression(segment.index, ctx, `linked index via "${segment.via}"`);
|
|
27824
27960
|
const target = ids[idx];
|
|
27825
27961
|
if (target === void 0) return void 0;
|
|
27826
|
-
return fetchRecordData(target, ctx);
|
|
27962
|
+
return fetchRecordData(assertLinkId(target, segment.via), ctx);
|
|
27827
27963
|
}
|
|
27828
|
-
function
|
|
27964
|
+
function linkIds(value, via) {
|
|
27829
27965
|
if (value === void 0 || value === null) return [];
|
|
27830
27966
|
if (!Array.isArray(value)) {
|
|
27831
27967
|
throw new WorkflowEvalError(
|
|
@@ -27833,16 +27969,17 @@ function extractLinkIds(value, via) {
|
|
|
27833
27969
|
{ kind: "read", at: "linked", extra: { via } }
|
|
27834
27970
|
);
|
|
27835
27971
|
}
|
|
27836
|
-
for (const item of value) {
|
|
27837
|
-
if (typeof item !== "string") {
|
|
27838
|
-
throw new WorkflowEvalError(
|
|
27839
|
-
`Linked field "${via}" contains a non-string item \u2014 record data must be normalized before evaluation`,
|
|
27840
|
-
{ kind: "read", at: "linked", extra: { via, item_type: typeof item } }
|
|
27841
|
-
);
|
|
27842
|
-
}
|
|
27843
|
-
}
|
|
27844
27972
|
return value;
|
|
27845
27973
|
}
|
|
27974
|
+
function assertLinkId(item, via) {
|
|
27975
|
+
if (typeof item !== "string") {
|
|
27976
|
+
throw new WorkflowEvalError(
|
|
27977
|
+
`Linked field "${via}" contains a non-string item \u2014 record data must be normalized before evaluation`,
|
|
27978
|
+
{ kind: "read", at: "linked", extra: { via, item_type: typeof item } }
|
|
27979
|
+
);
|
|
27980
|
+
}
|
|
27981
|
+
return item;
|
|
27982
|
+
}
|
|
27846
27983
|
async function fetchRecordData(recordId, ctx) {
|
|
27847
27984
|
if (ctx.record_cache.has(recordId)) {
|
|
27848
27985
|
return ctx.record_cache.get(recordId) ?? null;
|
|
@@ -27854,18 +27991,18 @@ async function fetchRecordData(recordId, ctx) {
|
|
|
27854
27991
|
}
|
|
27855
27992
|
var LINK_FETCH_CONCURRENCY = 20;
|
|
27856
27993
|
var MAX_LINK_FAN_OUT = 1e4;
|
|
27857
|
-
async function fetchRecordsBounded(ids,
|
|
27994
|
+
async function fetchRecordsBounded(ids, reading, ctx) {
|
|
27858
27995
|
if (ids.length > MAX_LINK_FAN_OUT) {
|
|
27859
27996
|
throw new WorkflowEvalError(
|
|
27860
|
-
|
|
27861
|
-
{ kind: "read", at: "linked", extra: {
|
|
27997
|
+
`${reading} would fetch ${ids.length} rows, over the cap of ${MAX_LINK_FAN_OUT}. Index one row \u2014 linked(...)[i] \u2014 or narrow the link.`,
|
|
27998
|
+
{ kind: "read", at: "linked", extra: { reading } }
|
|
27862
27999
|
);
|
|
27863
28000
|
}
|
|
27864
28001
|
const results = [];
|
|
27865
28002
|
for (let i = 0; i < ids.length; i += LINK_FETCH_CONCURRENCY) {
|
|
27866
28003
|
for (let pause = checkClock(ctx); pause !== null; pause = checkClock(ctx)) await pause;
|
|
27867
28004
|
const chunk = ids.slice(i, i + LINK_FETCH_CONCURRENCY);
|
|
27868
|
-
results.push(...await Promise.all(chunk.map((id) => fetchRecordData(id, ctx))));
|
|
28005
|
+
results.push(...await Promise.all(chunk.map((id) => id === null ? null : fetchRecordData(id, ctx))));
|
|
27869
28006
|
}
|
|
27870
28007
|
return results;
|
|
27871
28008
|
}
|
|
@@ -27885,12 +28022,12 @@ async function evaluateCall(fn, args, ctx) {
|
|
|
27885
28022
|
);
|
|
27886
28023
|
for (let pause = checkClock(ctx); pause !== null; pause = checkClock(ctx)) await pause;
|
|
27887
28024
|
const cost = helperCost(fn);
|
|
27888
|
-
if (cost === "parses")
|
|
28025
|
+
if (cost === "parses") charge(ctx, parsedSize(evaluatedArgs[0]));
|
|
27889
28026
|
const answer = await helper(...evaluatedArgs);
|
|
27890
28027
|
if (cost !== "builds" && cost !== "nested") return answer;
|
|
27891
28028
|
const handedBack = evaluatedArgs.indexOf(answer);
|
|
27892
28029
|
if (handedBack !== -1) return evaluatedArgs[handedBack];
|
|
27893
|
-
|
|
28030
|
+
charge(ctx, builtSize(answer) + (cost === "nested" ? builtSize(evaluatedArgs[0]) : 0));
|
|
27894
28031
|
return answer;
|
|
27895
28032
|
}
|
|
27896
28033
|
async function evaluateBinary(op, leftExpr, rightExpr, ctx) {
|
|
@@ -27911,9 +28048,9 @@ async function evaluateBinary(op, leftExpr, rightExpr, ctx) {
|
|
|
27911
28048
|
for (let pause = checkClock(ctx); pause !== null; pause = checkClock(ctx)) await pause;
|
|
27912
28049
|
switch (op) {
|
|
27913
28050
|
case "eq":
|
|
27914
|
-
return looseEq(left, right);
|
|
27915
28051
|
case "neq":
|
|
27916
|
-
|
|
28052
|
+
assertCheap(ctx.evaluation_budget, looselyComparedText(left, right));
|
|
28053
|
+
return looseEq(left, right) === (op === "eq");
|
|
27917
28054
|
case "seq":
|
|
27918
28055
|
return strictEq(left, right);
|
|
27919
28056
|
case "sneq":
|
|
@@ -27928,10 +28065,11 @@ async function evaluateBinary(op, leftExpr, rightExpr, ctx) {
|
|
|
27928
28065
|
return compareOrdered(left, right) <= 0;
|
|
27929
28066
|
case "add": {
|
|
27930
28067
|
if (typeof left === "string" || typeof right === "string") {
|
|
28068
|
+
assertCheap(ctx.evaluation_budget, left, right);
|
|
27931
28069
|
assertTextWithin("+", typeof left === "string" ? null : left, typeof right === "string" ? null : right);
|
|
27932
28070
|
}
|
|
27933
28071
|
const sum2 = addOrConcat(left, right, () => assertNumber(left, "add", "left") + assertNumber(right, "add", "right"));
|
|
27934
|
-
|
|
28072
|
+
charge(ctx, builtSize(sum2));
|
|
27935
28073
|
return sum2;
|
|
27936
28074
|
}
|
|
27937
28075
|
case "sub":
|
|
@@ -27955,8 +28093,21 @@ async function evaluateBinary(op, leftExpr, rightExpr, ctx) {
|
|
|
27955
28093
|
}
|
|
27956
28094
|
}
|
|
27957
28095
|
function looseEq(a, b) {
|
|
28096
|
+
if (isComposite(a) && b !== null && b !== void 0 && !isComposite(b)) return looseEq(textOf(a), b);
|
|
28097
|
+
if (isComposite(b) && a !== null && a !== void 0 && !isComposite(a)) return looseEq(a, textOf(b));
|
|
27958
28098
|
return a == b;
|
|
27959
28099
|
}
|
|
28100
|
+
function isComposite(value) {
|
|
28101
|
+
return typeof value === "object" && value !== null;
|
|
28102
|
+
}
|
|
28103
|
+
function looselyComparedText(a, b) {
|
|
28104
|
+
if (Array.isArray(a) && isScalar(b)) return a;
|
|
28105
|
+
if (Array.isArray(b) && isScalar(a)) return b;
|
|
28106
|
+
return null;
|
|
28107
|
+
}
|
|
28108
|
+
function isScalar(value) {
|
|
28109
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" || typeof value === "bigint";
|
|
28110
|
+
}
|
|
27960
28111
|
function strictEq(a, b) {
|
|
27961
28112
|
return a === b;
|
|
27962
28113
|
}
|
|
@@ -27990,8 +28141,14 @@ function describeValue(value) {
|
|
|
27990
28141
|
if (typeof value === "string") return `string ${jsonPreview(value, VALUE_PREVIEW_LENGTH)}`;
|
|
27991
28142
|
if (typeof value === "number") return `number ${String(value)}`;
|
|
27992
28143
|
if (typeof value === "boolean") return `boolean ${String(value)}`;
|
|
27993
|
-
|
|
27994
|
-
|
|
28144
|
+
if (!Array.isArray(value)) return typeof value;
|
|
28145
|
+
let length2 = 0;
|
|
28146
|
+
for (let at2 = 0; at2 < value.length && length2 <= VALUE_PREVIEW_LENGTH; at2++) {
|
|
28147
|
+
const element = value[at2];
|
|
28148
|
+
if (element !== null && element !== void 0 && !isScalar(element)) return "array";
|
|
28149
|
+
length2 += (typeof element === "string" ? element.length : LONGEST_NUMBER_TEXT) + 1;
|
|
28150
|
+
}
|
|
28151
|
+
return value.length > 0 && length2 <= VALUE_PREVIEW_LENGTH ? `array ${value.join(",")}` : "array";
|
|
27995
28152
|
}
|
|
27996
28153
|
async function evaluateUnary(op, argExpr, ctx) {
|
|
27997
28154
|
const value = await evaluateExpression(argExpr, ctx);
|
|
@@ -28013,9 +28170,10 @@ async function evaluateTemplate(parts, ctx) {
|
|
|
28013
28170
|
parts.map((part) => part.t === "text" ? part.s : evaluateExpression(part.e, ctx))
|
|
28014
28171
|
);
|
|
28015
28172
|
for (let pause = checkClock(ctx); pause !== null; pause = checkClock(ctx)) await pause;
|
|
28173
|
+
assertCheap(ctx.evaluation_budget, ...evaluated2);
|
|
28016
28174
|
assertTextWithin("template", ...evaluated2);
|
|
28017
28175
|
const text2 = evaluated2.map(stringifyForTemplate).join("");
|
|
28018
|
-
|
|
28176
|
+
charge(ctx, builtSize(text2));
|
|
28019
28177
|
return text2;
|
|
28020
28178
|
}
|
|
28021
28179
|
function assertTextWithin(writer, ...values2) {
|
|
@@ -28029,8 +28187,7 @@ function assertTextWithin(writer, ...values2) {
|
|
|
28029
28187
|
}
|
|
28030
28188
|
function stringifyForTemplate(value) {
|
|
28031
28189
|
if (value === null || value === void 0) return "";
|
|
28032
|
-
|
|
28033
|
-
return String(value);
|
|
28190
|
+
return textOf(value);
|
|
28034
28191
|
}
|
|
28035
28192
|
|
|
28036
28193
|
// ../shared/src/id.ts
|
|
@@ -28090,6 +28247,11 @@ function knownCells(tables, tableId, cells) {
|
|
|
28090
28247
|
},
|
|
28091
28248
|
has(target, key) {
|
|
28092
28249
|
return isField(key) || Reflect.has(target, key);
|
|
28250
|
+
},
|
|
28251
|
+
// An expression reads only what a row holds itself (`ownMember`).
|
|
28252
|
+
getOwnPropertyDescriptor(target, key) {
|
|
28253
|
+
if (isField(key) && !Object.hasOwn(target, key)) unread(key);
|
|
28254
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
|
28093
28255
|
}
|
|
28094
28256
|
}
|
|
28095
28257
|
);
|
|
@@ -28099,6 +28261,11 @@ function modelled(stepId, output) {
|
|
|
28099
28261
|
get(target, key) {
|
|
28100
28262
|
if (typeof key === "string" && key !== "then" && !(key in target)) unread(`${stepId}.${key}`);
|
|
28101
28263
|
return Reflect.get(target, key);
|
|
28264
|
+
},
|
|
28265
|
+
// An expression reads only what an output holds itself (`ownMember`).
|
|
28266
|
+
getOwnPropertyDescriptor(target, key) {
|
|
28267
|
+
if (typeof key === "string" && key !== "then" && !Object.hasOwn(target, key)) unread(`${stepId}.${key}`);
|
|
28268
|
+
return Reflect.getOwnPropertyDescriptor(target, key);
|
|
28102
28269
|
}
|
|
28103
28270
|
});
|
|
28104
28271
|
}
|
|
@@ -31353,33 +31520,37 @@ function buildDependencyGraph(formulaFields, allFields) {
|
|
|
31353
31520
|
}
|
|
31354
31521
|
return { sortedFields: result, circularDependencies };
|
|
31355
31522
|
}
|
|
31356
|
-
function readsFieldsOnlyThroughEmptinessPredicates(node) {
|
|
31523
|
+
function readsFieldsOnlyThroughEmptinessPredicates(node, taken) {
|
|
31524
|
+
const reads = (child) => readsFieldsOnlyThroughEmptinessPredicates(child, taken);
|
|
31357
31525
|
if (node === void 0) return true;
|
|
31358
31526
|
if (isFieldRead(node)) return false;
|
|
31359
31527
|
switch (node.type) {
|
|
31360
31528
|
case "Invoke": {
|
|
31361
31529
|
const args = node.arguments ?? [];
|
|
31362
31530
|
const predicate = node.method === void 0 && node.receiver.type === "ID" && EMPTINESS_PREDICATES.has(node.receiver.value);
|
|
31363
|
-
return (predicate ||
|
|
31364
|
-
(arg) => predicate && isFieldRead(arg) ||
|
|
31531
|
+
return (predicate || reads(node.receiver)) && args.every(
|
|
31532
|
+
(arg) => predicate && isFieldRead(arg) || reads(arg)
|
|
31365
31533
|
);
|
|
31366
31534
|
}
|
|
31367
31535
|
case "Unary":
|
|
31368
|
-
return
|
|
31536
|
+
return reads(node.child);
|
|
31369
31537
|
case "Binary":
|
|
31370
|
-
return
|
|
31538
|
+
return reads(node.left) && reads(node.right);
|
|
31371
31539
|
case "Getter":
|
|
31372
|
-
return
|
|
31540
|
+
return reads(node.receiver);
|
|
31373
31541
|
case "Index":
|
|
31374
|
-
return
|
|
31375
|
-
case "Ternary":
|
|
31376
|
-
|
|
31542
|
+
return reads(node.receiver) && reads(node.argument);
|
|
31543
|
+
case "Ternary": {
|
|
31544
|
+
if (!reads(node.condition)) return false;
|
|
31545
|
+
const decided = node.condition === void 0 || taken === void 0 ? void 0 : taken(node.condition);
|
|
31546
|
+
return decided === true ? reads(node.trueExpr) : decided === false ? reads(node.falseExpr) : reads(node.trueExpr) && reads(node.falseExpr);
|
|
31547
|
+
}
|
|
31377
31548
|
case "List":
|
|
31378
|
-
return (node.items ?? []).every(
|
|
31549
|
+
return (node.items ?? []).every((item) => reads(item));
|
|
31379
31550
|
case "Map":
|
|
31380
|
-
return Object.values(node.entries ?? {}).every(
|
|
31551
|
+
return Object.values(node.entries ?? {}).every((entry) => reads(entry));
|
|
31381
31552
|
case "ArrowFunction":
|
|
31382
|
-
return
|
|
31553
|
+
return reads(node.body);
|
|
31383
31554
|
case "ID":
|
|
31384
31555
|
return node.value !== "data";
|
|
31385
31556
|
case "Literal":
|
|
@@ -31392,8 +31563,13 @@ function isFieldRead(node) {
|
|
|
31392
31563
|
}
|
|
31393
31564
|
function evaluateFormulaWithJS(preparedExpression, data, timezone, everyReferenceEmpty) {
|
|
31394
31565
|
try {
|
|
31395
|
-
if (everyReferenceEmpty
|
|
31396
|
-
|
|
31566
|
+
if (everyReferenceEmpty) {
|
|
31567
|
+
const helpers = createTimezoneAwareFunctions(timezone);
|
|
31568
|
+
const taken = (condition2) => {
|
|
31569
|
+
const answer = condition2.evaluate({ ...data, ...helpers });
|
|
31570
|
+
return typeof answer === "boolean" ? answer : void 0;
|
|
31571
|
+
};
|
|
31572
|
+
if (!readsFieldsOnlyThroughEmptinessPredicates(parseExpression(preparedExpression), taken)) return null;
|
|
31397
31573
|
}
|
|
31398
31574
|
const result = evaluateJsExpression(preparedExpression, data, void 0, timezone);
|
|
31399
31575
|
if (result === null || result === void 0) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lotics/app-sdk",
|
|
3
|
-
"version": "0.115.
|
|
3
|
+
"version": "0.115.4",
|
|
4
4
|
"description": "The SDK a Lotics custom-code app reads and writes through \u2014 typed hooks over the host bridge, cell readers, mount() and AppRouter",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|