@nordcraft/search 1.0.37 → 1.0.39
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/fixProject.js +32 -0
- package/dist/fixProject.js.map +1 -0
- package/dist/problems.worker.js +45 -8
- package/dist/problems.worker.js.map +1 -1
- package/dist/rules/components/noReferenceComponentRule.js +31 -17
- package/dist/rules/components/noReferenceComponentRule.js.map +1 -1
- package/dist/rules/components/noReferenceComponentRule.test.js +86 -1
- package/dist/rules/components/noReferenceComponentRule.test.js.map +1 -1
- package/dist/rules/formulas/legacyFormulaRule.js +620 -6
- package/dist/rules/formulas/legacyFormulaRule.js.map +1 -1
- package/dist/rules/formulas/legacyFormulaRule.test.js +232 -1
- package/dist/rules/formulas/legacyFormulaRule.test.js.map +1 -1
- package/dist/searchProject.js +338 -217
- package/dist/searchProject.js.map +1 -1
- package/dist/util/helpers.js +18 -2
- package/dist/util/helpers.js.map +1 -1
- package/dist/util/helpers.test.js +58 -0
- package/dist/util/helpers.test.js.map +1 -0
- package/package.json +3 -2
- package/src/fixProject.ts +47 -0
- package/src/problems.worker.ts +90 -12
- package/src/rules/components/noReferenceComponentRule.test.ts +87 -1
- package/src/rules/components/noReferenceComponentRule.ts +38 -23
- package/src/rules/formulas/legacyFormulaRule.test.ts +242 -1
- package/src/rules/formulas/legacyFormulaRule.ts +719 -10
- package/src/searchProject.ts +217 -98
- package/src/types.d.ts +14 -3
- package/src/util/helpers.test.ts +80 -0
- package/src/util/helpers.ts +33 -5
|
@@ -1,8 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AndOperation,
|
|
3
|
+
ArrayOperation,
|
|
4
|
+
FunctionArgument,
|
|
5
|
+
FunctionOperation,
|
|
6
|
+
OrOperation,
|
|
7
|
+
SwitchOperation,
|
|
8
|
+
} from '@nordcraft/core/dist/formula/formula'
|
|
2
9
|
import { isToddleFormula } from '@nordcraft/core/dist/formula/formulaTypes'
|
|
10
|
+
import { omitKeys, set } from '@nordcraft/core/dist/utils/collections'
|
|
3
11
|
import { isDefined } from '@nordcraft/core/dist/utils/util'
|
|
4
12
|
import type { ProjectFiles } from '@nordcraft/ssr/dist/ssr.types'
|
|
5
|
-
import type { Rule } from '../../types'
|
|
13
|
+
import type { FormulaNode, NodeType, Rule } from '../../types'
|
|
6
14
|
|
|
7
15
|
export const legacyFormulaRule: Rule<{
|
|
8
16
|
name: string
|
|
@@ -10,18 +18,686 @@ export const legacyFormulaRule: Rule<{
|
|
|
10
18
|
code: 'legacy formula',
|
|
11
19
|
level: 'warning',
|
|
12
20
|
category: 'Deprecation',
|
|
13
|
-
visit: (report,
|
|
14
|
-
if (
|
|
15
|
-
nodeType !== 'formula' ||
|
|
16
|
-
value.type !== 'function' ||
|
|
17
|
-
!isLegacyFormula(value, files)
|
|
18
|
-
) {
|
|
21
|
+
visit: (report, data) => {
|
|
22
|
+
if (!isIssue(data)) {
|
|
19
23
|
return
|
|
20
24
|
}
|
|
21
|
-
report(
|
|
25
|
+
report(
|
|
26
|
+
data.path,
|
|
27
|
+
{ name: data.value.name },
|
|
28
|
+
// The TYPE formula cannot be autofixed since the types have changed between the 2 implementations
|
|
29
|
+
data.value.name !== 'TYPE' ? ['replace-legacy-formula'] : undefined,
|
|
30
|
+
)
|
|
31
|
+
},
|
|
32
|
+
fixes: {
|
|
33
|
+
'replace-legacy-formula': (data) => {
|
|
34
|
+
if (!isIssue(data)) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
switch (data.value.name) {
|
|
38
|
+
// Known legacy formulas first
|
|
39
|
+
case 'AND': {
|
|
40
|
+
const { name, ...legacyAndFormula } = data.value
|
|
41
|
+
const andFormula: AndOperation = {
|
|
42
|
+
...legacyAndFormula,
|
|
43
|
+
type: 'and',
|
|
44
|
+
arguments: legacyAndFormula.arguments.map((a) => {
|
|
45
|
+
const { name, ...argument } = a
|
|
46
|
+
return argument
|
|
47
|
+
}),
|
|
48
|
+
}
|
|
49
|
+
return set(data.files, data.path, andFormula)
|
|
50
|
+
}
|
|
51
|
+
case 'CONCAT': {
|
|
52
|
+
const newConcatFormula: FunctionOperation = {
|
|
53
|
+
...data.value,
|
|
54
|
+
name: '@toddle/concatenate',
|
|
55
|
+
display_name: 'Concatenate',
|
|
56
|
+
}
|
|
57
|
+
return set(data.files, data.path, newConcatFormula)
|
|
58
|
+
}
|
|
59
|
+
case 'DEFAULT': {
|
|
60
|
+
const newDefaultFormula: FunctionOperation = {
|
|
61
|
+
...data.value,
|
|
62
|
+
name: '@toddle/defaultTo',
|
|
63
|
+
// The old DEFAULT formula did not support variableArguments
|
|
64
|
+
variableArguments: true,
|
|
65
|
+
display_name: 'Default to',
|
|
66
|
+
}
|
|
67
|
+
return set(data.files, data.path, newDefaultFormula)
|
|
68
|
+
}
|
|
69
|
+
case 'DELETE': {
|
|
70
|
+
const newDeleteFormula: FunctionOperation = {
|
|
71
|
+
...data.value,
|
|
72
|
+
name: '@toddle/deleteKey',
|
|
73
|
+
display_name: 'Delete',
|
|
74
|
+
}
|
|
75
|
+
return set(data.files, data.path, newDeleteFormula)
|
|
76
|
+
}
|
|
77
|
+
case 'DROP_LAST': {
|
|
78
|
+
const newDropLastFormula: FunctionOperation = {
|
|
79
|
+
...data.value,
|
|
80
|
+
name: '@toddle/dropLast',
|
|
81
|
+
display_name: 'Drop Last',
|
|
82
|
+
arguments: renameArguments(
|
|
83
|
+
ARRAY_ARGUMENT_MAPPINGS,
|
|
84
|
+
data.value.arguments,
|
|
85
|
+
),
|
|
86
|
+
}
|
|
87
|
+
return set(data.files, data.path, newDropLastFormula)
|
|
88
|
+
}
|
|
89
|
+
case 'EQ': {
|
|
90
|
+
const newEqualsFormula: FunctionOperation = {
|
|
91
|
+
...data.value,
|
|
92
|
+
name: '@toddle/equals',
|
|
93
|
+
display_name: 'Equals',
|
|
94
|
+
}
|
|
95
|
+
return set(data.files, data.path, newEqualsFormula)
|
|
96
|
+
}
|
|
97
|
+
case 'FIND INDEX': {
|
|
98
|
+
const newFindIndexFormula: FunctionOperation = {
|
|
99
|
+
...data.value,
|
|
100
|
+
name: '@toddle/findIndex',
|
|
101
|
+
display_name: 'Find index',
|
|
102
|
+
arguments: renameArguments(
|
|
103
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
104
|
+
data.value.arguments,
|
|
105
|
+
),
|
|
106
|
+
}
|
|
107
|
+
return set(data.files, data.path, newFindIndexFormula)
|
|
108
|
+
}
|
|
109
|
+
case 'FLAT': {
|
|
110
|
+
const newFlattenFormula: FunctionOperation = {
|
|
111
|
+
...data.value,
|
|
112
|
+
name: '@toddle/flatten',
|
|
113
|
+
display_name: 'Flatten',
|
|
114
|
+
arguments: renameArguments(
|
|
115
|
+
ARRAY_ARGUMENT_MAPPINGS,
|
|
116
|
+
data.value.arguments,
|
|
117
|
+
),
|
|
118
|
+
}
|
|
119
|
+
return set(data.files, data.path, newFlattenFormula)
|
|
120
|
+
}
|
|
121
|
+
case 'GT': {
|
|
122
|
+
const newGreaterThanFormula: FunctionOperation = {
|
|
123
|
+
...data.value,
|
|
124
|
+
name: '@toddle/greaterThan',
|
|
125
|
+
display_name: 'Greater than',
|
|
126
|
+
}
|
|
127
|
+
return set(data.files, data.path, newGreaterThanFormula)
|
|
128
|
+
}
|
|
129
|
+
case 'GTE': {
|
|
130
|
+
const newGreaterOrEqualFormula: FunctionOperation = {
|
|
131
|
+
...data.value,
|
|
132
|
+
name: '@toddle/greaterOrEqueal',
|
|
133
|
+
display_name: 'Greater or equal',
|
|
134
|
+
}
|
|
135
|
+
return set(data.files, data.path, newGreaterOrEqualFormula)
|
|
136
|
+
}
|
|
137
|
+
case 'GROUP_BY': {
|
|
138
|
+
const newGroupbyFormula: FunctionOperation = {
|
|
139
|
+
...data.value,
|
|
140
|
+
name: '@toddle/groupBy',
|
|
141
|
+
display_name: 'Group by',
|
|
142
|
+
arguments: renameArguments(
|
|
143
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
144
|
+
data.value.arguments,
|
|
145
|
+
),
|
|
146
|
+
}
|
|
147
|
+
return set(data.files, data.path, newGroupbyFormula)
|
|
148
|
+
}
|
|
149
|
+
case 'IF': {
|
|
150
|
+
const legacyIfFormula = omitKeys(data.value, ['arguments', 'name'])
|
|
151
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
152
|
+
const ifArguments = data.value.arguments ?? []
|
|
153
|
+
const switchFormula: SwitchOperation = {
|
|
154
|
+
...legacyIfFormula,
|
|
155
|
+
type: 'switch',
|
|
156
|
+
cases: [
|
|
157
|
+
{
|
|
158
|
+
condition: ifArguments[0]?.formula,
|
|
159
|
+
formula: ifArguments[1]?.formula,
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
default: ifArguments[2]?.formula,
|
|
163
|
+
}
|
|
164
|
+
return set(data.files, data.path, switchFormula)
|
|
165
|
+
}
|
|
166
|
+
case 'INDEX OF': {
|
|
167
|
+
const newIndexofFormula: FunctionOperation = {
|
|
168
|
+
...data.value,
|
|
169
|
+
name: '@toddle/indexOf',
|
|
170
|
+
display_name: 'Index of',
|
|
171
|
+
arguments: renameArguments(
|
|
172
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
173
|
+
data.value.arguments,
|
|
174
|
+
),
|
|
175
|
+
}
|
|
176
|
+
return set(data.files, data.path, newIndexofFormula)
|
|
177
|
+
}
|
|
178
|
+
case 'JSON_PARSE': {
|
|
179
|
+
const newJsonParseFormula: FunctionOperation = {
|
|
180
|
+
...data.value,
|
|
181
|
+
name: '@toddle/parseJSON',
|
|
182
|
+
display_name: 'Parse JSON',
|
|
183
|
+
arguments: renameArguments(
|
|
184
|
+
{ Input: 'JSON string' },
|
|
185
|
+
data.value.arguments,
|
|
186
|
+
),
|
|
187
|
+
}
|
|
188
|
+
return set(data.files, data.path, newJsonParseFormula)
|
|
189
|
+
}
|
|
190
|
+
case 'KEY_BY': {
|
|
191
|
+
const newKeyByFormula: FunctionOperation = {
|
|
192
|
+
...data.value,
|
|
193
|
+
name: '@toddle/keyBy',
|
|
194
|
+
display_name: 'Key by',
|
|
195
|
+
arguments: renameArguments(
|
|
196
|
+
{
|
|
197
|
+
...ARRAY_ARGUMENT_MAPPINGS,
|
|
198
|
+
'Key formula': 'Formula',
|
|
199
|
+
},
|
|
200
|
+
data.value.arguments,
|
|
201
|
+
),
|
|
202
|
+
}
|
|
203
|
+
return set(data.files, data.path, newKeyByFormula)
|
|
204
|
+
}
|
|
205
|
+
case 'LIST': {
|
|
206
|
+
const newArrayFormula: ArrayOperation = {
|
|
207
|
+
type: 'array',
|
|
208
|
+
arguments: data.value.arguments,
|
|
209
|
+
}
|
|
210
|
+
return set(data.files, data.path, newArrayFormula)
|
|
211
|
+
}
|
|
212
|
+
case 'LOWER': {
|
|
213
|
+
const newLowercaseFormula: FunctionOperation = {
|
|
214
|
+
...data.value,
|
|
215
|
+
name: '@toddle/lowercase',
|
|
216
|
+
display_name: 'Lower case',
|
|
217
|
+
}
|
|
218
|
+
return set(data.files, data.path, newLowercaseFormula)
|
|
219
|
+
}
|
|
220
|
+
case 'LT': {
|
|
221
|
+
const newLessThanFormula: FunctionOperation = {
|
|
222
|
+
...data.value,
|
|
223
|
+
name: '@toddle/lessThan',
|
|
224
|
+
display_name: 'Less than',
|
|
225
|
+
}
|
|
226
|
+
return set(data.files, data.path, newLessThanFormula)
|
|
227
|
+
}
|
|
228
|
+
case 'LTE': {
|
|
229
|
+
const newLessOrEqualFormula: FunctionOperation = {
|
|
230
|
+
...data.value,
|
|
231
|
+
name: '@toddle/lessOrEqual',
|
|
232
|
+
display_name: 'Less or equal',
|
|
233
|
+
}
|
|
234
|
+
return set(data.files, data.path, newLessOrEqualFormula)
|
|
235
|
+
}
|
|
236
|
+
case 'MOD': {
|
|
237
|
+
const newModuloFormula: FunctionOperation = {
|
|
238
|
+
...data.value,
|
|
239
|
+
arguments: renameArguments(
|
|
240
|
+
{ Dividor: 'Divider' },
|
|
241
|
+
data.value.arguments,
|
|
242
|
+
),
|
|
243
|
+
name: '@toddle/modulo',
|
|
244
|
+
display_name: 'Modulo',
|
|
245
|
+
}
|
|
246
|
+
return set(data.files, data.path, newModuloFormula)
|
|
247
|
+
}
|
|
248
|
+
case 'NEQ': {
|
|
249
|
+
const newNotEqualFormula: FunctionOperation = {
|
|
250
|
+
...data.value,
|
|
251
|
+
name: '@toddle/notEqual',
|
|
252
|
+
display_name: 'Not equal',
|
|
253
|
+
}
|
|
254
|
+
return set(data.files, data.path, newNotEqualFormula)
|
|
255
|
+
}
|
|
256
|
+
case 'OR': {
|
|
257
|
+
const { name, ...legacyOrFormula } = data.value
|
|
258
|
+
// Replace the AND formula with an 'and' formula
|
|
259
|
+
const andFormula: OrOperation = {
|
|
260
|
+
...legacyOrFormula,
|
|
261
|
+
type: 'or',
|
|
262
|
+
arguments: legacyOrFormula.arguments.map((a) => {
|
|
263
|
+
const { name, ...argument } = a
|
|
264
|
+
return argument
|
|
265
|
+
}),
|
|
266
|
+
}
|
|
267
|
+
return set(data.files, data.path, andFormula)
|
|
268
|
+
}
|
|
269
|
+
case 'RANDOM': {
|
|
270
|
+
const newRandomNumberFormula: FunctionOperation = {
|
|
271
|
+
...data.value,
|
|
272
|
+
name: '@toddle/randomNumber',
|
|
273
|
+
display_name: 'Random number',
|
|
274
|
+
}
|
|
275
|
+
return set(data.files, data.path, newRandomNumberFormula)
|
|
276
|
+
}
|
|
277
|
+
case 'SIZE': {
|
|
278
|
+
const newSizeFormula: FunctionOperation = {
|
|
279
|
+
...data.value,
|
|
280
|
+
name: '@toddle/size',
|
|
281
|
+
display_name: 'Size',
|
|
282
|
+
}
|
|
283
|
+
return set(data.files, data.path, newSizeFormula)
|
|
284
|
+
}
|
|
285
|
+
case 'SQRT': {
|
|
286
|
+
const newSqrtFormula: FunctionOperation = {
|
|
287
|
+
...data.value,
|
|
288
|
+
name: '@toddle/squareRoot',
|
|
289
|
+
display_name: 'Square Root',
|
|
290
|
+
}
|
|
291
|
+
return set(data.files, data.path, newSqrtFormula)
|
|
292
|
+
}
|
|
293
|
+
case 'STARTS_WITH': {
|
|
294
|
+
const newStartsWithFormula: FunctionOperation = {
|
|
295
|
+
...data.value,
|
|
296
|
+
name: '@toddle/startsWith',
|
|
297
|
+
display_name: 'Starts with',
|
|
298
|
+
arguments: renameArguments(
|
|
299
|
+
{ Input: 'String' },
|
|
300
|
+
data.value.arguments,
|
|
301
|
+
),
|
|
302
|
+
}
|
|
303
|
+
return set(data.files, data.path, newStartsWithFormula)
|
|
304
|
+
}
|
|
305
|
+
case 'TAKE_LAST': {
|
|
306
|
+
const newTakeLastFormula: FunctionOperation = {
|
|
307
|
+
...data.value,
|
|
308
|
+
name: '@toddle/takeLast',
|
|
309
|
+
display_name: 'Take last',
|
|
310
|
+
arguments: renameArguments(
|
|
311
|
+
ARRAY_ARGUMENT_MAPPINGS,
|
|
312
|
+
data.value.arguments,
|
|
313
|
+
),
|
|
314
|
+
}
|
|
315
|
+
return set(data.files, data.path, newTakeLastFormula)
|
|
316
|
+
}
|
|
317
|
+
case 'TYPE':
|
|
318
|
+
// We can't autofix this one as the types have changed
|
|
319
|
+
break
|
|
320
|
+
case 'UPPER': {
|
|
321
|
+
const newUpperFormula: FunctionOperation = {
|
|
322
|
+
...data.value,
|
|
323
|
+
name: '@toddle/uppercase',
|
|
324
|
+
display_name: 'Uppercase',
|
|
325
|
+
arguments: renameArguments(
|
|
326
|
+
ARRAY_ARGUMENT_MAPPINGS,
|
|
327
|
+
data.value.arguments,
|
|
328
|
+
),
|
|
329
|
+
}
|
|
330
|
+
return set(data.files, data.path, newUpperFormula)
|
|
331
|
+
}
|
|
332
|
+
case 'URI_ENCODE': {
|
|
333
|
+
const newUriEncodeFormula: FunctionOperation = {
|
|
334
|
+
...data.value,
|
|
335
|
+
name: '@toddle/encodeURIComponent',
|
|
336
|
+
display_name: 'Encode URI Component',
|
|
337
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
338
|
+
arguments: data.value.arguments?.map((arg) => ({
|
|
339
|
+
...arg,
|
|
340
|
+
// Let's fix this typo as well
|
|
341
|
+
name: arg.name === 'URI' ? 'URIComponent' : arg.name,
|
|
342
|
+
})),
|
|
343
|
+
}
|
|
344
|
+
return set(data.files, data.path, newUriEncodeFormula)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
|
|
348
|
+
// ℹ️ Below is handling of the builtin formulas that can be updated ℹ️ //
|
|
349
|
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! //
|
|
350
|
+
|
|
351
|
+
case 'ABSOLUTE': {
|
|
352
|
+
const newAbsoluteFormula: FunctionOperation = {
|
|
353
|
+
...data.value,
|
|
354
|
+
name: '@toddle/absolute',
|
|
355
|
+
display_name: 'Absolute',
|
|
356
|
+
}
|
|
357
|
+
return set(data.files, data.path, newAbsoluteFormula)
|
|
358
|
+
}
|
|
359
|
+
case 'ADD': {
|
|
360
|
+
const newAddFormula: FunctionOperation = {
|
|
361
|
+
...data.value,
|
|
362
|
+
name: '@toddle/add',
|
|
363
|
+
display_name: 'Add',
|
|
364
|
+
}
|
|
365
|
+
return set(data.files, data.path, newAddFormula)
|
|
366
|
+
}
|
|
367
|
+
case 'APPEND': {
|
|
368
|
+
const newAppendFormula: FunctionOperation = {
|
|
369
|
+
...data.value,
|
|
370
|
+
name: '@toddle/append',
|
|
371
|
+
display_name: 'Append',
|
|
372
|
+
}
|
|
373
|
+
return set(data.files, data.path, newAppendFormula)
|
|
374
|
+
}
|
|
375
|
+
case 'BOOLEAN': {
|
|
376
|
+
const newBooleanFormula: FunctionOperation = {
|
|
377
|
+
...data.value,
|
|
378
|
+
name: '@toddle/boolean',
|
|
379
|
+
display_name: 'Boolean',
|
|
380
|
+
}
|
|
381
|
+
return set(data.files, data.path, newBooleanFormula)
|
|
382
|
+
}
|
|
383
|
+
case 'CLAMP': {
|
|
384
|
+
const newClampFormula: FunctionOperation = {
|
|
385
|
+
...data.value,
|
|
386
|
+
name: '@toddle/clamp',
|
|
387
|
+
display_name: 'Clamp',
|
|
388
|
+
}
|
|
389
|
+
return set(data.files, data.path, newClampFormula)
|
|
390
|
+
}
|
|
391
|
+
case 'DIVIDE': {
|
|
392
|
+
const newDivideFormula: FunctionOperation = {
|
|
393
|
+
...data.value,
|
|
394
|
+
name: '@toddle/divide',
|
|
395
|
+
display_name: 'Divide',
|
|
396
|
+
}
|
|
397
|
+
return set(data.files, data.path, newDivideFormula)
|
|
398
|
+
}
|
|
399
|
+
case 'DROP': {
|
|
400
|
+
const newDropFormula: FunctionOperation = {
|
|
401
|
+
...data.value,
|
|
402
|
+
name: '@toddle/drop',
|
|
403
|
+
display_name: 'Drop',
|
|
404
|
+
}
|
|
405
|
+
return set(data.files, data.path, newDropFormula)
|
|
406
|
+
}
|
|
407
|
+
case 'ENTRIES': {
|
|
408
|
+
const newEntriesFormula: FunctionOperation = {
|
|
409
|
+
...data.value,
|
|
410
|
+
name: '@toddle/entries',
|
|
411
|
+
display_name: 'Entries',
|
|
412
|
+
}
|
|
413
|
+
return set(data.files, data.path, newEntriesFormula)
|
|
414
|
+
}
|
|
415
|
+
case 'EVERY': {
|
|
416
|
+
const newEveryFormula: FunctionOperation = {
|
|
417
|
+
...data.value,
|
|
418
|
+
name: '@toddle/every',
|
|
419
|
+
display_name: 'Every',
|
|
420
|
+
arguments: renameArguments(
|
|
421
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
422
|
+
data.value.arguments,
|
|
423
|
+
),
|
|
424
|
+
}
|
|
425
|
+
return set(data.files, data.path, newEveryFormula)
|
|
426
|
+
}
|
|
427
|
+
case 'FILTER': {
|
|
428
|
+
const newFilterFormula: FunctionOperation = {
|
|
429
|
+
...data.value,
|
|
430
|
+
name: '@toddle/filter',
|
|
431
|
+
display_name: 'Filter',
|
|
432
|
+
arguments: renameArguments(
|
|
433
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
434
|
+
data.value.arguments,
|
|
435
|
+
),
|
|
436
|
+
}
|
|
437
|
+
return set(data.files, data.path, newFilterFormula)
|
|
438
|
+
}
|
|
439
|
+
case 'FIND': {
|
|
440
|
+
const newFindFormula: FunctionOperation = {
|
|
441
|
+
...data.value,
|
|
442
|
+
name: '@toddle/find',
|
|
443
|
+
display_name: 'Find',
|
|
444
|
+
arguments: renameArguments(
|
|
445
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
446
|
+
data.value.arguments,
|
|
447
|
+
),
|
|
448
|
+
}
|
|
449
|
+
return set(data.files, data.path, newFindFormula)
|
|
450
|
+
}
|
|
451
|
+
case 'FROMENTRIES': {
|
|
452
|
+
const newFromentriesFormula: FunctionOperation = {
|
|
453
|
+
...data.value,
|
|
454
|
+
name: '@toddle/fromEntries',
|
|
455
|
+
display_name: 'From entries',
|
|
456
|
+
arguments: renameArguments(
|
|
457
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
458
|
+
data.value.arguments,
|
|
459
|
+
),
|
|
460
|
+
}
|
|
461
|
+
return set(data.files, data.path, newFromentriesFormula)
|
|
462
|
+
}
|
|
463
|
+
case 'GET': {
|
|
464
|
+
const newGetFormula: FunctionOperation = {
|
|
465
|
+
...data.value,
|
|
466
|
+
name: '@toddle/get',
|
|
467
|
+
display_name: 'Get',
|
|
468
|
+
}
|
|
469
|
+
return set(data.files, data.path, newGetFormula)
|
|
470
|
+
}
|
|
471
|
+
case 'INCLUDES': {
|
|
472
|
+
const newIncludesFormula: FunctionOperation = {
|
|
473
|
+
...data.value,
|
|
474
|
+
name: '@toddle/includes',
|
|
475
|
+
display_name: 'Includes',
|
|
476
|
+
arguments: renameArguments(
|
|
477
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
478
|
+
data.value.arguments,
|
|
479
|
+
),
|
|
480
|
+
}
|
|
481
|
+
return set(data.files, data.path, newIncludesFormula)
|
|
482
|
+
}
|
|
483
|
+
case 'JOIN': {
|
|
484
|
+
const newJoinFormula: FunctionOperation = {
|
|
485
|
+
...data.value,
|
|
486
|
+
name: '@toddle/join',
|
|
487
|
+
display_name: 'Join',
|
|
488
|
+
arguments: renameArguments(
|
|
489
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
490
|
+
data.value.arguments,
|
|
491
|
+
),
|
|
492
|
+
}
|
|
493
|
+
return set(data.files, data.path, newJoinFormula)
|
|
494
|
+
}
|
|
495
|
+
case 'MAP': {
|
|
496
|
+
const newMapFormula: FunctionOperation = {
|
|
497
|
+
...data.value,
|
|
498
|
+
name: '@toddle/map',
|
|
499
|
+
display_name: 'Map',
|
|
500
|
+
arguments: renameArguments(
|
|
501
|
+
{
|
|
502
|
+
...ARRAY_ARGUMENT_MAPPINGS,
|
|
503
|
+
'Mapping fx': 'Formula',
|
|
504
|
+
},
|
|
505
|
+
data.value.arguments,
|
|
506
|
+
),
|
|
507
|
+
}
|
|
508
|
+
return set(data.files, data.path, newMapFormula)
|
|
509
|
+
}
|
|
510
|
+
case 'MAX': {
|
|
511
|
+
const newMaxFormula: FunctionOperation = {
|
|
512
|
+
...data.value,
|
|
513
|
+
name: '@toddle/max',
|
|
514
|
+
display_name: 'Max',
|
|
515
|
+
arguments: renameArguments(
|
|
516
|
+
ARRAY_ARGUMENT_MAPPINGS,
|
|
517
|
+
data.value.arguments,
|
|
518
|
+
),
|
|
519
|
+
}
|
|
520
|
+
return set(data.files, data.path, newMaxFormula)
|
|
521
|
+
}
|
|
522
|
+
case 'MIN': {
|
|
523
|
+
const newMinFormula: FunctionOperation = {
|
|
524
|
+
...data.value,
|
|
525
|
+
name: '@toddle/min',
|
|
526
|
+
display_name: 'Min',
|
|
527
|
+
arguments: renameArguments(
|
|
528
|
+
ARRAY_ARGUMENT_MAPPINGS,
|
|
529
|
+
data.value.arguments,
|
|
530
|
+
),
|
|
531
|
+
}
|
|
532
|
+
return set(data.files, data.path, newMinFormula)
|
|
533
|
+
}
|
|
534
|
+
case 'MINUS': {
|
|
535
|
+
const newMinusFormula: FunctionOperation = {
|
|
536
|
+
...data.value,
|
|
537
|
+
name: '@toddle/minus',
|
|
538
|
+
display_name: 'Minus',
|
|
539
|
+
}
|
|
540
|
+
return set(data.files, data.path, newMinusFormula)
|
|
541
|
+
}
|
|
542
|
+
case 'MULTIPLY': {
|
|
543
|
+
const newMultiplyFormula: FunctionOperation = {
|
|
544
|
+
...data.value,
|
|
545
|
+
name: '@toddle/multiply',
|
|
546
|
+
display_name: 'Multiply',
|
|
547
|
+
}
|
|
548
|
+
return set(data.files, data.path, newMultiplyFormula)
|
|
549
|
+
}
|
|
550
|
+
case 'NOT': {
|
|
551
|
+
const newNotFormula: FunctionOperation = {
|
|
552
|
+
...data.value,
|
|
553
|
+
name: '@toddle/not',
|
|
554
|
+
display_name: 'Not',
|
|
555
|
+
}
|
|
556
|
+
return set(data.files, data.path, newNotFormula)
|
|
557
|
+
}
|
|
558
|
+
case 'NUMBER': {
|
|
559
|
+
const newNumberFormula: FunctionOperation = {
|
|
560
|
+
...data.value,
|
|
561
|
+
name: '@toddle/number',
|
|
562
|
+
display_name: 'Number',
|
|
563
|
+
}
|
|
564
|
+
return set(data.files, data.path, newNumberFormula)
|
|
565
|
+
}
|
|
566
|
+
case 'RANGE': {
|
|
567
|
+
const newRangeFormula: FunctionOperation = {
|
|
568
|
+
...data.value,
|
|
569
|
+
name: '@toddle/range',
|
|
570
|
+
display_name: 'Range',
|
|
571
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
572
|
+
arguments: data.value.arguments?.map((arg, i) => ({
|
|
573
|
+
...arg,
|
|
574
|
+
// The Max argument didn't always have a name
|
|
575
|
+
name: i === 1 && typeof arg.name !== 'string' ? 'Max' : arg.name,
|
|
576
|
+
})),
|
|
577
|
+
}
|
|
578
|
+
return set(data.files, data.path, newRangeFormula)
|
|
579
|
+
}
|
|
580
|
+
case 'REDUCE': {
|
|
581
|
+
const newReduceFormula: FunctionOperation = {
|
|
582
|
+
...data.value,
|
|
583
|
+
name: '@toddle/reduce',
|
|
584
|
+
display_name: 'Reduce',
|
|
585
|
+
arguments: renameArguments(
|
|
586
|
+
{ 'Reducer fx': 'Formula' },
|
|
587
|
+
data.value.arguments,
|
|
588
|
+
),
|
|
589
|
+
}
|
|
590
|
+
return set(data.files, data.path, newReduceFormula)
|
|
591
|
+
}
|
|
592
|
+
case 'REPLACEALL': {
|
|
593
|
+
const newReplaceallFormula: FunctionOperation = {
|
|
594
|
+
...data.value,
|
|
595
|
+
name: '@toddle/replaceAll',
|
|
596
|
+
display_name: 'Replace all',
|
|
597
|
+
arguments: renameArguments(
|
|
598
|
+
// Yes, there was a typo in the old argument name
|
|
599
|
+
{ 'String to repalce': 'Search' },
|
|
600
|
+
data.value.arguments,
|
|
601
|
+
),
|
|
602
|
+
}
|
|
603
|
+
return set(data.files, data.path, newReplaceallFormula)
|
|
604
|
+
}
|
|
605
|
+
case 'REVERSE': {
|
|
606
|
+
const newReverseFormula: FunctionOperation = {
|
|
607
|
+
...data.value,
|
|
608
|
+
name: '@toddle/reverse',
|
|
609
|
+
display_name: 'Reverse',
|
|
610
|
+
arguments: renameArguments(
|
|
611
|
+
ARRAY_ARGUMENT_MAPPINGS,
|
|
612
|
+
data.value.arguments,
|
|
613
|
+
),
|
|
614
|
+
}
|
|
615
|
+
return set(data.files, data.path, newReverseFormula)
|
|
616
|
+
}
|
|
617
|
+
case 'ROUND': {
|
|
618
|
+
const newRoundFormula: FunctionOperation = {
|
|
619
|
+
...data.value,
|
|
620
|
+
name: '@toddle/round',
|
|
621
|
+
display_name: 'Round',
|
|
622
|
+
}
|
|
623
|
+
return set(data.files, data.path, newRoundFormula)
|
|
624
|
+
}
|
|
625
|
+
case 'SET': {
|
|
626
|
+
const newSetFormula: FunctionOperation = {
|
|
627
|
+
...data.value,
|
|
628
|
+
name: '@toddle/set',
|
|
629
|
+
display_name: 'Set',
|
|
630
|
+
}
|
|
631
|
+
return set(data.files, data.path, newSetFormula)
|
|
632
|
+
}
|
|
633
|
+
case 'SOME': {
|
|
634
|
+
const newSomeFormula: FunctionOperation = {
|
|
635
|
+
...data.value,
|
|
636
|
+
name: '@toddle/some',
|
|
637
|
+
display_name: 'Some',
|
|
638
|
+
arguments: renameArguments(
|
|
639
|
+
PREDICATE_ARGUMENT_MAPPINGS,
|
|
640
|
+
data.value.arguments,
|
|
641
|
+
),
|
|
642
|
+
}
|
|
643
|
+
return set(data.files, data.path, newSomeFormula)
|
|
644
|
+
}
|
|
645
|
+
case 'SPLIT': {
|
|
646
|
+
const newSplitFormula: FunctionOperation = {
|
|
647
|
+
...data.value,
|
|
648
|
+
name: '@toddle/split',
|
|
649
|
+
display_name: 'Split',
|
|
650
|
+
}
|
|
651
|
+
return set(data.files, data.path, newSplitFormula)
|
|
652
|
+
}
|
|
653
|
+
case 'STRING': {
|
|
654
|
+
const newStringFormula: FunctionOperation = {
|
|
655
|
+
...data.value,
|
|
656
|
+
name: '@toddle/string',
|
|
657
|
+
display_name: 'String',
|
|
658
|
+
}
|
|
659
|
+
return set(data.files, data.path, newStringFormula)
|
|
660
|
+
}
|
|
661
|
+
case 'SUM': {
|
|
662
|
+
const newSumFormula: FunctionOperation = {
|
|
663
|
+
...data.value,
|
|
664
|
+
name: '@toddle/sum',
|
|
665
|
+
display_name: 'Sum',
|
|
666
|
+
}
|
|
667
|
+
return set(data.files, data.path, newSumFormula)
|
|
668
|
+
}
|
|
669
|
+
case 'TAKE': {
|
|
670
|
+
const newTakeFormula: FunctionOperation = {
|
|
671
|
+
...data.value,
|
|
672
|
+
name: '@toddle/take',
|
|
673
|
+
display_name: 'Take',
|
|
674
|
+
arguments: renameArguments(
|
|
675
|
+
ARRAY_ARGUMENT_MAPPINGS,
|
|
676
|
+
data.value.arguments,
|
|
677
|
+
),
|
|
678
|
+
}
|
|
679
|
+
return set(data.files, data.path, newTakeFormula)
|
|
680
|
+
}
|
|
681
|
+
case 'TRIM': {
|
|
682
|
+
const newTrimFormula: FunctionOperation = {
|
|
683
|
+
...data.value,
|
|
684
|
+
name: '@toddle/trim',
|
|
685
|
+
display_name: 'Trim',
|
|
686
|
+
}
|
|
687
|
+
return set(data.files, data.path, newTrimFormula)
|
|
688
|
+
}
|
|
689
|
+
}
|
|
690
|
+
},
|
|
22
691
|
},
|
|
23
692
|
}
|
|
24
693
|
|
|
694
|
+
const isIssue = (data: NodeType): data is FormulaNode<FunctionOperation> =>
|
|
695
|
+
data.nodeType === 'formula' &&
|
|
696
|
+
data.value.type === 'function' &&
|
|
697
|
+
isLegacyFormula(data.value, data.files)
|
|
698
|
+
|
|
699
|
+
export type LegacyFormulaRuleFix = 'replace-legacy-formula'
|
|
700
|
+
|
|
25
701
|
const isLegacyFormula = (
|
|
26
702
|
formula: FunctionOperation,
|
|
27
703
|
files: Omit<ProjectFiles, 'config'> & Partial<Pick<ProjectFiles, 'config'>>,
|
|
@@ -47,21 +723,34 @@ const isUpperCase = (str: string) => str === str.toUpperCase()
|
|
|
47
723
|
const legacyFormulas = new Set([
|
|
48
724
|
'and',
|
|
49
725
|
'concat',
|
|
50
|
-
'count',
|
|
51
726
|
'default',
|
|
52
727
|
'delete',
|
|
728
|
+
'drop_last',
|
|
53
729
|
'eq',
|
|
730
|
+
'find index',
|
|
54
731
|
'flat',
|
|
55
732
|
'gt',
|
|
56
733
|
'gte',
|
|
734
|
+
'group_by',
|
|
57
735
|
'if',
|
|
736
|
+
'index of',
|
|
737
|
+
'json_parse',
|
|
738
|
+
'key_by',
|
|
58
739
|
'list',
|
|
740
|
+
'lower',
|
|
59
741
|
'lt',
|
|
60
742
|
'lte',
|
|
61
743
|
'mod',
|
|
62
744
|
'neq',
|
|
63
745
|
'or',
|
|
746
|
+
'random',
|
|
747
|
+
'size',
|
|
748
|
+
'sqrt',
|
|
749
|
+
'starts_with',
|
|
750
|
+
'take_last',
|
|
64
751
|
'type',
|
|
752
|
+
'upper',
|
|
753
|
+
'uri_encode',
|
|
65
754
|
])
|
|
66
755
|
|
|
67
756
|
// cSpell: disable
|
|
@@ -156,3 +845,23 @@ const builtInFormulas = new Set([
|
|
|
156
845
|
'uppercase',
|
|
157
846
|
])
|
|
158
847
|
// cSpell: enable
|
|
848
|
+
|
|
849
|
+
const ARRAY_ARGUMENT_MAPPINGS = { List: 'Array' }
|
|
850
|
+
const PREDICATE_ARGUMENT_MAPPINGS = {
|
|
851
|
+
...ARRAY_ARGUMENT_MAPPINGS,
|
|
852
|
+
'Predicate fx': 'Formula',
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
const renameArguments = (
|
|
856
|
+
mappings: Record<string, string>,
|
|
857
|
+
args: FunctionArgument[] | undefined,
|
|
858
|
+
): FunctionArgument[] =>
|
|
859
|
+
args?.map((arg) => ({
|
|
860
|
+
...arg,
|
|
861
|
+
// Let's adjust the names
|
|
862
|
+
name:
|
|
863
|
+
typeof arg.name === 'string'
|
|
864
|
+
? // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
865
|
+
(mappings[arg.name] ?? arg.name)
|
|
866
|
+
: arg.name,
|
|
867
|
+
})) ?? []
|