sf-plugin-formula 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,98 @@
1
+ # sf-plugin-formula
2
+
3
+ [![NPM](https://img.shields.io/npm/v/sf-plugin-formula.svg?label=sf-plugin-formula)](https://www.npmjs.com/package/sf-plugin-formula) [![Downloads/week](https://img.shields.io/npm/dw/sf-plugin-formula.svg)](https://npmjs.org/package/sf-plugin-formula) [![License](https://img.shields.io/badge/License-BSD%203--Clause-brightgreen.svg)](https://raw.githubusercontent.com/salesforcecli/sf-plugin-formula/main/LICENSE.txt)
4
+
5
+ # summary
6
+
7
+ Evaluates a Salesforce formula against one or more records and returns the result for each.
8
+
9
+ This extension is only possible because of the following awesome opensource projects:
10
+
11
+ - [Formulon](https://github.com/leifg/formulon)
12
+ - [SFDX Hardis](https://github.com/hardisgroupcom/sfdx-hardis)
13
+
14
+ # description
15
+
16
+ Evaluates a Salesforce formula against one or more records and returns the result for each.
17
+
18
+ This command uses [Formulon](https://github.com/leifg/formulon) to parse and evaluate Salesforce formulas entirely offline, no org connection required.
19
+
20
+ Key features:
21
+
22
+ - **Multi-record evaluation:** Supply multiple records (each as a variable map) to evaluate the same formula against all of them in one shot.
23
+ - **Inline or file input:** Provide the formula and records directly as CLI flags, or point to a JSON file that contains both.
24
+ - **Error transparency:** Formulon errors (wrong argument count, type mismatches, etc.) are surfaced per record rather than aborting the whole run.
25
+
26
+ ### Input JSON file format
27
+
28
+ When using \`--inputfile\`, the file must be a JSON object with the following shape:
29
+
30
+ ```json
31
+ {
32
+ "formula": "IF(IsActive**c, Amount**c * 1.1, Amount**c)",
33
+ "records": [
34
+ {
35
+ "IsActive**c": { "type": "literal", "dataType": "checkbox", "value": true },
36
+ "Amount**c": { "type": "literal", "dataType": "number", "value": 200, "options": { "length": 6, "scale": 2 } }
37
+ },
38
+ {
39
+ "IsActive**c": { "type": "literal", "dataType": "checkbox", "value": false },
40
+ "Amount__c": { "type": "literal", "dataType": "number", "value": 150, "options": { "length": 6, "scale": 2 } }
41
+ }
42
+ ]
43
+ }
44
+ ```
45
+
46
+ Each entry in \`records\` is a map of **field API name → Formulon variable descriptor**.
47
+ The variable descriptor shape is:
48
+
49
+ ```json
50
+ {
51
+ "type": "literal",
52
+ "dataType": "<text|number|checkbox|date|time|datetime|geolocation|null>",
53
+ "value": <js-native-value>,
54
+ "options": { }
55
+ }
56
+ ```
57
+
58
+ # flags.formula.summary
59
+
60
+ Salesforce formula to evaluate.
61
+
62
+ # flags.formula.description
63
+
64
+ Ignored when --inputfile is provided.
65
+
66
+ # flags.records.summary
67
+
68
+ JSON array of record variable maps.
69
+
70
+ # flags.records.description
71
+
72
+ Each element represents one record. Ignored when --inputfile is provided.
73
+
74
+ # flags.inputfile.summary
75
+
76
+ Path to a JSON file containing "formula" and "records".
77
+
78
+ # flags.inputfile.description
79
+
80
+ When supplied, --formula and --records are ignored.
81
+
82
+ # flags.debug.summary
83
+
84
+ Activate debug mode (more logs)
85
+
86
+ # examples
87
+
88
+ - Run a formula without variables:
89
+
90
+ <%= config.bin %> <%= command.id %> --formula 'IF(TRUE, "Yes", "No")'
91
+
92
+ - Run a formula with variables and multiple records:
93
+
94
+ <%= config.bin %> <%= command.id %> --formula 'Amount\_\_c \* 2' --records '[{"Amount**c":{"type":"literal" "dataType":"number","value":100,"options":{"length":6,"scale":2}}}]
95
+
96
+ - Run a formula from a JSON file:
97
+
98
+ <%= config.bin %> <%= command.id %> --inputfile ./my-formula.json
@@ -0,0 +1,20 @@
1
+ import { SfCommand } from '@salesforce/sf-plugins-core';
2
+ import { AnyJson } from '@salesforce/ts-types';
3
+ export default class FormulaEvaluate extends SfCommand<AnyJson> {
4
+ static readonly summary: string;
5
+ static readonly description: string;
6
+ static readonly examples: string[];
7
+ static readonly flags: {
8
+ formula: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ records: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ inputfile: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
12
+ };
13
+ private static buildVariablePrompt;
14
+ private static coerceValue;
15
+ run(): Promise<AnyJson>;
16
+ private runInteractiveLoop;
17
+ private runJsonContent;
18
+ private evaluate;
19
+ private display;
20
+ }
@@ -0,0 +1,343 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { SfCommand, Flags } from '@salesforce/sf-plugins-core';
3
+ import { extract } from '@steedos/formula';
4
+ import c from 'chalk';
5
+ import { Messages } from '@salesforce/core';
6
+ import { uxLog, uxLogTable, prompts } from 'sfdx-hardis/plugin-api';
7
+ import { evaluateFormulaForRecords, formatEvaluationSummary, summaryToJson, buildModelJson, } from '../../utils/formulaUtils.js';
8
+ Messages.importMessagesDirectoryFromMetaUrl(import.meta.url);
9
+ const messages = Messages.loadMessages('sf-plugin-formula', 'sf-plugin-formula.evaluate');
10
+ export default class FormulaEvaluate extends SfCommand {
11
+ static summary = messages.getMessage('summary');
12
+ static description = messages.getMessage('description');
13
+ static examples = [messages.getMessage('examples')];
14
+ static flags = {
15
+ formula: Flags.string({
16
+ char: 'f',
17
+ summary: messages.getMessage('flags.formula.summary'),
18
+ description: messages.getMessage('flags.formula.description'),
19
+ }),
20
+ records: Flags.string({
21
+ char: 'r',
22
+ summary: messages.getMessage('flags.records.summary'),
23
+ description: messages.getMessage('flags.records.description'),
24
+ }),
25
+ inputfile: Flags.string({
26
+ char: 'x',
27
+ summary: messages.getMessage('flags.inputfile.summary'),
28
+ description: messages.getMessage('flags.inputfile.description'),
29
+ }),
30
+ debug: Flags.boolean({
31
+ char: 'd',
32
+ default: false,
33
+ summary: messages.getMessage('flags.debug.summary'),
34
+ }),
35
+ };
36
+ static buildVariablePrompt(varName, dataType) {
37
+ const base = {
38
+ name: varName,
39
+ description: `Value for the "${varName}" field (${dataType})`,
40
+ placeholder: '',
41
+ };
42
+ switch (dataType) {
43
+ case 'checkbox':
44
+ return {
45
+ ...base,
46
+ type: 'select',
47
+ message: `Value for "${varName}" (checkbox)`,
48
+ choices: [
49
+ { title: 'TRUE', value: 'true' },
50
+ { title: 'FALSE', value: 'false' },
51
+ ],
52
+ };
53
+ case 'number':
54
+ return {
55
+ ...base,
56
+ type: 'text',
57
+ message: `Value for "${varName}" (number)`,
58
+ placeholder: '0',
59
+ validate: (v) => (v?.trim() === '' || !isNaN(Number(v)) ? true : 'Please enter a valid number'),
60
+ };
61
+ case 'date':
62
+ return {
63
+ ...base,
64
+ type: 'text',
65
+ message: `Value for "${varName}" (date: YYYY-MM-DD)`,
66
+ placeholder: new Date().toISOString().slice(0, 10),
67
+ validate: (v) => (/^\d{4}-\d{2}-\d{2}$/.test(v?.trim()) ? true : 'Use YYYY-MM-DD format'),
68
+ };
69
+ case 'datetime':
70
+ return {
71
+ ...base,
72
+ type: 'text',
73
+ message: `Value for "${varName}" (datetime: ISO 8601)`,
74
+ placeholder: new Date().toISOString(),
75
+ validate: (v) => (!isNaN(Date.parse(v?.trim())) ? true : 'Enter a valid ISO 8601 datetime string'),
76
+ };
77
+ case 'time':
78
+ return {
79
+ ...base,
80
+ type: 'text',
81
+ message: `Value for "${varName}" (time: HH:MM:SS)`,
82
+ placeholder: '09:00:00',
83
+ validate: (v) => (/^\d{2}:\d{2}(:\d{2})?$/.test(v?.trim()) ? true : 'Use HH:MM or HH:MM:SS format'),
84
+ };
85
+ case 'null':
86
+ return {
87
+ ...base,
88
+ type: 'confirm',
89
+ message: `"${varName}" will be set to null. Confirm?`,
90
+ initial: true,
91
+ };
92
+ default:
93
+ return {
94
+ ...base,
95
+ type: 'text',
96
+ message: `Value for "${varName}" (text)`,
97
+ };
98
+ }
99
+ }
100
+ static coerceValue(raw, dataType) {
101
+ switch (dataType) {
102
+ case 'checkbox':
103
+ return raw === 'true' || raw === true;
104
+ case 'number':
105
+ return raw === '' || raw === undefined ? 0 : Number(raw);
106
+ case 'date':
107
+ case 'datetime':
108
+ case 'time':
109
+ return new Date(raw);
110
+ case 'null':
111
+ return null;
112
+ default:
113
+ return raw ?? '';
114
+ }
115
+ }
116
+ async run() {
117
+ const { flags } = await this.parse(FormulaEvaluate);
118
+ const debugMode = flags.debug ?? false;
119
+ let formula;
120
+ let records = null;
121
+ let lastSummary = null;
122
+ if (flags.inputfile) {
123
+ uxLog('log', this, c.grey(`Reading formula and records from ${flags.inputfile}…`));
124
+ const fileContent = readFileSync(flags.inputfile, 'utf-8');
125
+ const raw = JSON.parse(fileContent);
126
+ if (typeof raw?.formula !== 'string') {
127
+ throw new Error(`"formula" key (string) is required in ${flags.inputfile}`);
128
+ }
129
+ if (!Array.isArray(raw?.records)) {
130
+ throw new Error(`"records" key (array) is required in ${flags.inputfile}`);
131
+ }
132
+ formula = raw.formula;
133
+ records = raw.records;
134
+ lastSummary = this.evaluate(formula, records);
135
+ this.display(lastSummary, debugMode);
136
+ return summaryToJson(lastSummary);
137
+ }
138
+ if (flags.formula) {
139
+ formula = flags.formula;
140
+ if (flags.records) {
141
+ try {
142
+ const parsed = JSON.parse(flags.records);
143
+ if (!Array.isArray(parsed))
144
+ throw new Error('--records must be a JSON array.');
145
+ records = parsed;
146
+ }
147
+ catch (e) {
148
+ throw new Error(`Failed to parse --records as JSON: ${e.message}`);
149
+ }
150
+ }
151
+ records = records ?? [{}];
152
+ lastSummary = this.evaluate(formula, records);
153
+ this.display(lastSummary, debugMode);
154
+ return summaryToJson(lastSummary);
155
+ }
156
+ const modeAnswer = await prompts({
157
+ type: 'select',
158
+ name: 'mode',
159
+ message: 'How do you want to evaluate the formula?',
160
+ description: 'Interactive mode lets you fill in values manually and repeat. JSON mode evaluates a set of records from a file.',
161
+ choices: [
162
+ { title: '✏️ [Interactive] fill in values manually (repeatable)', value: 'interactive' },
163
+ { title: '📄 [JSON format] evaluate a set of records from a JSON file', value: 'json' },
164
+ ],
165
+ });
166
+ if (modeAnswer.mode === 'json') {
167
+ lastSummary = await this.runJsonContent(debugMode);
168
+ }
169
+ else {
170
+ const formulaAnswer = await prompts({
171
+ type: 'text',
172
+ name: 'formula',
173
+ message: 'Enter the Salesforce formula to evaluate',
174
+ description: 'Example: IF(IsActive__c, Amount__c * 1.1, Amount__c)',
175
+ placeholder: 'IF(Active__c, "Yes", "No")',
176
+ validate: (v) => (v?.trim() ? true : 'Formula cannot be empty'),
177
+ });
178
+ formula = formulaAnswer.formula.trim();
179
+ const referencedVariables = extract(formula);
180
+ lastSummary = await this.runInteractiveLoop(formula, referencedVariables, debugMode);
181
+ }
182
+ return summaryToJson(lastSummary);
183
+ }
184
+ async runInteractiveLoop(formula, referencedVariables, debugMode) {
185
+ let summary = null;
186
+ let keepGoing = true;
187
+ let iterationCount = 0;
188
+ const evaluatedRecords = [];
189
+ while (keepGoing) {
190
+ iterationCount++;
191
+ uxLog('log', this, c.cyan(`\n[Evaluation ${iterationCount}]`));
192
+ const record = {};
193
+ if (referencedVariables.length > 0) {
194
+ for (const varName of referencedVariables) {
195
+ // eslint-disable-next-line no-await-in-loop
196
+ const typeAnswer = await prompts({
197
+ type: 'select',
198
+ name: 'dataType',
199
+ message: `Data type for "${varName}"`,
200
+ description: `Select the Salesforce field type that matches ${varName}`,
201
+ choices: [
202
+ { title: 'Text', value: 'text' },
203
+ { title: 'Number', value: 'number' },
204
+ { title: 'Checkbox', value: 'checkbox' },
205
+ { title: 'Date', value: 'date' },
206
+ { title: 'Time', value: 'time' },
207
+ { title: 'Datetime', value: 'datetime' },
208
+ { title: 'Picklist', value: 'picklist' },
209
+ { title: 'MultiPicklist', value: 'multipicklist' },
210
+ { title: 'Null', value: 'null' },
211
+ ],
212
+ });
213
+ const dataType = typeAnswer.dataType;
214
+ const varQuestion = FormulaEvaluate.buildVariablePrompt(varName, dataType);
215
+ // eslint-disable-next-line no-await-in-loop
216
+ const varAnswer = await prompts(varQuestion);
217
+ const rawValue = varAnswer[varName];
218
+ record[varName] = {
219
+ type: 'literal',
220
+ dataType,
221
+ value: FormulaEvaluate.coerceValue(rawValue, dataType),
222
+ };
223
+ }
224
+ }
225
+ else {
226
+ uxLog('log', this, c.grey('No field variables detected. Evaluating as a constant formula.'));
227
+ }
228
+ const iterationSummary = this.evaluate(formula, [record]);
229
+ evaluatedRecords.push(...iterationSummary.results);
230
+ const mergedResults = evaluatedRecords.map((r, idx) => ({
231
+ ...r,
232
+ recordIndex: idx,
233
+ }));
234
+ summary = {
235
+ ...iterationSummary,
236
+ results: mergedResults,
237
+ successCount: mergedResults.filter((r) => !r.isError).length,
238
+ errorCount: mergedResults.filter((r) => r.isError).length,
239
+ };
240
+ this.display(summary, debugMode);
241
+ // eslint-disable-next-line no-await-in-loop
242
+ const repeatAnswer = await prompts({
243
+ type: 'confirm',
244
+ name: 'repeat',
245
+ message: 'Evaluate again with different values?',
246
+ description: 'Select Yes to enter new variable values and re-evaluate the same formula.',
247
+ initial: false,
248
+ });
249
+ keepGoing = repeatAnswer.repeat === true;
250
+ }
251
+ return summary;
252
+ }
253
+ async runJsonContent(debugMode) {
254
+ const modelContent = JSON.stringify(buildModelJson("IF(MyField__c, 'Yes', 'No')"), null, 2);
255
+ const fileAnswer = await prompts({
256
+ type: 'text',
257
+ name: 'fileContent',
258
+ message: 'JSON content for multi-evaluation',
259
+ description: 'Edit the "records" array. Each field key maps to a formula variable. Supported dataType values: text | number | checkbox | date | time | datetime | geolocation | null',
260
+ placeholder: modelContent,
261
+ initial: modelContent,
262
+ validate: (v) => {
263
+ try {
264
+ const parsed = JSON.parse(v);
265
+ if (typeof parsed?.formula !== 'string')
266
+ return '"formula" key (string) is required';
267
+ if (!Array.isArray(parsed?.records))
268
+ return '"records" key (array) is required';
269
+ return true;
270
+ }
271
+ catch (_) {
272
+ return 'Invalid JSON';
273
+ }
274
+ },
275
+ });
276
+ uxLog('log', this, c.grey('Reading records from JSON…'));
277
+ try {
278
+ const raw = JSON.parse(fileAnswer.fileContent);
279
+ const resolvedFormula = raw.formula;
280
+ const fileRecords = Array.isArray(raw?.records) ? raw.records : [];
281
+ if (fileRecords.length === 0) {
282
+ throw new Error('No records found. Make sure the JSON has a "records" array with at least one entry.');
283
+ }
284
+ const summary = this.evaluate(resolvedFormula, fileRecords);
285
+ this.display(summary, debugMode);
286
+ return summary;
287
+ }
288
+ catch (_) {
289
+ throw new Error('The JSON provided is invalid.');
290
+ }
291
+ }
292
+ evaluate(formula, records) {
293
+ uxLog('log', this, c.grey(`\nEvaluating formula against ${records.length} record(s)…`));
294
+ const normalizedRecords = records.map((record) => Object.fromEntries(Object.entries(record).map(([key, descriptor]) => [key, { ...descriptor, type: 'literal' }])));
295
+ return evaluateFormulaForRecords(formula, normalizedRecords);
296
+ }
297
+ display(summary, debugMode) {
298
+ const variableColumns = [...new Set(summary.results.flatMap((r) => Object.keys(r.variables)))];
299
+ const columns = [
300
+ 'record',
301
+ ...variableColumns.map((v) => `${v}_type`),
302
+ ...variableColumns.map((v) => `${v}_value`),
303
+ 'result_type',
304
+ 'result_value',
305
+ 'status',
306
+ ];
307
+ uxLog('success', this, c.green('Formula evaluation results'));
308
+ const tableRows = summary.results.map((r) => {
309
+ const row = {
310
+ record: `#${r.recordIndex + 1}`,
311
+ };
312
+ for (const varName of variableColumns) {
313
+ const varDescriptor = r.variables[varName];
314
+ row[`${varName}_type`] = varDescriptor?.dataType ?? '—';
315
+ row[`${varName}_value`] = varDescriptor !== undefined ? JSON.stringify(varDescriptor.value) : '-';
316
+ }
317
+ if (r.isError) {
318
+ const err = r.result;
319
+ row['result_type'] = err.errorType ?? 'error';
320
+ row['result_value'] = err.message ?? '';
321
+ row['status'] = 'ERROR';
322
+ }
323
+ else {
324
+ const lit = r.result;
325
+ row['result_type'] = lit.dataType ?? '';
326
+ row['result_value'] = JSON.stringify(lit.value);
327
+ row['status'] = 'OK';
328
+ }
329
+ return row;
330
+ });
331
+ uxLogTable(this, tableRows, columns);
332
+ if (summary.errorCount === 0) {
333
+ uxLog('action', this, c.green(`Formula evaluated successfully for all ${summary.successCount} record(s).`));
334
+ }
335
+ else {
336
+ uxLog('warning', this, c.yellow(`Evaluation complete: ${summary.successCount} succeeded, ${summary.errorCount} failed.`));
337
+ }
338
+ if (debugMode) {
339
+ uxLog('log', this, c.grey(formatEvaluationSummary(summary)));
340
+ }
341
+ }
342
+ }
343
+ //# sourceMappingURL=evaluate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate.js","sourceRoot":"","sources":["../../../src/commands/formula/evaluate.ts"],"names":[],"mappings":"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"}
package/lib/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ declare const _default: {};
2
+ export default _default;
package/lib/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export default {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,eAAe,EAAE,CAAC"}
@@ -0,0 +1,38 @@
1
+ export type FormulaDataType = 'text' | 'number' | 'checkbox' | 'date' | 'time' | 'datetime' | 'geolocation' | 'null';
2
+ export type FormulaVariable = {
3
+ type: 'literal';
4
+ dataType: FormulaDataType;
5
+ value: unknown;
6
+ options?: Record<string, unknown>;
7
+ };
8
+ export type FormulaVariableMap = Record<string, FormulaVariable>;
9
+ export type FormulaLiteralResult = {
10
+ type: 'literal';
11
+ value: unknown;
12
+ dataType: FormulaDataType;
13
+ options?: Record<string, unknown>;
14
+ };
15
+ export type FormulaErrorResult = {
16
+ [key: string]: unknown;
17
+ type: 'error';
18
+ errorType: string;
19
+ message: string;
20
+ };
21
+ export type FormulaParseResult = FormulaLiteralResult | FormulaErrorResult;
22
+ export type FormulaEvaluationResult = {
23
+ recordIndex: number;
24
+ variables: FormulaVariableMap;
25
+ result: FormulaParseResult;
26
+ isError: boolean;
27
+ };
28
+ export type FormulaEvaluationSummary = {
29
+ formula: string;
30
+ referencedVariables: string[];
31
+ results: FormulaEvaluationResult[];
32
+ successCount: number;
33
+ errorCount: number;
34
+ };
35
+ export declare function evaluateFormulaForRecords(formula: string, records: FormulaVariableMap[]): FormulaEvaluationSummary;
36
+ export declare function formatEvaluationSummary(summary: FormulaEvaluationSummary): string;
37
+ export declare function summaryToJson(summary: FormulaEvaluationSummary): Record<string, unknown>;
38
+ export declare function buildModelJson(formula: string): Record<string, unknown>;
@@ -0,0 +1,87 @@
1
+ import { parse, extract } from '@steedos/formula';
2
+ export function evaluateFormulaForRecords(formula, records) {
3
+ let referencedVariables = [];
4
+ try {
5
+ referencedVariables = extract(formula);
6
+ }
7
+ catch (_) {
8
+ // even if not parseable, we still want to return a structured error
9
+ }
10
+ const results = records.map((variables, recordIndex) => {
11
+ let isError = false;
12
+ let rawResult;
13
+ try {
14
+ rawResult = parse(formula, variables);
15
+ isError = rawResult.type === 'error';
16
+ }
17
+ catch (_) {
18
+ rawResult = {
19
+ type: 'error',
20
+ errorType: 'Unparsable formula',
21
+ message: "The formula couldn't be parsed.",
22
+ };
23
+ isError = true;
24
+ }
25
+ return { recordIndex, variables, result: rawResult, isError };
26
+ });
27
+ const errorCount = results.filter((r) => r.isError).length;
28
+ return {
29
+ formula,
30
+ referencedVariables,
31
+ results,
32
+ successCount: results.length - errorCount,
33
+ errorCount,
34
+ };
35
+ }
36
+ export function formatEvaluationSummary(summary) {
37
+ const lines = [];
38
+ lines.push(`Formula : ${summary.formula}`);
39
+ if (summary.referencedVariables.length > 0) {
40
+ lines.push(`Variables referenced: ${summary.referencedVariables.join(', ')}`);
41
+ }
42
+ lines.push(`Records evaluated : ${summary.results.length} (${summary.successCount} ok, ${summary.errorCount} errors)`);
43
+ lines.push('');
44
+ for (const r of summary.results) {
45
+ const prefix = ` [Record ${r.recordIndex + 1}]`;
46
+ if (r.isError) {
47
+ const err = r.result;
48
+ lines.push(`${prefix} ERROR: ${err.errorType}: ${err.message}`);
49
+ }
50
+ else {
51
+ const lit = r.result;
52
+ lines.push(`${prefix} ${lit.dataType} → ${JSON.stringify(lit.value)}`);
53
+ }
54
+ }
55
+ return lines.join('\n');
56
+ }
57
+ export function summaryToJson(summary) {
58
+ return {
59
+ formula: summary.formula,
60
+ referencedVariables: summary.referencedVariables,
61
+ successCount: summary.successCount,
62
+ errorCount: summary.errorCount,
63
+ results: summary.results.map((r) => ({
64
+ recordIndex: r.recordIndex,
65
+ variables: r.variables,
66
+ isError: r.isError,
67
+ result: r.result,
68
+ })),
69
+ };
70
+ }
71
+ export function buildModelJson(formula) {
72
+ const placeholderRecord = {};
73
+ const referencedVariables = extract(formula);
74
+ for (const varName of referencedVariables) {
75
+ placeholderRecord[varName] = {
76
+ type: 'literal',
77
+ dataType: 'text',
78
+ value: '',
79
+ options: {},
80
+ };
81
+ }
82
+ return {
83
+ formula,
84
+ records: [placeholderRecord],
85
+ };
86
+ }
87
+ //# sourceMappingURL=formulaUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formulaUtils.js","sourceRoot":"","sources":["../../src/utils/formulaUtils.ts"],"names":[],"mappings":"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"}