@nordcraft/search 1.0.43 → 1.0.44
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/rules/actions/legacyActionRule.fix.js +140 -0
- package/dist/rules/actions/legacyActionRule.fix.js.map +1 -0
- package/dist/rules/actions/legacyActionRule.js +3 -144
- package/dist/rules/actions/legacyActionRule.js.map +1 -1
- package/dist/rules/actions/legacyActionRule.test.js +1 -0
- package/dist/rules/actions/legacyActionRule.test.js.map +1 -1
- package/dist/rules/actions/noReferenceProjectActionRule.js +33 -40
- package/dist/rules/actions/noReferenceProjectActionRule.js.map +1 -1
- package/dist/rules/apis/noReferenceApiRule.js +7 -2
- package/dist/rules/apis/noReferenceApiRule.js.map +1 -1
- package/dist/rules/apis/noReferenceApiRule.test.js +65 -1
- package/dist/rules/apis/noReferenceApiRule.test.js.map +1 -1
- package/dist/rules/attributes/noReferenceAttributeRule.js +5 -1
- package/dist/rules/attributes/noReferenceAttributeRule.js.map +1 -1
- package/dist/rules/attributes/noReferenceAttributeRule.test.js +33 -1
- package/dist/rules/attributes/noReferenceAttributeRule.test.js.map +1 -1
- package/dist/rules/components/noReferenceComponentRule.js +18 -28
- package/dist/rules/components/noReferenceComponentRule.js.map +1 -1
- package/dist/rules/events/noReferenceEventRule.js +6 -2
- package/dist/rules/events/noReferenceEventRule.js.map +1 -1
- package/dist/rules/events/noReferenceEventRule.test.js +57 -1
- package/dist/rules/events/noReferenceEventRule.test.js.map +1 -1
- package/dist/rules/formulas/legacyFormulaRule.fix.js +574 -0
- package/dist/rules/formulas/legacyFormulaRule.fix.js.map +1 -0
- package/dist/rules/formulas/legacyFormulaRule.js +5 -580
- package/dist/rules/formulas/legacyFormulaRule.js.map +1 -1
- package/dist/rules/formulas/noReferenceComponentFormulaRule.js +8 -1
- package/dist/rules/formulas/noReferenceComponentFormulaRule.js.map +1 -1
- package/dist/rules/formulas/noReferenceProjectFormulaRule.js +63 -72
- package/dist/rules/formulas/noReferenceProjectFormulaRule.js.map +1 -1
- package/dist/searchProject.js +36 -16
- package/dist/searchProject.js.map +1 -1
- package/dist/util/removeUnused.fix.js +3 -0
- package/dist/util/removeUnused.fix.js.map +1 -0
- package/package.json +2 -2
- package/src/rules/actions/legacyActionRule.fix.ts +157 -0
- package/src/rules/actions/legacyActionRule.test.ts +1 -0
- package/src/rules/actions/legacyActionRule.ts +3 -159
- package/src/rules/actions/noReferenceProjectActionRule.ts +39 -47
- package/src/rules/apis/noReferenceApiRule.test.ts +67 -1
- package/src/rules/apis/noReferenceApiRule.ts +9 -2
- package/src/rules/attributes/noReferenceAttributeRule.test.ts +35 -1
- package/src/rules/attributes/noReferenceAttributeRule.ts +7 -2
- package/src/rules/components/noReferenceComponentRule.ts +23 -34
- package/src/rules/events/noReferenceEventRule.test.ts +59 -1
- package/src/rules/events/noReferenceEventRule.ts +8 -3
- package/src/rules/formulas/legacyFormulaRule.fix.ts +661 -0
- package/src/rules/formulas/legacyFormulaRule.ts +9 -670
- package/src/rules/formulas/noReferenceComponentFormulaRule.ts +15 -3
- package/src/rules/formulas/noReferenceProjectFormulaRule.ts +70 -77
- package/src/searchProject.ts +42 -22
- package/src/types.d.ts +16 -8
- package/src/util/removeUnused.fix.ts +5 -0
|
@@ -1,11 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
ActionModel,
|
|
3
|
-
CustomActionArgument,
|
|
4
|
-
} from '@nordcraft/core/dist/component/component.types'
|
|
5
|
-
import { valueFormula } from '@nordcraft/core/dist/formula/formulaUtils'
|
|
6
|
-
import { set } from '@nordcraft/core/dist/utils/collections'
|
|
7
1
|
import type { Rule } from '../../types'
|
|
8
|
-
import { isLegacyAction
|
|
2
|
+
import { isLegacyAction } from '../../util/helpers'
|
|
3
|
+
import { replaceLegacyAction } from './legacyActionRule.fix'
|
|
9
4
|
|
|
10
5
|
export const legacyActionRule: Rule<{
|
|
11
6
|
name: string
|
|
@@ -39,158 +34,7 @@ export const legacyActionRule: Rule<{
|
|
|
39
34
|
}
|
|
40
35
|
},
|
|
41
36
|
fixes: {
|
|
42
|
-
'replace-legacy-action':
|
|
43
|
-
if (nodeType !== 'action-model') {
|
|
44
|
-
return
|
|
45
|
-
}
|
|
46
|
-
if (!isLegacyAction(value)) {
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
let newAction: ActionModel | undefined
|
|
51
|
-
switch (value.name) {
|
|
52
|
-
case 'If': {
|
|
53
|
-
const trueActions = value.events?.['true']?.actions ?? []
|
|
54
|
-
const falseActions = value.events?.['false']?.actions ?? []
|
|
55
|
-
const trueCondition: CustomActionArgument | undefined =
|
|
56
|
-
(value.arguments ?? [])[0]
|
|
57
|
-
newAction = {
|
|
58
|
-
type: 'Switch',
|
|
59
|
-
cases: [
|
|
60
|
-
{
|
|
61
|
-
condition: trueCondition?.formula ?? null,
|
|
62
|
-
actions: trueActions,
|
|
63
|
-
},
|
|
64
|
-
],
|
|
65
|
-
default: { actions: falseActions },
|
|
66
|
-
}
|
|
67
|
-
break
|
|
68
|
-
}
|
|
69
|
-
case 'PreventDefault': {
|
|
70
|
-
newAction = {
|
|
71
|
-
name: '@toddle/preventDefault',
|
|
72
|
-
arguments: [],
|
|
73
|
-
label: 'Prevent default',
|
|
74
|
-
}
|
|
75
|
-
break
|
|
76
|
-
}
|
|
77
|
-
case 'StopPropagation': {
|
|
78
|
-
newAction = {
|
|
79
|
-
name: '@toddle/stopPropagation',
|
|
80
|
-
arguments: [],
|
|
81
|
-
label: 'Stop propagation',
|
|
82
|
-
}
|
|
83
|
-
break
|
|
84
|
-
}
|
|
85
|
-
case 'UpdateVariable':
|
|
86
|
-
case 'Update Variable': {
|
|
87
|
-
const variableName =
|
|
88
|
-
value.arguments?.[0]?.formula.type === 'value'
|
|
89
|
-
? value.arguments[0].formula.value
|
|
90
|
-
: undefined
|
|
91
|
-
if (typeof variableName !== 'string') {
|
|
92
|
-
break
|
|
93
|
-
}
|
|
94
|
-
const variableValue = value.arguments?.[1]?.formula
|
|
95
|
-
if (!variableValue) {
|
|
96
|
-
break
|
|
97
|
-
}
|
|
98
|
-
newAction = {
|
|
99
|
-
type: 'SetVariable',
|
|
100
|
-
variable: variableName,
|
|
101
|
-
data: variableValue,
|
|
102
|
-
}
|
|
103
|
-
break
|
|
104
|
-
}
|
|
105
|
-
case 'SetTimeout': {
|
|
106
|
-
newAction = {
|
|
107
|
-
...value,
|
|
108
|
-
name: '@toddle/sleep',
|
|
109
|
-
arguments: renameArguments(
|
|
110
|
-
{ 'Delay in ms': 'Delay in milliseconds' },
|
|
111
|
-
value.arguments,
|
|
112
|
-
),
|
|
113
|
-
events: value.events?.['timeout']
|
|
114
|
-
? { tick: value.events.timeout }
|
|
115
|
-
: undefined,
|
|
116
|
-
label: 'Sleep',
|
|
117
|
-
}
|
|
118
|
-
break
|
|
119
|
-
}
|
|
120
|
-
case 'SetInterval': {
|
|
121
|
-
newAction = {
|
|
122
|
-
...value,
|
|
123
|
-
name: '@toddle/interval',
|
|
124
|
-
arguments: renameArguments(
|
|
125
|
-
{ 'Interval in ms': 'Interval in milliseconds' },
|
|
126
|
-
value.arguments,
|
|
127
|
-
),
|
|
128
|
-
label: 'Interval',
|
|
129
|
-
}
|
|
130
|
-
break
|
|
131
|
-
}
|
|
132
|
-
case 'Debug': {
|
|
133
|
-
newAction = {
|
|
134
|
-
...value,
|
|
135
|
-
name: '@toddle/logToConsole',
|
|
136
|
-
label: 'Log to console',
|
|
137
|
-
}
|
|
138
|
-
break
|
|
139
|
-
}
|
|
140
|
-
case 'GoToURL': {
|
|
141
|
-
newAction = {
|
|
142
|
-
name: '@toddle/gotToURL', // Yes, the typo is in the action name
|
|
143
|
-
arguments: renameArguments({ url: 'URL' }, value.arguments),
|
|
144
|
-
label: 'Go to URL',
|
|
145
|
-
}
|
|
146
|
-
break
|
|
147
|
-
}
|
|
148
|
-
case 'TriggerEvent': {
|
|
149
|
-
const eventName =
|
|
150
|
-
value.arguments?.[0]?.formula.type === 'value'
|
|
151
|
-
? value.arguments[0].formula.value
|
|
152
|
-
: undefined
|
|
153
|
-
if (typeof eventName !== 'string') {
|
|
154
|
-
break
|
|
155
|
-
}
|
|
156
|
-
const eventData = value.arguments?.[1]?.formula
|
|
157
|
-
if (!eventData) {
|
|
158
|
-
break
|
|
159
|
-
}
|
|
160
|
-
newAction = {
|
|
161
|
-
type: 'TriggerEvent',
|
|
162
|
-
event: eventName,
|
|
163
|
-
data: eventData,
|
|
164
|
-
}
|
|
165
|
-
break
|
|
166
|
-
}
|
|
167
|
-
case 'FocusElement': {
|
|
168
|
-
newAction = {
|
|
169
|
-
name: '@toddle/focus',
|
|
170
|
-
arguments: [
|
|
171
|
-
{
|
|
172
|
-
name: 'Element',
|
|
173
|
-
formula: {
|
|
174
|
-
type: 'function',
|
|
175
|
-
name: '@toddle/getElementById',
|
|
176
|
-
arguments: [
|
|
177
|
-
{
|
|
178
|
-
name: 'Id',
|
|
179
|
-
formula:
|
|
180
|
-
value.arguments?.[0]?.formula ?? valueFormula(null),
|
|
181
|
-
},
|
|
182
|
-
],
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
],
|
|
186
|
-
label: 'Focus',
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
if (newAction) {
|
|
191
|
-
return set(files, path, newAction)
|
|
192
|
-
}
|
|
193
|
-
},
|
|
37
|
+
'replace-legacy-action': replaceLegacyAction,
|
|
194
38
|
},
|
|
195
39
|
}
|
|
196
40
|
|
|
@@ -1,61 +1,53 @@
|
|
|
1
1
|
import type { CustomActionModel } from '@nordcraft/core/dist/component/component.types'
|
|
2
2
|
import { ToddleComponent } from '@nordcraft/core/dist/component/ToddleComponent'
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import type { Rule } from '../../types'
|
|
4
|
+
import { removeFromPathFix } from '../../util/removeUnused.fix'
|
|
5
5
|
|
|
6
6
|
export const noReferenceProjectActionRule: Rule<void> = {
|
|
7
7
|
code: 'no-reference project action',
|
|
8
8
|
level: 'warning',
|
|
9
9
|
category: 'No References',
|
|
10
|
-
visit: (report,
|
|
11
|
-
if (
|
|
12
|
-
|
|
10
|
+
visit: (report, { value, path, files, nodeType, memo }) => {
|
|
11
|
+
if (nodeType !== 'project-action' || value.exported === true) {
|
|
12
|
+
return
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const projectActionReferences = memo('projectActionReferences', () => {
|
|
16
|
+
const usedActions = new Set<string>()
|
|
17
|
+
for (const component of Object.values(files.components)) {
|
|
18
|
+
const c = new ToddleComponent({
|
|
19
|
+
// Enforce that the component is not undefined since we're iterating
|
|
20
|
+
component: component!,
|
|
21
|
+
getComponent: (name, packageName) =>
|
|
22
|
+
packageName
|
|
23
|
+
? files.packages?.[packageName]?.components[name]
|
|
24
|
+
: files.components[name],
|
|
25
|
+
packageName: undefined,
|
|
26
|
+
globalFormulas: {
|
|
27
|
+
formulas: files.formulas,
|
|
28
|
+
packages: files.packages,
|
|
29
|
+
},
|
|
30
|
+
})
|
|
31
|
+
for (const [, action] of c.actionModelsInComponent()) {
|
|
32
|
+
if (
|
|
33
|
+
action.type === 'Custom' ||
|
|
34
|
+
action.type === ('function' as any) ||
|
|
35
|
+
action.type === undefined
|
|
36
|
+
) {
|
|
37
|
+
usedActions.add((action as CustomActionModel).name)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return usedActions
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
if (!projectActionReferences.has(value.name)) {
|
|
45
|
+
report(path, undefined, ['delete-project-action'])
|
|
13
46
|
}
|
|
14
47
|
},
|
|
15
48
|
fixes: {
|
|
16
|
-
'delete-project-action':
|
|
17
|
-
if (!hasReferences(data)) {
|
|
18
|
-
return omit(data.files, data.path)
|
|
19
|
-
}
|
|
20
|
-
},
|
|
49
|
+
'delete-project-action': removeFromPathFix,
|
|
21
50
|
},
|
|
22
51
|
}
|
|
23
52
|
|
|
24
53
|
export type NoReferenceProjectActionRuleFix = 'delete-project-action'
|
|
25
|
-
|
|
26
|
-
const hasReferences = ({ value, files, nodeType, memo }: NodeType) => {
|
|
27
|
-
if (nodeType !== 'project-action' || value.exported === true) {
|
|
28
|
-
return true
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const projectActionReferences = memo('projectActionReferences', () => {
|
|
32
|
-
const usedActions = new Set<string>()
|
|
33
|
-
for (const component of Object.values(files.components)) {
|
|
34
|
-
const c = new ToddleComponent({
|
|
35
|
-
// Enforce that the component is not undefined since we're iterating
|
|
36
|
-
component: component!,
|
|
37
|
-
getComponent: (name, packageName) =>
|
|
38
|
-
packageName
|
|
39
|
-
? files.packages?.[packageName]?.components[name]
|
|
40
|
-
: files.components[name],
|
|
41
|
-
packageName: undefined,
|
|
42
|
-
globalFormulas: {
|
|
43
|
-
formulas: files.formulas,
|
|
44
|
-
packages: files.packages,
|
|
45
|
-
},
|
|
46
|
-
})
|
|
47
|
-
for (const [, action] of c.actionModelsInComponent()) {
|
|
48
|
-
if (
|
|
49
|
-
action.type === 'Custom' ||
|
|
50
|
-
action.type === ('function' as any) ||
|
|
51
|
-
action.type === undefined
|
|
52
|
-
) {
|
|
53
|
-
usedActions.add((action as CustomActionModel).name)
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return usedActions
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
return projectActionReferences.has(value.name)
|
|
61
|
-
}
|
|
@@ -2,11 +2,13 @@ import {
|
|
|
2
2
|
pathFormula,
|
|
3
3
|
valueFormula,
|
|
4
4
|
} from '@nordcraft/core/dist/formula/formulaUtils'
|
|
5
|
+
import type { ProjectFiles } from '@nordcraft/ssr/dist/ssr.types'
|
|
5
6
|
import { describe, expect, test } from 'bun:test'
|
|
7
|
+
import { fixProject } from '../../fixProject'
|
|
6
8
|
import { searchProject } from '../../searchProject'
|
|
7
9
|
import { noReferenceApiRule } from './noReferenceApiRule'
|
|
8
10
|
|
|
9
|
-
describe('noReferenceApiRule', () => {
|
|
11
|
+
describe('find noReferenceApiRule', () => {
|
|
10
12
|
test('should detect APIs with no references', () => {
|
|
11
13
|
const problems = Array.from(
|
|
12
14
|
searchProject({
|
|
@@ -163,3 +165,67 @@ describe('noReferenceApiRule', () => {
|
|
|
163
165
|
expect(problems).toEqual([])
|
|
164
166
|
})
|
|
165
167
|
})
|
|
168
|
+
|
|
169
|
+
describe('fix noReferenceApiRule', () => {
|
|
170
|
+
test('should remove unused APIs', () => {
|
|
171
|
+
const project: ProjectFiles = {
|
|
172
|
+
formulas: {},
|
|
173
|
+
components: {
|
|
174
|
+
apiComponent: {
|
|
175
|
+
name: 'test',
|
|
176
|
+
nodes: {},
|
|
177
|
+
formulas: {},
|
|
178
|
+
apis: {
|
|
179
|
+
'my-legacy-api': {
|
|
180
|
+
name: 'my-legacy-api',
|
|
181
|
+
type: 'REST',
|
|
182
|
+
autoFetch: valueFormula(true),
|
|
183
|
+
onCompleted: null,
|
|
184
|
+
onFailed: null,
|
|
185
|
+
},
|
|
186
|
+
'my-api': {
|
|
187
|
+
name: 'my-api',
|
|
188
|
+
type: 'http',
|
|
189
|
+
version: 2,
|
|
190
|
+
autoFetch: valueFormula(true),
|
|
191
|
+
inputs: {},
|
|
192
|
+
'@nordcraft/metadata': {
|
|
193
|
+
comments: null,
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
'used-api': {
|
|
197
|
+
name: 'used-api',
|
|
198
|
+
type: 'http',
|
|
199
|
+
version: 2,
|
|
200
|
+
autoFetch: valueFormula(true),
|
|
201
|
+
inputs: {},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
onLoad: {
|
|
205
|
+
trigger: 'onLoad',
|
|
206
|
+
actions: [
|
|
207
|
+
{
|
|
208
|
+
type: 'Fetch',
|
|
209
|
+
api: 'used-api',
|
|
210
|
+
inputs: {},
|
|
211
|
+
onSuccess: { actions: [] },
|
|
212
|
+
onError: { actions: [] },
|
|
213
|
+
},
|
|
214
|
+
],
|
|
215
|
+
},
|
|
216
|
+
attributes: {},
|
|
217
|
+
variables: {},
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
}
|
|
221
|
+
const fixedProject = fixProject({
|
|
222
|
+
files: project,
|
|
223
|
+
rule: noReferenceApiRule,
|
|
224
|
+
fixType: 'delete-api',
|
|
225
|
+
})
|
|
226
|
+
// 2/3 APIs should be removed
|
|
227
|
+
expect(Object.keys(fixedProject.components['apiComponent']!.apis)).toEqual([
|
|
228
|
+
'used-api',
|
|
229
|
+
])
|
|
230
|
+
})
|
|
231
|
+
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Rule } from '../../types'
|
|
2
|
+
import { removeFromPathFix } from '../../util/removeUnused.fix'
|
|
2
3
|
|
|
3
4
|
export const noReferenceApiRule: Rule<void> = {
|
|
4
5
|
code: 'no-reference api',
|
|
@@ -8,7 +9,8 @@ export const noReferenceApiRule: Rule<void> = {
|
|
|
8
9
|
if (args.nodeType !== 'component-api') {
|
|
9
10
|
return
|
|
10
11
|
}
|
|
11
|
-
const {
|
|
12
|
+
const { value, memo, component } = args
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
12
14
|
if (!component) {
|
|
13
15
|
return
|
|
14
16
|
}
|
|
@@ -37,6 +39,11 @@ export const noReferenceApiRule: Rule<void> = {
|
|
|
37
39
|
if (componentApiReferences.has(value.name)) {
|
|
38
40
|
return
|
|
39
41
|
}
|
|
40
|
-
report(path)
|
|
42
|
+
report(args.path, undefined, ['delete-api'])
|
|
43
|
+
},
|
|
44
|
+
fixes: {
|
|
45
|
+
'delete-api': removeFromPathFix,
|
|
41
46
|
},
|
|
42
47
|
}
|
|
48
|
+
|
|
49
|
+
export type NoReferenceApiRuleFix = 'delete-api'
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import type { ProjectFiles } from '@nordcraft/ssr/dist/ssr.types'
|
|
1
2
|
import { describe, expect, test } from 'bun:test'
|
|
3
|
+
import { fixProject } from '../../fixProject'
|
|
2
4
|
import { searchProject } from '../../searchProject'
|
|
3
5
|
import { noReferenceAttributeRule } from './noReferenceAttributeRule'
|
|
4
6
|
|
|
5
|
-
describe('noReferenceAttributeRule', () => {
|
|
7
|
+
describe('find noReferenceAttributeRule', () => {
|
|
6
8
|
test('should detect attributes with no references', () => {
|
|
7
9
|
const problems = Array.from(
|
|
8
10
|
searchProject({
|
|
@@ -137,3 +139,35 @@ describe('noReferenceAttributeRule', () => {
|
|
|
137
139
|
expect(problems).toEqual([])
|
|
138
140
|
})
|
|
139
141
|
})
|
|
142
|
+
|
|
143
|
+
describe('fix noReferenceAttributeRule', () => {
|
|
144
|
+
test('should remove attributes with no references', () => {
|
|
145
|
+
const files: ProjectFiles = {
|
|
146
|
+
formulas: {},
|
|
147
|
+
components: {
|
|
148
|
+
test: {
|
|
149
|
+
name: 'test',
|
|
150
|
+
nodes: {},
|
|
151
|
+
formulas: {},
|
|
152
|
+
apis: {},
|
|
153
|
+
attributes: {
|
|
154
|
+
'my-attribute': {
|
|
155
|
+
name: 'my-attribute-name',
|
|
156
|
+
testValue: { type: 'value', value: null },
|
|
157
|
+
'@nordcraft/metadata': {
|
|
158
|
+
comments: null,
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
variables: {},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
}
|
|
166
|
+
const fixedFiles = fixProject({
|
|
167
|
+
files,
|
|
168
|
+
rule: noReferenceAttributeRule,
|
|
169
|
+
fixType: 'delete-attribute',
|
|
170
|
+
})
|
|
171
|
+
expect(fixedFiles.components['test']?.attributes).toEqual({})
|
|
172
|
+
})
|
|
173
|
+
})
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Rule } from '../../types'
|
|
2
|
+
import { removeFromPathFix } from '../../util/removeUnused.fix'
|
|
2
3
|
|
|
3
4
|
export const noReferenceAttributeRule: Rule<void> = {
|
|
4
5
|
code: 'no-reference attribute',
|
|
@@ -26,7 +27,11 @@ export const noReferenceAttributeRule: Rule<void> = {
|
|
|
26
27
|
if (attrs.has(attributeKey)) {
|
|
27
28
|
return
|
|
28
29
|
}
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
report(args.path, undefined, ['delete-attribute'])
|
|
31
|
+
},
|
|
32
|
+
fixes: {
|
|
33
|
+
'delete-attribute': removeFromPathFix,
|
|
31
34
|
},
|
|
32
35
|
}
|
|
36
|
+
|
|
37
|
+
export type NoReferenceAttributeRuleFix = 'delete-attribute'
|
|
@@ -1,53 +1,42 @@
|
|
|
1
1
|
import type { Component } from '@nordcraft/core/dist/component/component.types'
|
|
2
|
-
import { omit } from '@nordcraft/core/dist/utils/collections'
|
|
3
2
|
import { isDefined } from '@nordcraft/core/dist/utils/util'
|
|
4
|
-
import type {
|
|
3
|
+
import type { Rule } from '../../types'
|
|
4
|
+
import { removeFromPathFix } from '../../util/removeUnused.fix'
|
|
5
5
|
|
|
6
6
|
export const noReferenceComponentRule: Rule<void> = {
|
|
7
7
|
code: 'no-reference component',
|
|
8
8
|
level: 'warning',
|
|
9
9
|
category: 'No References',
|
|
10
10
|
visit: (report, data, state) => {
|
|
11
|
-
if (
|
|
11
|
+
if (
|
|
12
|
+
data.nodeType !== 'component' ||
|
|
13
|
+
isPage(data.value) ||
|
|
14
|
+
(state?.projectDetails?.type === 'package' &&
|
|
15
|
+
data.value.exported === true)
|
|
16
|
+
) {
|
|
12
17
|
return
|
|
13
18
|
}
|
|
19
|
+
for (const component of Object.values(data.files.components)) {
|
|
20
|
+
// Enforce that the component is not undefined since we're iterating
|
|
21
|
+
for (const node of Object.values(component!.nodes ?? {})) {
|
|
22
|
+
if (
|
|
23
|
+
node.type === 'component' &&
|
|
24
|
+
node.name === data.value.name &&
|
|
25
|
+
// Circular references from a component to itself should
|
|
26
|
+
// not count as a reference
|
|
27
|
+
node.name !== component!.name
|
|
28
|
+
) {
|
|
29
|
+
return
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
14
33
|
report(data.path, undefined, ['delete-component'])
|
|
15
34
|
},
|
|
16
35
|
fixes: {
|
|
17
|
-
'delete-component':
|
|
18
|
-
if (hasReferences(data, state)) {
|
|
19
|
-
return
|
|
20
|
-
}
|
|
21
|
-
return omit(data.files, data.path)
|
|
22
|
-
},
|
|
36
|
+
'delete-component': removeFromPathFix,
|
|
23
37
|
},
|
|
24
38
|
}
|
|
25
39
|
|
|
26
|
-
const hasReferences = (data: NodeType, state?: ApplicationState) => {
|
|
27
|
-
if (
|
|
28
|
-
data.nodeType !== 'component' ||
|
|
29
|
-
isPage(data.value) ||
|
|
30
|
-
(state?.projectDetails?.type === 'package' && data.value.exported === true)
|
|
31
|
-
) {
|
|
32
|
-
return true
|
|
33
|
-
}
|
|
34
|
-
for (const component of Object.values(data.files.components)) {
|
|
35
|
-
// Enforce that the component is not undefined since we're iterating
|
|
36
|
-
for (const node of Object.values(component!.nodes ?? {})) {
|
|
37
|
-
if (
|
|
38
|
-
node.type === 'component' &&
|
|
39
|
-
node.name === data.value.name &&
|
|
40
|
-
// Circular references from a component to itself should
|
|
41
|
-
// not count as a reference
|
|
42
|
-
node.name !== component!.name
|
|
43
|
-
) {
|
|
44
|
-
return true
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return false
|
|
49
|
-
}
|
|
50
|
-
|
|
51
40
|
export type NoReferenceComponentRuleFix = 'delete-component'
|
|
52
41
|
|
|
53
42
|
const isPage = (
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { valueFormula } from '@nordcraft/core/dist/formula/formulaUtils'
|
|
2
|
+
import type { ProjectFiles } from '@nordcraft/ssr/dist/ssr.types'
|
|
2
3
|
import { describe, expect, test } from 'bun:test'
|
|
4
|
+
import { fixProject } from '../../fixProject'
|
|
3
5
|
import { searchProject } from '../../searchProject'
|
|
4
6
|
import { noReferenceEventRule } from './noReferenceEventRule'
|
|
5
7
|
|
|
6
|
-
describe('noReferenceEventRule', () => {
|
|
8
|
+
describe('find noReferenceEventRule', () => {
|
|
7
9
|
test('should detect events with no references', () => {
|
|
8
10
|
const problems = Array.from(
|
|
9
11
|
searchProject({
|
|
@@ -146,3 +148,59 @@ describe('noReferenceEventRule', () => {
|
|
|
146
148
|
expect(problems).toEqual([])
|
|
147
149
|
})
|
|
148
150
|
})
|
|
151
|
+
|
|
152
|
+
describe('fix noReferenceEventRule', () => {
|
|
153
|
+
test('should remove events with no references', () => {
|
|
154
|
+
const files: ProjectFiles = {
|
|
155
|
+
components: {
|
|
156
|
+
test: {
|
|
157
|
+
name: 'test',
|
|
158
|
+
nodes: {
|
|
159
|
+
root: {
|
|
160
|
+
type: 'element',
|
|
161
|
+
attrs: {},
|
|
162
|
+
classes: {},
|
|
163
|
+
events: {
|
|
164
|
+
click: {
|
|
165
|
+
trigger: 'click',
|
|
166
|
+
actions: [
|
|
167
|
+
{
|
|
168
|
+
type: 'TriggerEvent',
|
|
169
|
+
event: 'unknown-event',
|
|
170
|
+
data: valueFormula(null),
|
|
171
|
+
},
|
|
172
|
+
],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
tag: 'div',
|
|
176
|
+
children: [],
|
|
177
|
+
style: {},
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
formulas: {},
|
|
181
|
+
apis: {},
|
|
182
|
+
attributes: {},
|
|
183
|
+
variables: {},
|
|
184
|
+
events: [
|
|
185
|
+
{
|
|
186
|
+
name: 'unused-event',
|
|
187
|
+
// eslint-disable-next-line inclusive-language/use-inclusive-words
|
|
188
|
+
dummyEvent: {
|
|
189
|
+
name: 'Name',
|
|
190
|
+
},
|
|
191
|
+
'@nordcraft/metadata': {
|
|
192
|
+
comments: null,
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
}
|
|
199
|
+
const fixedFiles = fixProject({
|
|
200
|
+
files,
|
|
201
|
+
rule: noReferenceEventRule,
|
|
202
|
+
fixType: 'delete-event',
|
|
203
|
+
})
|
|
204
|
+
expect(fixedFiles.components['test']?.events).toEqual([])
|
|
205
|
+
})
|
|
206
|
+
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Rule } from '../../types'
|
|
2
2
|
import { isLegacyAction } from '../../util/helpers'
|
|
3
|
+
import { removeFromPathFix } from '../../util/removeUnused.fix'
|
|
3
4
|
|
|
4
5
|
export const noReferenceEventRule: Rule<{ name: string }> = {
|
|
5
6
|
code: 'no-reference event',
|
|
@@ -9,7 +10,7 @@ export const noReferenceEventRule: Rule<{ name: string }> = {
|
|
|
9
10
|
if (args.nodeType !== 'component-event') {
|
|
10
11
|
return
|
|
11
12
|
}
|
|
12
|
-
const {
|
|
13
|
+
const { memo, value } = args
|
|
13
14
|
const { component, event } = value
|
|
14
15
|
const events = memo(`${component.name}-events`, () => {
|
|
15
16
|
const events = new Set<string>()
|
|
@@ -40,7 +41,11 @@ export const noReferenceEventRule: Rule<{ name: string }> = {
|
|
|
40
41
|
if (events.has(event.name)) {
|
|
41
42
|
return
|
|
42
43
|
}
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
report(args.path, { name: args.value.event.name }, ['delete-event'])
|
|
45
|
+
},
|
|
46
|
+
fixes: {
|
|
47
|
+
'delete-event': removeFromPathFix,
|
|
45
48
|
},
|
|
46
49
|
}
|
|
50
|
+
|
|
51
|
+
export type NoReferenceEventRuleFix = 'delete-event'
|