@atlaskit/eslint-plugin-platform 2.7.0 → 2.7.2

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 (158) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/index.js +4 -9
  3. package/dist/cjs/rules/constants.js +1 -1
  4. package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +7 -7
  5. package/dist/cjs/rules/ensure-native-and-af-exports-synced/index.js +3 -0
  6. package/dist/cjs/rules/ensure-no-private-dependencies/index.js +48 -66
  7. package/dist/cjs/rules/feature-gating/inline-usage/index.js +14 -3
  8. package/dist/cjs/rules/feature-gating/no-alias/index.js +2 -2
  9. package/dist/cjs/rules/feature-gating/no-module-level-eval/index.js +1 -1
  10. package/dist/cjs/rules/feature-gating/no-module-level-eval-nav4/index.js +1 -1
  11. package/dist/cjs/rules/feature-gating/no-preconditioning/index.js +4 -1
  12. package/dist/cjs/rules/feature-gating/prefer-fg/index.js +1 -1
  13. package/dist/cjs/rules/feature-gating/static-feature-flags/index.js +2 -2
  14. package/dist/cjs/rules/feature-gating/use-recommended-utils/index.js +1 -1
  15. package/dist/cjs/rules/no-invalid-storybook-decorator-usage/index.js +1 -1
  16. package/dist/cjs/rules/no-sparse-checkout/index.js +1 -1
  17. package/dist/cjs/rules/prefer-crypto-random-uuid/index.js +87 -0
  18. package/dist/cjs/rules/use-entrypoints-in-examples/index.js +1 -1
  19. package/dist/cjs/rules/util/context-compat.js +4 -2
  20. package/dist/es2019/index.js +4 -9
  21. package/dist/es2019/rules/constants.js +1 -1
  22. package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +7 -7
  23. package/dist/es2019/rules/ensure-native-and-af-exports-synced/index.js +3 -0
  24. package/dist/es2019/rules/ensure-no-private-dependencies/index.js +10 -9
  25. package/dist/es2019/rules/feature-gating/inline-usage/index.js +14 -3
  26. package/dist/es2019/rules/feature-gating/no-alias/index.js +2 -2
  27. package/dist/es2019/rules/feature-gating/no-module-level-eval/index.js +1 -1
  28. package/dist/es2019/rules/feature-gating/no-module-level-eval-nav4/index.js +1 -1
  29. package/dist/es2019/rules/feature-gating/no-preconditioning/index.js +4 -1
  30. package/dist/es2019/rules/feature-gating/prefer-fg/index.js +1 -1
  31. package/dist/es2019/rules/feature-gating/static-feature-flags/index.js +2 -2
  32. package/dist/es2019/rules/feature-gating/use-recommended-utils/index.js +1 -1
  33. package/dist/es2019/rules/no-invalid-storybook-decorator-usage/index.js +1 -1
  34. package/dist/es2019/rules/no-sparse-checkout/index.js +1 -1
  35. package/dist/es2019/rules/prefer-crypto-random-uuid/index.js +81 -0
  36. package/dist/es2019/rules/use-entrypoints-in-examples/index.js +1 -1
  37. package/dist/es2019/rules/util/context-compat.js +4 -2
  38. package/dist/esm/index.js +4 -9
  39. package/dist/esm/rules/constants.js +1 -1
  40. package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +7 -7
  41. package/dist/esm/rules/ensure-native-and-af-exports-synced/index.js +3 -0
  42. package/dist/esm/rules/ensure-no-private-dependencies/index.js +48 -65
  43. package/dist/esm/rules/feature-gating/inline-usage/index.js +14 -3
  44. package/dist/esm/rules/feature-gating/no-alias/index.js +2 -2
  45. package/dist/esm/rules/feature-gating/no-module-level-eval/index.js +1 -1
  46. package/dist/esm/rules/feature-gating/no-module-level-eval-nav4/index.js +1 -1
  47. package/dist/esm/rules/feature-gating/no-preconditioning/index.js +4 -1
  48. package/dist/esm/rules/feature-gating/prefer-fg/index.js +1 -1
  49. package/dist/esm/rules/feature-gating/static-feature-flags/index.js +2 -2
  50. package/dist/esm/rules/feature-gating/use-recommended-utils/index.js +1 -1
  51. package/dist/esm/rules/no-invalid-storybook-decorator-usage/index.js +1 -1
  52. package/dist/esm/rules/no-sparse-checkout/index.js +1 -1
  53. package/dist/esm/rules/prefer-crypto-random-uuid/index.js +81 -0
  54. package/dist/esm/rules/use-entrypoints-in-examples/index.js +1 -1
  55. package/dist/esm/rules/util/context-compat.js +4 -2
  56. package/dist/types/index.d.ts +6 -20
  57. package/dist/types/rules/util/handle-ast-object.d.ts +1 -1
  58. package/dist/types-ts4.5/index.d.ts +6 -32
  59. package/dist/types-ts4.5/rules/util/handle-ast-object.d.ts +1 -1
  60. package/package.json +2 -5
  61. package/afm-cc/tsconfig.json +0 -24
  62. package/afm-jira/tsconfig.json +0 -24
  63. package/build/tsconfig.json +0 -17
  64. package/dist/cjs/rules/ensure-feature-flag-prefix/index.js +0 -75
  65. package/dist/cjs/rules/ensure-valid-platform-yarn-protocol-usage/index.js +0 -79
  66. package/dist/es2019/rules/ensure-feature-flag-prefix/index.js +0 -65
  67. package/dist/es2019/rules/ensure-valid-platform-yarn-protocol-usage/index.js +0 -62
  68. package/dist/esm/rules/ensure-feature-flag-prefix/index.js +0 -69
  69. package/dist/esm/rules/ensure-valid-platform-yarn-protocol-usage/index.js +0 -75
  70. package/dist/types/rules/ensure-feature-flag-prefix/index.d.ts +0 -3
  71. package/dist/types/rules/ensure-valid-platform-yarn-protocol-usage/index.d.ts +0 -3
  72. package/src/__tests__/utils/_tester.tsx +0 -26
  73. package/src/index.tsx +0 -254
  74. package/src/rules/compiled/README.md +0 -3
  75. package/src/rules/compiled/expand-background-shorthand/README.md +0 -23
  76. package/src/rules/compiled/expand-background-shorthand/__tests__/rule.test.ts +0 -160
  77. package/src/rules/compiled/expand-background-shorthand/index.tsx +0 -43
  78. package/src/rules/compiled/expand-border-shorthand/README.md +0 -51
  79. package/src/rules/compiled/expand-border-shorthand/__tests__/rule.test.ts +0 -211
  80. package/src/rules/compiled/expand-border-shorthand/index.ts +0 -103
  81. package/src/rules/compiled/expand-spacing-shorthand/README.md +0 -38
  82. package/src/rules/compiled/expand-spacing-shorthand/__tests__/rule.test.ts +0 -448
  83. package/src/rules/compiled/expand-spacing-shorthand/index.ts +0 -240
  84. package/src/rules/constants.tsx +0 -20
  85. package/src/rules/ensure-atlassian-team/__tests__/unit/rule.test.ts +0 -24
  86. package/src/rules/ensure-atlassian-team/index.ts +0 -51
  87. package/src/rules/ensure-critical-dependency-resolutions/__test__/unit/rule.test.tsx +0 -200
  88. package/src/rules/ensure-critical-dependency-resolutions/index.tsx +0 -172
  89. package/src/rules/ensure-feature-flag-prefix/__tests__/unit/rule.test.tsx +0 -65
  90. package/src/rules/ensure-feature-flag-prefix/index.tsx +0 -81
  91. package/src/rules/ensure-feature-flag-registration/__tests__/unit/rule.test.tsx +0 -115
  92. package/src/rules/ensure-feature-flag-registration/index.tsx +0 -106
  93. package/src/rules/ensure-native-and-af-exports-synced/__tests__/unit/rule.test.tsx +0 -199
  94. package/src/rules/ensure-native-and-af-exports-synced/index.tsx +0 -188
  95. package/src/rules/ensure-no-private-dependencies/__tests__/unit/rule.test.ts +0 -212
  96. package/src/rules/ensure-no-private-dependencies/index.ts +0 -64
  97. package/src/rules/ensure-publish-valid/__tests__/unit/rule.test.ts +0 -39
  98. package/src/rules/ensure-publish-valid/index.ts +0 -81
  99. package/src/rules/ensure-test-runner-arguments/__tests__/unit/rule.test.tsx +0 -298
  100. package/src/rules/ensure-test-runner-arguments/index.tsx +0 -121
  101. package/src/rules/ensure-test-runner-nested-count/__tests__/unit/rule.test.tsx +0 -308
  102. package/src/rules/ensure-test-runner-nested-count/index.tsx +0 -82
  103. package/src/rules/ensure-valid-bin-values/__tests__/unit/rule.test.ts +0 -159
  104. package/src/rules/ensure-valid-bin-values/index.ts +0 -70
  105. package/src/rules/ensure-valid-platform-yarn-protocol-usage/__tests__/unit/rule.test.ts +0 -147
  106. package/src/rules/ensure-valid-platform-yarn-protocol-usage/index.ts +0 -67
  107. package/src/rules/feature-gating/README.md +0 -8
  108. package/src/rules/feature-gating/inline-usage/README.md +0 -53
  109. package/src/rules/feature-gating/inline-usage/__tests__/rule.test.tsx +0 -106
  110. package/src/rules/feature-gating/inline-usage/index.tsx +0 -135
  111. package/src/rules/feature-gating/no-alias/README.md +0 -29
  112. package/src/rules/feature-gating/no-alias/__tests__/rule.test.tsx +0 -76
  113. package/src/rules/feature-gating/no-alias/index.tsx +0 -80
  114. package/src/rules/feature-gating/no-module-level-eval/README.md +0 -53
  115. package/src/rules/feature-gating/no-module-level-eval/__tests__/test.tsx +0 -133
  116. package/src/rules/feature-gating/no-module-level-eval/index.tsx +0 -54
  117. package/src/rules/feature-gating/no-module-level-eval-nav4/README.md +0 -8
  118. package/src/rules/feature-gating/no-module-level-eval-nav4/__tests__/test.tsx +0 -130
  119. package/src/rules/feature-gating/no-module-level-eval-nav4/index.tsx +0 -73
  120. package/src/rules/feature-gating/no-preconditioning/README.md +0 -69
  121. package/src/rules/feature-gating/no-preconditioning/__tests__/rule.test.tsx +0 -164
  122. package/src/rules/feature-gating/no-preconditioning/index.tsx +0 -138
  123. package/src/rules/feature-gating/prefer-fg/README.md +0 -3
  124. package/src/rules/feature-gating/prefer-fg/__tests__/rule.test.tsx +0 -83
  125. package/src/rules/feature-gating/prefer-fg/index.tsx +0 -110
  126. package/src/rules/feature-gating/static-feature-flags/README.md +0 -3
  127. package/src/rules/feature-gating/static-feature-flags/__tests__/test.tsx +0 -135
  128. package/src/rules/feature-gating/static-feature-flags/index.tsx +0 -103
  129. package/src/rules/feature-gating/use-recommended-utils/README.md +0 -67
  130. package/src/rules/feature-gating/use-recommended-utils/__tests__/rule.test.tsx +0 -78
  131. package/src/rules/feature-gating/use-recommended-utils/index.tsx +0 -57
  132. package/src/rules/feature-gating/utils.tsx +0 -48
  133. package/src/rules/no-direct-document-usage/index.tsx +0 -111
  134. package/src/rules/no-duplicate-dependencies/__tests__/unit/rule.test.ts +0 -116
  135. package/src/rules/no-duplicate-dependencies/index.ts +0 -79
  136. package/src/rules/no-invalid-feature-flag-usage/__tests__/unit/rule.test.tsx +0 -69
  137. package/src/rules/no-invalid-feature-flag-usage/index.tsx +0 -128
  138. package/src/rules/no-invalid-storybook-decorator-usage/__tests__/unit/rule.test.tsx +0 -18
  139. package/src/rules/no-invalid-storybook-decorator-usage/index.tsx +0 -39
  140. package/src/rules/no-pre-post-installs/__tests__/unit/rule.test.ts +0 -41
  141. package/src/rules/no-pre-post-installs/index.ts +0 -35
  142. package/src/rules/no-set-immediate/index.tsx +0 -43
  143. package/src/rules/no-sparse-checkout/__tests__/unit/rule.test.tsx +0 -48
  144. package/src/rules/no-sparse-checkout/index.tsx +0 -54
  145. package/src/rules/use-entrypoints-in-examples/README.md +0 -27
  146. package/src/rules/use-entrypoints-in-examples/__tests__/rule.test.tsx +0 -34
  147. package/src/rules/use-entrypoints-in-examples/index.tsx +0 -43
  148. package/src/rules/util/__tests__/context-compat.test.ts +0 -122
  149. package/src/rules/util/compiled-utils.ts +0 -27
  150. package/src/rules/util/context-compat.ts +0 -41
  151. package/src/rules/util/file-exclusions.ts +0 -39
  152. package/src/rules/util/handle-ast-object.ts +0 -33
  153. package/src/rules/util/registration-utils.ts +0 -59
  154. package/tsconfig.app.json +0 -43
  155. package/tsconfig.dev.json +0 -40
  156. package/tsconfig.json +0 -23
  157. /package/dist/{types-ts4.5/rules/ensure-valid-platform-yarn-protocol-usage → types/rules/prefer-crypto-random-uuid}/index.d.ts +0 -0
  158. /package/dist/types-ts4.5/rules/{ensure-feature-flag-prefix → prefer-crypto-random-uuid}/index.d.ts +0 -0
@@ -1,106 +0,0 @@
1
- // eslint-disable-next-line import/no-extraneous-dependencies
2
- import type { Rule } from 'eslint';
3
- import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
4
-
5
- const rule: Rule.RuleModule = {
6
- meta: {
7
- docs: {
8
- recommended: false,
9
- },
10
- type: 'problem',
11
- messages: {
12
- registrationSectionMissing:
13
- 'Please add a "platform-feature-flags" section to your package.json! See http://go/pff-eslint for more details',
14
- featureFlagMissing: `Please add a "{{ featureFlag }}" section to the "platform-feature-flags" section in your package.json. See http://go/pff-eslint for more details`,
15
- changeFeatureFlag: `Change flag key to "{{ closestFlag }}" already defined in package.json`,
16
- featureFlagIncorrectType: `Please change the type for "{{ featureFlag }}" to "{{ expectedType }}" in the section to the "platform-feature-flags" section in your package.json. See http://go/pff-eslint for more details"`,
17
- },
18
-
19
- hasSuggestions: true,
20
- },
21
- create(context) {
22
- return Object.fromEntries(
23
- (
24
- Object.keys(getterIdentifierToFlagTypeMap) as (keyof typeof getterIdentifierToFlagTypeMap)[]
25
- ).map((getterIdentifier) => [
26
- `CallExpression[callee.name=/${getterIdentifier}/]`,
27
- (node: Rule.Node) => {
28
- // to make typescript happy
29
- if (node.type === 'CallExpression') {
30
- const args = node.arguments;
31
-
32
- const filename = context.getFilename();
33
- const { pkgJson: packageJson, fuse } = getMetadataForFilename(filename);
34
- const platformFeatureFlags = packageJson['platform-feature-flags'];
35
-
36
- if (!platformFeatureFlags) {
37
- return context.report({
38
- node: node,
39
- messageId: 'registrationSectionMissing',
40
- });
41
- }
42
-
43
- if (args.length === 1 && args[0].type === 'Literal' && args[0].raw) {
44
- const featureFlag = args[0].value as string;
45
- const featureFlagRegistration = platformFeatureFlags[featureFlag];
46
-
47
- const expectedType = getterIdentifierToFlagTypeMap[getterIdentifier];
48
-
49
- // ensure the flag type matches what is registered
50
- if (
51
- featureFlagRegistration != null &&
52
- expectedType != null &&
53
- featureFlagRegistration?.type !== expectedType
54
- ) {
55
- return context.report({
56
- node: args[0],
57
- messageId: 'featureFlagIncorrectType',
58
- data: {
59
- featureFlag,
60
- expectedType,
61
- },
62
- });
63
- }
64
-
65
- if (!featureFlagRegistration) {
66
- // find the closest match in existing section for suggestion text
67
- let closestMatchFix: Rule.SuggestionReportDescriptor | null = null;
68
-
69
- if (fuse) {
70
- const closestFlagMatches = fuse.search(featureFlag);
71
- if (closestFlagMatches.length > 0) {
72
- const closestFlag = closestFlagMatches[0].item;
73
-
74
- closestMatchFix = {
75
- messageId: 'changeFeatureFlag',
76
- data: {
77
- closestFlag,
78
- },
79
- fix: (fixer) => {
80
- return fixer.replaceText(node.arguments[0], `'${closestFlag}'`);
81
- },
82
- };
83
- }
84
- }
85
-
86
- return context.report({
87
- node: args[0],
88
- messageId: 'featureFlagMissing',
89
- data: {
90
- featureFlag,
91
- },
92
- // only suggest if we have a close flag to match
93
- ...(closestMatchFix != null ? { suggest: [closestMatchFix] } : {}),
94
- });
95
- }
96
- }
97
- }
98
-
99
- return {};
100
- },
101
- ]),
102
- );
103
- },
104
- };
105
-
106
- export default rule;
@@ -1,199 +0,0 @@
1
- import { tester } from '../../../../__tests__/utils/_tester';
2
- import rule from '../../index';
3
- import { type PackageJson } from 'read-pkg-up';
4
-
5
- let mockPath = 'packages/test/package.json';
6
-
7
- let mockPackageJson: PackageJson = {};
8
- jest.mock('read-pkg-up', () => ({
9
- sync: () => ({
10
- path: mockPath,
11
- packageJson: mockPackageJson,
12
- }),
13
- }));
14
-
15
- describe('valid test cases', () => {
16
- describe('allows @atlaskit/tokens babel-plugin entrypoint', () => {
17
- beforeEach(() => {
18
- mockPackageJson = {
19
- name: '@atlaskit/tokens',
20
- 'af:exports': {
21
- './babel-plugin': './src/entry-points/babel-plugin.tsx',
22
- },
23
- exports: {
24
- './babel-plugin': './babel-plugin.js',
25
- },
26
- };
27
- });
28
- tester.run('ensure-native-and-af-exports-synced', rule, {
29
- valid: [{ code: '' }],
30
- invalid: [],
31
- });
32
- });
33
-
34
- describe('passes for valid directory export', () => {
35
- beforeEach(() => {
36
- mockPackageJson = {
37
- name: '@atlaskit/tokens',
38
- 'af:exports': {
39
- './glyph': './glyph',
40
- './test/icon': './test/icon',
41
- './button': './button',
42
- '.': './src',
43
- },
44
- exports: {
45
- './glyph/*': './glyph/*',
46
- './test/icon/*': './test/icon/*',
47
- './button/*': './button/*.js',
48
- './*': './src/*',
49
- },
50
- };
51
- });
52
- tester.run('ensure-native-and-af-exports-synced', rule, {
53
- valid: [
54
- {
55
- code: '',
56
- filename: 'packages/test/package.json',
57
- },
58
- ],
59
- invalid: [],
60
- });
61
- });
62
-
63
- describe('passes for index.js files', () => {
64
- beforeEach(() => {
65
- mockPackageJson = {
66
- name: '@atlaskit/tokens',
67
- 'af:exports': {
68
- '.': './src/index.tsx',
69
- './gas-v3': './src/gas-v3/index.ts',
70
- './reader': './src/reader/reader.ts',
71
- './writer': './src/writer/writer.ts',
72
- './report': './src/report/report.ts',
73
- },
74
- exports: {
75
- '.': './index.js',
76
- './gas-v3': './gas-v3/index.js',
77
- './reader': './reader/index.js',
78
- './writer': './writer/index.js',
79
- './report': './report/index.js',
80
- },
81
- };
82
- });
83
- tester.run('ensure-native-and-af-exports-synced', rule, {
84
- valid: [
85
- {
86
- code: '',
87
- filename: 'packages/test/package.json',
88
- },
89
- ],
90
- invalid: [],
91
- });
92
- });
93
-
94
- describe('should pass for multiple valid entrypoints', () => {
95
- beforeEach(() => {
96
- mockPackageJson = {
97
- name: '@atlaskit/tokens',
98
- 'af:exports': {
99
- '.': './src/index.tsx',
100
- './rename-mapping': './src/entry-points/rename-mapping.tsx',
101
- './babel-plugin': './src/entry-points/babel-plugin.tsx',
102
- './glyph': './glyph',
103
- './button': './button',
104
- },
105
- exports: {
106
- '.': './index.js',
107
- './rename-mapping': './src/entry-points/rename-mapping.tsx',
108
- './babel-plugin': './src/entry-points/babel-plugin.tsx',
109
- './glyph/*': './glyph/*',
110
- './button/*': './button/*.js',
111
- },
112
- };
113
- });
114
- tester.run('ensure-native-and-af-exports-synced', rule, {
115
- valid: [
116
- {
117
- code: '',
118
- filename: 'packages/test/package.json',
119
- },
120
- ],
121
- invalid: [],
122
- });
123
- });
124
- });
125
-
126
- describe('invalid test cases', () => {
127
- describe('should fail for mismatched invalid entrypoints', () => {
128
- beforeEach(() => {
129
- mockPackageJson = {
130
- name: '@atlaskit/test',
131
- 'af:exports': {
132
- '.': './src/index.ts',
133
- },
134
- exports: {
135
- '.': './test/index.ts',
136
- },
137
- };
138
- });
139
- tester.run('ensure-native-and-af-exports-synced', rule, {
140
- valid: [],
141
- invalid: [
142
- {
143
- code: '',
144
- filename: 'packages/test/package.json',
145
- errors: [{ messageId: 'unexpectedExportsValue' }],
146
- },
147
- ],
148
- });
149
- });
150
-
151
- describe('should fail for missing entrypoints', () => {
152
- beforeEach(() => {
153
- mockPackageJson = {
154
- name: '@atlaskit/tokens',
155
- 'af:exports': {
156
- '.': './src/index.ts',
157
- './button': './button',
158
- },
159
- exports: {
160
- '.': './src/index.ts',
161
- },
162
- };
163
- });
164
- tester.run('ensure-native-and-af-exports-synced', rule, {
165
- valid: [],
166
- invalid: [
167
- {
168
- code: '',
169
- filename: 'packages/test/package.json',
170
- errors: [{ messageId: 'missingExportsKey' }],
171
- },
172
- ],
173
- });
174
- });
175
-
176
- describe('should fail for invalid directory export', () => {
177
- beforeEach(() => {
178
- mockPackageJson = {
179
- name: '@atlaskit/tokens',
180
- 'af:exports': {
181
- './button': './button',
182
- },
183
- exports: {
184
- './button/*': './src/button/*',
185
- },
186
- };
187
- });
188
- tester.run('ensure-native-and-af-exports-synced', rule, {
189
- valid: [],
190
- invalid: [
191
- {
192
- code: '',
193
- filename: 'packages/test/package.json',
194
- errors: [{ messageId: 'unexpectedExportsValue' }],
195
- },
196
- ],
197
- });
198
- });
199
- });
@@ -1,188 +0,0 @@
1
- import type { Rule } from 'eslint';
2
- import path from 'path';
3
-
4
- import { getMetadataForFilename } from '../util/registration-utils';
5
-
6
- interface ExportsValidationExceptions {
7
- [key: string]: { ignoredAfExportKeys: string[] };
8
- }
9
-
10
- const exportsValidationExceptions: ExportsValidationExceptions = {
11
- '@af/yarn-workspace': {
12
- ignoredAfExportKeys: ['./lock-parser'],
13
- },
14
- '@atlaskit/tokens': {
15
- ignoredAfExportKeys: ['./babel-plugin'],
16
- },
17
- '@atlaskit/storybook-addon-design-system': {
18
- ignoredAfExportKeys: ['.'],
19
- },
20
- };
21
-
22
- const rule: Rule.RuleModule = {
23
- meta: {
24
- docs: {
25
- recommended: false,
26
- },
27
- type: 'problem',
28
- messages: {
29
- missingExportsProperty: `The exports property must be defined for {{pkgName}}; it most likely can just be a duplicate of the "af:exports" property. See http://go/eslint-exports for details`,
30
- missingExportsKey: `Missing package.json exports key "{{expectedKey}}" in {{pkgName}}. The exports entry should be "{{expectedKey}}": "{{expectedValue}}". See http://go/eslint-exports for details`,
31
- unexpectedExportsKey: `Unexpected package.json exports key "{{key}}" in {{pkgName}}. The exports entry should be "{{expectedKey}}": "{{expectedValue}}". See http://go/eslint-exports for details`,
32
- unexpectedExportsValue: `Unexpected package.json exports value in {{pkgName}} for the "{{key}}" key. The exports entry should be "{{key}}": "{{expectedValue}}". See http://go/eslint-exports for details`,
33
- },
34
- },
35
-
36
- create(context) {
37
- const fileName = context.getFilename();
38
-
39
- if (!fileName.endsWith('package.json')) {
40
- return {};
41
- }
42
-
43
- const { pkgJson: packageJson } = getMetadataForFilename(fileName);
44
-
45
- const pkgName = packageJson.name;
46
-
47
- if (!pkgName || !packageJson['af:exports']) {
48
- return {};
49
- }
50
-
51
- if (!packageJson['exports']) {
52
- context.report({
53
- node: context.getSourceCode().ast,
54
- messageId: 'missingExportsProperty',
55
- data: { pkgName },
56
- });
57
- return {};
58
- }
59
-
60
- const afExports: { [key: string]: any } = packageJson['af:exports'];
61
- const nativeExports: { [key: string]: any } = packageJson['exports'];
62
-
63
- return {
64
- Program(node) {
65
- for (const [afExportsKey, afExportsValue] of Object.entries(afExports)) {
66
- if (exportsValidationExceptions[pkgName]?.ignoredAfExportKeys.includes(afExportsKey)) {
67
- continue;
68
- }
69
-
70
- const exportKeyViolations = getExportKeyViolation(
71
- afExportsKey,
72
- afExportsValue,
73
- nativeExports,
74
- );
75
-
76
- if (exportKeyViolations) {
77
- context.report({
78
- data: { ...exportKeyViolations, key: afExportsKey, pkgName },
79
- node,
80
- messageId: exportKeyViolations.messageId,
81
- });
82
-
83
- continue;
84
- }
85
-
86
- const exportValueViolations = getExportValueViolation(
87
- afExportsKey,
88
- afExportsValue,
89
- nativeExports,
90
- );
91
-
92
- if (exportValueViolations) {
93
- context.report({
94
- data: { ...exportValueViolations, pkgName },
95
- node,
96
- messageId: 'unexpectedExportsValue',
97
- });
98
-
99
- continue;
100
- }
101
- }
102
- },
103
- };
104
- },
105
- };
106
-
107
- function getExportKeyViolation(
108
- afExportsKey: string,
109
- afExportsValue: string,
110
- nativeExports: { [key: string]: any },
111
- ) {
112
- const afExportsValueHasExtension = path.extname(afExportsValue) !== '';
113
-
114
- if (afExportsValueHasExtension && !nativeExports.hasOwnProperty(afExportsKey)) {
115
- return {
116
- messageId: 'missingExportsKey',
117
- expectedKey: afExportsKey,
118
- expectedValue: afExportsValue,
119
- };
120
- }
121
-
122
- if (!afExportsValueHasExtension && nativeExports.hasOwnProperty(afExportsKey)) {
123
- return {
124
- messageId: 'unexpectedExportsKey',
125
- expectedKey: `${afExportsKey}/*`,
126
- expectedValue: `${afExportsValue}/*`,
127
- };
128
- }
129
-
130
- if (!afExportsValueHasExtension && !nativeExports.hasOwnProperty(`${afExportsKey}/*`)) {
131
- return {
132
- messageId: 'missingExportsKey',
133
- expectedKey: `${afExportsKey}/*`,
134
- expectedValue: `${afExportsValue}/*`,
135
- };
136
- }
137
- }
138
-
139
- function getNativeExportsValue(
140
- afExportsKey: string,
141
- afExportsValueHasExtension: boolean,
142
- nativeExports: { [key: string]: any },
143
- ) {
144
- const nativeExportsKey = afExportsValueHasExtension ? afExportsKey : `${afExportsKey}/*`;
145
-
146
- if (typeof nativeExports[nativeExportsKey] === 'object') {
147
- return nativeExports[nativeExportsKey].default;
148
- }
149
-
150
- return nativeExports[nativeExportsKey];
151
- }
152
-
153
- function getExportValueViolation(
154
- afExportsKey: string,
155
- afExportsValue: string,
156
- nativeExports: { [key: string]: any },
157
- ) {
158
- const afExportsValueHasExtension = path.extname(afExportsValue) !== '';
159
-
160
- const nativeExportsValue = getNativeExportsValue(
161
- afExportsKey,
162
- afExportsValueHasExtension,
163
- nativeExports,
164
- );
165
-
166
- // Some entrypoints have been updated to an index.js file that registers ts-node
167
- // Use path.basename to get the file name to see if it is equal to 'index.js'
168
- if (afExportsValueHasExtension && path.basename(nativeExportsValue) === 'index.js') {
169
- return;
170
- }
171
-
172
- if (afExportsValueHasExtension && nativeExportsValue !== afExportsValue) {
173
- return {
174
- key: afExportsKey,
175
- expectedValue: afExportsValue,
176
- };
177
- }
178
-
179
- // af:exports entrypoints without a file extension export the whole directory so check to ensure the exports value includes the wildcard
180
- if (!afExportsValueHasExtension && !nativeExportsValue.startsWith(`${afExportsValue}/*`)) {
181
- return {
182
- key: `${afExportsKey}/*`,
183
- expectedValue: `${afExportsValue}/*`,
184
- };
185
- }
186
- }
187
-
188
- export default rule;
@@ -1,212 +0,0 @@
1
- import { tester } from '../../../../__tests__/utils/_tester';
2
- import rule from '../../index';
3
-
4
- const cwd = process.cwd();
5
-
6
- jest.mock('@manypkg/find-root');
7
-
8
- jest.mock('@manypkg/get-packages', () => ({
9
- getPackagesSync: () => {
10
- return {
11
- packages: [
12
- // Private packages
13
- {
14
- packageJson: {
15
- name: '@af/private-pkg',
16
- private: true,
17
- },
18
- },
19
- {
20
- packageJson: {
21
- name: '@atlassian/private-pkg',
22
- private: true,
23
- },
24
- },
25
- {
26
- packageJson: {
27
- name: '@atlassiansox/private-pkg',
28
- private: true,
29
- },
30
- },
31
- // Public packages
32
- {
33
- packageJson: {
34
- name: '@atlassian/public-pkg',
35
- publishConfig: { registry: 'https://pkg-registry.com' },
36
- },
37
- },
38
- {
39
- packageJson: {
40
- name: '@atlassiansox/public-pkg',
41
- publishConfig: { registry: 'https://pkg-registry.com' },
42
- },
43
- },
44
- {
45
- packageJson: {
46
- name: '@atlaskit/public-pkg',
47
- publishConfig: { registry: 'https://pkg-registry.com' },
48
- },
49
- },
50
- ],
51
- };
52
- },
53
- }));
54
-
55
- const getErrorMessage = (pkgName: string) =>
56
- `Published package has private dependency '${pkgName}'. To resolve this error, remove the private dependency or set this package to private.`;
57
-
58
- describe('test ensure-no-private-dependencies', () => {
59
- tester.run('ensure-no-private-dependencies', rule, {
60
- valid: [
61
- // Private and public dependencies are allowed in private '@af' scoped packages
62
- {
63
- code: `const foo = {
64
- "name:": "@af/test",
65
- "private": true,
66
- "dependencies": {
67
- "@af/private-pkg": "workspace:*",
68
- "@af/public-pkg": "workspace:*",
69
- "@atlassian/private-pkg": "workspace:*",
70
- "@atlassian/public-pkg": "workspace:*",
71
- "@atlassiansox/private-pkg": "workspace:*",
72
- "@atlassiansox/public-pkg": "workspace:*",
73
- "react": "root:*"
74
- }
75
- }`,
76
- filename: `${cwd}/packages/fpp/package.json`,
77
- },
78
- // Private and public dependencies are allowed in private '@atlassian' scoped packages
79
- {
80
- code: `const foo = {
81
- "name:": "@atlassian/test",
82
- "private": true,
83
- "dependencies": {
84
- "@af/private-pkg": "workspace:*",
85
- "@af/public-pkg": "workspace:*",
86
- "@atlassian/private-pkg": "workspace:*",
87
- "@atlassian/public-pkg": "workspace:*",
88
- "@atlassiansox/private-pkg": "workspace:*",
89
- "@atlassiansox/public-pkg": "workspace:*",
90
- "react": "root:*"
91
- }
92
- }`,
93
- filename: `${cwd}/packages/fpp/package.json`,
94
- },
95
- // Private dependencies are allowed in private '@atlassiansox' scoped packages
96
- {
97
- code: `const foo = {
98
- "name:": "@atlassiansox/test",
99
- "private": true,
100
- "dependencies": {
101
- "@af/private-pkg": "workspace:*",
102
- "@atlassian/private-pkg": "workspace:*",
103
- "@atlassiansox/private-pkg": "workspace:*",
104
- "react": "root:*"
105
- }
106
- }`,
107
- filename: `${cwd}/packages/foo/package.json`,
108
- },
109
- // Private and public dependencies are allowed in private '@atlassiansox' scoped packages
110
- {
111
- code: `const foo = {
112
- "name:": "@atlassiansox/test",
113
- "private": true,
114
- "dependencies": {
115
- "@af/private-pkg": "workspace:*",
116
- "@af/public-pkg": "workspace:*",
117
- "@atlassian/private-pkg": "workspace:*",
118
- "@atlassian/public-pkg": "workspace:*",
119
- "@atlassiansox/private-pkg": "workspace:*",
120
- "@atlassiansox/public-pkg": "workspace:*",
121
- "react": "root:*"
122
- }
123
- }`,
124
- filename: `${cwd}/packages/fpp/package.json`,
125
- },
126
- ],
127
- invalid: [
128
- // Disallow private dependencies in public '@atlaskit' scoped packages
129
- {
130
- code: `const foo = {
131
- "name": "@atlaskit/test",
132
- "publishConfig": { "registry": "https://pkg-registry.com" },
133
- "dependencies": {
134
- "@af/private-pkg": "workspace:*",
135
- "@atlassian/private-pkg": "workspace:*",
136
- "@atlassiansox/private-pkg": "workspace:*",
137
- "react": "root:*"
138
- }
139
- }`,
140
- filename: `${cwd}/packages/foo/package.json`,
141
- errors: [
142
- {
143
- message:
144
- "Published package has private dependency '@af/private-pkg'. To resolve this error, remove the private dependency or set this package to private.",
145
- },
146
- {
147
- message:
148
- "Published package has private dependency '@atlassian/private-pkg'. To resolve this error, remove the private dependency or set this package to private.",
149
- },
150
- {
151
- message:
152
- "Published package has private dependency '@atlassiansox/private-pkg'. To resolve this error, remove the private dependency or set this package to private.",
153
- },
154
- ],
155
- },
156
- // Disallow private dependencies in public '@atlassian' scoped packages
157
- {
158
- code: `const foo = {
159
- "name": "@atlassian/test",
160
- "publishConfig": { "registry": "https://registry.npmjs.org/" },
161
- "dependencies": {
162
- "@af/private-pkg": "workspace:*",
163
- "@atlassian/private-pkg": "workspace:*",
164
- "@atlassiansox/private-pkg": "workspace:*"
165
- }
166
- }`,
167
- filename: `${cwd}/packages/foo/package.json`,
168
- errors: [
169
- { message: getErrorMessage('@af/private-pkg') },
170
- { message: getErrorMessage('@atlassian/private-pkg') },
171
- { message: getErrorMessage('@atlassiansox/private-pkg') },
172
- ],
173
- },
174
- // Disallow private dependencies in public '@atlassiansox' scoped packages
175
- {
176
- code: `const foo = {
177
- "name": "@atlassian/test3",
178
- "publishConfig": { "registry": "https://registry.npmjs.org/" },
179
- "dependencies": {
180
- "@af/private-pkg": "workspace:*",
181
- "@atlassian/private-pkg": "workspace:*",
182
- "@atlassiansox/private-pkg": "workspace:*"
183
- }
184
- }`,
185
- filename: `${cwd}/packages/foo/package.json`,
186
- errors: [
187
- { message: getErrorMessage('@af/private-pkg') },
188
- { message: getErrorMessage('@atlassian/private-pkg') },
189
- { message: getErrorMessage('@atlassiansox/private-pkg') },
190
- ],
191
- },
192
- // Disallow private peer dependencies
193
- {
194
- code: `const foo = {
195
- "name": "@atlaskit/test",
196
- "publishConfig": { "registry": "https://registry.npmjs.org/" },
197
- "peerDependencies": {
198
- "@af/private-pkg": "workspace:*",
199
- "@atlassian/private-pkg": "workspace:*",
200
- "@atlassiansox/private-pkg": "workspace:*"
201
- }
202
- }`,
203
- filename: `${cwd}/packages/foo/package.json`,
204
- errors: [
205
- { message: getErrorMessage('@af/private-pkg') },
206
- { message: getErrorMessage('@atlassian/private-pkg') },
207
- { message: getErrorMessage('@atlassiansox/private-pkg') },
208
- ],
209
- },
210
- ],
211
- });
212
- });