@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.
Files changed (126) hide show
  1. package/CHANGELOG.md +103 -28
  2. package/afm-jira/tsconfig.json +20 -0
  3. package/dist/cjs/index.js +48 -2
  4. package/dist/cjs/rules/constants.js +11 -0
  5. package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +54 -6
  6. package/dist/cjs/rules/ensure-native-and-af-exports-synced/index.js +16 -7
  7. package/dist/cjs/rules/ensure-valid-emotion-css-prop/index.js +91 -0
  8. package/dist/cjs/rules/inline-usage/index.js +94 -0
  9. package/dist/cjs/rules/no-alias/index.js +64 -0
  10. package/dist/cjs/rules/no-module-level-eval/index.js +45 -0
  11. package/dist/cjs/rules/no-preconditioning/index.js +108 -0
  12. package/dist/cjs/rules/prefer-fg/index.js +106 -0
  13. package/dist/cjs/rules/static-feature-flags/index.js +63 -0
  14. package/dist/cjs/rules/use-recommended-utils/index.js +47 -0
  15. package/dist/cjs/rules/util/registration-utils.js +2 -1
  16. package/dist/cjs/rules/utils.js +53 -0
  17. package/dist/es2019/index.js +52 -2
  18. package/dist/es2019/rules/constants.js +5 -0
  19. package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +52 -6
  20. package/dist/es2019/rules/ensure-native-and-af-exports-synced/index.js +15 -7
  21. package/dist/es2019/rules/ensure-valid-emotion-css-prop/index.js +87 -0
  22. package/dist/es2019/rules/inline-usage/index.js +90 -0
  23. package/dist/es2019/rules/no-alias/index.js +58 -0
  24. package/dist/es2019/rules/no-module-level-eval/index.js +39 -0
  25. package/dist/es2019/rules/no-preconditioning/index.js +105 -0
  26. package/dist/es2019/rules/prefer-fg/index.js +81 -0
  27. package/dist/es2019/rules/static-feature-flags/index.js +54 -0
  28. package/dist/es2019/rules/use-recommended-utils/index.js +41 -0
  29. package/dist/es2019/rules/util/registration-utils.js +2 -1
  30. package/dist/es2019/rules/utils.js +29 -0
  31. package/dist/esm/index.js +48 -2
  32. package/dist/esm/rules/constants.js +5 -0
  33. package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +54 -6
  34. package/dist/esm/rules/ensure-native-and-af-exports-synced/index.js +16 -7
  35. package/dist/esm/rules/ensure-valid-emotion-css-prop/index.js +85 -0
  36. package/dist/esm/rules/inline-usage/index.js +87 -0
  37. package/dist/esm/rules/no-alias/index.js +57 -0
  38. package/dist/esm/rules/no-module-level-eval/index.js +39 -0
  39. package/dist/esm/rules/no-preconditioning/index.js +102 -0
  40. package/dist/esm/rules/prefer-fg/index.js +99 -0
  41. package/dist/esm/rules/static-feature-flags/index.js +56 -0
  42. package/dist/esm/rules/use-recommended-utils/index.js +41 -0
  43. package/dist/esm/rules/util/registration-utils.js +2 -1
  44. package/dist/esm/rules/utils.js +45 -0
  45. package/dist/types/index.d.ts +15 -0
  46. package/dist/types/rules/constants.d.ts +3 -0
  47. package/dist/types/rules/ensure-valid-emotion-css-prop/index.d.ts +3 -0
  48. package/dist/types/rules/inline-usage/index.d.ts +3 -0
  49. package/dist/types/rules/no-alias/index.d.ts +3 -0
  50. package/dist/types/rules/no-module-level-eval/index.d.ts +3 -0
  51. package/dist/types/rules/no-preconditioning/index.d.ts +3 -0
  52. package/dist/types/rules/prefer-fg/index.d.ts +3 -0
  53. package/dist/types/rules/static-feature-flags/index.d.ts +3 -0
  54. package/dist/types/rules/use-recommended-utils/index.d.ts +3 -0
  55. package/dist/types/rules/util/registration-utils.d.ts +1 -0
  56. package/dist/types/rules/utils.d.ts +7 -0
  57. package/dist/types-ts4.5/index.d.ts +15 -0
  58. package/dist/types-ts4.5/rules/constants.d.ts +3 -0
  59. package/dist/types-ts4.5/rules/ensure-valid-emotion-css-prop/index.d.ts +3 -0
  60. package/dist/types-ts4.5/rules/inline-usage/index.d.ts +3 -0
  61. package/dist/types-ts4.5/rules/no-alias/index.d.ts +3 -0
  62. package/dist/types-ts4.5/rules/no-module-level-eval/index.d.ts +3 -0
  63. package/dist/types-ts4.5/rules/no-preconditioning/index.d.ts +3 -0
  64. package/dist/types-ts4.5/rules/prefer-fg/index.d.ts +3 -0
  65. package/dist/types-ts4.5/rules/static-feature-flags/index.d.ts +3 -0
  66. package/dist/types-ts4.5/rules/use-recommended-utils/index.d.ts +3 -0
  67. package/dist/types-ts4.5/rules/util/registration-utils.d.ts +1 -0
  68. package/dist/types-ts4.5/rules/utils.d.ts +7 -0
  69. package/index.js +9 -9
  70. package/package.json +43 -44
  71. package/report.api.md +31 -30
  72. package/src/__tests__/utils/_tester.tsx +16 -16
  73. package/src/index.tsx +102 -51
  74. package/src/rules/constants.tsx +20 -0
  75. package/src/rules/ensure-atlassian-team/__tests__/unit/rule.test.ts +19 -19
  76. package/src/rules/ensure-atlassian-team/index.ts +39 -52
  77. package/src/rules/ensure-critical-dependency-resolutions/__test__/unit/rule.test.tsx +146 -81
  78. package/src/rules/ensure-critical-dependency-resolutions/index.tsx +152 -97
  79. package/src/rules/ensure-feature-flag-prefix/__tests__/unit/rule.test.tsx +51 -51
  80. package/src/rules/ensure-feature-flag-prefix/index.tsx +65 -80
  81. package/src/rules/ensure-feature-flag-registration/__tests__/unit/rule.test.tsx +97 -97
  82. package/src/rules/ensure-feature-flag-registration/index.tsx +88 -105
  83. package/src/rules/ensure-native-and-af-exports-synced/__tests__/unit/rule.test.tsx +180 -180
  84. package/src/rules/ensure-native-and-af-exports-synced/index.tsx +162 -168
  85. package/src/rules/ensure-publish-valid/__tests__/unit/rule.test.ts +34 -36
  86. package/src/rules/ensure-publish-valid/index.ts +66 -81
  87. package/src/rules/ensure-test-runner-arguments/__tests__/unit/rule.test.tsx +93 -93
  88. package/src/rules/ensure-test-runner-arguments/index.tsx +107 -121
  89. package/src/rules/ensure-test-runner-nested-count/__tests__/unit/rule.test.tsx +43 -43
  90. package/src/rules/ensure-test-runner-nested-count/index.tsx +68 -70
  91. package/src/rules/ensure-valid-emotion-css-prop/__tests__/unit/rule.test.ts +142 -0
  92. package/src/rules/ensure-valid-emotion-css-prop/index.ts +96 -0
  93. package/src/rules/inline-usage/README.md +53 -0
  94. package/src/rules/inline-usage/__tests__/rule.test.tsx +106 -0
  95. package/src/rules/inline-usage/index.tsx +130 -0
  96. package/src/rules/no-alias/README.md +29 -0
  97. package/src/rules/no-alias/__tests__/rule.test.tsx +76 -0
  98. package/src/rules/no-alias/index.tsx +75 -0
  99. package/src/rules/no-duplicate-dependencies/__tests__/unit/rule.test.ts +44 -44
  100. package/src/rules/no-duplicate-dependencies/index.ts +68 -73
  101. package/src/rules/no-invalid-feature-flag-usage/__tests__/unit/rule.test.tsx +64 -64
  102. package/src/rules/no-invalid-feature-flag-usage/index.tsx +105 -112
  103. package/src/rules/no-invalid-storybook-decorator-usage/__tests__/unit/rule.test.tsx +13 -13
  104. package/src/rules/no-invalid-storybook-decorator-usage/index.tsx +28 -30
  105. package/src/rules/no-module-level-eval/README.md +53 -0
  106. package/src/rules/no-module-level-eval/__tests__/test.tsx +133 -0
  107. package/src/rules/no-module-level-eval/index.tsx +52 -0
  108. package/src/rules/no-pre-post-installs/__tests__/unit/rule.test.ts +36 -36
  109. package/src/rules/no-pre-post-installs/index.ts +27 -27
  110. package/src/rules/no-preconditioning/README.md +69 -0
  111. package/src/rules/no-preconditioning/__tests__/rule.test.tsx +164 -0
  112. package/src/rules/no-preconditioning/index.tsx +138 -0
  113. package/src/rules/prefer-fg/README.md +3 -0
  114. package/src/rules/prefer-fg/__tests__/rule.test.tsx +83 -0
  115. package/src/rules/prefer-fg/index.tsx +108 -0
  116. package/src/rules/static-feature-flags/README.md +3 -0
  117. package/src/rules/static-feature-flags/__tests__/test.tsx +135 -0
  118. package/src/rules/static-feature-flags/index.tsx +103 -0
  119. package/src/rules/use-recommended-utils/README.md +67 -0
  120. package/src/rules/use-recommended-utils/__tests__/rule.test.tsx +78 -0
  121. package/src/rules/use-recommended-utils/index.tsx +57 -0
  122. package/src/rules/util/handle-ast-object.ts +21 -32
  123. package/src/rules/util/registration-utils.ts +31 -30
  124. package/src/rules/utils.tsx +46 -0
  125. package/tsconfig.app.json +35 -35
  126. 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
- tester.run('ensure-critical-dependency-resolutions', rule, {
8
- valid: [
9
- // Root package.json, have all of the correct resolutions
10
- {
11
- code: `const foo = {
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
- filename: `${cwd}/package.json`,
18
- },
19
- // Root package.json, have all of the correct resolutions
20
- {
21
- code: `const foo = {
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
- filename: `${cwd}/package.json`,
28
- },
29
- // Root package.json, have all of the correct resolutions with ~
30
- {
31
- code: `const foo = {
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
- filename: `${cwd}/package.json`,
38
- },
39
- // Individual package's package.json. Have part of correct resolutions
40
- {
41
- code: `const foo = {
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
- filename: `${cwd}/package/name/package.json`,
47
- },
48
- // Individual package's package.json. Not have relevant package resolutions
49
- {
50
- code: `const foo = {
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
- filename: `${cwd}/package/name/package.json`,
56
- },
57
- ],
58
- invalid: [
59
- // Root package.json. One package is correct, the other is missing
60
- {
61
- code: `const foo = {
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
- filename: `${cwd}/package.json`,
67
- errors: [
68
- {
69
- messageId: 'invalidPackageResolution',
70
- },
71
- ],
72
- },
73
- // Root package.json. Both packages have the wrong version ranges
74
- {
75
- code: `const foo = {
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
- filename: `${cwd}/package.json`,
82
- errors: [
83
- {
84
- messageId: 'invalidPackageResolution',
85
- },
86
- ],
87
- },
88
- // Root package.json. One package is correct, the other has wrong version range
89
- {
90
- code: `const foo = {
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
- filename: `${cwd}/package.json`,
97
- errors: [
98
- {
99
- messageId: 'invalidPackageResolution',
100
- },
101
- ],
102
- },
103
- // Root package.json. One package is correct, the other has ^ in its version
104
- {
105
- code: `const foo = {
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
- filename: `${cwd}/package.json`,
112
- errors: [
113
- {
114
- messageId: 'invalidPackageResolution',
115
- },
116
- ],
117
- },
118
- // Individual package's package.json. One package is correct, the other is wrong
119
- {
120
- code: `const foo = {
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
- filename: `${cwd}/packages/packge/directory/package.json`,
127
- errors: [
128
- {
129
- messageId: 'invalidPackageResolution',
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
- typescript: ['5.4'],
12
- '@types/react': ['16.14', '18.2'],
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
- desiredVersion: string,
17
- versionInResolutions: string,
18
- ): boolean => {
19
- const firstChar = versionInResolutions[0];
20
- // The version is invalid if it doesn't start with a number or ~
21
- if (!/^\d$/.test(firstChar) && firstChar !== '~') {
22
- return false;
23
- }
24
-
25
- return (
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
- node: ObjectExpression,
33
- pkg: string,
34
- version: string,
35
- optional: boolean,
36
- ): boolean => {
37
- // For root package.json, we require the critical packages' resolutions exist and with matching version
38
- // For individual package's package.json, it's ok if resolutions don't exist. But if they do, the version should match
39
- const resolutionExist = node.properties.some(
40
- (p) =>
41
- p.type === 'Property' && p.key.type === 'Literal' && p.key.value === pkg,
42
- );
43
-
44
- if (!resolutionExist) {
45
- return optional;
46
- }
47
-
48
- const resolutionExistAndMatch = node.properties.some(
49
- (p) =>
50
- p.type === 'Property' &&
51
- p.key.type === 'Literal' &&
52
- p.key.value === pkg &&
53
- p.value.type === 'Literal' &&
54
- matchMinorVersion(version, p.value.value as string),
55
- );
56
-
57
- return resolutionExistAndMatch;
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
- meta: {
62
- type: 'problem',
63
- docs: {
64
- description:
65
- 'Enforce the versions of critical packages are within desired ranges by checking resolutions section in package.json',
66
- recommended: true,
67
- },
68
- hasSuggestions: false,
69
- messages: {
70
- invalidPackageResolution: `Make sure the resolutions for the following packages match major and minor version ranges ${JSON.stringify(
71
- DESIRED_PKG_VERSIONS,
72
- )}`,
73
- },
74
- },
75
- create(context) {
76
- const fileName = context.getFilename();
77
- return {
78
- ObjectExpression: (node: Rule.Node) => {
79
- if (
80
- !fileName.endsWith('package.json') ||
81
- node.type !== 'ObjectExpression'
82
- ) {
83
- return;
84
- }
85
-
86
- const packageResolutions = getObjectPropertyAsObject(
87
- node,
88
- 'resolutions',
89
- );
90
- const rootDir = findRootSync(process.cwd());
91
- const isRootPackageJson = fileName.endsWith(`${rootDir}/package.json`);
92
-
93
- if (packageResolutions !== null) {
94
- for (const [key, values] of Object.entries(DESIRED_PKG_VERSIONS)) {
95
- if (
96
- !values.some((value) => {
97
- return verifyResolutionFromObject(
98
- packageResolutions as ObjectExpression,
99
- key,
100
- value,
101
- !isRootPackageJson,
102
- );
103
- })
104
- ) {
105
- return context.report({
106
- node,
107
- messageId: 'invalidPackageResolution',
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
- 'platform-feature-flags': {
9
- 'test-flag': {
10
- type: 'boolean',
11
- },
12
- },
8
+ 'platform-feature-flags': {
9
+ 'test-flag': {
10
+ type: 'boolean',
11
+ },
12
+ },
13
13
  };
14
14
  jest.mock('read-pkg-up', () => ({
15
- sync: () => ({
16
- path: mockPath,
17
- packageJson: mockPackageJson,
18
- }),
15
+ sync: () => ({
16
+ path: mockPath,
17
+ packageJson: mockPackageJson,
18
+ }),
19
19
  }));
20
20
 
21
21
  describe('test prefix rule', () => {
22
- beforeEach(() => {
23
- mockPath = 'test/package.json';
22
+ beforeEach(() => {
23
+ mockPath = 'test/package.json';
24
24
 
25
- mockPackageJson = {
26
- 'platform-feature-flags': {
27
- 'prefix-flag': {
28
- type: 'boolean',
29
- },
30
- 'no-prefix-flag': {
31
- type: 'boolean',
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
- // 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
- });
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
  });