@atlaskit/eslint-plugin-platform 0.2.6 → 0.4.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 (62) hide show
  1. package/CHANGELOG.md +34 -22
  2. package/dist/cjs/index.js +26 -11
  3. package/dist/cjs/rules/ensure-atlassian-team/index.js +3 -2
  4. package/dist/cjs/rules/ensure-critical-dependency-resolutions/index.js +23 -13
  5. package/dist/cjs/rules/ensure-feature-flag-prefix/index.js +3 -2
  6. package/dist/cjs/rules/ensure-feature-flag-registration/index.js +2 -3
  7. package/dist/cjs/rules/ensure-publish-valid/index.js +3 -2
  8. package/dist/cjs/rules/ensure-test-runner-arguments/index.js +3 -2
  9. package/dist/cjs/rules/ensure-test-runner-nested-count/index.js +3 -2
  10. package/dist/cjs/rules/no-duplicate-dependencies/index.js +92 -0
  11. package/dist/cjs/rules/no-invalid-feature-flag-usage/index.js +3 -2
  12. package/dist/cjs/rules/no-invalid-storybook-decorator-usage/index.js +3 -2
  13. package/dist/cjs/rules/no-pre-post-installs/index.js +3 -2
  14. package/dist/cjs/rules/util/handle-ast-object.js +3 -5
  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-atlassian-team/index.js +2 -0
  18. package/dist/es2019/rules/ensure-critical-dependency-resolutions/index.js +8 -4
  19. package/dist/es2019/rules/ensure-feature-flag-prefix/index.js +2 -0
  20. package/dist/es2019/rules/ensure-feature-flag-registration/index.js +2 -0
  21. package/dist/es2019/rules/ensure-publish-valid/index.js +2 -0
  22. package/dist/es2019/rules/ensure-test-runner-arguments/index.js +2 -0
  23. package/dist/es2019/rules/ensure-test-runner-nested-count/index.js +2 -0
  24. package/dist/es2019/rules/no-duplicate-dependencies/index.js +67 -0
  25. package/dist/es2019/rules/no-invalid-feature-flag-usage/index.js +2 -0
  26. package/dist/es2019/rules/no-invalid-storybook-decorator-usage/index.js +2 -0
  27. package/dist/es2019/rules/no-pre-post-installs/index.js +2 -0
  28. package/dist/esm/index.js +24 -4
  29. package/dist/esm/rules/ensure-atlassian-team/index.js +2 -0
  30. package/dist/esm/rules/ensure-critical-dependency-resolutions/index.js +22 -11
  31. package/dist/esm/rules/ensure-feature-flag-prefix/index.js +2 -0
  32. package/dist/esm/rules/ensure-feature-flag-registration/index.js +2 -0
  33. package/dist/esm/rules/ensure-publish-valid/index.js +2 -0
  34. package/dist/esm/rules/ensure-test-runner-arguments/index.js +2 -0
  35. package/dist/esm/rules/ensure-test-runner-nested-count/index.js +2 -0
  36. package/dist/esm/rules/no-duplicate-dependencies/index.js +85 -0
  37. package/dist/esm/rules/no-invalid-feature-flag-usage/index.js +2 -0
  38. package/dist/esm/rules/no-invalid-storybook-decorator-usage/index.js +2 -0
  39. package/dist/esm/rules/no-pre-post-installs/index.js +2 -0
  40. package/dist/types/index.d.ts +1 -0
  41. package/dist/types/rules/no-duplicate-dependencies/index.d.ts +3 -0
  42. package/dist/types-ts4.5/index.d.ts +1 -0
  43. package/dist/types-ts4.5/rules/no-duplicate-dependencies/index.d.ts +3 -0
  44. package/package.json +3 -2
  45. package/report.api.md +1 -0
  46. package/src/index.tsx +25 -4
  47. package/src/rules/ensure-atlassian-team/index.ts +1 -0
  48. package/src/rules/ensure-critical-dependency-resolutions/__test__/unit/rule.test.tsx +10 -0
  49. package/src/rules/ensure-critical-dependency-resolutions/index.tsx +13 -10
  50. package/src/rules/ensure-feature-flag-prefix/index.tsx +1 -0
  51. package/src/rules/ensure-feature-flag-registration/index.tsx +1 -0
  52. package/src/rules/ensure-publish-valid/index.ts +1 -0
  53. package/src/rules/ensure-test-runner-arguments/index.tsx +1 -0
  54. package/src/rules/ensure-test-runner-nested-count/index.tsx +1 -0
  55. package/src/rules/no-duplicate-dependencies/__tests__/unit/rule.test.ts +116 -0
  56. package/src/rules/no-duplicate-dependencies/index.ts +84 -0
  57. package/src/rules/no-invalid-feature-flag-usage/index.tsx +1 -0
  58. package/src/rules/no-invalid-storybook-decorator-usage/index.tsx +1 -0
  59. package/src/rules/no-pre-post-installs/index.ts +1 -0
  60. package/tmp/api-report-tmp.d.ts +1 -0
  61. package/tsconfig.app.json +2 -1
  62. package/tsconfig.dev.json +2 -1
@@ -1,8 +1,11 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  import ensureFeatureFlagRegistration from './rules/ensure-feature-flag-registration';
2
4
  import noPreAndPostInstallScripts from './rules/no-pre-post-installs';
3
5
  import ensureTestRunnerArguments from './rules/ensure-test-runner-arguments';
4
6
  import ensureTestRunnerNestedCount from './rules/ensure-test-runner-nested-count';
5
7
  import ensureAtlassianTeam from './rules/ensure-atlassian-team';
8
+ import noDuplicateDependencies from './rules/no-duplicate-dependencies';
6
9
  import noInvalidFeatureFlagUsage from './rules/no-invalid-feature-flag-usage';
7
10
  import ensureFeatureFlagPrefix from './rules/ensure-feature-flag-prefix';
8
11
  import ensureCriticalDependencyResolutions from './rules/ensure-critical-dependency-resolutions';
@@ -15,6 +18,7 @@ export const rules = {
15
18
  'ensure-test-runner-nested-count': ensureTestRunnerNestedCount,
16
19
  'ensure-atlassian-team': ensureAtlassianTeam,
17
20
  'ensure-critical-dependency-resolutions': ensureCriticalDependencyResolutions,
21
+ 'no-duplicate-dependencies': noDuplicateDependencies,
18
22
  'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
19
23
  'no-pre-post-install-scripts': noPreAndPostInstallScripts,
20
24
  'no-invalid-storybook-decorator-usage': noInvalidStorybookDecoratorUsage,
@@ -36,12 +40,31 @@ export const configs = {
36
40
  }
37
41
  }
38
42
  };
43
+ const jsonPrefix = '/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ';
39
44
  export const processors = {
40
45
  'package-json-processor': {
41
46
  preprocess: source => {
42
47
  // augment the json into a js file
43
- return [`/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ${source.trim()}`];
48
+ return [jsonPrefix + source.trim()];
44
49
  },
45
- postprocess: errors => errors[0]
50
+ postprocess: messages => {
51
+ return messages[0].map(message => {
52
+ const {
53
+ fix
54
+ } = message;
55
+ if (!fix) {
56
+ return message;
57
+ }
58
+ const offset = jsonPrefix.length;
59
+ return {
60
+ ...message,
61
+ fix: {
62
+ ...fix,
63
+ range: [fix.range[0] - offset, fix.range[1] - offset]
64
+ }
65
+ };
66
+ });
67
+ },
68
+ supportsAutofix: true
46
69
  }
47
70
  };
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  const rule = {
2
4
  meta: {
3
5
  type: 'problem',
@@ -1,11 +1,13 @@
1
1
  import { findRootSync } from '@manypkg/find-root';
2
+ // eslint-disable-next-line import/no-extraneous-dependencies
3
+
2
4
  import { getObjectPropertyAsObject } from '../util/handle-ast-object';
3
5
 
4
6
  // Here we only need to specify the major and minor versions
5
7
  // In matchMinorVersion, we will check if the versions in resolutions fall in the right ranges.
6
8
  const DESIRED_PKG_VERSIONS = {
7
- typescript: '4.9',
8
- '@types/react': '16.14'
9
+ typescript: ['4.9'],
10
+ '@types/react': ['16.14', '18.2']
9
11
  };
10
12
  const matchMinorVersion = (desiredVersion, versionInResolutions) => {
11
13
  const firstChar = versionInResolutions[0];
@@ -48,8 +50,10 @@ const rule = {
48
50
  const rootDir = findRootSync(process.cwd());
49
51
  const isRootPackageJson = fileName.endsWith(`${rootDir}/package.json`);
50
52
  if (packageResolutions !== null) {
51
- for (const [key, value] of Object.entries(DESIRED_PKG_VERSIONS)) {
52
- if (!verifyResolutionFromObject(packageResolutions, key, value, !isRootPackageJson)) {
53
+ for (const [key, values] of Object.entries(DESIRED_PKG_VERSIONS)) {
54
+ if (!values.some(value => {
55
+ return verifyResolutionFromObject(packageResolutions, key, value, !isRootPackageJson);
56
+ })) {
53
57
  return context.report({
54
58
  node,
55
59
  messageId: 'invalidPackageResolution'
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
2
4
  const rule = {
3
5
  meta: {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
2
4
  const rule = {
3
5
  meta: {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  import { getObjectPropertyAsLiteral, getObjectPropertyAsObject } from '../util/handle-ast-object';
2
4
  const rule = {
3
5
  meta: {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  const TEST_RUNNER_IDENTIFIER = 'ffTest';
2
4
  const rule = {
3
5
  meta: {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  const NESTED_LIMIT = 4;
2
4
  const TEST_RUNNER_IDENTIFIER = 'ffTest';
3
5
  const getDepthOfNestedRunner = node => {
@@ -0,0 +1,67 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
3
+ const rule = {
4
+ meta: {
5
+ type: 'problem',
6
+ docs: {
7
+ description: 'This rule disallows a dependency to be defined in both dependencies and devDependencies',
8
+ recommended: false
9
+ },
10
+ fixable: 'code',
11
+ messages: {
12
+ unexpectedDuplicateDependency: 'Unexpected duplicate dependency {{name}}'
13
+ }
14
+ },
15
+ create(context) {
16
+ const dependencies = new Map();
17
+ const devDependencies = new Map();
18
+ return {
19
+ 'ObjectExpression Property[key.value=dependencies] Property': node => {
20
+ // @ts-expect-error
21
+ dependencies.set(node.key.value, node.key);
22
+ },
23
+ 'ObjectExpression Property[key.value=devDependencies] Property': node => {
24
+ // @ts-expect-error
25
+ devDependencies.set(node.key.value, node.key);
26
+ },
27
+ 'Program:exit': () => {
28
+ for (const [dependency, node] of devDependencies) {
29
+ if (dependencies.has(dependency)) {
30
+ context.report({
31
+ data: {
32
+ name: dependency
33
+ },
34
+ fix(fixer) {
35
+ var _sourceCode$getTokenA;
36
+ const sourceCode = context.getSourceCode();
37
+ const property = node.parent;
38
+ const isLastLine = ((_sourceCode$getTokenA = sourceCode.getTokenAfter(property)) === null || _sourceCode$getTokenA === void 0 ? void 0 : _sourceCode$getTokenA.value) === '}';
39
+ const end = property.loc.end;
40
+ if (!isLastLine) {
41
+ return fixer.removeRange([sourceCode.getIndexFromLoc({
42
+ line: property.loc.start.line,
43
+ column: 0
44
+ }), sourceCode.getIndexFromLoc({
45
+ line: end.line + 1,
46
+ column: 0
47
+ })]);
48
+ }
49
+ const previousToken = sourceCode.getTokenBefore(property);
50
+ return fixer.removeRange([sourceCode.getIndexFromLoc({
51
+ line: previousToken.loc.end.line,
52
+ column: previousToken.loc.end.column - 1
53
+ }), sourceCode.getIndexFromLoc({
54
+ line: end.line,
55
+ column: end.column
56
+ })]);
57
+ },
58
+ messageId: 'unexpectedDuplicateDependency',
59
+ node
60
+ });
61
+ }
62
+ }
63
+ }
64
+ };
65
+ }
66
+ };
67
+ export default rule;
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  const FF_GETTER_BOOLEAN_IDENTIFIER = 'getBooleanFF';
2
4
  const __isOnlyOneFlagCheckInExpression = (root, ignoredNode) => {
3
5
  switch (root.type) {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  const STORYBOOK_DECORATOR_IDENTIFIER = 'withPlatformFeatureFlags';
2
4
  const rule = {
3
5
  meta: {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  const rule = {
2
4
  meta: {
3
5
  type: 'problem',
package/dist/esm/index.js CHANGED
@@ -1,8 +1,14 @@
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; }
4
+ // eslint-disable-next-line import/no-extraneous-dependencies
5
+
1
6
  import ensureFeatureFlagRegistration from './rules/ensure-feature-flag-registration';
2
7
  import noPreAndPostInstallScripts from './rules/no-pre-post-installs';
3
8
  import ensureTestRunnerArguments from './rules/ensure-test-runner-arguments';
4
9
  import ensureTestRunnerNestedCount from './rules/ensure-test-runner-nested-count';
5
10
  import ensureAtlassianTeam from './rules/ensure-atlassian-team';
11
+ import noDuplicateDependencies from './rules/no-duplicate-dependencies';
6
12
  import noInvalidFeatureFlagUsage from './rules/no-invalid-feature-flag-usage';
7
13
  import ensureFeatureFlagPrefix from './rules/ensure-feature-flag-prefix';
8
14
  import ensureCriticalDependencyResolutions from './rules/ensure-critical-dependency-resolutions';
@@ -15,6 +21,7 @@ export var rules = {
15
21
  'ensure-test-runner-nested-count': ensureTestRunnerNestedCount,
16
22
  'ensure-atlassian-team': ensureAtlassianTeam,
17
23
  'ensure-critical-dependency-resolutions': ensureCriticalDependencyResolutions,
24
+ 'no-duplicate-dependencies': noDuplicateDependencies,
18
25
  'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
19
26
  'no-pre-post-install-scripts': noPreAndPostInstallScripts,
20
27
  'no-invalid-storybook-decorator-usage': noInvalidStorybookDecoratorUsage,
@@ -36,14 +43,27 @@ export var configs = {
36
43
  }
37
44
  }
38
45
  };
46
+ var jsonPrefix = '/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ';
39
47
  export var processors = {
40
48
  'package-json-processor': {
41
49
  preprocess: function preprocess(source) {
42
50
  // augment the json into a js file
43
- return ["/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ".concat(source.trim())];
51
+ return [jsonPrefix + source.trim()];
44
52
  },
45
- postprocess: function postprocess(errors) {
46
- return errors[0];
47
- }
53
+ postprocess: function postprocess(messages) {
54
+ return messages[0].map(function (message) {
55
+ var fix = message.fix;
56
+ if (!fix) {
57
+ return message;
58
+ }
59
+ var offset = jsonPrefix.length;
60
+ return _objectSpread(_objectSpread({}, message), {}, {
61
+ fix: _objectSpread(_objectSpread({}, fix), {}, {
62
+ range: [fix.range[0] - offset, fix.range[1] - offset]
63
+ })
64
+ });
65
+ });
66
+ },
67
+ supportsAutofix: true
48
68
  }
49
69
  };
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  var rule = {
2
4
  meta: {
3
5
  type: 'problem',
@@ -1,12 +1,14 @@
1
1
  import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
2
  import { findRootSync } from '@manypkg/find-root';
3
+ // eslint-disable-next-line import/no-extraneous-dependencies
4
+
3
5
  import { getObjectPropertyAsObject } from '../util/handle-ast-object';
4
6
 
5
7
  // Here we only need to specify the major and minor versions
6
8
  // In matchMinorVersion, we will check if the versions in resolutions fall in the right ranges.
7
9
  var DESIRED_PKG_VERSIONS = {
8
- typescript: '4.9',
9
- '@types/react': '16.14'
10
+ typescript: ['4.9'],
11
+ '@types/react': ['16.14', '18.2']
10
12
  };
11
13
  var matchMinorVersion = function matchMinorVersion(desiredVersion, versionInResolutions) {
12
14
  var firstChar = versionInResolutions[0];
@@ -61,16 +63,25 @@ var rule = {
61
63
  var rootDir = findRootSync(process.cwd());
62
64
  var isRootPackageJson = fileName.endsWith("".concat(rootDir, "/package.json"));
63
65
  if (packageResolutions !== null) {
66
+ var _loop = function _loop() {
67
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
68
+ key = _Object$entries$_i[0],
69
+ values = _Object$entries$_i[1];
70
+ if (!values.some(function (value) {
71
+ return verifyResolutionFromObject(packageResolutions, key, value, !isRootPackageJson);
72
+ })) {
73
+ return {
74
+ v: context.report({
75
+ node: node,
76
+ messageId: 'invalidPackageResolution'
77
+ })
78
+ };
79
+ }
80
+ },
81
+ _ret;
64
82
  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
- }
83
+ _ret = _loop();
84
+ if (_ret) return _ret.v;
74
85
  }
75
86
  }
76
87
  })
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
2
4
  var rule = {
3
5
  meta: {
@@ -1,6 +1,8 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
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
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
+ // eslint-disable-next-line import/no-extraneous-dependencies
5
+
4
6
  import { getMetadataForFilename, getterIdentifierToFlagTypeMap } from '../util/registration-utils';
5
7
  var rule = {
6
8
  meta: {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  import { getObjectPropertyAsLiteral, getObjectPropertyAsObject } from '../util/handle-ast-object';
2
4
  var rule = {
3
5
  meta: {
@@ -1,4 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ // eslint-disable-next-line import/no-extraneous-dependencies
3
+
2
4
  var TEST_RUNNER_IDENTIFIER = 'ffTest';
3
5
  var rule = {
4
6
  meta: {
@@ -1,6 +1,8 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
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
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
+ // eslint-disable-next-line import/no-extraneous-dependencies
5
+
4
6
  var NESTED_LIMIT = 4;
5
7
  var TEST_RUNNER_IDENTIFIER = 'ffTest';
6
8
  var getDepthOfNestedRunner = function getDepthOfNestedRunner(node) {
@@ -0,0 +1,85 @@
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
+ // eslint-disable-next-line import/no-extraneous-dependencies
6
+
7
+ var rule = {
8
+ meta: {
9
+ type: 'problem',
10
+ docs: {
11
+ description: 'This rule disallows a dependency to be defined in both dependencies and devDependencies',
12
+ recommended: false
13
+ },
14
+ fixable: 'code',
15
+ messages: {
16
+ unexpectedDuplicateDependency: 'Unexpected duplicate dependency {{name}}'
17
+ }
18
+ },
19
+ create: function create(context) {
20
+ var dependencies = new Map();
21
+ var devDependencies = new Map();
22
+ return {
23
+ 'ObjectExpression Property[key.value=dependencies] Property': function ObjectExpressionPropertyKeyValueDependenciesProperty(node) {
24
+ // @ts-expect-error
25
+ dependencies.set(node.key.value, node.key);
26
+ },
27
+ 'ObjectExpression Property[key.value=devDependencies] Property': function ObjectExpressionPropertyKeyValueDevDependenciesProperty(node) {
28
+ // @ts-expect-error
29
+ devDependencies.set(node.key.value, node.key);
30
+ },
31
+ 'Program:exit': function ProgramExit() {
32
+ var _iterator = _createForOfIteratorHelper(devDependencies),
33
+ _step;
34
+ try {
35
+ var _loop = function _loop() {
36
+ var _step$value = _slicedToArray(_step.value, 2),
37
+ dependency = _step$value[0],
38
+ node = _step$value[1];
39
+ if (dependencies.has(dependency)) {
40
+ context.report({
41
+ data: {
42
+ name: dependency
43
+ },
44
+ fix: function fix(fixer) {
45
+ var _sourceCode$getTokenA;
46
+ var sourceCode = context.getSourceCode();
47
+ var property = node.parent;
48
+ var isLastLine = ((_sourceCode$getTokenA = sourceCode.getTokenAfter(property)) === null || _sourceCode$getTokenA === void 0 ? void 0 : _sourceCode$getTokenA.value) === '}';
49
+ var end = property.loc.end;
50
+ if (!isLastLine) {
51
+ return fixer.removeRange([sourceCode.getIndexFromLoc({
52
+ line: property.loc.start.line,
53
+ column: 0
54
+ }), sourceCode.getIndexFromLoc({
55
+ line: end.line + 1,
56
+ column: 0
57
+ })]);
58
+ }
59
+ var previousToken = sourceCode.getTokenBefore(property);
60
+ return fixer.removeRange([sourceCode.getIndexFromLoc({
61
+ line: previousToken.loc.end.line,
62
+ column: previousToken.loc.end.column - 1
63
+ }), sourceCode.getIndexFromLoc({
64
+ line: end.line,
65
+ column: end.column
66
+ })]);
67
+ },
68
+ messageId: 'unexpectedDuplicateDependency',
69
+ node: node
70
+ });
71
+ }
72
+ };
73
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
74
+ _loop();
75
+ }
76
+ } catch (err) {
77
+ _iterator.e(err);
78
+ } finally {
79
+ _iterator.f();
80
+ }
81
+ }
82
+ };
83
+ }
84
+ };
85
+ export default rule;
@@ -1,4 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ // eslint-disable-next-line import/no-extraneous-dependencies
3
+
2
4
  var FF_GETTER_BOOLEAN_IDENTIFIER = 'getBooleanFF';
3
5
  var __isOnlyOneFlagCheckInExpression = function __isOnlyOneFlagCheckInExpression(root, ignoredNode) {
4
6
  switch (root.type) {
@@ -1,4 +1,6 @@
1
1
  import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ // eslint-disable-next-line import/no-extraneous-dependencies
3
+
2
4
  var STORYBOOK_DECORATOR_IDENTIFIER = 'withPlatformFeatureFlags';
3
5
  var rule = {
4
6
  meta: {
@@ -1,3 +1,5 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+
1
3
  var rule = {
2
4
  meta: {
3
5
  type: 'problem',
@@ -6,6 +6,7 @@ export declare const rules: {
6
6
  'ensure-test-runner-nested-count': import("eslint").Rule.RuleModule;
7
7
  'ensure-atlassian-team': import("eslint").Rule.RuleModule;
8
8
  'ensure-critical-dependency-resolutions': import("eslint").Rule.RuleModule;
9
+ 'no-duplicate-dependencies': import("eslint").Rule.RuleModule;
9
10
  'no-invalid-feature-flag-usage': import("eslint").Rule.RuleModule;
10
11
  'no-pre-post-install-scripts': import("eslint").Rule.RuleModule;
11
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;
@@ -6,6 +6,7 @@ export declare const rules: {
6
6
  'ensure-test-runner-nested-count': import("eslint").Rule.RuleModule;
7
7
  'ensure-atlassian-team': import("eslint").Rule.RuleModule;
8
8
  'ensure-critical-dependency-resolutions': import("eslint").Rule.RuleModule;
9
+ 'no-duplicate-dependencies': import("eslint").Rule.RuleModule;
9
10
  'no-invalid-feature-flag-usage': import("eslint").Rule.RuleModule;
10
11
  'no-pre-post-install-scripts': import("eslint").Rule.RuleModule;
11
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;
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.6",
4
+ "version": "0.4.0",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "atlassian": {
7
7
  "team": "UIP - Platform Integration Trust (PITa)",
@@ -37,8 +37,9 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@atlassian/atlassian-frontend-prettier-config-1.0.1": "npm:@atlassian/atlassian-frontend-prettier-config@1.0.1",
40
+ "@types/eslint": "^8.4.5",
40
41
  "eslint": "^7.7.0",
41
- "tsconfig-paths": "^3.9.0"
42
+ "tsconfig-paths": "^4.2.0"
42
43
  },
43
44
  "prettier": "@atlassian/atlassian-frontend-prettier-config-1.0.1"
44
45
  }
package/report.api.md CHANGED
@@ -52,6 +52,7 @@ export const rules: {
52
52
  'ensure-test-runner-nested-count': Rule.RuleModule;
53
53
  'ensure-atlassian-team': Rule.RuleModule;
54
54
  'ensure-critical-dependency-resolutions': Rule.RuleModule;
55
+ 'no-duplicate-dependencies': Rule.RuleModule;
55
56
  'no-invalid-feature-flag-usage': Rule.RuleModule;
56
57
  'no-pre-post-install-scripts': Rule.RuleModule;
57
58
  'no-invalid-storybook-decorator-usage': Rule.RuleModule;
package/src/index.tsx CHANGED
@@ -1,9 +1,11 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
1
2
  import type { Linter } from 'eslint';
2
3
  import ensureFeatureFlagRegistration from './rules/ensure-feature-flag-registration';
3
4
  import noPreAndPostInstallScripts from './rules/no-pre-post-installs';
4
5
  import ensureTestRunnerArguments from './rules/ensure-test-runner-arguments';
5
6
  import ensureTestRunnerNestedCount from './rules/ensure-test-runner-nested-count';
6
7
  import ensureAtlassianTeam from './rules/ensure-atlassian-team';
8
+ import noDuplicateDependencies from './rules/no-duplicate-dependencies';
7
9
  import noInvalidFeatureFlagUsage from './rules/no-invalid-feature-flag-usage';
8
10
  import ensureFeatureFlagPrefix from './rules/ensure-feature-flag-prefix';
9
11
  import ensureCriticalDependencyResolutions from './rules/ensure-critical-dependency-resolutions';
@@ -17,6 +19,7 @@ export const rules = {
17
19
  'ensure-test-runner-nested-count': ensureTestRunnerNestedCount,
18
20
  'ensure-atlassian-team': ensureAtlassianTeam,
19
21
  'ensure-critical-dependency-resolutions': ensureCriticalDependencyResolutions,
22
+ 'no-duplicate-dependencies': noDuplicateDependencies,
20
23
  'no-invalid-feature-flag-usage': noInvalidFeatureFlagUsage,
21
24
  'no-pre-post-install-scripts': noPreAndPostInstallScripts,
22
25
  'no-invalid-storybook-decorator-usage': noInvalidStorybookDecoratorUsage,
@@ -41,14 +44,32 @@ export const configs = {
41
44
  },
42
45
  };
43
46
 
47
+ const jsonPrefix =
48
+ '/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ';
49
+
44
50
  export const processors = {
45
51
  'package-json-processor': {
46
52
  preprocess: (source: string) => {
47
53
  // augment the json into a js file
48
- return [
49
- `/* eslint-disable quote-props, comma-dangle, quotes, semi, eol-last, @typescript-eslint/semi, no-template-curly-in-string */ module.exports = ${source.trim()}`,
50
- ];
54
+ return [jsonPrefix + source.trim()];
55
+ },
56
+ postprocess: (messages) => {
57
+ return messages[0].map((message) => {
58
+ const { fix } = message;
59
+ if (!fix) {
60
+ return message;
61
+ }
62
+
63
+ const offset = jsonPrefix.length;
64
+ return {
65
+ ...message,
66
+ fix: {
67
+ ...fix,
68
+ range: [fix.range[0] - offset, fix.range[1] - offset],
69
+ },
70
+ };
71
+ });
51
72
  },
52
- postprocess: (errors) => errors[0],
73
+ supportsAutofix: true,
53
74
  } as Linter.Processor,
54
75
  };
@@ -1,3 +1,4 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
1
2
  import type { Rule } from 'eslint';
2
3
 
3
4
  const rule: Rule.RuleModule = {
@@ -16,6 +16,16 @@ describe('test ensure-critical-dependency-resolutions rule', () => {
16
16
  }`,
17
17
  filename: `${cwd}/package.json`,
18
18
  },
19
+ // Root package.json, have all of the correct resolutions
20
+ {
21
+ code: `const foo = {
22
+ "resolutions": {
23
+ "@types/react": "18.2.28",
24
+ "typescript": "4.9.5",
25
+ }
26
+ }`,
27
+ filename: `${cwd}/package.json`,
28
+ },
19
29
  // Root package.json, have all of the correct resolutions with ~
20
30
  {
21
31
  code: `const foo = {