@nordcraft/search 1.0.38 → 1.0.40
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/actions/legacyActionRule.js +144 -2
- package/dist/rules/actions/legacyActionRule.js.map +1 -1
- package/dist/rules/actions/legacyActionRule.test.js +235 -1
- package/dist/rules/actions/legacyActionRule.test.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 +602 -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/rules/formulas/noReferenceProjectFormulaRule.js +73 -58
- package/dist/rules/formulas/noReferenceProjectFormulaRule.js.map +1 -1
- package/dist/rules/formulas/noReferenceProjectFormulaRule.test.js +34 -1
- package/dist/rules/formulas/noReferenceProjectFormulaRule.test.js.map +1 -1
- package/dist/searchProject.js +338 -217
- package/dist/searchProject.js.map +1 -1
- package/dist/util/helpers.js +31 -5
- 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/actions/legacyActionRule.test.ts +245 -1
- package/src/rules/actions/legacyActionRule.ts +166 -4
- 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 +697 -10
- package/src/rules/formulas/noReferenceProjectFormulaRule.test.ts +36 -1
- package/src/rules/formulas/noReferenceProjectFormulaRule.ts +78 -64
- package/src/searchProject.ts +217 -98
- package/src/types.d.ts +20 -3
- package/src/util/helpers.test.ts +80 -0
- package/src/util/helpers.ts +61 -9
package/src/types.d.ts
CHANGED
|
@@ -21,6 +21,10 @@ import type {
|
|
|
21
21
|
Route,
|
|
22
22
|
ToddleProject,
|
|
23
23
|
} from '@nordcraft/ssr/dist/ssr.types'
|
|
24
|
+
import type { LegacyActionRuleFix } from './rules/actions/legacyActionRule'
|
|
25
|
+
import type { NoReferenceComponentRuleFix } from './rules/components/noReferenceComponentRule'
|
|
26
|
+
import type { LegacyFormulaRuleFix } from './rules/formulas/legacyFormulaRule'
|
|
27
|
+
import type { NoReferenceProjectFormulaRuleFix } from './rules/formulas/noReferenceProjectFormulaRule'
|
|
24
28
|
|
|
25
29
|
type Code =
|
|
26
30
|
| 'ambiguous style variable syntax'
|
|
@@ -106,6 +110,7 @@ export type Result = {
|
|
|
106
110
|
category: Category
|
|
107
111
|
level: Level
|
|
108
112
|
details?: any
|
|
113
|
+
fixes?: FixType[]
|
|
109
114
|
}
|
|
110
115
|
|
|
111
116
|
interface ApplicationCookie {
|
|
@@ -239,9 +244,9 @@ type ComponentAttributeNode = {
|
|
|
239
244
|
component: ToddleComponent<Function>
|
|
240
245
|
} & Base
|
|
241
246
|
|
|
242
|
-
type FormulaNode = {
|
|
247
|
+
type FormulaNode<F = Formula> = {
|
|
243
248
|
nodeType: 'formula'
|
|
244
|
-
value:
|
|
249
|
+
value: F
|
|
245
250
|
component?: ToddleComponent<Function>
|
|
246
251
|
} & Base
|
|
247
252
|
|
|
@@ -308,13 +313,25 @@ export type NodeType =
|
|
|
308
313
|
| ProjectRoute
|
|
309
314
|
| StyleVariantNode
|
|
310
315
|
|
|
316
|
+
type FixType =
|
|
317
|
+
| LegacyFormulaRuleFix
|
|
318
|
+
| LegacyActionRuleFix
|
|
319
|
+
| NoReferenceComponentRuleFix
|
|
320
|
+
| NoReferenceProjectFormulaRuleFix
|
|
321
|
+
|
|
311
322
|
export interface Rule<T = unknown, V = NodeType> {
|
|
312
323
|
category: Category
|
|
313
324
|
code: Code
|
|
314
325
|
level: Level
|
|
315
326
|
visit: (
|
|
316
|
-
report: (path: (string | number)[], details?: T) => void,
|
|
327
|
+
report: (path: (string | number)[], details?: T, fixes?: FixType[]) => void,
|
|
317
328
|
data: V,
|
|
318
329
|
state?: ApplicationState | undefined,
|
|
319
330
|
) => void
|
|
331
|
+
fixes?: Partial<
|
|
332
|
+
Record<
|
|
333
|
+
FixType,
|
|
334
|
+
(data: V, state?: ApplicationState | undefined) => ProjectFiles | void
|
|
335
|
+
>
|
|
336
|
+
>
|
|
320
337
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test'
|
|
2
|
+
import { shouldSearchExactPath, shouldVisitTree } from './helpers'
|
|
3
|
+
|
|
4
|
+
describe('shouldSearchPath', () => {
|
|
5
|
+
test('should return true for paths in pathsToVisit', () => {
|
|
6
|
+
const pathsToVisit = [
|
|
7
|
+
['components', 'Button'],
|
|
8
|
+
['components', 'Input'],
|
|
9
|
+
]
|
|
10
|
+
expect(
|
|
11
|
+
shouldVisitTree({
|
|
12
|
+
path: ['components', 'Button', 'attrs', 'attr1', 'testValue'],
|
|
13
|
+
pathsToVisit,
|
|
14
|
+
}),
|
|
15
|
+
).toBe(true)
|
|
16
|
+
expect(
|
|
17
|
+
shouldVisitTree({ path: ['components', 'Input'], pathsToVisit }),
|
|
18
|
+
).toBe(true)
|
|
19
|
+
expect(
|
|
20
|
+
shouldVisitTree({
|
|
21
|
+
path: ['components', 'Button', 'formulas'],
|
|
22
|
+
pathsToVisit,
|
|
23
|
+
}),
|
|
24
|
+
).toBe(true)
|
|
25
|
+
expect(
|
|
26
|
+
shouldVisitTree({
|
|
27
|
+
path: ['components', 'project-sidebar-item'],
|
|
28
|
+
pathsToVisit: [
|
|
29
|
+
[
|
|
30
|
+
'components',
|
|
31
|
+
'project-sidebar-item',
|
|
32
|
+
'formulas',
|
|
33
|
+
'p_Z1PzOcDop79KGafQ7Lm',
|
|
34
|
+
'formula',
|
|
35
|
+
],
|
|
36
|
+
],
|
|
37
|
+
}),
|
|
38
|
+
).toBe(true)
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
test('should return false for paths not in pathsToVisit', () => {
|
|
42
|
+
const pathsToVisit = [
|
|
43
|
+
['components', 'Button'],
|
|
44
|
+
['components', 'Input'],
|
|
45
|
+
]
|
|
46
|
+
expect(
|
|
47
|
+
shouldVisitTree({ path: ['components', 'Card'], pathsToVisit }),
|
|
48
|
+
).toBe(false)
|
|
49
|
+
expect(
|
|
50
|
+
shouldVisitTree({ path: ['components', 'Form'], pathsToVisit }),
|
|
51
|
+
).toBe(false)
|
|
52
|
+
})
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
describe('shouldSearchExactPath', () => {
|
|
56
|
+
test.only('should only return true for exact matches', () => {
|
|
57
|
+
const pathsToVisit = [
|
|
58
|
+
['components', 'Button'],
|
|
59
|
+
['components', 'Input'],
|
|
60
|
+
]
|
|
61
|
+
expect(
|
|
62
|
+
shouldSearchExactPath({ path: ['components', 'Button'], pathsToVisit }),
|
|
63
|
+
).toBe(true)
|
|
64
|
+
expect(
|
|
65
|
+
shouldSearchExactPath({ path: ['components', 'Input'], pathsToVisit }),
|
|
66
|
+
).toBe(true)
|
|
67
|
+
expect(
|
|
68
|
+
shouldSearchExactPath({
|
|
69
|
+
path: ['components', 'Button', 'formulas'],
|
|
70
|
+
pathsToVisit,
|
|
71
|
+
}),
|
|
72
|
+
).toBe(false)
|
|
73
|
+
expect(
|
|
74
|
+
shouldSearchExactPath({
|
|
75
|
+
path: ['components', 'project-sidebar-item'],
|
|
76
|
+
pathsToVisit,
|
|
77
|
+
}),
|
|
78
|
+
).toBe(false)
|
|
79
|
+
})
|
|
80
|
+
})
|
package/src/util/helpers.ts
CHANGED
|
@@ -1,22 +1,55 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
ActionModel,
|
|
3
|
+
CustomActionArgument,
|
|
4
|
+
CustomActionModel,
|
|
3
5
|
ElementNodeModel,
|
|
4
6
|
} from '@nordcraft/core/dist/component/component.types'
|
|
7
|
+
import type { FunctionArgument } from '@nordcraft/core/dist/formula/formula'
|
|
5
8
|
import { isDefined } from '@nordcraft/core/dist/utils/util'
|
|
6
9
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Returns true if the full path is included in any of the pathsToVisit
|
|
12
|
+
* This allows searching only certain sub-trees in the files
|
|
13
|
+
* If pathsToVisit is empty, all paths are searched
|
|
14
|
+
*/
|
|
15
|
+
export function shouldVisitTree({
|
|
16
|
+
path,
|
|
17
|
+
pathsToVisit = [],
|
|
18
|
+
}: {
|
|
19
|
+
path: (string | number)[]
|
|
20
|
+
pathsToVisit?: (string | number)[][]
|
|
21
|
+
}) {
|
|
11
22
|
return (
|
|
12
23
|
pathsToVisit.length === 0 ||
|
|
13
24
|
pathsToVisit.some((pathToVisit) =>
|
|
14
|
-
|
|
25
|
+
// Either the index is outside the current path (we are deeper in the tree)
|
|
26
|
+
// or the path matches on each index
|
|
27
|
+
pathToVisit.every((p1, i) => i >= path.length || path[i] === p1),
|
|
15
28
|
)
|
|
16
29
|
)
|
|
17
30
|
}
|
|
18
31
|
|
|
19
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Returns true if the exact path is included in pathsToVisit
|
|
34
|
+
* This allows searching only certain nodes in the files
|
|
35
|
+
*/
|
|
36
|
+
export function shouldSearchExactPath({
|
|
37
|
+
path,
|
|
38
|
+
pathsToVisit,
|
|
39
|
+
}: {
|
|
40
|
+
path: (string | number)[]
|
|
41
|
+
pathsToVisit: (string | number)[][]
|
|
42
|
+
}) {
|
|
43
|
+
return pathsToVisit.some(
|
|
44
|
+
(pathToVisit) =>
|
|
45
|
+
path.length === pathToVisit.length &&
|
|
46
|
+
pathToVisit.every((p1, i) => path[i] === p1),
|
|
47
|
+
)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const isLegacyAction = (
|
|
51
|
+
model: ActionModel,
|
|
52
|
+
): model is CustomActionModel => {
|
|
20
53
|
switch (model.type) {
|
|
21
54
|
case 'Custom':
|
|
22
55
|
case undefined:
|
|
@@ -30,14 +63,11 @@ const LEGACY_CUSTOM_ACTIONS = new Set([
|
|
|
30
63
|
'If',
|
|
31
64
|
'PreventDefault',
|
|
32
65
|
'StopPropagation',
|
|
33
|
-
'Copy To Clipboard',
|
|
34
66
|
'CopyToClipboard',
|
|
35
67
|
'UpdateVariable',
|
|
36
|
-
'Update Variable',
|
|
37
68
|
'Update URL parameter',
|
|
38
69
|
'updateUrlParameters',
|
|
39
70
|
'UpdateQueryParam',
|
|
40
|
-
'Update Query',
|
|
41
71
|
'Fetch',
|
|
42
72
|
'SetTimeout',
|
|
43
73
|
'SetInterval',
|
|
@@ -46,6 +76,7 @@ const LEGACY_CUSTOM_ACTIONS = new Set([
|
|
|
46
76
|
'GoToURL',
|
|
47
77
|
'TriggerEvent',
|
|
48
78
|
'Set session cookies',
|
|
79
|
+
'@toddle/setSessionCookies',
|
|
49
80
|
])
|
|
50
81
|
|
|
51
82
|
interface BaseInteractiveContent {
|
|
@@ -102,3 +133,24 @@ export const interactiveContentElementDefinition = (
|
|
|
102
133
|
}
|
|
103
134
|
return true
|
|
104
135
|
})
|
|
136
|
+
|
|
137
|
+
export const ARRAY_ARGUMENT_MAPPINGS = { List: 'Array' }
|
|
138
|
+
export const PREDICATE_ARGUMENT_MAPPINGS = {
|
|
139
|
+
...ARRAY_ARGUMENT_MAPPINGS,
|
|
140
|
+
'Predicate fx': 'Formula',
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export const renameArguments = <
|
|
144
|
+
T extends FunctionArgument | CustomActionArgument,
|
|
145
|
+
>(
|
|
146
|
+
mappings: Record<string, string>,
|
|
147
|
+
args: T[] | undefined,
|
|
148
|
+
): T[] =>
|
|
149
|
+
args?.map((arg) => ({
|
|
150
|
+
...arg,
|
|
151
|
+
// Let's adjust the names
|
|
152
|
+
name:
|
|
153
|
+
typeof arg.name === 'string'
|
|
154
|
+
? (mappings[arg.name] ?? arg.name)
|
|
155
|
+
: arg.name,
|
|
156
|
+
})) ?? []
|