@adminide-stack/yantra-mobile 12.0.140 → 12.0.141
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/lib/features/agent-chat/NativeAgentChat.js +21 -4
- package/lib/features/agent-chat/NativeAgentChat.js.map +1 -1
- package/lib/features/chat/ApprovalCard.js +353 -0
- package/lib/features/chat/ApprovalCard.js.map +1 -0
- package/lib/features/chat/AskUserCard.js +9 -2
- package/lib/features/chat/AskUserCard.js.map +1 -1
- package/lib/features/chat/askUser.js +25 -3
- package/lib/features/chat/askUser.js.map +1 -1
- package/lib/features/chat/queuedFollowUpRows.js +13 -0
- package/lib/features/chat/queuedFollowUpRows.js.map +1 -0
- package/lib/features/discover/DiscoverArticle.js +105 -92
- package/lib/features/discover/DiscoverArticle.js.map +1 -1
- package/lib/features/discover/DiscoverFeed.js +97 -48
- package/lib/features/discover/DiscoverFeed.js.map +1 -1
- package/lib/features/discover/DiscoverFollowUp.js +135 -0
- package/lib/features/discover/DiscoverFollowUp.js.map +1 -0
- package/lib/features/discover/DiscoverSidebar.js +555 -0
- package/lib/features/discover/DiscoverSidebar.js.map +1 -0
- package/lib/features/discover/DiscoverSkeletons.js +123 -0
- package/lib/features/discover/DiscoverSkeletons.js.map +1 -0
- package/lib/features/discover/DiscoverStoryCards.js +193 -87
- package/lib/features/discover/DiscoverStoryCards.js.map +1 -1
- package/lib/features/discover/followUpQuery.js +42 -0
- package/lib/features/discover/followUpQuery.js.map +1 -0
- package/lib/features/discover/markets.js +37 -0
- package/lib/features/discover/markets.js.map +1 -0
- package/lib/features/discover/useDiscoverSidebar.js +148 -0
- package/lib/features/discover/useDiscoverSidebar.js.map +1 -0
- package/lib/features/discover/weather.js +42 -0
- package/lib/features/discover/weather.js.map +1 -0
- package/lib/features/expenses/ExpensesAgentChatPane.js +1 -1
- package/lib/features/expenses/ExpensesAgentChatPane.js.map +1 -1
- package/lib/features/inbox/InboxAgentChatPane.js +1 -1
- package/lib/features/inbox/InboxAgentChatPane.js.map +1 -1
- package/lib/features/job-search/JobSearchAgentChatPane.js +1 -0
- package/lib/features/job-search/JobSearchAgentChatPane.js.map +1 -1
- package/lib/features/local-services/LocalServicesAgentChatPane.js +1 -1
- package/lib/features/local-services/LocalServicesAgentChatPane.js.map +1 -1
- package/lib/features/movies/MoviesAgentChatPane.js +1 -1
- package/lib/features/movies/MoviesAgentChatPane.js.map +1 -1
- package/lib/features/notion/NotionBlockSheets.js +206 -0
- package/lib/features/notion/NotionBlockSheets.js.map +1 -0
- package/lib/features/notion/NotionBlockView.js +36 -0
- package/lib/features/notion/NotionBlockView.js.map +1 -0
- package/lib/features/notion/NotionCommentsSheet.js +461 -0
- package/lib/features/notion/NotionCommentsSheet.js.map +1 -0
- package/lib/features/notion/NotionConnectionsSheet.js +244 -0
- package/lib/features/notion/NotionConnectionsSheet.js.map +1 -0
- package/lib/features/notion/NotionHistorySheet.js +439 -0
- package/lib/features/notion/NotionHistorySheet.js.map +1 -0
- package/lib/features/notion/NotionMediaBlocks.js +803 -0
- package/lib/features/notion/NotionMediaBlocks.js.map +1 -0
- package/lib/features/notion/NotionMentionSheet.js +279 -0
- package/lib/features/notion/NotionMentionSheet.js.map +1 -0
- package/lib/features/notion/NotionPageMenu.js +585 -0
- package/lib/features/notion/NotionPageMenu.js.map +1 -0
- package/lib/features/notion/NotionPageTree.js +220 -0
- package/lib/features/notion/NotionPageTree.js.map +1 -0
- package/lib/features/notion/NotionPageView.js +1253 -152
- package/lib/features/notion/NotionPageView.js.map +1 -1
- package/lib/features/notion/NotionShareSheet.js +606 -0
- package/lib/features/notion/NotionShareSheet.js.map +1 -0
- package/lib/features/notion/NotionSheets.js +87 -15
- package/lib/features/notion/NotionSheets.js.map +1 -1
- package/lib/features/notion/NotionSidebarSections.js +492 -0
- package/lib/features/notion/NotionSidebarSections.js.map +1 -0
- package/lib/features/notion/NotionWorkspaceAdmin.js +659 -0
- package/lib/features/notion/NotionWorkspaceAdmin.js.map +1 -0
- package/lib/features/notion/NotionWorkspaceView.js +257 -45
- package/lib/features/notion/NotionWorkspaceView.js.map +1 -1
- package/lib/features/notion/database/DatabaseCells.js +554 -0
- package/lib/features/notion/database/DatabaseCells.js.map +1 -0
- package/lib/features/notion/database/DatabaseDateLayouts.js +792 -0
- package/lib/features/notion/database/DatabaseDateLayouts.js.map +1 -0
- package/lib/features/notion/database/DatabaseLayouts.js +461 -0
- package/lib/features/notion/database/DatabaseLayouts.js.map +1 -0
- package/lib/features/notion/database/DatabaseSheets.js +791 -0
- package/lib/features/notion/database/DatabaseSheets.js.map +1 -0
- package/lib/features/notion/database/NotionDatabaseView.js +817 -0
- package/lib/features/notion/database/NotionDatabaseView.js.map +1 -0
- package/lib/features/notion/database/RowPropertiesPanel.js +162 -0
- package/lib/features/notion/database/RowPropertiesPanel.js.map +1 -0
- package/lib/features/notion/database/chartData.js +89 -0
- package/lib/features/notion/database/chartData.js.map +1 -0
- package/lib/features/notion/database/chartView.js +112 -0
- package/lib/features/notion/database/chartView.js.map +1 -0
- package/lib/features/notion/database/connectorButton.js +33 -0
- package/lib/features/notion/database/connectorButton.js.map +1 -0
- package/lib/features/notion/database/databaseCalc.js +208 -0
- package/lib/features/notion/database/databaseCalc.js.map +1 -0
- package/lib/features/notion/database/databaseCalendar.js +157 -0
- package/lib/features/notion/database/databaseCalendar.js.map +1 -0
- package/lib/features/notion/database/databaseCsv.js +98 -0
- package/lib/features/notion/database/databaseCsv.js.map +1 -0
- package/lib/features/notion/database/databaseCsvActions.js +58 -0
- package/lib/features/notion/database/databaseCsvActions.js.map +1 -0
- package/lib/features/notion/database/databaseFilter.js +473 -0
- package/lib/features/notion/database/databaseFilter.js.map +1 -0
- package/lib/features/notion/database/databaseFormula.js +1072 -0
- package/lib/features/notion/database/databaseFormula.js.map +1 -0
- package/lib/features/notion/database/databaseGroup.js +151 -0
- package/lib/features/notion/database/databaseGroup.js.map +1 -0
- package/lib/features/notion/database/databaseRollup.js +58 -0
- package/lib/features/notion/database/databaseRollup.js.map +1 -0
- package/lib/features/notion/database/databaseTimeline.js +156 -0
- package/lib/features/notion/database/databaseTimeline.js.map +1 -0
- package/lib/features/notion/database/databaseView.js +1188 -0
- package/lib/features/notion/database/databaseView.js.map +1 -0
- package/lib/features/notion/database/databaseViews.js +310 -0
- package/lib/features/notion/database/databaseViews.js.map +1 -0
- package/lib/features/notion/database/relationSource.js +92 -0
- package/lib/features/notion/database/relationSource.js.map +1 -0
- package/lib/features/notion/database/uniqueId.js +17 -0
- package/lib/features/notion/database/uniqueId.js.map +1 -0
- package/lib/features/notion/database/useNotionDatabase.js +617 -0
- package/lib/features/notion/database/useNotionDatabase.js.map +1 -0
- package/lib/features/notion/notionAgentRunStatus.js +39 -0
- package/lib/features/notion/notionAgentRunStatus.js.map +1 -0
- package/lib/features/notion/notionCodeLanguages.js +112 -0
- package/lib/features/notion/notionCodeLanguages.js.map +1 -0
- package/lib/features/notion/notionComments.js +86 -0
- package/lib/features/notion/notionComments.js.map +1 -0
- package/lib/features/notion/notionConnections.js +74 -0
- package/lib/features/notion/notionConnections.js.map +1 -0
- package/lib/features/notion/notionDocuments.js +453 -1
- package/lib/features/notion/notionDocuments.js.map +1 -1
- package/lib/features/notion/notionEditorModel.js +142 -7
- package/lib/features/notion/notionEditorModel.js.map +1 -1
- package/lib/features/notion/notionMarkdownShortcuts.js +51 -0
- package/lib/features/notion/notionMarkdownShortcuts.js.map +1 -0
- package/lib/features/notion/notionMedia.js +119 -0
- package/lib/features/notion/notionMedia.js.map +1 -0
- package/lib/features/notion/notionMentionDate.js +32 -0
- package/lib/features/notion/notionMentionDate.js.map +1 -0
- package/lib/features/notion/notionMentionOptions.js +162 -0
- package/lib/features/notion/notionMentionOptions.js.map +1 -0
- package/lib/features/notion/notionNotesAgent.js +445 -0
- package/lib/features/notion/notionNotesAgent.js.map +1 -0
- package/lib/features/notion/notionPageAccess.js +168 -0
- package/lib/features/notion/notionPageAccess.js.map +1 -0
- package/lib/features/notion/notionPageActions.js +138 -0
- package/lib/features/notion/notionPageActions.js.map +1 -0
- package/lib/features/notion/notionPageHistory.js +154 -0
- package/lib/features/notion/notionPageHistory.js.map +1 -0
- package/lib/features/notion/notionPageKinds.js +200 -0
- package/lib/features/notion/notionPageKinds.js.map +1 -0
- package/lib/features/notion/notionRecents.js +48 -0
- package/lib/features/notion/notionRecents.js.map +1 -0
- package/lib/features/notion/notionRichText.js +177 -0
- package/lib/features/notion/notionRichText.js.map +1 -0
- package/lib/features/notion/notionRichTitle.js +336 -0
- package/lib/features/notion/notionRichTitle.js.map +1 -0
- package/lib/features/notion/useNotionWorkspace.js +272 -13
- package/lib/features/notion/useNotionWorkspace.js.map +1 -1
- package/lib/features/notion/usePageActions.js +155 -0
- package/lib/features/notion/usePageActions.js.map +1 -0
- package/lib/features/resume/ResumeAgentChatPane.js +1 -1
- package/lib/features/resume/ResumeAgentChatPane.js.map +1 -1
- package/lib/features/shopping/ShoppingAgentChatPane.js +1 -1
- package/lib/features/shopping/ShoppingAgentChatPane.js.map +1 -1
- package/lib/features/study/StudyAgentChatPane.js +1 -1
- package/lib/features/study/StudyAgentChatPane.js.map +1 -1
- package/lib/features/travel/TravelAgentChatPane.js +1 -1
- package/lib/features/travel/TravelAgentChatPane.js.map +1 -1
- package/lib/features/webbuilder/WebBuilderExperience.js +40 -8
- package/lib/features/webbuilder/WebBuilderExperience.js.map +1 -1
- package/lib/features/webbuilder/buildFragments.js +1 -1
- package/lib/features/webbuilder/buildFragments.js.map +1 -1
- package/lib/features/webbuilder/codeFiles.js +302 -0
- package/lib/features/webbuilder/codeFiles.js.map +1 -0
- package/lib/features/webbuilder/codeHighlight.js +209 -0
- package/lib/features/webbuilder/codeHighlight.js.map +1 -0
- package/lib/features/webbuilder/components/CodeView.js +682 -52
- package/lib/features/webbuilder/components/CodeView.js.map +1 -1
- package/lib/features/webbuilder/components/PreviewScreen.js +59 -38
- package/lib/features/webbuilder/components/PreviewScreen.js.map +1 -1
- package/lib/features/webbuilder/components/ProjectChat.js +3 -3
- package/lib/features/webbuilder/components/ProjectChat.js.map +1 -1
- package/lib/features/webbuilder/stepLabels.js +68 -0
- package/lib/features/webbuilder/stepLabels.js.map +1 -0
- package/lib/hooks/useHostChatSteering.js +45 -0
- package/lib/hooks/useHostChatSteering.js.map +1 -0
- package/lib/screens/Chat/index.js +2 -12
- package/lib/screens/Chat/index.js.map +1 -1
- package/lib/screens/ExpensesNative/useExpensesHostChat.js +25 -5
- package/lib/screens/ExpensesNative/useExpensesHostChat.js.map +1 -1
- package/lib/screens/InboxNative/useInboxHostChat.js +25 -5
- package/lib/screens/InboxNative/useInboxHostChat.js.map +1 -1
- package/lib/screens/JobSearchNative/useJobSearchHostChat.js +25 -5
- package/lib/screens/JobSearchNative/useJobSearchHostChat.js.map +1 -1
- package/lib/screens/LocalServicesNative/useLocalServicesHostChat.js +25 -5
- package/lib/screens/LocalServicesNative/useLocalServicesHostChat.js.map +1 -1
- package/lib/screens/MoviesNative/useMoviesHostChat.js +25 -5
- package/lib/screens/MoviesNative/useMoviesHostChat.js.map +1 -1
- package/lib/screens/NotionPage/index.js +2 -2
- package/lib/screens/NotionPage/index.js.map +1 -1
- package/lib/screens/ResumeNative/useResumeHostChat.js +25 -5
- package/lib/screens/ResumeNative/useResumeHostChat.js.map +1 -1
- package/lib/screens/ShoppingNative/useShoppingHostChat.js +25 -5
- package/lib/screens/ShoppingNative/useShoppingHostChat.js.map +1 -1
- package/lib/screens/StudyNative/useStudyHostChat.js +25 -5
- package/lib/screens/StudyNative/useStudyHostChat.js.map +1 -1
- package/lib/screens/TravelNative/useTravelHostChat.js +25 -5
- package/lib/screens/TravelNative/useTravelHostChat.js.map +1 -1
- package/lib/screens/WebBuilderNative/codeWorkspaceApi.js +222 -0
- package/lib/screens/WebBuilderNative/codeWorkspaceApi.js.map +1 -0
- package/lib/screens/WebBuilderNative/index.js +1 -1
- package/lib/screens/WebBuilderNative/index.js.map +1 -1
- package/lib/screens/WebBuilderNative/sandboxProxyApi.js +126 -4
- package/lib/screens/WebBuilderNative/sandboxProxyApi.js.map +1 -1
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js +120 -11
- package/lib/screens/WebBuilderNative/useWebBuilderHost.js.map +1 -1
- package/package.json +3 -3
|
@@ -0,0 +1,1072 @@
|
|
|
1
|
+
import {baseCellValue,richTextToPlain,cellDisplayText,multiSelectNames,connectorCellValue,numberValue,dateString}from'./databaseView.js';var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
4
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
7
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
8
|
+
var __spreadValues = (a, b) => {
|
|
9
|
+
for (var prop in b || (b = {}))
|
|
10
|
+
if (__hasOwnProp.call(b, prop))
|
|
11
|
+
__defNormalProp(a, prop, b[prop]);
|
|
12
|
+
if (__getOwnPropSymbols)
|
|
13
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
14
|
+
if (__propIsEnum.call(b, prop))
|
|
15
|
+
__defNormalProp(a, prop, b[prop]);
|
|
16
|
+
}
|
|
17
|
+
return a;
|
|
18
|
+
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
20
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
21
|
+
class FormulaError extends Error {
|
|
22
|
+
}
|
|
23
|
+
class FormulaCycleError extends Error {
|
|
24
|
+
}
|
|
25
|
+
const MAX_SOURCE = 2e3;
|
|
26
|
+
const MAX_NESTING = 64;
|
|
27
|
+
const OPERATORS = ["==", "!=", ">=", "<=", "&&", "||", "+", "-", "*", "/", "%", "^", ">", "<", "!", "="];
|
|
28
|
+
function tokenize(src) {
|
|
29
|
+
var _a;
|
|
30
|
+
const out = [];
|
|
31
|
+
let i = 0;
|
|
32
|
+
while (i < src.length) {
|
|
33
|
+
const ch = src[i];
|
|
34
|
+
if (/\s/.test(ch)) {
|
|
35
|
+
i += 1;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (/[0-9]/.test(ch) || ch === "." && /[0-9]/.test((_a = src[i + 1]) != null ? _a : "")) {
|
|
39
|
+
const m = /^(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/.exec(src.slice(i));
|
|
40
|
+
if (!m) throw new FormulaError(`Unexpected "${ch}" at ${i + 1}`);
|
|
41
|
+
out.push({
|
|
42
|
+
t: "num",
|
|
43
|
+
v: Number(m[0]),
|
|
44
|
+
pos: i
|
|
45
|
+
});
|
|
46
|
+
i += m[0].length;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
if (ch === '"' || ch === "'") {
|
|
50
|
+
let j = i + 1;
|
|
51
|
+
let text2 = "";
|
|
52
|
+
while (j < src.length && src[j] !== ch) {
|
|
53
|
+
if (src[j] === "\\" && j + 1 < src.length) {
|
|
54
|
+
const next = src[j + 1];
|
|
55
|
+
text2 += next === "n" ? "\n" : next === "t" ? " " : next;
|
|
56
|
+
j += 2;
|
|
57
|
+
} else {
|
|
58
|
+
text2 += src[j];
|
|
59
|
+
j += 1;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (j >= src.length) throw new FormulaError("Missing closing quote");
|
|
63
|
+
out.push({
|
|
64
|
+
t: "str",
|
|
65
|
+
v: text2,
|
|
66
|
+
pos: i
|
|
67
|
+
});
|
|
68
|
+
i = j + 1;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (/[A-Za-z_]/.test(ch)) {
|
|
72
|
+
const m = /^[A-Za-z_][A-Za-z0-9_]*/.exec(src.slice(i));
|
|
73
|
+
out.push({
|
|
74
|
+
t: "id",
|
|
75
|
+
v: m[0],
|
|
76
|
+
pos: i
|
|
77
|
+
});
|
|
78
|
+
i += m[0].length;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
if (ch === "(" || ch === ")" || ch === "," || ch === "[" || ch === "]" || ch === ".") {
|
|
82
|
+
out.push({
|
|
83
|
+
t: ch,
|
|
84
|
+
pos: i
|
|
85
|
+
});
|
|
86
|
+
i += 1;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
const op = OPERATORS.find((o) => src.startsWith(o, i));
|
|
90
|
+
if (op) {
|
|
91
|
+
out.push({
|
|
92
|
+
t: "op",
|
|
93
|
+
v: op === "=" ? "==" : op,
|
|
94
|
+
pos: i
|
|
95
|
+
});
|
|
96
|
+
i += op.length;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
throw new FormulaError(`Unexpected "${ch}" at ${i + 1}`);
|
|
100
|
+
}
|
|
101
|
+
out.push({
|
|
102
|
+
t: "eof",
|
|
103
|
+
pos: src.length
|
|
104
|
+
});
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
const BINARY_BP = {
|
|
108
|
+
or: 1,
|
|
109
|
+
and: 2,
|
|
110
|
+
"==": 3,
|
|
111
|
+
"!=": 3,
|
|
112
|
+
">": 4,
|
|
113
|
+
"<": 4,
|
|
114
|
+
">=": 4,
|
|
115
|
+
"<=": 4,
|
|
116
|
+
"+": 5,
|
|
117
|
+
"-": 5,
|
|
118
|
+
"*": 6,
|
|
119
|
+
"/": 6,
|
|
120
|
+
"%": 6,
|
|
121
|
+
"^": 7
|
|
122
|
+
};
|
|
123
|
+
const FUNCTIONS = {
|
|
124
|
+
if: [3, 3],
|
|
125
|
+
concat: [1, 50],
|
|
126
|
+
length: [1, 1],
|
|
127
|
+
lower: [1, 1],
|
|
128
|
+
upper: [1, 1],
|
|
129
|
+
contains: [2, 2],
|
|
130
|
+
empty: [1, 1],
|
|
131
|
+
format: [1, 1],
|
|
132
|
+
tonumber: [1, 1],
|
|
133
|
+
round: [1, 2],
|
|
134
|
+
floor: [1, 1],
|
|
135
|
+
ceil: [1, 1],
|
|
136
|
+
abs: [1, 1],
|
|
137
|
+
sqrt: [1, 1],
|
|
138
|
+
min: [1, 50],
|
|
139
|
+
max: [1, 50],
|
|
140
|
+
now: [0, 0],
|
|
141
|
+
today: [0, 0],
|
|
142
|
+
datebetween: [3, 3],
|
|
143
|
+
dateadd: [3, 3],
|
|
144
|
+
not: [1, 1],
|
|
145
|
+
and: [2, 50],
|
|
146
|
+
or: [2, 50],
|
|
147
|
+
// Formula 2.0
|
|
148
|
+
ifs: [3, 51],
|
|
149
|
+
map: [2, 2],
|
|
150
|
+
filter: [2, 2],
|
|
151
|
+
find: [2, 2],
|
|
152
|
+
some: [2, 2],
|
|
153
|
+
every: [2, 2],
|
|
154
|
+
join: [1, 2],
|
|
155
|
+
at: [2, 2],
|
|
156
|
+
first: [1, 1],
|
|
157
|
+
last: [1, 1],
|
|
158
|
+
sum: [1, 50],
|
|
159
|
+
average: [1, 50],
|
|
160
|
+
median: [1, 50],
|
|
161
|
+
sort: [1, 1],
|
|
162
|
+
reverse: [1, 1],
|
|
163
|
+
unique: [1, 1],
|
|
164
|
+
includes: [2, 2],
|
|
165
|
+
slice: [2, 3],
|
|
166
|
+
split: [2, 2],
|
|
167
|
+
trim: [1, 1],
|
|
168
|
+
replace: [3, 3],
|
|
169
|
+
replaceall: [3, 3],
|
|
170
|
+
substring: [2, 3],
|
|
171
|
+
repeat: [2, 2],
|
|
172
|
+
startswith: [2, 2],
|
|
173
|
+
endswith: [2, 2],
|
|
174
|
+
padstart: [2, 3],
|
|
175
|
+
formatdate: [2, 2],
|
|
176
|
+
parsedate: [1, 1],
|
|
177
|
+
year: [1, 1],
|
|
178
|
+
month: [1, 1],
|
|
179
|
+
date: [1, 1],
|
|
180
|
+
day: [1, 1],
|
|
181
|
+
week: [1, 1],
|
|
182
|
+
hour: [1, 1],
|
|
183
|
+
minute: [1, 1],
|
|
184
|
+
timestamp: [1, 1],
|
|
185
|
+
tostring: [1, 1]
|
|
186
|
+
};
|
|
187
|
+
const LIST_LAMBDAS = /* @__PURE__ */ new Set(["map", "filter", "find", "some", "every"]);
|
|
188
|
+
class Parser {
|
|
189
|
+
constructor(tokens) {
|
|
190
|
+
this.tokens = tokens;
|
|
191
|
+
__publicField(this, "i", 0);
|
|
192
|
+
__publicField(this, "depth", 0);
|
|
193
|
+
__publicField(this, "refs", /* @__PURE__ */ new Set());
|
|
194
|
+
/** Names in scope: let / lets variables, `current` / `index` inside map() & co. */
|
|
195
|
+
__publicField(this, "scopes", []);
|
|
196
|
+
}
|
|
197
|
+
inScope(name) {
|
|
198
|
+
return this.scopes.some((s) => s.includes(name));
|
|
199
|
+
}
|
|
200
|
+
withScope(names, fn) {
|
|
201
|
+
this.scopes.push(names);
|
|
202
|
+
try {
|
|
203
|
+
return fn();
|
|
204
|
+
} finally {
|
|
205
|
+
this.scopes.pop();
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
peekAt(offset) {
|
|
209
|
+
return this.tokens[Math.min(this.i + offset, this.tokens.length - 1)];
|
|
210
|
+
}
|
|
211
|
+
/** `x.f(a)` → f(x, a); repeated for chains. */
|
|
212
|
+
parsePostfix(node) {
|
|
213
|
+
let out = node;
|
|
214
|
+
while (this.peek().t === ".") {
|
|
215
|
+
const dot = this.next();
|
|
216
|
+
const name = this.next();
|
|
217
|
+
if (name.t !== "id") throw new FormulaError(`Expected a function name after "." at ${dot.pos + 1}`);
|
|
218
|
+
this.expect("(", `"(" after .${name.v}`);
|
|
219
|
+
out = this.parseCallRest(name.v, out);
|
|
220
|
+
}
|
|
221
|
+
return out;
|
|
222
|
+
}
|
|
223
|
+
parseArgList() {
|
|
224
|
+
const args = [];
|
|
225
|
+
if (this.peek().t !== ")") {
|
|
226
|
+
for (; ; ) {
|
|
227
|
+
args.push(this.parseExpr(0));
|
|
228
|
+
if (this.peek().t === ",") {
|
|
229
|
+
this.next();
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return args;
|
|
236
|
+
}
|
|
237
|
+
/** After `name(` (and an optional receiver from `x.name(`): the arguments and `)`. */
|
|
238
|
+
parseCallRest(word, receiver) {
|
|
239
|
+
const lower = word.toLowerCase();
|
|
240
|
+
if (lower === "let" || lower === "lets") {
|
|
241
|
+
if (receiver) throw new FormulaError(`${word}() can't be chained`);
|
|
242
|
+
const names = [];
|
|
243
|
+
const values = [];
|
|
244
|
+
for (; ; ) {
|
|
245
|
+
const id = this.next();
|
|
246
|
+
if (id.t !== "id") throw new FormulaError(`${word}() needs a variable name, e.g. let(x, 1, x + 1)`);
|
|
247
|
+
this.expect(",", `"," after ${id.v}`);
|
|
248
|
+
values.push(this.withScope(names.slice(), () => this.parseExpr(0)));
|
|
249
|
+
names.push(id.v);
|
|
250
|
+
this.expect(",", `"," in ${word}()`);
|
|
251
|
+
const more = lower === "lets" && this.peek().t === "id" && this.peekAt(1).t === "," && this.peekAt(1) !== void 0;
|
|
252
|
+
if (!more) break;
|
|
253
|
+
}
|
|
254
|
+
const body = this.withScope(names, () => this.parseExpr(0));
|
|
255
|
+
this.expect(")", `")" to close ${word}(`);
|
|
256
|
+
return {
|
|
257
|
+
k: "let",
|
|
258
|
+
names,
|
|
259
|
+
values,
|
|
260
|
+
body
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
let args;
|
|
264
|
+
if (LIST_LAMBDAS.has(lower)) {
|
|
265
|
+
const list2 = receiver != null ? receiver : this.parseExpr(0);
|
|
266
|
+
if (!receiver) this.expect(",", `"," in ${word}()`);
|
|
267
|
+
const fn = this.withScope(["current", "index"], () => this.parseExpr(0));
|
|
268
|
+
args = [list2, fn];
|
|
269
|
+
} else {
|
|
270
|
+
args = this.parseArgList();
|
|
271
|
+
if (receiver) args = [receiver, ...args];
|
|
272
|
+
}
|
|
273
|
+
this.expect(")", `")" to close ${word}(`);
|
|
274
|
+
if (lower === "prop") {
|
|
275
|
+
const a = args[0];
|
|
276
|
+
if (receiver || args.length !== 1 || a.k !== "lit" || typeof a.v !== "string") {
|
|
277
|
+
throw new FormulaError('prop() takes one property name in quotes, e.g. prop("Price")');
|
|
278
|
+
}
|
|
279
|
+
this.refs.add(a.v);
|
|
280
|
+
return {
|
|
281
|
+
k: "prop",
|
|
282
|
+
name: a.v
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
const arity = FUNCTIONS[lower];
|
|
286
|
+
if (!arity) throw new FormulaError(`Unknown function "${word}"`);
|
|
287
|
+
if (args.length < arity[0] || args.length > arity[1]) {
|
|
288
|
+
const want = arity[0] === arity[1] ? `${arity[0]}` : `${arity[0]}\u2013${arity[1]}`;
|
|
289
|
+
throw new FormulaError(`${word}() takes ${want} argument${arity[1] === 1 ? "" : "s"}`);
|
|
290
|
+
}
|
|
291
|
+
return {
|
|
292
|
+
k: "call",
|
|
293
|
+
name: lower,
|
|
294
|
+
args
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
peek() {
|
|
298
|
+
return this.tokens[this.i];
|
|
299
|
+
}
|
|
300
|
+
next() {
|
|
301
|
+
return this.tokens[this.i++];
|
|
302
|
+
}
|
|
303
|
+
expect(t, what) {
|
|
304
|
+
const tok = this.next();
|
|
305
|
+
if (tok.t !== t) throw new FormulaError(`Expected ${what} at ${tok.pos + 1}`);
|
|
306
|
+
return tok;
|
|
307
|
+
}
|
|
308
|
+
/** Binary operator name of a token (`&&` → and), or null. */
|
|
309
|
+
binaryOp(tok) {
|
|
310
|
+
if (tok.t === "op") {
|
|
311
|
+
if (tok.v === "&&") return "and";
|
|
312
|
+
if (tok.v === "||") return "or";
|
|
313
|
+
return tok.v in BINARY_BP ? tok.v : null;
|
|
314
|
+
}
|
|
315
|
+
if (tok.t === "id" && (tok.v === "and" || tok.v === "or")) return tok.v;
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
parseAll() {
|
|
319
|
+
if (this.peek().t === "eof") throw new FormulaError("Formula is empty");
|
|
320
|
+
const node = this.parseExpr(0);
|
|
321
|
+
const tok = this.peek();
|
|
322
|
+
if (tok.t !== "eof") throw new FormulaError(`Unexpected ${describe(tok)} at ${tok.pos + 1}`);
|
|
323
|
+
return node;
|
|
324
|
+
}
|
|
325
|
+
parseExpr(minBp) {
|
|
326
|
+
if (++this.depth > MAX_NESTING) throw new FormulaError("Formula is nested too deeply");
|
|
327
|
+
let left = this.parsePrefix();
|
|
328
|
+
for (; ; ) {
|
|
329
|
+
const op = this.binaryOp(this.peek());
|
|
330
|
+
if (!op) break;
|
|
331
|
+
const bp = BINARY_BP[op];
|
|
332
|
+
if (bp <= minBp) break;
|
|
333
|
+
this.next();
|
|
334
|
+
const right = this.parseExpr(op === "^" ? bp - 1 : bp);
|
|
335
|
+
left = {
|
|
336
|
+
k: "bin",
|
|
337
|
+
op,
|
|
338
|
+
l: left,
|
|
339
|
+
r: right
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
this.depth -= 1;
|
|
343
|
+
return left;
|
|
344
|
+
}
|
|
345
|
+
parsePrefix() {
|
|
346
|
+
return this.parsePostfix(this.parsePrimary());
|
|
347
|
+
}
|
|
348
|
+
parsePrimary() {
|
|
349
|
+
const tok = this.next();
|
|
350
|
+
switch (tok.t) {
|
|
351
|
+
case "num":
|
|
352
|
+
return {
|
|
353
|
+
k: "lit",
|
|
354
|
+
v: tok.v
|
|
355
|
+
};
|
|
356
|
+
case "str":
|
|
357
|
+
return {
|
|
358
|
+
k: "lit",
|
|
359
|
+
v: tok.v
|
|
360
|
+
};
|
|
361
|
+
case "(": {
|
|
362
|
+
const inner = this.parseExpr(0);
|
|
363
|
+
this.expect(")", '")"');
|
|
364
|
+
return inner;
|
|
365
|
+
}
|
|
366
|
+
case "[": {
|
|
367
|
+
const items = [];
|
|
368
|
+
if (this.peek().t !== "]") {
|
|
369
|
+
for (; ; ) {
|
|
370
|
+
items.push(this.parseExpr(0));
|
|
371
|
+
if (this.peek().t === ",") {
|
|
372
|
+
this.next();
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
this.expect("]", '"]" to close the list');
|
|
379
|
+
return {
|
|
380
|
+
k: "list",
|
|
381
|
+
items
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
case "op":
|
|
385
|
+
if (tok.v === "-") return {
|
|
386
|
+
k: "unary",
|
|
387
|
+
op: "-",
|
|
388
|
+
arg: this.parseExpr(6)
|
|
389
|
+
};
|
|
390
|
+
if (tok.v === "+") return this.parseExpr(6);
|
|
391
|
+
if (tok.v === "!") return {
|
|
392
|
+
k: "unary",
|
|
393
|
+
op: "not",
|
|
394
|
+
arg: this.parseExpr(2)
|
|
395
|
+
};
|
|
396
|
+
throw new FormulaError(`Unexpected "${tok.v}" at ${tok.pos + 1}`);
|
|
397
|
+
case "id": {
|
|
398
|
+
const word = tok.v;
|
|
399
|
+
const lower = word.toLowerCase();
|
|
400
|
+
if (lower === "true" || lower === "false") return {
|
|
401
|
+
k: "lit",
|
|
402
|
+
v: lower === "true"
|
|
403
|
+
};
|
|
404
|
+
if (lower === "not" && this.peek().t !== "(") {
|
|
405
|
+
return {
|
|
406
|
+
k: "unary",
|
|
407
|
+
op: "not",
|
|
408
|
+
arg: this.parseExpr(2)
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
if (this.peek().t !== "(") {
|
|
412
|
+
if (this.inScope(word)) return {
|
|
413
|
+
k: "var",
|
|
414
|
+
name: word
|
|
415
|
+
};
|
|
416
|
+
throw new FormulaError(`Unknown name "${word}" \u2014 use prop("${word}")`);
|
|
417
|
+
}
|
|
418
|
+
this.next();
|
|
419
|
+
return this.parseCallRest(word);
|
|
420
|
+
}
|
|
421
|
+
case ")":
|
|
422
|
+
throw new FormulaError(`Unexpected ")" at ${tok.pos + 1}`);
|
|
423
|
+
case ",":
|
|
424
|
+
throw new FormulaError(`Unexpected "," at ${tok.pos + 1}`);
|
|
425
|
+
case "]":
|
|
426
|
+
case ".":
|
|
427
|
+
throw new FormulaError(`Unexpected "${tok.t}" at ${tok.pos + 1}`);
|
|
428
|
+
default:
|
|
429
|
+
throw new FormulaError("Formula ended unexpectedly");
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function describe(tok) {
|
|
434
|
+
if (tok.t === "num" || tok.t === "id") return `"${tok.v}"`;
|
|
435
|
+
if (tok.t === "str") return "text";
|
|
436
|
+
if (tok.t === "op") return `"${tok.v}"`;
|
|
437
|
+
if (tok.t === "eof") return "end";
|
|
438
|
+
return `"${tok.t}"`;
|
|
439
|
+
}
|
|
440
|
+
function compileFormula(source, opts = {}) {
|
|
441
|
+
try {
|
|
442
|
+
if ((source != null ? source : "").length > MAX_SOURCE) throw new FormulaError("Formula is too long");
|
|
443
|
+
const parser = new Parser(tokenize(source != null ? source : ""));
|
|
444
|
+
const ast = parser.parseAll();
|
|
445
|
+
const refs = [...parser.refs];
|
|
446
|
+
if (opts.self && refs.includes(opts.self)) throw new FormulaError("A formula cannot reference itself");
|
|
447
|
+
if (opts.properties) {
|
|
448
|
+
const missing = refs.find((r) => !opts.properties.includes(r));
|
|
449
|
+
if (missing) throw new FormulaError(`Unknown property "${missing}"`);
|
|
450
|
+
}
|
|
451
|
+
return {
|
|
452
|
+
ok: true,
|
|
453
|
+
ast,
|
|
454
|
+
refs
|
|
455
|
+
};
|
|
456
|
+
} catch (e) {
|
|
457
|
+
if (e instanceof FormulaError) return {
|
|
458
|
+
ok: false,
|
|
459
|
+
error: e.message
|
|
460
|
+
};
|
|
461
|
+
throw e;
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
const compileCache = /* @__PURE__ */ new Map();
|
|
465
|
+
function compileCached(source) {
|
|
466
|
+
let hit = compileCache.get(source);
|
|
467
|
+
if (!hit) {
|
|
468
|
+
if (compileCache.size > 500) compileCache.clear();
|
|
469
|
+
hit = compileFormula(source);
|
|
470
|
+
compileCache.set(source, hit);
|
|
471
|
+
}
|
|
472
|
+
return hit;
|
|
473
|
+
}
|
|
474
|
+
const MAX_STEPS = 1e5;
|
|
475
|
+
const MAX_LIST = 1e4;
|
|
476
|
+
const MAX_TEXT = 1e5;
|
|
477
|
+
const isDate = (v) => v instanceof Date;
|
|
478
|
+
function formatFormulaValue(v) {
|
|
479
|
+
if (v === null) return "";
|
|
480
|
+
if (Array.isArray(v)) return v.map(formatFormulaValue).join(", ");
|
|
481
|
+
if (isDate(v)) {
|
|
482
|
+
const midnight = v.getHours() === 0 && v.getMinutes() === 0 && v.getSeconds() === 0;
|
|
483
|
+
return midnight ? v.toLocaleDateString(void 0, {
|
|
484
|
+
year: "numeric",
|
|
485
|
+
month: "short",
|
|
486
|
+
day: "numeric"
|
|
487
|
+
}) : v.toLocaleString(void 0, {
|
|
488
|
+
dateStyle: "medium",
|
|
489
|
+
timeStyle: "short"
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
if (typeof v === "number") return String(Number(v.toPrecision(12)));
|
|
493
|
+
return String(v);
|
|
494
|
+
}
|
|
495
|
+
function truthy(v) {
|
|
496
|
+
if (v === null) return false;
|
|
497
|
+
if (Array.isArray(v)) return v.length > 0;
|
|
498
|
+
if (typeof v === "boolean") return v;
|
|
499
|
+
if (typeof v === "number") return v !== 0;
|
|
500
|
+
if (typeof v === "string") return v.length > 0;
|
|
501
|
+
return true;
|
|
502
|
+
}
|
|
503
|
+
function num(v, what) {
|
|
504
|
+
if (v === null) return 0;
|
|
505
|
+
if (typeof v === "number") return v;
|
|
506
|
+
if (typeof v === "boolean") return v ? 1 : 0;
|
|
507
|
+
throw new FormulaError(`${what} needs a number, got ${kind(v)}`);
|
|
508
|
+
}
|
|
509
|
+
function date(v, what) {
|
|
510
|
+
if (isDate(v)) return v;
|
|
511
|
+
throw new FormulaError(`${what} needs a date`);
|
|
512
|
+
}
|
|
513
|
+
function text(v) {
|
|
514
|
+
return formatFormulaValue(v);
|
|
515
|
+
}
|
|
516
|
+
const DAY = 864e5;
|
|
517
|
+
function wallClockDiff(a, b) {
|
|
518
|
+
return a.getTime() - b.getTime() - (a.getTimezoneOffset() - b.getTimezoneOffset()) * 6e4;
|
|
519
|
+
}
|
|
520
|
+
function addMonthsClamped(d, months) {
|
|
521
|
+
const out = new Date(d.getTime());
|
|
522
|
+
const day = d.getDate();
|
|
523
|
+
out.setDate(1);
|
|
524
|
+
out.setMonth(out.getMonth() + months);
|
|
525
|
+
const last = new Date(out.getFullYear(), out.getMonth() + 1, 0).getDate();
|
|
526
|
+
out.setDate(Math.min(day, last));
|
|
527
|
+
return out;
|
|
528
|
+
}
|
|
529
|
+
function monthsBetween(a, b) {
|
|
530
|
+
let m = (a.getFullYear() - b.getFullYear()) * 12 + (a.getMonth() - b.getMonth());
|
|
531
|
+
const anchor = addMonthsClamped(b, m);
|
|
532
|
+
if (m > 0 && anchor.getTime() > a.getTime()) m -= 1;
|
|
533
|
+
else if (m < 0 && anchor.getTime() < a.getTime()) m += 1;
|
|
534
|
+
return m;
|
|
535
|
+
}
|
|
536
|
+
function normUnit(u) {
|
|
537
|
+
const s = String(u != null ? u : "").toLowerCase().trim();
|
|
538
|
+
const unit = s.endsWith("s") ? s : `${s}s`;
|
|
539
|
+
if (!["years", "quarters", "months", "weeks", "days", "hours", "minutes"].includes(unit)) {
|
|
540
|
+
throw new FormulaError(`Unknown unit "${String(u)}" (use "days", "weeks", "months", \u2026)`);
|
|
541
|
+
}
|
|
542
|
+
return unit;
|
|
543
|
+
}
|
|
544
|
+
function dateBetween(a, b, unitIn) {
|
|
545
|
+
const unit = normUnit(unitIn);
|
|
546
|
+
switch (unit) {
|
|
547
|
+
case "years":
|
|
548
|
+
return Math.trunc(monthsBetween(a, b) / 12);
|
|
549
|
+
case "quarters":
|
|
550
|
+
return Math.trunc(monthsBetween(a, b) / 3);
|
|
551
|
+
case "months":
|
|
552
|
+
return monthsBetween(a, b);
|
|
553
|
+
case "weeks":
|
|
554
|
+
return Math.trunc(wallClockDiff(a, b) / (7 * DAY));
|
|
555
|
+
case "days":
|
|
556
|
+
return Math.trunc(wallClockDiff(a, b) / DAY);
|
|
557
|
+
case "hours":
|
|
558
|
+
return Math.trunc((a.getTime() - b.getTime()) / 36e5);
|
|
559
|
+
default:
|
|
560
|
+
return Math.trunc((a.getTime() - b.getTime()) / 6e4);
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
function dateAdd(d, n, unitIn) {
|
|
564
|
+
const unit = normUnit(unitIn);
|
|
565
|
+
const whole = Math.trunc(n);
|
|
566
|
+
switch (unit) {
|
|
567
|
+
case "years":
|
|
568
|
+
return addMonthsClamped(d, whole * 12);
|
|
569
|
+
case "quarters":
|
|
570
|
+
return addMonthsClamped(d, whole * 3);
|
|
571
|
+
case "months":
|
|
572
|
+
return addMonthsClamped(d, whole);
|
|
573
|
+
case "weeks":
|
|
574
|
+
case "days": {
|
|
575
|
+
const out = new Date(d.getTime());
|
|
576
|
+
out.setDate(out.getDate() + whole * (unit === "weeks" ? 7 : 1));
|
|
577
|
+
return out;
|
|
578
|
+
}
|
|
579
|
+
case "hours":
|
|
580
|
+
return new Date(d.getTime() + n * 36e5);
|
|
581
|
+
default:
|
|
582
|
+
return new Date(d.getTime() + n * 6e4);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
function sameValue(l, r) {
|
|
586
|
+
if (isDate(l) && isDate(r)) return l.getTime() === r.getTime();
|
|
587
|
+
if (Array.isArray(l) && Array.isArray(r)) return l.length === r.length && l.every((x, i) => sameValue(x, r[i]));
|
|
588
|
+
return l === r;
|
|
589
|
+
}
|
|
590
|
+
function compare(op, l, r) {
|
|
591
|
+
if (op === "==" || op === "!=") {
|
|
592
|
+
const eq = sameValue(l, r);
|
|
593
|
+
return op === "==" ? eq : !eq;
|
|
594
|
+
}
|
|
595
|
+
let a;
|
|
596
|
+
let b;
|
|
597
|
+
if (isDate(l) && isDate(r)) {
|
|
598
|
+
a = l.getTime();
|
|
599
|
+
b = r.getTime();
|
|
600
|
+
} else if (typeof l === "string" && typeof r === "string") {
|
|
601
|
+
const c = l.localeCompare(r, void 0, {
|
|
602
|
+
numeric: true,
|
|
603
|
+
sensitivity: "base"
|
|
604
|
+
});
|
|
605
|
+
a = c;
|
|
606
|
+
b = 0;
|
|
607
|
+
} else if ((typeof l === "number" || l === null || typeof l === "boolean") && (typeof r === "number" || r === null || typeof r === "boolean")) {
|
|
608
|
+
a = num(l, op);
|
|
609
|
+
b = num(r, op);
|
|
610
|
+
} else {
|
|
611
|
+
throw new FormulaError(`Can't compare ${kind(l)} with ${kind(r)}`);
|
|
612
|
+
}
|
|
613
|
+
switch (op) {
|
|
614
|
+
case ">":
|
|
615
|
+
return a > b;
|
|
616
|
+
case "<":
|
|
617
|
+
return a < b;
|
|
618
|
+
case ">=":
|
|
619
|
+
return a >= b;
|
|
620
|
+
default:
|
|
621
|
+
return a <= b;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
function kind(v) {
|
|
625
|
+
if (v === null) return "empty";
|
|
626
|
+
if (Array.isArray(v)) return "a list";
|
|
627
|
+
if (isDate(v)) return "a date";
|
|
628
|
+
if (typeof v === "string") return "text";
|
|
629
|
+
if (typeof v === "boolean") return "a checkbox";
|
|
630
|
+
return "a number";
|
|
631
|
+
}
|
|
632
|
+
function evalNode(node, ctx) {
|
|
633
|
+
var _a;
|
|
634
|
+
if (ctx.budget && --ctx.budget.left < 0) throw new FormulaError("Formula is too complex");
|
|
635
|
+
switch (node.k) {
|
|
636
|
+
case "lit":
|
|
637
|
+
return node.v;
|
|
638
|
+
case "prop":
|
|
639
|
+
return ctx.getProp(node.name);
|
|
640
|
+
case "var": {
|
|
641
|
+
const vars = (_a = ctx.vars) != null ? _a : {};
|
|
642
|
+
if (!(node.name in vars)) throw new FormulaError(`"${node.name}" has no value here`);
|
|
643
|
+
return vars[node.name];
|
|
644
|
+
}
|
|
645
|
+
case "list":
|
|
646
|
+
return node.items.map((n) => evalNode(n, ctx));
|
|
647
|
+
case "let": {
|
|
648
|
+
let scope = ctx;
|
|
649
|
+
node.names.forEach((name, i) => {
|
|
650
|
+
var _a2;
|
|
651
|
+
const v = evalNode(node.values[i], scope);
|
|
652
|
+
scope = __spreadProps(__spreadValues({}, scope), {
|
|
653
|
+
vars: __spreadProps(__spreadValues({}, (_a2 = scope.vars) != null ? _a2 : {}), {
|
|
654
|
+
[name]: v
|
|
655
|
+
})
|
|
656
|
+
});
|
|
657
|
+
});
|
|
658
|
+
return evalNode(node.body, scope);
|
|
659
|
+
}
|
|
660
|
+
case "unary": {
|
|
661
|
+
const v = evalNode(node.arg, ctx);
|
|
662
|
+
return node.op === "-" ? -num(v, "Minus") : !truthy(v);
|
|
663
|
+
}
|
|
664
|
+
case "bin": {
|
|
665
|
+
if (node.op === "and") return truthy(evalNode(node.l, ctx)) && truthy(evalNode(node.r, ctx));
|
|
666
|
+
if (node.op === "or") return truthy(evalNode(node.l, ctx)) || truthy(evalNode(node.r, ctx));
|
|
667
|
+
const l = evalNode(node.l, ctx);
|
|
668
|
+
const r = evalNode(node.r, ctx);
|
|
669
|
+
switch (node.op) {
|
|
670
|
+
case "+":
|
|
671
|
+
if (typeof l === "string" || typeof r === "string") return text(l) + text(r);
|
|
672
|
+
if (isDate(l) || isDate(r)) throw new FormulaError("Use dateAdd() to add to a date");
|
|
673
|
+
return num(l, "+") + num(r, "+");
|
|
674
|
+
case "-":
|
|
675
|
+
if (isDate(l) || isDate(r)) throw new FormulaError("Use dateBetween() to subtract dates");
|
|
676
|
+
return num(l, "-") - num(r, "-");
|
|
677
|
+
case "*":
|
|
678
|
+
return num(l, "*") * num(r, "*");
|
|
679
|
+
case "/": {
|
|
680
|
+
const d = num(r, "/");
|
|
681
|
+
if (d === 0) throw new FormulaError("Division by zero");
|
|
682
|
+
return num(l, "/") / d;
|
|
683
|
+
}
|
|
684
|
+
case "%": {
|
|
685
|
+
const d = num(r, "%");
|
|
686
|
+
if (d === 0) throw new FormulaError("Division by zero");
|
|
687
|
+
return num(l, "%") % d;
|
|
688
|
+
}
|
|
689
|
+
case "^":
|
|
690
|
+
return num(l, "^") ** num(r, "^");
|
|
691
|
+
default:
|
|
692
|
+
return compare(node.op, l, r);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
case "call":
|
|
696
|
+
return callFunction(node.name, node.args, ctx);
|
|
697
|
+
default:
|
|
698
|
+
return null;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
function list(v) {
|
|
702
|
+
if (Array.isArray(v)) return v;
|
|
703
|
+
return v === null ? [] : [v];
|
|
704
|
+
}
|
|
705
|
+
function numbers(args, what) {
|
|
706
|
+
const out = [];
|
|
707
|
+
for (const a of args) for (const x of list(a)) if (x !== null) out.push(num(x, what));
|
|
708
|
+
return out;
|
|
709
|
+
}
|
|
710
|
+
function capList(v) {
|
|
711
|
+
if (v.length > MAX_LIST) throw new FormulaError("List is too long");
|
|
712
|
+
return v;
|
|
713
|
+
}
|
|
714
|
+
function capText(t) {
|
|
715
|
+
if (t.length > MAX_TEXT) throw new FormulaError("Text is too long");
|
|
716
|
+
return t;
|
|
717
|
+
}
|
|
718
|
+
const pad2 = (n) => String(n).padStart(2, "0");
|
|
719
|
+
function isoWeek(d) {
|
|
720
|
+
const t = new Date(Date.UTC(d.getFullYear(), d.getMonth(), d.getDate()));
|
|
721
|
+
const dayNum = t.getUTCDay() || 7;
|
|
722
|
+
t.setUTCDate(t.getUTCDate() + 4 - dayNum);
|
|
723
|
+
const yearStart = new Date(Date.UTC(t.getUTCFullYear(), 0, 1));
|
|
724
|
+
return Math.ceil(((t.getTime() - yearStart.getTime()) / DAY + 1) / 7);
|
|
725
|
+
}
|
|
726
|
+
function formatDatePattern(d, pattern) {
|
|
727
|
+
const month = (style) => d.toLocaleDateString("en-US", {
|
|
728
|
+
month: style
|
|
729
|
+
});
|
|
730
|
+
const weekday = (style) => d.toLocaleDateString("en-US", {
|
|
731
|
+
weekday: style
|
|
732
|
+
});
|
|
733
|
+
const h12 = d.getHours() % 12 || 12;
|
|
734
|
+
const tokens = {
|
|
735
|
+
YYYY: () => String(d.getFullYear()),
|
|
736
|
+
YY: () => String(d.getFullYear()).slice(-2),
|
|
737
|
+
MMMM: () => month("long"),
|
|
738
|
+
MMM: () => month("short"),
|
|
739
|
+
MM: () => pad2(d.getMonth() + 1),
|
|
740
|
+
M: () => String(d.getMonth() + 1),
|
|
741
|
+
DD: () => pad2(d.getDate()),
|
|
742
|
+
D: () => String(d.getDate()),
|
|
743
|
+
dddd: () => weekday("long"),
|
|
744
|
+
ddd: () => weekday("short"),
|
|
745
|
+
HH: () => pad2(d.getHours()),
|
|
746
|
+
H: () => String(d.getHours()),
|
|
747
|
+
hh: () => pad2(h12),
|
|
748
|
+
h: () => String(h12),
|
|
749
|
+
mm: () => pad2(d.getMinutes()),
|
|
750
|
+
ss: () => pad2(d.getSeconds()),
|
|
751
|
+
A: () => d.getHours() < 12 ? "AM" : "PM",
|
|
752
|
+
a: () => d.getHours() < 12 ? "am" : "pm"
|
|
753
|
+
};
|
|
754
|
+
return pattern.replace(/\[([^\]]*)\]|YYYY|YY|MMMM|MMM|MM|M|DD|D|dddd|ddd|HH|H|hh|h|mm|ss|A|a/g, (m, lit) => lit !== void 0 ? lit : tokens[m]());
|
|
755
|
+
}
|
|
756
|
+
function callFunction(name, argNodes, ctx) {
|
|
757
|
+
var _a, _b, _c, _d;
|
|
758
|
+
if (name === "if") return truthy(evalNode(argNodes[0], ctx)) ? evalNode(argNodes[1], ctx) : evalNode(argNodes[2], ctx);
|
|
759
|
+
if (name === "ifs") {
|
|
760
|
+
let i = 0;
|
|
761
|
+
for (; i + 1 < argNodes.length; i += 2) if (truthy(evalNode(argNodes[i], ctx))) return evalNode(argNodes[i + 1], ctx);
|
|
762
|
+
return i < argNodes.length ? evalNode(argNodes[i], ctx) : null;
|
|
763
|
+
}
|
|
764
|
+
if (LIST_LAMBDAS.has(name)) {
|
|
765
|
+
const items = list(evalNode(argNodes[0], ctx));
|
|
766
|
+
const each = (x, i) => {
|
|
767
|
+
var _a2;
|
|
768
|
+
return evalNode(argNodes[1], __spreadProps(__spreadValues({}, ctx), {
|
|
769
|
+
vars: __spreadProps(__spreadValues({}, (_a2 = ctx.vars) != null ? _a2 : {}), {
|
|
770
|
+
current: x,
|
|
771
|
+
index: i
|
|
772
|
+
})
|
|
773
|
+
}));
|
|
774
|
+
};
|
|
775
|
+
switch (name) {
|
|
776
|
+
case "map":
|
|
777
|
+
return capList(items.map(each));
|
|
778
|
+
case "filter":
|
|
779
|
+
return items.filter((x, i) => truthy(each(x, i)));
|
|
780
|
+
case "find":
|
|
781
|
+
return (_a = items.find((x, i) => truthy(each(x, i)))) != null ? _a : null;
|
|
782
|
+
case "some":
|
|
783
|
+
return items.some((x, i) => truthy(each(x, i)));
|
|
784
|
+
default:
|
|
785
|
+
return items.every((x, i) => truthy(each(x, i)));
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
if (name === "and") return argNodes.every((a2) => truthy(evalNode(a2, ctx)));
|
|
789
|
+
if (name === "or") return argNodes.some((a2) => truthy(evalNode(a2, ctx)));
|
|
790
|
+
const args = argNodes.map((a2) => evalNode(a2, ctx));
|
|
791
|
+
const [a, b, c] = args;
|
|
792
|
+
switch (name) {
|
|
793
|
+
case "concat":
|
|
794
|
+
if (args.some(Array.isArray)) return capList(args.flatMap((x) => list(x)));
|
|
795
|
+
return capText(args.map(text).join(""));
|
|
796
|
+
case "length":
|
|
797
|
+
return Array.isArray(a) ? a.length : text(a).length;
|
|
798
|
+
case "lower":
|
|
799
|
+
return text(a).toLowerCase();
|
|
800
|
+
case "upper":
|
|
801
|
+
return text(a).toUpperCase();
|
|
802
|
+
case "contains":
|
|
803
|
+
if (Array.isArray(a)) return a.some((x) => text(x).toLowerCase().includes(text(b).toLowerCase()));
|
|
804
|
+
return text(a).toLowerCase().includes(text(b).toLowerCase());
|
|
805
|
+
case "empty":
|
|
806
|
+
return a === null || a === "" || Array.isArray(a) && a.length === 0 || typeof a === "number" && Number.isNaN(a);
|
|
807
|
+
case "format":
|
|
808
|
+
return text(a);
|
|
809
|
+
case "not":
|
|
810
|
+
return !truthy(a);
|
|
811
|
+
case "tonumber": {
|
|
812
|
+
if (a === null) return null;
|
|
813
|
+
if (isDate(a)) return a.getTime();
|
|
814
|
+
if (typeof a === "boolean") return a ? 1 : 0;
|
|
815
|
+
if (typeof a === "number") return a;
|
|
816
|
+
const n = Number(String(a).trim().replace(/,/g, ""));
|
|
817
|
+
return String(a).trim() && Number.isFinite(n) ? n : null;
|
|
818
|
+
}
|
|
819
|
+
case "round": {
|
|
820
|
+
const digits = b === void 0 ? 0 : Math.max(0, Math.min(10, Math.trunc(num(b, "round"))));
|
|
821
|
+
const f = 10 ** digits;
|
|
822
|
+
return Math.round(num(a, "round") * f) / f;
|
|
823
|
+
}
|
|
824
|
+
case "floor":
|
|
825
|
+
return Math.floor(num(a, "floor"));
|
|
826
|
+
case "ceil":
|
|
827
|
+
return Math.ceil(num(a, "ceil"));
|
|
828
|
+
case "abs":
|
|
829
|
+
return Math.abs(num(a, "abs"));
|
|
830
|
+
case "sqrt": {
|
|
831
|
+
const n = num(a, "sqrt");
|
|
832
|
+
if (n < 0) throw new FormulaError("sqrt() of a negative number");
|
|
833
|
+
return Math.sqrt(n);
|
|
834
|
+
}
|
|
835
|
+
case "min": {
|
|
836
|
+
const ns = numbers(args, "min");
|
|
837
|
+
return ns.length ? Math.min(...ns) : null;
|
|
838
|
+
}
|
|
839
|
+
case "max": {
|
|
840
|
+
const ns = numbers(args, "max");
|
|
841
|
+
return ns.length ? Math.max(...ns) : null;
|
|
842
|
+
}
|
|
843
|
+
case "sum":
|
|
844
|
+
return numbers(args, "sum").reduce((x, y) => x + y, 0);
|
|
845
|
+
case "average": {
|
|
846
|
+
const ns = numbers(args, "average");
|
|
847
|
+
return ns.length ? ns.reduce((x, y) => x + y, 0) / ns.length : null;
|
|
848
|
+
}
|
|
849
|
+
case "median": {
|
|
850
|
+
const ns = numbers(args, "median").sort((x, y) => x - y);
|
|
851
|
+
if (!ns.length) return null;
|
|
852
|
+
const m = Math.floor(ns.length / 2);
|
|
853
|
+
return ns.length % 2 ? ns[m] : (ns[m - 1] + ns[m]) / 2;
|
|
854
|
+
}
|
|
855
|
+
case "join":
|
|
856
|
+
return capText(list(a).map(text).join(b === void 0 ? ", " : text(b)));
|
|
857
|
+
case "at": {
|
|
858
|
+
const items = list(a);
|
|
859
|
+
const i = Math.trunc(num(b, "at()"));
|
|
860
|
+
return (_b = items[i < 0 ? items.length + i : i]) != null ? _b : null;
|
|
861
|
+
}
|
|
862
|
+
case "first":
|
|
863
|
+
return (_c = list(a)[0]) != null ? _c : null;
|
|
864
|
+
case "last": {
|
|
865
|
+
const items = list(a);
|
|
866
|
+
return (_d = items[items.length - 1]) != null ? _d : null;
|
|
867
|
+
}
|
|
868
|
+
case "sort":
|
|
869
|
+
return [...list(a)].sort((x, y) => {
|
|
870
|
+
if (x === null) return 1;
|
|
871
|
+
if (y === null) return -1;
|
|
872
|
+
if (typeof x === "number" && typeof y === "number") return x - y;
|
|
873
|
+
if (isDate(x) && isDate(y)) return x.getTime() - y.getTime();
|
|
874
|
+
return text(x).localeCompare(text(y), void 0, {
|
|
875
|
+
numeric: true,
|
|
876
|
+
sensitivity: "base"
|
|
877
|
+
});
|
|
878
|
+
});
|
|
879
|
+
case "reverse":
|
|
880
|
+
return Array.isArray(a) ? [...a].reverse() : [...text(a)].reverse().join("");
|
|
881
|
+
case "unique": {
|
|
882
|
+
const out = [];
|
|
883
|
+
const seen = /* @__PURE__ */ new Set();
|
|
884
|
+
for (const x of list(a)) {
|
|
885
|
+
const key = x === null ? "null" : typeof x !== "object" ? `${typeof x}:${String(x)}` : isDate(x) ? `date:${x.getTime()}` : void 0;
|
|
886
|
+
if (key !== void 0) {
|
|
887
|
+
if (seen.has(key)) continue;
|
|
888
|
+
seen.add(key);
|
|
889
|
+
} else if (out.some((y) => sameValue(x, y))) continue;
|
|
890
|
+
out.push(x);
|
|
891
|
+
}
|
|
892
|
+
return out;
|
|
893
|
+
}
|
|
894
|
+
case "includes":
|
|
895
|
+
return list(a).some((x) => sameValue(x, b) || typeof x === "string" && typeof b === "string" && x.toLowerCase() === b.toLowerCase());
|
|
896
|
+
case "slice": {
|
|
897
|
+
const start = Math.trunc(num(b, "slice()"));
|
|
898
|
+
const end = c === void 0 ? void 0 : Math.trunc(num(c, "slice()"));
|
|
899
|
+
return Array.isArray(a) ? a.slice(start, end) : text(a).slice(start, end);
|
|
900
|
+
}
|
|
901
|
+
case "split":
|
|
902
|
+
return capList(text(a).split(text(b)));
|
|
903
|
+
case "trim":
|
|
904
|
+
return text(a).trim();
|
|
905
|
+
case "replace":
|
|
906
|
+
return text(a).replace(text(b), () => text(c));
|
|
907
|
+
case "replaceall":
|
|
908
|
+
return capText(text(b) ? text(a).split(text(b)).join(text(c)) : text(a));
|
|
909
|
+
case "substring": {
|
|
910
|
+
const start = Math.trunc(num(b, "substring()"));
|
|
911
|
+
return c === void 0 ? text(a).substring(start) : text(a).substring(start, Math.trunc(num(c, "substring()")));
|
|
912
|
+
}
|
|
913
|
+
case "repeat": {
|
|
914
|
+
const n = Math.max(0, Math.trunc(num(b, "repeat()")));
|
|
915
|
+
if (text(a).length * n > MAX_TEXT) throw new FormulaError("Text is too long");
|
|
916
|
+
return text(a).repeat(n);
|
|
917
|
+
}
|
|
918
|
+
case "startswith":
|
|
919
|
+
return text(a).startsWith(text(b));
|
|
920
|
+
case "endswith":
|
|
921
|
+
return text(a).endsWith(text(b));
|
|
922
|
+
case "padstart": {
|
|
923
|
+
const n = Math.min(1e3, Math.max(0, Math.trunc(num(b, "padStart()"))));
|
|
924
|
+
return text(a).padStart(n, c === void 0 ? " " : text(c) || " ");
|
|
925
|
+
}
|
|
926
|
+
case "formatdate":
|
|
927
|
+
if (a === null) return null;
|
|
928
|
+
return formatDatePattern(date(a, "formatDate()"), text(b));
|
|
929
|
+
case "parsedate": {
|
|
930
|
+
if (a === null || text(a).trim() === "") return null;
|
|
931
|
+
const d = parseDateValue(text(a).trim());
|
|
932
|
+
if (!d) throw new FormulaError(`parseDate() can't read "${text(a)}"`);
|
|
933
|
+
return d;
|
|
934
|
+
}
|
|
935
|
+
case "year":
|
|
936
|
+
return a === null ? null : date(a, "year()").getFullYear();
|
|
937
|
+
case "month":
|
|
938
|
+
return a === null ? null : date(a, "month()").getMonth() + 1;
|
|
939
|
+
case "date":
|
|
940
|
+
return a === null ? null : date(a, "date()").getDate();
|
|
941
|
+
case "day":
|
|
942
|
+
return a === null ? null : date(a, "day()").getDay() || 7;
|
|
943
|
+
case "week":
|
|
944
|
+
return a === null ? null : isoWeek(date(a, "week()"));
|
|
945
|
+
case "hour":
|
|
946
|
+
return a === null ? null : date(a, "hour()").getHours();
|
|
947
|
+
case "minute":
|
|
948
|
+
return a === null ? null : date(a, "minute()").getMinutes();
|
|
949
|
+
case "timestamp":
|
|
950
|
+
return a === null ? null : date(a, "timestamp()").getTime();
|
|
951
|
+
case "tostring":
|
|
952
|
+
return text(a);
|
|
953
|
+
case "now":
|
|
954
|
+
return new Date(ctx.now.getTime());
|
|
955
|
+
case "today":
|
|
956
|
+
return new Date(ctx.now.getFullYear(), ctx.now.getMonth(), ctx.now.getDate());
|
|
957
|
+
case "datebetween":
|
|
958
|
+
if (a === null || b === null) return null;
|
|
959
|
+
return dateBetween(date(a, "dateBetween()"), date(b, "dateBetween()"), String(c));
|
|
960
|
+
case "dateadd":
|
|
961
|
+
if (a === null) return null;
|
|
962
|
+
return dateAdd(date(a, "dateAdd()"), num(b, "dateAdd()"), String(c));
|
|
963
|
+
default:
|
|
964
|
+
throw new FormulaError(`Unknown function "${name}"`);
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
function evaluateFormula(ast, ctx) {
|
|
968
|
+
var _a;
|
|
969
|
+
try {
|
|
970
|
+
const value = evalNode(ast, __spreadProps(__spreadValues({}, ctx), {
|
|
971
|
+
budget: (_a = ctx.budget) != null ? _a : {
|
|
972
|
+
left: MAX_STEPS
|
|
973
|
+
}
|
|
974
|
+
}));
|
|
975
|
+
if (typeof value === "number" && !Number.isFinite(value)) return {
|
|
976
|
+
ok: false,
|
|
977
|
+
error: "Result is not a number"
|
|
978
|
+
};
|
|
979
|
+
return {
|
|
980
|
+
ok: true,
|
|
981
|
+
value
|
|
982
|
+
};
|
|
983
|
+
} catch (e) {
|
|
984
|
+
if (e instanceof FormulaError) return {
|
|
985
|
+
ok: false,
|
|
986
|
+
error: e.message
|
|
987
|
+
};
|
|
988
|
+
if (e instanceof RangeError) return {
|
|
989
|
+
ok: false,
|
|
990
|
+
error: "Formula is too complex"
|
|
991
|
+
};
|
|
992
|
+
throw e;
|
|
993
|
+
}
|
|
994
|
+
}
|
|
995
|
+
function parseDateValue(value) {
|
|
996
|
+
const s = dateString(value);
|
|
997
|
+
if (!s) return null;
|
|
998
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
|
|
999
|
+
if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
|
|
1000
|
+
const d = new Date(s);
|
|
1001
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
1002
|
+
}
|
|
1003
|
+
function toFormulaValue(value, type) {
|
|
1004
|
+
switch (type) {
|
|
1005
|
+
case "number":
|
|
1006
|
+
return numberValue(value);
|
|
1007
|
+
case "checkbox":
|
|
1008
|
+
return value === true || value === "true";
|
|
1009
|
+
case "date":
|
|
1010
|
+
case "created_time":
|
|
1011
|
+
case "last_edited_time":
|
|
1012
|
+
return parseDateValue(value);
|
|
1013
|
+
case "formula":
|
|
1014
|
+
return value === void 0 ? null : value;
|
|
1015
|
+
case "connector":
|
|
1016
|
+
return connectorCellValue(value);
|
|
1017
|
+
case "multi_select":
|
|
1018
|
+
case "person":
|
|
1019
|
+
return multiSelectNames(value);
|
|
1020
|
+
case "rollup":
|
|
1021
|
+
if (Array.isArray(value)) return value.map((v) => v instanceof Date || typeof v !== "object" ? v : richTextToPlain(v));
|
|
1022
|
+
if (typeof value === "number" || typeof value === "boolean" || value === null) return value;
|
|
1023
|
+
if (value instanceof Date) return value;
|
|
1024
|
+
return richTextToPlain(value);
|
|
1025
|
+
case "select":
|
|
1026
|
+
case "status":
|
|
1027
|
+
case "files":
|
|
1028
|
+
case "relation":
|
|
1029
|
+
return cellDisplayText(value, type);
|
|
1030
|
+
default:
|
|
1031
|
+
return richTextToPlain(value);
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
const MAX_FORMULA_DEPTH = 8;
|
|
1035
|
+
function rowCellValue(row, column, columns, now = /* @__PURE__ */ new Date(), depth = 0, extra) {
|
|
1036
|
+
var _a;
|
|
1037
|
+
if (column.type !== "formula") {
|
|
1038
|
+
const v = extra == null ? void 0 : extra(row, column);
|
|
1039
|
+
return v !== void 0 ? v : baseCellValue(row, column);
|
|
1040
|
+
}
|
|
1041
|
+
const compiled = compileCached((_a = column.expression) != null ? _a : "");
|
|
1042
|
+
if (!compiled.ok) return null;
|
|
1043
|
+
if (depth === 0) {
|
|
1044
|
+
try {
|
|
1045
|
+
return rowCellValue(row, column, columns, now, 1, extra);
|
|
1046
|
+
} catch (e) {
|
|
1047
|
+
if (e instanceof FormulaCycleError) return null;
|
|
1048
|
+
throw e;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
const r = evaluateFormula(compiled.ast, {
|
|
1052
|
+
now,
|
|
1053
|
+
getProp: (name) => {
|
|
1054
|
+
const c = columns.find((x) => x.name === name);
|
|
1055
|
+
if (!c) throw new FormulaError(`Unknown property "${name}"`);
|
|
1056
|
+
if (c.type === "formula" && depth + 1 > MAX_FORMULA_DEPTH) throw new FormulaCycleError("Circular reference");
|
|
1057
|
+
return toFormulaValue(rowCellValue(row, c, columns, now, depth + 1, extra), c.type);
|
|
1058
|
+
}
|
|
1059
|
+
});
|
|
1060
|
+
return r.ok ? r.value : null;
|
|
1061
|
+
}
|
|
1062
|
+
function makeCellGetter(columns, now = /* @__PURE__ */ new Date(), extra) {
|
|
1063
|
+
const hasFormula = columns.some((c) => c.type === "formula");
|
|
1064
|
+
if (!hasFormula && !extra) return baseCellValue;
|
|
1065
|
+
return (row, column) => {
|
|
1066
|
+
if (extra) {
|
|
1067
|
+
const v = extra(row, column);
|
|
1068
|
+
if (v !== void 0) return v;
|
|
1069
|
+
}
|
|
1070
|
+
return hasFormula ? rowCellValue(row, column, columns, now, 0, extra) : baseCellValue(row, column);
|
|
1071
|
+
};
|
|
1072
|
+
}export{addMonthsClamped,compileCached,compileFormula,dateAdd,dateBetween,evaluateFormula,formatDatePattern,formatFormulaValue,makeCellGetter,rowCellValue,toFormulaValue};//# sourceMappingURL=databaseFormula.js.map
|