@atlaskit/eslint-plugin-platform 0.6.1 → 0.7.0
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/CHANGELOG.md +103 -28
- package/afm-jira/tsconfig.json +20 -0
- package/dist/cjs/index.js +48 -2
- package/dist/cjs/rules/constants.js +11 -0
- package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +54 -6
- package/dist/cjs/rules/ensure-native-and-af-exports-synced/index.js +16 -7
- package/dist/cjs/rules/ensure-valid-emotion-css-prop/index.js +91 -0
- package/dist/cjs/rules/inline-usage/index.js +94 -0
- package/dist/cjs/rules/no-alias/index.js +64 -0
- package/dist/cjs/rules/no-module-level-eval/index.js +45 -0
- package/dist/cjs/rules/no-preconditioning/index.js +108 -0
- package/dist/cjs/rules/prefer-fg/index.js +106 -0
- package/dist/cjs/rules/static-feature-flags/index.js +63 -0
- package/dist/cjs/rules/use-recommended-utils/index.js +47 -0
- package/dist/cjs/rules/util/registration-utils.js +2 -1
- package/dist/cjs/rules/utils.js +53 -0
- package/dist/es2019/index.js +52 -2
- package/dist/es2019/rules/constants.js +5 -0
- package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +52 -6
- package/dist/es2019/rules/ensure-native-and-af-exports-synced/index.js +15 -7
- package/dist/es2019/rules/ensure-valid-emotion-css-prop/index.js +87 -0
- package/dist/es2019/rules/inline-usage/index.js +90 -0
- package/dist/es2019/rules/no-alias/index.js +58 -0
- package/dist/es2019/rules/no-module-level-eval/index.js +39 -0
- package/dist/es2019/rules/no-preconditioning/index.js +105 -0
- package/dist/es2019/rules/prefer-fg/index.js +81 -0
- package/dist/es2019/rules/static-feature-flags/index.js +54 -0
- package/dist/es2019/rules/use-recommended-utils/index.js +41 -0
- package/dist/es2019/rules/util/registration-utils.js +2 -1
- package/dist/es2019/rules/utils.js +29 -0
- package/dist/esm/index.js +48 -2
- package/dist/esm/rules/constants.js +5 -0
- package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +54 -6
- package/dist/esm/rules/ensure-native-and-af-exports-synced/index.js +16 -7
- package/dist/esm/rules/ensure-valid-emotion-css-prop/index.js +85 -0
- package/dist/esm/rules/inline-usage/index.js +87 -0
- package/dist/esm/rules/no-alias/index.js +57 -0
- package/dist/esm/rules/no-module-level-eval/index.js +39 -0
- package/dist/esm/rules/no-preconditioning/index.js +102 -0
- package/dist/esm/rules/prefer-fg/index.js +99 -0
- package/dist/esm/rules/static-feature-flags/index.js +56 -0
- package/dist/esm/rules/use-recommended-utils/index.js +41 -0
- package/dist/esm/rules/util/registration-utils.js +2 -1
- package/dist/esm/rules/utils.js +45 -0
- package/dist/types/index.d.ts +15 -0
- package/dist/types/rules/constants.d.ts +3 -0
- package/dist/types/rules/ensure-valid-emotion-css-prop/index.d.ts +3 -0
- package/dist/types/rules/inline-usage/index.d.ts +3 -0
- package/dist/types/rules/no-alias/index.d.ts +3 -0
- package/dist/types/rules/no-module-level-eval/index.d.ts +3 -0
- package/dist/types/rules/no-preconditioning/index.d.ts +3 -0
- package/dist/types/rules/prefer-fg/index.d.ts +3 -0
- package/dist/types/rules/static-feature-flags/index.d.ts +3 -0
- package/dist/types/rules/use-recommended-utils/index.d.ts +3 -0
- package/dist/types/rules/util/registration-utils.d.ts +1 -0
- package/dist/types/rules/utils.d.ts +7 -0
- package/dist/types-ts4.5/index.d.ts +15 -0
- package/dist/types-ts4.5/rules/constants.d.ts +3 -0
- package/dist/types-ts4.5/rules/ensure-valid-emotion-css-prop/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/inline-usage/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-alias/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-module-level-eval/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/no-preconditioning/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/prefer-fg/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/static-feature-flags/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/use-recommended-utils/index.d.ts +3 -0
- package/dist/types-ts4.5/rules/util/registration-utils.d.ts +1 -0
- package/dist/types-ts4.5/rules/utils.d.ts +7 -0
- package/index.js +9 -9
- package/package.json +43 -44
- package/report.api.md +31 -30
- package/src/__tests__/utils/_tester.tsx +16 -16
- package/src/index.tsx +102 -51
- package/src/rules/constants.tsx +20 -0
- package/src/rules/ensure-atlassian-team/__tests__/unit/rule.test.ts +19 -19
- package/src/rules/ensure-atlassian-team/index.ts +39 -52
- package/src/rules/ensure-critical-dependency-resolutions/__test__/unit/rule.test.tsx +146 -81
- package/src/rules/ensure-critical-dependency-resolutions/index.tsx +152 -97
- package/src/rules/ensure-feature-flag-prefix/__tests__/unit/rule.test.tsx +51 -51
- package/src/rules/ensure-feature-flag-prefix/index.tsx +65 -80
- package/src/rules/ensure-feature-flag-registration/__tests__/unit/rule.test.tsx +97 -97
- package/src/rules/ensure-feature-flag-registration/index.tsx +88 -105
- package/src/rules/ensure-native-and-af-exports-synced/__tests__/unit/rule.test.tsx +180 -180
- package/src/rules/ensure-native-and-af-exports-synced/index.tsx +162 -168
- package/src/rules/ensure-publish-valid/__tests__/unit/rule.test.ts +34 -36
- package/src/rules/ensure-publish-valid/index.ts +66 -81
- package/src/rules/ensure-test-runner-arguments/__tests__/unit/rule.test.tsx +93 -93
- package/src/rules/ensure-test-runner-arguments/index.tsx +107 -121
- package/src/rules/ensure-test-runner-nested-count/__tests__/unit/rule.test.tsx +43 -43
- package/src/rules/ensure-test-runner-nested-count/index.tsx +68 -70
- package/src/rules/ensure-valid-emotion-css-prop/__tests__/unit/rule.test.ts +142 -0
- package/src/rules/ensure-valid-emotion-css-prop/index.ts +96 -0
- package/src/rules/inline-usage/README.md +53 -0
- package/src/rules/inline-usage/__tests__/rule.test.tsx +106 -0
- package/src/rules/inline-usage/index.tsx +130 -0
- package/src/rules/no-alias/README.md +29 -0
- package/src/rules/no-alias/__tests__/rule.test.tsx +76 -0
- package/src/rules/no-alias/index.tsx +75 -0
- package/src/rules/no-duplicate-dependencies/__tests__/unit/rule.test.ts +44 -44
- package/src/rules/no-duplicate-dependencies/index.ts +68 -73
- package/src/rules/no-invalid-feature-flag-usage/__tests__/unit/rule.test.tsx +64 -64
- package/src/rules/no-invalid-feature-flag-usage/index.tsx +105 -112
- package/src/rules/no-invalid-storybook-decorator-usage/__tests__/unit/rule.test.tsx +13 -13
- package/src/rules/no-invalid-storybook-decorator-usage/index.tsx +28 -30
- package/src/rules/no-module-level-eval/README.md +53 -0
- package/src/rules/no-module-level-eval/__tests__/test.tsx +133 -0
- package/src/rules/no-module-level-eval/index.tsx +52 -0
- package/src/rules/no-pre-post-installs/__tests__/unit/rule.test.ts +36 -36
- package/src/rules/no-pre-post-installs/index.ts +27 -27
- package/src/rules/no-preconditioning/README.md +69 -0
- package/src/rules/no-preconditioning/__tests__/rule.test.tsx +164 -0
- package/src/rules/no-preconditioning/index.tsx +138 -0
- package/src/rules/prefer-fg/README.md +3 -0
- package/src/rules/prefer-fg/__tests__/rule.test.tsx +83 -0
- package/src/rules/prefer-fg/index.tsx +108 -0
- package/src/rules/static-feature-flags/README.md +3 -0
- package/src/rules/static-feature-flags/__tests__/test.tsx +135 -0
- package/src/rules/static-feature-flags/index.tsx +103 -0
- package/src/rules/use-recommended-utils/README.md +67 -0
- package/src/rules/use-recommended-utils/__tests__/rule.test.tsx +78 -0
- package/src/rules/use-recommended-utils/index.tsx +57 -0
- package/src/rules/util/handle-ast-object.ts +21 -32
- package/src/rules/util/registration-utils.ts +31 -30
- package/src/rules/utils.tsx +46 -0
- package/tsconfig.app.json +35 -35
- package/tsconfig.dev.json +39 -39
|
@@ -4,132 +4,197 @@ import rule from '../../index';
|
|
|
4
4
|
const cwd = process.cwd();
|
|
5
5
|
|
|
6
6
|
describe('test ensure-critical-dependency-resolutions rule', () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
tester.run('ensure-critical-dependency-resolutions', rule, {
|
|
8
|
+
valid: [
|
|
9
|
+
// Root package.json, have all of the correct resolutions
|
|
10
|
+
{
|
|
11
|
+
code: `const foo = {
|
|
12
12
|
"resolutions": {
|
|
13
13
|
"@types/react": "16.14.15",
|
|
14
14
|
"typescript": "5.4.2",
|
|
15
|
+
"tslib": "2.6.3",
|
|
16
|
+
"react-relay": "npm:atl-react-relay@0.0.0-main-2ccd6998",
|
|
17
|
+
"relay-compiler": "npm:atl-relay-compiler@0.0.0-main-2ccd6998",
|
|
18
|
+
"relay-runtime": "npm:atl-relay-runtime@0.0.0-main-2ccd6998",
|
|
19
|
+
"relay-test-utils": "npm:atl-relay-test-utils@0.0.0-main-2ccd6998",
|
|
15
20
|
}
|
|
16
21
|
}`,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
filename: `${cwd}/package.json`,
|
|
23
|
+
},
|
|
24
|
+
// Root package.json, have all of the correct resolutions
|
|
25
|
+
{
|
|
26
|
+
code: `const foo = {
|
|
22
27
|
"resolutions": {
|
|
23
28
|
"@types/react": "18.2.28",
|
|
24
29
|
"typescript": "5.4.2",
|
|
30
|
+
"tslib": "2.6.3",
|
|
31
|
+
"react-relay": "npm:atl-react-relay@0.0.0-main-2ccd6998",
|
|
32
|
+
"relay-compiler": "npm:atl-relay-compiler@0.0.0-main-2ccd6998",
|
|
33
|
+
"relay-runtime": "npm:atl-relay-runtime@0.0.0-main-2ccd6998",
|
|
34
|
+
"relay-test-utils": "npm:atl-relay-test-utils@0.0.0-main-2ccd6998",
|
|
25
35
|
}
|
|
26
36
|
}`,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
filename: `${cwd}/package.json`,
|
|
38
|
+
},
|
|
39
|
+
// Root package.json, have all of the correct resolutions with ~
|
|
40
|
+
{
|
|
41
|
+
code: `const foo = {
|
|
32
42
|
"resolutions": {
|
|
33
43
|
"@types/react": "~16.14.25",
|
|
34
44
|
"typescript": "~5.4.2",
|
|
45
|
+
"tslib": "~2.6.3",
|
|
46
|
+
"react-relay": "npm:atl-react-relay@0.0.0-main-2ccd6998",
|
|
47
|
+
"relay-compiler": "npm:atl-relay-compiler@0.0.0-main-2ccd6998",
|
|
48
|
+
"relay-runtime": "npm:atl-relay-runtime@0.0.0-main-2ccd6998",
|
|
49
|
+
"relay-test-utils": "npm:atl-relay-test-utils@0.0.0-main-2ccd6998",
|
|
35
50
|
}
|
|
36
51
|
}`,
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
52
|
+
filename: `${cwd}/package.json`,
|
|
53
|
+
},
|
|
54
|
+
// Root package.json, have some of the correct resolutions
|
|
55
|
+
{
|
|
56
|
+
code: `const foo = {
|
|
57
|
+
"resolutions": {
|
|
58
|
+
"@types/react": "~16.14.25",
|
|
59
|
+
"typescript": "~5.4.2",
|
|
60
|
+
"tslib": "~2.6.3",
|
|
61
|
+
}
|
|
62
|
+
}`,
|
|
63
|
+
filename: `${cwd}/package.json`,
|
|
64
|
+
},
|
|
65
|
+
// Root package.json, have some of the correct resolutions
|
|
66
|
+
{
|
|
67
|
+
code: `const foo = {
|
|
68
|
+
"resolutions": {
|
|
69
|
+
"@types/react": "~16.14.25",
|
|
70
|
+
"typescript": "~5.4.2",
|
|
71
|
+
"react-relay": "npm:atl-react-relay@0.0.0-main-2ccd6998",
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"@types/react": "~16.14.25",
|
|
75
|
+
"typescript": "~5.4.2",
|
|
76
|
+
"react-relay": "npm:atl-react-relay@0.0.0-main-2ccd6998",
|
|
77
|
+
}
|
|
78
|
+
}`,
|
|
79
|
+
filename: `${cwd}/package.json`,
|
|
80
|
+
},
|
|
81
|
+
// Individual package's package.json. Have part of correct resolutions
|
|
82
|
+
{
|
|
83
|
+
code: `const foo = {
|
|
42
84
|
"resolutions": {
|
|
43
85
|
"@types/react": "16.14.15",
|
|
44
86
|
}
|
|
45
87
|
}`,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
88
|
+
filename: `${cwd}/package/name/package.json`,
|
|
89
|
+
},
|
|
90
|
+
// Individual package's package.json. Not have relevant package resolutions
|
|
91
|
+
{
|
|
92
|
+
code: `const foo = {
|
|
51
93
|
"resolutions": {
|
|
52
94
|
"@types/abcd": "1.2.3",
|
|
53
95
|
}
|
|
54
96
|
}`,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
97
|
+
filename: `${cwd}/package/name/package.json`,
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
invalid: [
|
|
101
|
+
// Root package.json. One package is correct, the other is missing
|
|
102
|
+
{
|
|
103
|
+
code: `const foo = {
|
|
62
104
|
"resolutions": {
|
|
63
105
|
"typescript": "~5.4.2",
|
|
106
|
+
},
|
|
107
|
+
|
|
108
|
+
"dependencies": {
|
|
109
|
+
"@types/react": "~16.14.25",
|
|
110
|
+
"typescript": "~5.4.2",
|
|
111
|
+
}
|
|
112
|
+
}`,
|
|
113
|
+
filename: `${cwd}/package.json`,
|
|
114
|
+
errors: [
|
|
115
|
+
{
|
|
116
|
+
messageId: 'invalidPackageResolution',
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
},
|
|
120
|
+
// Root package.json. Resolutions are missing but package is present in dependencies
|
|
121
|
+
{
|
|
122
|
+
code: `const foo = {
|
|
123
|
+
"resolutions": {
|
|
124
|
+
},
|
|
125
|
+
|
|
126
|
+
"dependencies": {
|
|
127
|
+
"@types/react": "~16.14.25",
|
|
128
|
+
"typescript": "~5.4.2",
|
|
64
129
|
}
|
|
65
130
|
}`,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
131
|
+
filename: `${cwd}/package.json`,
|
|
132
|
+
errors: [
|
|
133
|
+
{
|
|
134
|
+
messageId: 'invalidPackageResolution',
|
|
135
|
+
},
|
|
136
|
+
],
|
|
137
|
+
},
|
|
138
|
+
// Root package.json. Both packages have the wrong version ranges
|
|
139
|
+
{
|
|
140
|
+
code: `const foo = {
|
|
76
141
|
"resolutions": {
|
|
77
142
|
"@types/react": "16.8.25",
|
|
78
143
|
"typescript": "5.1.1",
|
|
79
144
|
}
|
|
80
145
|
}`,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
146
|
+
filename: `${cwd}/package.json`,
|
|
147
|
+
errors: [
|
|
148
|
+
{
|
|
149
|
+
messageId: 'invalidPackageResolution',
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
// Root package.json. One package is correct, the other has wrong version range
|
|
154
|
+
{
|
|
155
|
+
code: `const foo = {
|
|
91
156
|
"resolutions": {
|
|
92
157
|
"@types/react": "~16.14.25",
|
|
93
158
|
"typescript": "~5.1.1",
|
|
94
159
|
}
|
|
95
160
|
}`,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
161
|
+
filename: `${cwd}/package.json`,
|
|
162
|
+
errors: [
|
|
163
|
+
{
|
|
164
|
+
messageId: 'invalidPackageResolution',
|
|
165
|
+
},
|
|
166
|
+
],
|
|
167
|
+
},
|
|
168
|
+
// Root package.json. One package is correct, the other has ^ in its version
|
|
169
|
+
{
|
|
170
|
+
code: `const foo = {
|
|
106
171
|
"resolutions": {
|
|
107
172
|
"@types/react": "~16.14.25",
|
|
108
173
|
"typescript": "^5.4.2",
|
|
109
174
|
}
|
|
110
175
|
}`,
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
176
|
+
filename: `${cwd}/package.json`,
|
|
177
|
+
errors: [
|
|
178
|
+
{
|
|
179
|
+
messageId: 'invalidPackageResolution',
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
},
|
|
183
|
+
// Individual package's package.json. One package is correct, the other is wrong
|
|
184
|
+
{
|
|
185
|
+
code: `const foo = {
|
|
121
186
|
"resolutions": {
|
|
122
187
|
"@types/react": "16.14.15",
|
|
123
188
|
"typescript": "5.1.1",
|
|
124
189
|
}
|
|
125
190
|
}`,
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
191
|
+
filename: `${cwd}/packages/packge/directory/package.json`,
|
|
192
|
+
errors: [
|
|
193
|
+
{
|
|
194
|
+
messageId: 'invalidPackageResolution',
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
});
|
|
135
200
|
});
|
|
@@ -8,110 +8,165 @@ import { getObjectPropertyAsObject } from '../util/handle-ast-object';
|
|
|
8
8
|
// In matchMinorVersion, we will check if the versions in resolutions fall in the right ranges.
|
|
9
9
|
//
|
|
10
10
|
const DESIRED_PKG_VERSIONS: Record<string, string[]> = {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
typescript: ['5.4'],
|
|
12
|
+
tslib: ['2.6'],
|
|
13
|
+
'@types/react': ['16.14', '18.2'],
|
|
14
|
+
'react-relay': ['npm:atl-react-relay@0.0.0-main-2ccd6998'],
|
|
15
|
+
'relay-compiler': ['npm:atl-relay-compiler@0.0.0-main-2ccd6998'],
|
|
16
|
+
'relay-runtime': ['npm:atl-relay-runtime@0.0.0-main-2ccd6998'],
|
|
17
|
+
'relay-test-utils': ['npm:atl-relay-test-utils@0.0.0-main-2ccd6998'],
|
|
13
18
|
};
|
|
14
19
|
|
|
15
|
-
const matchMinorVersion = (
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
versionInResolutions.startsWith(desiredVersion) ||
|
|
27
|
-
versionInResolutions.startsWith('~' + desiredVersion)
|
|
28
|
-
);
|
|
20
|
+
const matchMinorVersion = (desiredVersion: string, versionInResolutions: string): boolean => {
|
|
21
|
+
const firstChar = versionInResolutions[0];
|
|
22
|
+
// The version is invalid if it doesn't start with a number or ~
|
|
23
|
+
if (!/^\d$/.test(firstChar) && firstChar !== '~' && !versionInResolutions.startsWith('npm:')) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
versionInResolutions.startsWith(desiredVersion) ||
|
|
29
|
+
versionInResolutions.startsWith('~' + desiredVersion)
|
|
30
|
+
);
|
|
29
31
|
};
|
|
30
32
|
|
|
31
|
-
const verifyResolutionFromObject = (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
33
|
+
const verifyResolutionFromObject = ({
|
|
34
|
+
resolutions,
|
|
35
|
+
dependencies,
|
|
36
|
+
devDependencies,
|
|
37
|
+
pkg,
|
|
38
|
+
version,
|
|
39
|
+
optional,
|
|
40
|
+
}: {
|
|
41
|
+
resolutions: ObjectExpression;
|
|
42
|
+
dependencies: ObjectExpression | null;
|
|
43
|
+
devDependencies: ObjectExpression | null;
|
|
44
|
+
pkg: string;
|
|
45
|
+
version: string;
|
|
46
|
+
optional: boolean;
|
|
47
|
+
}): boolean => {
|
|
48
|
+
// For root package.json, we require the critical packages' resolutions exist and with matching version
|
|
49
|
+
// For individual package's package.json, it's ok if resolutions don't exist. But if they do, the version should match
|
|
50
|
+
const resolutionExist = resolutions.properties.some(
|
|
51
|
+
(p) => p.type === 'Property' && p.key.type === 'Literal' && p.key.value === pkg,
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
isDependencyPresent({
|
|
55
|
+
resolutions,
|
|
56
|
+
dependencies,
|
|
57
|
+
devDependencies,
|
|
58
|
+
pkg,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
if (!resolutionExist) {
|
|
62
|
+
// when package is not a part of dependencies/devDependencies
|
|
63
|
+
if (
|
|
64
|
+
optional === false &&
|
|
65
|
+
!isDependencyPresent({
|
|
66
|
+
resolutions,
|
|
67
|
+
dependencies,
|
|
68
|
+
devDependencies,
|
|
69
|
+
pkg,
|
|
70
|
+
})
|
|
71
|
+
) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return optional;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const resolutionExistAndMatch = resolutions.properties.some(
|
|
79
|
+
(p) =>
|
|
80
|
+
p.type === 'Property' &&
|
|
81
|
+
p.key.type === 'Literal' &&
|
|
82
|
+
p.key.value === pkg &&
|
|
83
|
+
p.value.type === 'Literal' &&
|
|
84
|
+
matchMinorVersion(version, p.value.value as string),
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
return resolutionExistAndMatch;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
type IsDependencyPresentProps = {
|
|
91
|
+
resolutions: ObjectExpression | null;
|
|
92
|
+
dependencies: ObjectExpression | null;
|
|
93
|
+
devDependencies: ObjectExpression | null;
|
|
94
|
+
pkg: string;
|
|
95
|
+
};
|
|
96
|
+
const isDependencyPresent = ({
|
|
97
|
+
resolutions,
|
|
98
|
+
dependencies,
|
|
99
|
+
devDependencies,
|
|
100
|
+
pkg,
|
|
101
|
+
}: IsDependencyPresentProps) => {
|
|
102
|
+
const dependencyExist =
|
|
103
|
+
dependencies !== null &&
|
|
104
|
+
dependencies.properties.some(
|
|
105
|
+
(p) => p.type === 'Property' && p.key.type === 'Literal' && p.key.value === pkg,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
const devDependencyExist =
|
|
109
|
+
devDependencies !== null &&
|
|
110
|
+
devDependencies.properties.some(
|
|
111
|
+
(p) => p.type === 'Property' && p.key.type === 'Literal' && p.key.value === pkg,
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
return dependencyExist || devDependencyExist;
|
|
58
115
|
};
|
|
59
116
|
|
|
60
117
|
const rule: Rule.RuleModule = {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
};
|
|
114
|
-
},
|
|
118
|
+
meta: {
|
|
119
|
+
type: 'problem',
|
|
120
|
+
docs: {
|
|
121
|
+
description:
|
|
122
|
+
'Enforce the versions of critical packages are within desired ranges by checking resolutions section in package.json',
|
|
123
|
+
recommended: true,
|
|
124
|
+
},
|
|
125
|
+
hasSuggestions: false,
|
|
126
|
+
messages: {
|
|
127
|
+
invalidPackageResolution: `Make sure the resolutions for the following packages match major and minor version ranges ${JSON.stringify(
|
|
128
|
+
DESIRED_PKG_VERSIONS,
|
|
129
|
+
)}`,
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
create(context) {
|
|
133
|
+
const fileName = context.getFilename();
|
|
134
|
+
return {
|
|
135
|
+
ObjectExpression: (node: Rule.Node) => {
|
|
136
|
+
if (!fileName.endsWith('package.json') || node.type !== 'ObjectExpression') {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const packageResolutions = getObjectPropertyAsObject(node, 'resolutions');
|
|
141
|
+
const packageDependencies = getObjectPropertyAsObject(node, 'dependencies');
|
|
142
|
+
const packageDevDependencies = getObjectPropertyAsObject(node, 'devDependencies');
|
|
143
|
+
const rootDir = findRootSync(process.cwd());
|
|
144
|
+
const isRootPackageJson = fileName.endsWith(`${rootDir}/package.json`);
|
|
145
|
+
|
|
146
|
+
if (packageResolutions !== null) {
|
|
147
|
+
for (const [key, values] of Object.entries(DESIRED_PKG_VERSIONS)) {
|
|
148
|
+
if (
|
|
149
|
+
!values.some((value) => {
|
|
150
|
+
return verifyResolutionFromObject({
|
|
151
|
+
resolutions: packageResolutions as ObjectExpression,
|
|
152
|
+
dependencies: packageDependencies,
|
|
153
|
+
devDependencies: packageDevDependencies,
|
|
154
|
+
pkg: key,
|
|
155
|
+
version: value,
|
|
156
|
+
optional: !isRootPackageJson,
|
|
157
|
+
});
|
|
158
|
+
})
|
|
159
|
+
) {
|
|
160
|
+
return context.report({
|
|
161
|
+
node,
|
|
162
|
+
messageId: 'invalidPackageResolution',
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
},
|
|
168
|
+
};
|
|
169
|
+
},
|
|
115
170
|
};
|
|
116
171
|
|
|
117
172
|
export default rule;
|
|
@@ -1,65 +1,65 @@
|
|
|
1
1
|
import { tester } from '../../../../__tests__/utils/_tester';
|
|
2
2
|
import rule from '../../index';
|
|
3
|
-
import { PackageJson } from 'read-pkg-up';
|
|
3
|
+
import { type PackageJson } from 'read-pkg-up';
|
|
4
4
|
|
|
5
5
|
let mockPath = 'test/package.json';
|
|
6
6
|
|
|
7
7
|
let mockPackageJson: PackageJson = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
'platform-feature-flags': {
|
|
9
|
+
'test-flag': {
|
|
10
|
+
type: 'boolean',
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
13
|
};
|
|
14
14
|
jest.mock('read-pkg-up', () => ({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
sync: () => ({
|
|
16
|
+
path: mockPath,
|
|
17
|
+
packageJson: mockPackageJson,
|
|
18
|
+
}),
|
|
19
19
|
}));
|
|
20
20
|
|
|
21
21
|
describe('test prefix rule', () => {
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
mockPath = 'test/package.json';
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
25
|
+
mockPackageJson = {
|
|
26
|
+
'platform-feature-flags': {
|
|
27
|
+
'prefix-flag': {
|
|
28
|
+
type: 'boolean',
|
|
29
|
+
},
|
|
30
|
+
'no-prefix-flag': {
|
|
31
|
+
type: 'boolean',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
};
|
|
35
|
+
});
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
37
|
+
// this isolates the invalid case so we can test the suggestion properly
|
|
38
|
+
tester.run('ensure-feature-flag-registration', rule, {
|
|
39
|
+
valid: [
|
|
40
|
+
{
|
|
41
|
+
options: [{ allowedPrefixes: ['prefix'] }],
|
|
42
|
+
code: `ffTest('prefix-flag')`,
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
options: [{ allowedPrefixes: ['prefix'] }],
|
|
46
|
+
code: `getBooleanFF('prefix-flag')`,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
invalid: [
|
|
50
|
+
{
|
|
51
|
+
options: [{ allowedPrefixes: ['prefix'] }],
|
|
52
|
+
code: `ffTest('no-prefix-flag')`,
|
|
53
|
+
errors: [
|
|
54
|
+
{
|
|
55
|
+
messageId: 'featureFlagIncorrectPrefix',
|
|
56
|
+
data: {
|
|
57
|
+
featureFlag: 'no-prefix-flag',
|
|
58
|
+
allowedPrefixes: 'prefix',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
});
|
|
65
65
|
});
|