@atlaskit/eslint-plugin-platform 0.2.5 → 0.3.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 (47) hide show
  1. package/CHANGELOG.md +33 -21
  2. package/dist/cjs/index.js +28 -11
  3. package/dist/cjs/rules/ensure-atlassian-team/index.js +1 -2
  4. package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +86 -0
  5. package/dist/cjs/rules/ensure-feature-flag-prefix/index.js +1 -2
  6. package/dist/cjs/rules/ensure-feature-flag-registration/index.js +3 -4
  7. package/dist/cjs/rules/ensure-publish-valid/index.js +5 -29
  8. package/dist/cjs/rules/ensure-test-runner-arguments/index.js +1 -2
  9. package/dist/cjs/rules/ensure-test-runner-nested-count/index.js +3 -4
  10. package/dist/cjs/rules/no-duplicate-dependencies/index.js +90 -0
  11. package/dist/cjs/rules/no-invalid-feature-flag-usage/index.js +1 -2
  12. package/dist/cjs/rules/no-invalid-storybook-decorator-usage/index.js +1 -2
  13. package/dist/cjs/rules/no-pre-post-installs/index.js +1 -2
  14. package/dist/cjs/rules/util/handle-ast-object.js +30 -0
  15. package/dist/cjs/rules/util/registration-utils.js +3 -5
  16. package/dist/es2019/index.js +25 -2
  17. package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +64 -0
  18. package/dist/es2019/rules/ensure-publish-valid/index.js +1 -20
  19. package/dist/es2019/rules/no-duplicate-dependencies/index.js +65 -0
  20. package/dist/es2019/rules/util/handle-ast-object.js +20 -0
  21. package/dist/esm/index.js +24 -4
  22. package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +80 -0
  23. package/dist/esm/rules/ensure-feature-flag-registration/index.js +2 -2
  24. package/dist/esm/rules/ensure-publish-valid/index.js +1 -24
  25. package/dist/esm/rules/ensure-test-runner-nested-count/index.js +2 -2
  26. package/dist/esm/rules/no-duplicate-dependencies/index.js +83 -0
  27. package/dist/esm/rules/util/handle-ast-object.js +24 -0
  28. package/dist/types/index.d.ts +2 -0
  29. package/dist/types/rules/ensure-critical-dependency-resolutions/index.d.ts +3 -0
  30. package/dist/types/rules/no-duplicate-dependencies/index.d.ts +3 -0
  31. package/dist/types/rules/util/handle-ast-object.d.ts +3 -0
  32. package/dist/types-ts4.5/index.d.ts +2 -0
  33. package/dist/types-ts4.5/rules/ensure-critical-dependency-resolutions/index.d.ts +3 -0
  34. package/dist/types-ts4.5/rules/no-duplicate-dependencies/index.d.ts +3 -0
  35. package/dist/types-ts4.5/rules/util/handle-ast-object.d.ts +3 -0
  36. package/package.json +3 -2
  37. package/report.api.md +2 -0
  38. package/src/index.tsx +26 -4
  39. package/src/rules/ensure-critical-dependency-resolutions/__test__/unit/rule.test.tsx +125 -0
  40. package/src/rules/ensure-critical-dependency-resolutions/index.tsx +113 -0
  41. package/src/rules/ensure-publish-valid/index.ts +4 -43
  42. package/src/rules/no-duplicate-dependencies/__tests__/unit/rule.test.ts +116 -0
  43. package/src/rules/no-duplicate-dependencies/index.ts +83 -0
  44. package/src/rules/util/handle-ast-object.ts +44 -0
  45. package/tmp/api-report-tmp.d.ts +2 -0
  46. package/tsconfig.app.json +36 -0
  47. package/tsconfig.dev.json +40 -0
@@ -3,8 +3,10 @@ import noPreAndPostInstallScripts from './rules/no-pre-post-installs';
3
3
  import ensureTestRunnerArguments from './rules/ensure-test-runner-arguments';
4
4
  import ensureTestRunnerNestedCount from './rules/ensure-test-runner-nested-count';
5
5
  import ensureAtlassianTeam from './rules/ensure-atlassian-team';
6
+ import noDuplicateDependencies from './rules/no-duplicate-dependencies';
6
7
  import noInvalidFeatureFlagUsage from './rules/no-invalid-feature-flag-usage';
7
8
  import ensureFeatureFlagPrefix from './rules/ensure-feature-flag-prefix';
9
+ import ensureCriticalDependencyResolutions from './rules/ensure-critical-dependency-resolutions';
8
10
  import noInvalidStorybookDecoratorUsage from './rules/no-invalid-storybook-decorator-usage';
9
11
  import ensurePublishValid from './rules/ensure-publish-valid';
10
12
  export const rules = {
@@ -13,6 +15,8 @@ export const rules = {
13
15
  'ensure-test-runner-arguments': ensureTestRunnerArguments,
14
16
  'ensure-test-runner-nested-count': ensureTestRunnerNestedCount,
15
17
  'ensure-atlassian-team': ensureAtlassianTeam,
18
+ 'ensure-critical-dependency-resolutions': ensureCriticalDependencyResolutions,
19
+ 'no-duplicate-dependencies': noDuplicateDependencies,
16
20
  'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
17
21
  'no-pre-post-install-scripts': noPreAndPostInstallScripts,
18
22
  'no-invalid-storybook-decorator-usage': noInvalidStorybookDecoratorUsage,
@@ -34,12 +38,31 @@ export const configs = {
34
38
  }
35
39
  }
36
40
  };
41
+ const jsonPrefix = '/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ';
37
42
  export const processors = {
38
43
  'package-json-processor': {
39
44
  preprocess: source => {
40
45
  // augment the json into a js file
41
- return [`/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ${source.trim()}`];
46
+ return [jsonPrefix + source.trim()];
42
47
  },
43
- postprocess: errors => errors[0]
48
+ postprocess: messages => {
49
+ return messages[0].map(message => {
50
+ const {
51
+ fix
52
+ } = message;
53
+ if (!fix) {
54
+ return message;
55
+ }
56
+ const offset = jsonPrefix.length;
57
+ return {
58
+ ...message,
59
+ fix: {
60
+ ...fix,
61
+ range: [fix.range[0] - offset, fix.range[1] - offset]
62
+ }
63
+ };
64
+ });
65
+ },
66
+ supportsAutofix: true
44
67
  }
45
68
  };
@@ -0,0 +1,64 @@
1
+ import { findRootSync } from '@manypkg/find-root';
2
+ import { getObjectPropertyAsObject } from '../util/handle-ast-object';
3
+
4
+ // Here we only need to specify the major and minor versions
5
+ // In matchMinorVersion, we will check if the versions in resolutions fall in the right ranges.
6
+ const DESIRED_PKG_VERSIONS = {
7
+ typescript: '4.9',
8
+ '@types/react': '16.14'
9
+ };
10
+ const matchMinorVersion = (desiredVersion, versionInResolutions) => {
11
+ const firstChar = versionInResolutions[0];
12
+ // The version is invalid if it doesn't start with a number or ~
13
+ if (!/^\d$/.test(firstChar) && firstChar !== '~') {
14
+ return false;
15
+ }
16
+ return versionInResolutions.startsWith(desiredVersion) || versionInResolutions.startsWith('~' + desiredVersion);
17
+ };
18
+ const verifyResolutionFromObject = (node, pkg, version, optional) => {
19
+ // For root package.json, we require the critical packages' resolutions exist and with matching version
20
+ // For individual package's package.json, it's ok if resolutions don't exist. But if they do, the version should match
21
+ const resolutionExist = node.properties.some(p => p.type === 'Property' && p.key.type === 'Literal' && p.key.value === pkg);
22
+ if (!resolutionExist) {
23
+ return optional;
24
+ }
25
+ const resolutionExistAndMatch = node.properties.some(p => p.type === 'Property' && p.key.type === 'Literal' && p.key.value === pkg && p.value.type === 'Literal' && matchMinorVersion(version, p.value.value));
26
+ return resolutionExistAndMatch;
27
+ };
28
+ const rule = {
29
+ meta: {
30
+ type: 'problem',
31
+ docs: {
32
+ description: 'Enforce the versions of critical packages are within desired ranges by checking resolutions section in package.json',
33
+ recommended: true
34
+ },
35
+ hasSuggestions: false,
36
+ messages: {
37
+ invalidPackageResolution: `Make sure the resolutions for the following packages match major and minor version ranges ${JSON.stringify(DESIRED_PKG_VERSIONS)}`
38
+ }
39
+ },
40
+ create(context) {
41
+ const fileName = context.getFilename();
42
+ return {
43
+ ObjectExpression: node => {
44
+ if (!fileName.endsWith('package.json') || node.type !== 'ObjectExpression') {
45
+ return;
46
+ }
47
+ const packageResolutions = getObjectPropertyAsObject(node, 'resolutions');
48
+ const rootDir = findRootSync(process.cwd());
49
+ const isRootPackageJson = fileName.endsWith(`${rootDir}/package.json`);
50
+ if (packageResolutions !== null) {
51
+ for (const [key, value] of Object.entries(DESIRED_PKG_VERSIONS)) {
52
+ if (!verifyResolutionFromObject(packageResolutions, key, value, !isRootPackageJson)) {
53
+ return context.report({
54
+ node,
55
+ messageId: 'invalidPackageResolution'
56
+ });
57
+ }
58
+ }
59
+ }
60
+ }
61
+ };
62
+ }
63
+ };
64
+ export default rule;
@@ -1,23 +1,4 @@
1
- const getObjectPropertyAsLiteral = (node, property) => {
2
- const prop = node.properties.find(p => p.type === 'Property' && p.key.type === 'Literal' && p.key.value === property);
3
-
4
- // double check for property is to make typescript happy
5
- if ((prop === null || prop === void 0 ? void 0 : prop.type) === 'Property' && (prop === null || prop === void 0 ? void 0 : prop.value.type) === 'Literal') {
6
- var _prop$value$value;
7
- return (_prop$value$value = prop.value.value) !== null && _prop$value$value !== void 0 ? _prop$value$value : null;
8
- }
9
- return null;
10
- };
11
- const getObjectPropertyAsObject = (node, property) => {
12
- const prop = node.properties.find(p => p.type === 'Property' && p.key.type === 'Literal' && p.key.value === property);
13
-
14
- // double check for property is to make typescript happy
15
- if ((prop === null || prop === void 0 ? void 0 : prop.type) === 'Property' && (prop === null || prop === void 0 ? void 0 : prop.value.type) === 'ObjectExpression') {
16
- var _prop$value;
17
- return (_prop$value = prop.value) !== null && _prop$value !== void 0 ? _prop$value : null;
18
- }
19
- return null;
20
- };
1
+ import { getObjectPropertyAsLiteral, getObjectPropertyAsObject } from '../util/handle-ast-object';
21
2
  const rule = {
22
3
  meta: {
23
4
  type: 'problem',
@@ -0,0 +1,65 @@
1
+ const rule = {
2
+ meta: {
3
+ type: 'problem',
4
+ docs: {
5
+ description: 'This rule disallows a dependency to be defined in both dependencies and devDependencies',
6
+ recommended: false
7
+ },
8
+ fixable: 'code',
9
+ messages: {
10
+ unexpectedDuplicateDependency: 'Unexpected duplicate dependency {{name}}'
11
+ }
12
+ },
13
+ create(context) {
14
+ const dependencies = new Map();
15
+ const devDependencies = new Map();
16
+ return {
17
+ 'ObjectExpression Property[key.value=dependencies] Property': node => {
18
+ // @ts-expect-error
19
+ dependencies.set(node.key.value, node.key);
20
+ },
21
+ 'ObjectExpression Property[key.value=devDependencies] Property': node => {
22
+ // @ts-expect-error
23
+ devDependencies.set(node.key.value, node.key);
24
+ },
25
+ 'Program:exit': () => {
26
+ for (const [dependency, node] of devDependencies) {
27
+ if (dependencies.has(dependency)) {
28
+ context.report({
29
+ data: {
30
+ name: dependency
31
+ },
32
+ fix(fixer) {
33
+ var _sourceCode$getTokenA;
34
+ const sourceCode = context.getSourceCode();
35
+ const property = node.parent;
36
+ const isLastLine = ((_sourceCode$getTokenA = sourceCode.getTokenAfter(property)) === null || _sourceCode$getTokenA === void 0 ? void 0 : _sourceCode$getTokenA.value) === '}';
37
+ const end = property.loc.end;
38
+ if (!isLastLine) {
39
+ return fixer.removeRange([sourceCode.getIndexFromLoc({
40
+ line: property.loc.start.line,
41
+ column: 0
42
+ }), sourceCode.getIndexFromLoc({
43
+ line: end.line + 1,
44
+ column: 0
45
+ })]);
46
+ }
47
+ const previousToken = sourceCode.getTokenBefore(property);
48
+ return fixer.removeRange([sourceCode.getIndexFromLoc({
49
+ line: previousToken.loc.end.line,
50
+ column: previousToken.loc.end.column - 1
51
+ }), sourceCode.getIndexFromLoc({
52
+ line: end.line,
53
+ column: end.column
54
+ })]);
55
+ },
56
+ messageId: 'unexpectedDuplicateDependency',
57
+ node
58
+ });
59
+ }
60
+ }
61
+ }
62
+ };
63
+ }
64
+ };
65
+ export default rule;
@@ -0,0 +1,20 @@
1
+ export const getObjectPropertyAsLiteral = (node, property) => {
2
+ const prop = node.properties.find(p => p.type === 'Property' && p.key.type === 'Literal' && p.key.value === property);
3
+
4
+ // double check for property is to make typescript happy
5
+ if ((prop === null || prop === void 0 ? void 0 : prop.type) === 'Property' && (prop === null || prop === void 0 ? void 0 : prop.value.type) === 'Literal') {
6
+ var _prop$value$value;
7
+ return (_prop$value$value = prop.value.value) !== null && _prop$value$value !== void 0 ? _prop$value$value : null;
8
+ }
9
+ return null;
10
+ };
11
+ export const getObjectPropertyAsObject = (node, property) => {
12
+ const prop = node.properties.find(p => p.type === 'Property' && p.key.type === 'Literal' && p.key.value === property);
13
+
14
+ // double check for property is to make typescript happy
15
+ if ((prop === null || prop === void 0 ? void 0 : prop.type) === 'Property' && (prop === null || prop === void 0 ? void 0 : prop.value.type) === 'ObjectExpression') {
16
+ var _prop$value;
17
+ return (_prop$value = prop.value) !== null && _prop$value !== void 0 ? _prop$value : null;
18
+ }
19
+ return null;
20
+ };
package/dist/esm/index.js CHANGED
@@ -1,10 +1,15 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
1
4
  import ensureFeatureFlagRegistration from './rules/ensure-feature-flag-registration';
2
5
  import noPreAndPostInstallScripts from './rules/no-pre-post-installs';
3
6
  import ensureTestRunnerArguments from './rules/ensure-test-runner-arguments';
4
7
  import ensureTestRunnerNestedCount from './rules/ensure-test-runner-nested-count';
5
8
  import ensureAtlassianTeam from './rules/ensure-atlassian-team';
9
+ import noDuplicateDependencies from './rules/no-duplicate-dependencies';
6
10
  import noInvalidFeatureFlagUsage from './rules/no-invalid-feature-flag-usage';
7
11
  import ensureFeatureFlagPrefix from './rules/ensure-feature-flag-prefix';
12
+ import ensureCriticalDependencyResolutions from './rules/ensure-critical-dependency-resolutions';
8
13
  import noInvalidStorybookDecoratorUsage from './rules/no-invalid-storybook-decorator-usage';
9
14
  import ensurePublishValid from './rules/ensure-publish-valid';
10
15
  export var rules = {
@@ -13,6 +18,8 @@ export var rules = {
13
18
  'ensure-test-runner-arguments': ensureTestRunnerArguments,
14
19
  'ensure-test-runner-nested-count': ensureTestRunnerNestedCount,
15
20
  'ensure-atlassian-team': ensureAtlassianTeam,
21
+ 'ensure-critical-dependency-resolutions': ensureCriticalDependencyResolutions,
22
+ 'no-duplicate-dependencies': noDuplicateDependencies,
16
23
  'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
17
24
  'no-pre-post-install-scripts': noPreAndPostInstallScripts,
18
25
  'no-invalid-storybook-decorator-usage': noInvalidStorybookDecoratorUsage,
@@ -34,14 +41,27 @@ export var configs = {
34
41
  }
35
42
  }
36
43
  };
44
+ var jsonPrefix = '/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ';
37
45
  export var processors = {
38
46
  'package-json-processor': {
39
47
  preprocess: function preprocess(source) {
40
48
  // augment the json into a js file
41
- return ["/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ".concat(source.trim())];
49
+ return [jsonPrefix + source.trim()];
42
50
  },
43
- postprocess: function postprocess(errors) {
44
- return errors[0];
45
- }
51
+ postprocess: function postprocess(messages) {
52
+ return messages[0].map(function (message) {
53
+ var fix = message.fix;
54
+ if (!fix) {
55
+ return message;
56
+ }
57
+ var offset = jsonPrefix.length;
58
+ return _objectSpread(_objectSpread({}, message), {}, {
59
+ fix: _objectSpread(_objectSpread({}, fix), {}, {
60
+ range: [fix.range[0] - offset, fix.range[1] - offset]
61
+ })
62
+ });
63
+ });
64
+ },
65
+ supportsAutofix: true
46
66
  }
47
67
  };
@@ -0,0 +1,80 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { findRootSync } from '@manypkg/find-root';
3
+ import { getObjectPropertyAsObject } from '../util/handle-ast-object';
4
+
5
+ // Here we only need to specify the major and minor versions
6
+ // In matchMinorVersion, we will check if the versions in resolutions fall in the right ranges.
7
+ var DESIRED_PKG_VERSIONS = {
8
+ typescript: '4.9',
9
+ '@types/react': '16.14'
10
+ };
11
+ var matchMinorVersion = function matchMinorVersion(desiredVersion, versionInResolutions) {
12
+ var firstChar = versionInResolutions[0];
13
+ // The version is invalid if it doesn't start with a number or ~
14
+ if (!/^\d$/.test(firstChar) && firstChar !== '~') {
15
+ return false;
16
+ }
17
+ return versionInResolutions.startsWith(desiredVersion) || versionInResolutions.startsWith('~' + desiredVersion);
18
+ };
19
+ var verifyResolutionFromObject = function verifyResolutionFromObject(node, pkg, version, optional) {
20
+ // For root package.json, we require the critical packages' resolutions exist and with matching version
21
+ // For individual package's package.json, it's ok if resolutions don't exist. But if they do, the version should match
22
+ var resolutionExist = node.properties.some(function (p) {
23
+ return p.type === 'Property' && p.key.type === 'Literal' && p.key.value === pkg;
24
+ });
25
+ if (!resolutionExist) {
26
+ return optional;
27
+ }
28
+ var resolutionExistAndMatch = node.properties.some(function (p) {
29
+ return p.type === 'Property' && p.key.type === 'Literal' && p.key.value === pkg && p.value.type === 'Literal' && matchMinorVersion(version, p.value.value);
30
+ });
31
+ return resolutionExistAndMatch;
32
+ };
33
+ var rule = {
34
+ meta: {
35
+ type: 'problem',
36
+ docs: {
37
+ description: 'Enforce the versions of critical packages are within desired ranges by checking resolutions section in package.json',
38
+ recommended: true
39
+ },
40
+ hasSuggestions: false,
41
+ messages: {
42
+ invalidPackageResolution: "Make sure the resolutions for the following packages match major and minor version ranges ".concat(JSON.stringify(DESIRED_PKG_VERSIONS))
43
+ }
44
+ },
45
+ create: function create(context) {
46
+ var fileName = context.getFilename();
47
+ return {
48
+ ObjectExpression: function (_ObjectExpression) {
49
+ function ObjectExpression(_x) {
50
+ return _ObjectExpression.apply(this, arguments);
51
+ }
52
+ ObjectExpression.toString = function () {
53
+ return _ObjectExpression.toString();
54
+ };
55
+ return ObjectExpression;
56
+ }(function (node) {
57
+ if (!fileName.endsWith('package.json') || node.type !== 'ObjectExpression') {
58
+ return;
59
+ }
60
+ var packageResolutions = getObjectPropertyAsObject(node, 'resolutions');
61
+ var rootDir = findRootSync(process.cwd());
62
+ var isRootPackageJson = fileName.endsWith("".concat(rootDir, "/package.json"));
63
+ if (packageResolutions !== null) {
64
+ for (var _i = 0, _Object$entries = Object.entries(DESIRED_PKG_VERSIONS); _i < _Object$entries.length; _i++) {
65
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
66
+ key = _Object$entries$_i[0],
67
+ value = _Object$entries$_i[1];
68
+ if (!verifyResolutionFromObject(packageResolutions, key, value, !isRootPackageJson)) {
69
+ return context.report({
70
+ node: node,
71
+ messageId: 'invalidPackageResolution'
72
+ });
73
+ }
74
+ }
75
+ }
76
+ })
77
+ };
78
+ }
79
+ };
80
+ export default rule;
@@ -1,6 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
3
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
5
5
  var rule = {
6
6
  meta: {
@@ -1,27 +1,4 @@
1
- var getObjectPropertyAsLiteral = function getObjectPropertyAsLiteral(node, property) {
2
- var prop = node.properties.find(function (p) {
3
- return p.type === 'Property' && p.key.type === 'Literal' && p.key.value === property;
4
- });
5
-
6
- // double check for property is to make typescript happy
7
- if ((prop === null || prop === void 0 ? void 0 : prop.type) === 'Property' && (prop === null || prop === void 0 ? void 0 : prop.value.type) === 'Literal') {
8
- var _prop$value$value;
9
- return (_prop$value$value = prop.value.value) !== null && _prop$value$value !== void 0 ? _prop$value$value : null;
10
- }
11
- return null;
12
- };
13
- var getObjectPropertyAsObject = function getObjectPropertyAsObject(node, property) {
14
- var prop = node.properties.find(function (p) {
15
- return p.type === 'Property' && p.key.type === 'Literal' && p.key.value === property;
16
- });
17
-
18
- // double check for property is to make typescript happy
19
- if ((prop === null || prop === void 0 ? void 0 : prop.type) === 'Property' && (prop === null || prop === void 0 ? void 0 : prop.value.type) === 'ObjectExpression') {
20
- var _prop$value;
21
- return (_prop$value = prop.value) !== null && _prop$value !== void 0 ? _prop$value : null;
22
- }
23
- return null;
24
- };
1
+ import { getObjectPropertyAsLiteral, getObjectPropertyAsObject } from '../util/handle-ast-object';
25
2
  var rule = {
26
3
  meta: {
27
4
  type: 'problem',
@@ -1,6 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
- function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
3
- function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
2
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
3
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
4
4
  var NESTED_LIMIT = 4;
5
5
  var TEST_RUNNER_IDENTIFIER = 'ffTest';
6
6
  var getDepthOfNestedRunner = function getDepthOfNestedRunner(node) {
@@ -0,0 +1,83 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
3
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
4
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
5
+ var rule = {
6
+ meta: {
7
+ type: 'problem',
8
+ docs: {
9
+ description: 'This rule disallows a dependency to be defined in both dependencies and devDependencies',
10
+ recommended: false
11
+ },
12
+ fixable: 'code',
13
+ messages: {
14
+ unexpectedDuplicateDependency: 'Unexpected duplicate dependency {{name}}'
15
+ }
16
+ },
17
+ create: function create(context) {
18
+ var dependencies = new Map();
19
+ var devDependencies = new Map();
20
+ return {
21
+ 'ObjectExpression Property[key.value=dependencies] Property': function ObjectExpressionPropertyKeyValueDependenciesProperty(node) {
22
+ // @ts-expect-error
23
+ dependencies.set(node.key.value, node.key);
24
+ },
25
+ 'ObjectExpression Property[key.value=devDependencies] Property': function ObjectExpressionPropertyKeyValueDevDependenciesProperty(node) {
26
+ // @ts-expect-error
27
+ devDependencies.set(node.key.value, node.key);
28
+ },
29
+ 'Program:exit': function ProgramExit() {
30
+ var _iterator = _createForOfIteratorHelper(devDependencies),
31
+ _step;
32
+ try {
33
+ var _loop = function _loop() {
34
+ var _step$value = _slicedToArray(_step.value, 2),
35
+ dependency = _step$value[0],
36
+ node = _step$value[1];
37
+ if (dependencies.has(dependency)) {
38
+ context.report({
39
+ data: {
40
+ name: dependency
41
+ },
42
+ fix: function fix(fixer) {
43
+ var _sourceCode$getTokenA;
44
+ var sourceCode = context.getSourceCode();
45
+ var property = node.parent;
46
+ var isLastLine = ((_sourceCode$getTokenA = sourceCode.getTokenAfter(property)) === null || _sourceCode$getTokenA === void 0 ? void 0 : _sourceCode$getTokenA.value) === '}';
47
+ var end = property.loc.end;
48
+ if (!isLastLine) {
49
+ return fixer.removeRange([sourceCode.getIndexFromLoc({
50
+ line: property.loc.start.line,
51
+ column: 0
52
+ }), sourceCode.getIndexFromLoc({
53
+ line: end.line + 1,
54
+ column: 0
55
+ })]);
56
+ }
57
+ var previousToken = sourceCode.getTokenBefore(property);
58
+ return fixer.removeRange([sourceCode.getIndexFromLoc({
59
+ line: previousToken.loc.end.line,
60
+ column: previousToken.loc.end.column - 1
61
+ }), sourceCode.getIndexFromLoc({
62
+ line: end.line,
63
+ column: end.column
64
+ })]);
65
+ },
66
+ messageId: 'unexpectedDuplicateDependency',
67
+ node: node
68
+ });
69
+ }
70
+ };
71
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
72
+ _loop();
73
+ }
74
+ } catch (err) {
75
+ _iterator.e(err);
76
+ } finally {
77
+ _iterator.f();
78
+ }
79
+ }
80
+ };
81
+ }
82
+ };
83
+ export default rule;
@@ -0,0 +1,24 @@
1
+ export var getObjectPropertyAsLiteral = function getObjectPropertyAsLiteral(node, property) {
2
+ var prop = node.properties.find(function (p) {
3
+ return p.type === 'Property' && p.key.type === 'Literal' && p.key.value === property;
4
+ });
5
+
6
+ // double check for property is to make typescript happy
7
+ if ((prop === null || prop === void 0 ? void 0 : prop.type) === 'Property' && (prop === null || prop === void 0 ? void 0 : prop.value.type) === 'Literal') {
8
+ var _prop$value$value;
9
+ return (_prop$value$value = prop.value.value) !== null && _prop$value$value !== void 0 ? _prop$value$value : null;
10
+ }
11
+ return null;
12
+ };
13
+ export var getObjectPropertyAsObject = function getObjectPropertyAsObject(node, property) {
14
+ var prop = node.properties.find(function (p) {
15
+ return p.type === 'Property' && p.key.type === 'Literal' && p.key.value === property;
16
+ });
17
+
18
+ // double check for property is to make typescript happy
19
+ if ((prop === null || prop === void 0 ? void 0 : prop.type) === 'Property' && (prop === null || prop === void 0 ? void 0 : prop.value.type) === 'ObjectExpression') {
20
+ var _prop$value;
21
+ return (_prop$value = prop.value) !== null && _prop$value !== void 0 ? _prop$value : null;
22
+ }
23
+ return null;
24
+ };
@@ -5,6 +5,8 @@ export declare const rules: {
5
5
  'ensure-test-runner-arguments': import("eslint").Rule.RuleModule;
6
6
  'ensure-test-runner-nested-count': import("eslint").Rule.RuleModule;
7
7
  'ensure-atlassian-team': import("eslint").Rule.RuleModule;
8
+ 'ensure-critical-dependency-resolutions': import("eslint").Rule.RuleModule;
9
+ 'no-duplicate-dependencies': import("eslint").Rule.RuleModule;
8
10
  'no-invalid-feature-flag-usage': import("eslint").Rule.RuleModule;
9
11
  'no-pre-post-install-scripts': import("eslint").Rule.RuleModule;
10
12
  'no-invalid-storybook-decorator-usage': import("eslint").Rule.RuleModule;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const rule: Rule.RuleModule;
3
+ export default rule;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const rule: Rule.RuleModule;
3
+ export default rule;
@@ -0,0 +1,3 @@
1
+ import type { ObjectExpression, SimpleLiteral, RegExpLiteral, BigIntLiteral } from 'estree';
2
+ export declare const getObjectPropertyAsLiteral: (node: ObjectExpression, property: string) => SimpleLiteral['value'] | RegExpLiteral['value'] | BigIntLiteral['value'];
3
+ export declare const getObjectPropertyAsObject: (node: ObjectExpression, property: string) => ObjectExpression | null;
@@ -5,6 +5,8 @@ export declare const rules: {
5
5
  'ensure-test-runner-arguments': import("eslint").Rule.RuleModule;
6
6
  'ensure-test-runner-nested-count': import("eslint").Rule.RuleModule;
7
7
  'ensure-atlassian-team': import("eslint").Rule.RuleModule;
8
+ 'ensure-critical-dependency-resolutions': import("eslint").Rule.RuleModule;
9
+ 'no-duplicate-dependencies': import("eslint").Rule.RuleModule;
8
10
  'no-invalid-feature-flag-usage': import("eslint").Rule.RuleModule;
9
11
  'no-pre-post-install-scripts': import("eslint").Rule.RuleModule;
10
12
  'no-invalid-storybook-decorator-usage': import("eslint").Rule.RuleModule;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const rule: Rule.RuleModule;
3
+ export default rule;
@@ -0,0 +1,3 @@
1
+ import type { Rule } from 'eslint';
2
+ declare const rule: Rule.RuleModule;
3
+ export default rule;
@@ -0,0 +1,3 @@
1
+ import type { ObjectExpression, SimpleLiteral, RegExpLiteral, BigIntLiteral } from 'estree';
2
+ export declare const getObjectPropertyAsLiteral: (node: ObjectExpression, property: string) => SimpleLiteral['value'] | RegExpLiteral['value'] | BigIntLiteral['value'];
3
+ export declare const getObjectPropertyAsObject: (node: ObjectExpression, property: string) => ObjectExpression | null;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-platform",
3
3
  "description": "The essential plugin for use with Atlassian frontend platform tools",
4
- "version": "0.2.5",
4
+ "version": "0.3.0",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "atlassian": {
7
7
  "team": "UIP - Platform Integration Trust (PITa)",
@@ -31,13 +31,14 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@babel/runtime": "^7.0.0",
34
+ "@manypkg/find-root": "^1.1.0",
34
35
  "fuse.js": "^6.6.2",
35
36
  "read-pkg-up": "^7.0.1"
36
37
  },
37
38
  "devDependencies": {
38
39
  "@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",
39
40
  "eslint": "^7.7.0",
40
- "tsconfig-paths": "^3.9.0"
41
+ "tsconfig-paths": "^4.2.0"
41
42
  },
42
43
  "prettier": "@atlassian/atlassian-frontend-prettier-config-1.0.1"
43
44
  }
package/report.api.md CHANGED
@@ -51,6 +51,8 @@ export const rules: {
51
51
  'ensure-test-runner-arguments': Rule.RuleModule;
52
52
  'ensure-test-runner-nested-count': Rule.RuleModule;
53
53
  'ensure-atlassian-team': Rule.RuleModule;
54
+ 'ensure-critical-dependency-resolutions': Rule.RuleModule;
55
+ 'no-duplicate-dependencies': Rule.RuleModule;
54
56
  'no-invalid-feature-flag-usage': Rule.RuleModule;
55
57
  'no-pre-post-install-scripts': Rule.RuleModule;
56
58
  'no-invalid-storybook-decorator-usage': Rule.RuleModule;