@atlaskit/eslint-plugin-platform 2.7.0 → 2.7.1
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 +7 -0
- package/dist/cjs/index.js +0 -2
- package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +2 -2
- package/dist/cjs/rules/ensure-native-and-af-exports-synced/index.js +3 -0
- package/dist/cjs/rules/feature-gating/no-alias/index.js +1 -1
- package/dist/cjs/rules/util/context-compat.js +4 -2
- package/dist/es2019/index.js +0 -2
- package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +2 -2
- package/dist/es2019/rules/ensure-native-and-af-exports-synced/index.js +3 -0
- package/dist/es2019/rules/feature-gating/no-alias/index.js +1 -1
- package/dist/es2019/rules/util/context-compat.js +4 -2
- package/dist/esm/index.js +0 -2
- package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +2 -2
- package/dist/esm/rules/ensure-native-and-af-exports-synced/index.js +3 -0
- package/dist/esm/rules/feature-gating/no-alias/index.js +1 -1
- package/dist/esm/rules/util/context-compat.js +4 -2
- package/dist/types/index.d.ts +4 -6
- package/dist/types/rules/util/handle-ast-object.d.ts +1 -1
- package/dist/types-ts4.5/index.d.ts +4 -6
- package/dist/types-ts4.5/rules/util/handle-ast-object.d.ts +1 -1
- package/package.json +2 -2
- package/afm-cc/tsconfig.json +0 -24
- package/afm-jira/tsconfig.json +0 -24
- package/build/tsconfig.json +0 -17
- package/dist/cjs/rules/ensure-valid-platform-yarn-protocol-usage/index.js +0 -79
- package/dist/es2019/rules/ensure-valid-platform-yarn-protocol-usage/index.js +0 -62
- package/dist/esm/rules/ensure-valid-platform-yarn-protocol-usage/index.js +0 -75
- package/dist/types/rules/ensure-valid-platform-yarn-protocol-usage/index.d.ts +0 -3
- package/dist/types-ts4.5/rules/ensure-valid-platform-yarn-protocol-usage/index.d.ts +0 -3
- package/src/__tests__/utils/_tester.tsx +0 -26
- package/src/index.tsx +0 -254
- package/src/rules/compiled/README.md +0 -3
- package/src/rules/compiled/expand-background-shorthand/README.md +0 -23
- package/src/rules/compiled/expand-background-shorthand/__tests__/rule.test.ts +0 -160
- package/src/rules/compiled/expand-background-shorthand/index.tsx +0 -43
- package/src/rules/compiled/expand-border-shorthand/README.md +0 -51
- package/src/rules/compiled/expand-border-shorthand/__tests__/rule.test.ts +0 -211
- package/src/rules/compiled/expand-border-shorthand/index.ts +0 -103
- package/src/rules/compiled/expand-spacing-shorthand/README.md +0 -38
- package/src/rules/compiled/expand-spacing-shorthand/__tests__/rule.test.ts +0 -448
- package/src/rules/compiled/expand-spacing-shorthand/index.ts +0 -240
- package/src/rules/constants.tsx +0 -20
- package/src/rules/ensure-atlassian-team/__tests__/unit/rule.test.ts +0 -24
- package/src/rules/ensure-atlassian-team/index.ts +0 -51
- package/src/rules/ensure-critical-dependency-resolutions/__test__/unit/rule.test.tsx +0 -200
- package/src/rules/ensure-critical-dependency-resolutions/index.tsx +0 -172
- package/src/rules/ensure-feature-flag-prefix/__tests__/unit/rule.test.tsx +0 -65
- package/src/rules/ensure-feature-flag-prefix/index.tsx +0 -81
- package/src/rules/ensure-feature-flag-registration/__tests__/unit/rule.test.tsx +0 -115
- package/src/rules/ensure-feature-flag-registration/index.tsx +0 -106
- package/src/rules/ensure-native-and-af-exports-synced/__tests__/unit/rule.test.tsx +0 -199
- package/src/rules/ensure-native-and-af-exports-synced/index.tsx +0 -188
- package/src/rules/ensure-no-private-dependencies/__tests__/unit/rule.test.ts +0 -212
- package/src/rules/ensure-no-private-dependencies/index.ts +0 -64
- package/src/rules/ensure-publish-valid/__tests__/unit/rule.test.ts +0 -39
- package/src/rules/ensure-publish-valid/index.ts +0 -81
- package/src/rules/ensure-test-runner-arguments/__tests__/unit/rule.test.tsx +0 -298
- package/src/rules/ensure-test-runner-arguments/index.tsx +0 -121
- package/src/rules/ensure-test-runner-nested-count/__tests__/unit/rule.test.tsx +0 -308
- package/src/rules/ensure-test-runner-nested-count/index.tsx +0 -82
- package/src/rules/ensure-valid-bin-values/__tests__/unit/rule.test.ts +0 -159
- package/src/rules/ensure-valid-bin-values/index.ts +0 -70
- package/src/rules/ensure-valid-platform-yarn-protocol-usage/__tests__/unit/rule.test.ts +0 -147
- package/src/rules/ensure-valid-platform-yarn-protocol-usage/index.ts +0 -67
- package/src/rules/feature-gating/README.md +0 -8
- package/src/rules/feature-gating/inline-usage/README.md +0 -53
- package/src/rules/feature-gating/inline-usage/__tests__/rule.test.tsx +0 -106
- package/src/rules/feature-gating/inline-usage/index.tsx +0 -135
- package/src/rules/feature-gating/no-alias/README.md +0 -29
- package/src/rules/feature-gating/no-alias/__tests__/rule.test.tsx +0 -76
- package/src/rules/feature-gating/no-alias/index.tsx +0 -80
- package/src/rules/feature-gating/no-module-level-eval/README.md +0 -53
- package/src/rules/feature-gating/no-module-level-eval/__tests__/test.tsx +0 -133
- package/src/rules/feature-gating/no-module-level-eval/index.tsx +0 -54
- package/src/rules/feature-gating/no-module-level-eval-nav4/README.md +0 -8
- package/src/rules/feature-gating/no-module-level-eval-nav4/__tests__/test.tsx +0 -130
- package/src/rules/feature-gating/no-module-level-eval-nav4/index.tsx +0 -73
- package/src/rules/feature-gating/no-preconditioning/README.md +0 -69
- package/src/rules/feature-gating/no-preconditioning/__tests__/rule.test.tsx +0 -164
- package/src/rules/feature-gating/no-preconditioning/index.tsx +0 -138
- package/src/rules/feature-gating/prefer-fg/README.md +0 -3
- package/src/rules/feature-gating/prefer-fg/__tests__/rule.test.tsx +0 -83
- package/src/rules/feature-gating/prefer-fg/index.tsx +0 -110
- package/src/rules/feature-gating/static-feature-flags/README.md +0 -3
- package/src/rules/feature-gating/static-feature-flags/__tests__/test.tsx +0 -135
- package/src/rules/feature-gating/static-feature-flags/index.tsx +0 -103
- package/src/rules/feature-gating/use-recommended-utils/README.md +0 -67
- package/src/rules/feature-gating/use-recommended-utils/__tests__/rule.test.tsx +0 -78
- package/src/rules/feature-gating/use-recommended-utils/index.tsx +0 -57
- package/src/rules/feature-gating/utils.tsx +0 -48
- package/src/rules/no-direct-document-usage/index.tsx +0 -111
- package/src/rules/no-duplicate-dependencies/__tests__/unit/rule.test.ts +0 -116
- package/src/rules/no-duplicate-dependencies/index.ts +0 -79
- package/src/rules/no-invalid-feature-flag-usage/__tests__/unit/rule.test.tsx +0 -69
- package/src/rules/no-invalid-feature-flag-usage/index.tsx +0 -128
- package/src/rules/no-invalid-storybook-decorator-usage/__tests__/unit/rule.test.tsx +0 -18
- package/src/rules/no-invalid-storybook-decorator-usage/index.tsx +0 -39
- package/src/rules/no-pre-post-installs/__tests__/unit/rule.test.ts +0 -41
- package/src/rules/no-pre-post-installs/index.ts +0 -35
- package/src/rules/no-set-immediate/index.tsx +0 -43
- package/src/rules/no-sparse-checkout/__tests__/unit/rule.test.tsx +0 -48
- package/src/rules/no-sparse-checkout/index.tsx +0 -54
- package/src/rules/use-entrypoints-in-examples/README.md +0 -27
- package/src/rules/use-entrypoints-in-examples/__tests__/rule.test.tsx +0 -34
- package/src/rules/use-entrypoints-in-examples/index.tsx +0 -43
- package/src/rules/util/__tests__/context-compat.test.ts +0 -122
- package/src/rules/util/compiled-utils.ts +0 -27
- package/src/rules/util/context-compat.ts +0 -41
- package/src/rules/util/file-exclusions.ts +0 -39
- package/src/rules/util/handle-ast-object.ts +0 -33
- package/src/rules/util/registration-utils.ts +0 -59
- package/tsconfig.app.json +0 -43
- package/tsconfig.dev.json +0 -40
- package/tsconfig.json +0 -23
|
@@ -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
|
-
});
|