@atlaskit/eslint-plugin-design-system 4.15.6 → 4.16.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @atlaskit/eslint-plugin-design-system
2
2
 
3
+ ## 4.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`efadee8e999`](https://bitbucket.org/atlassian/atlassian-frontend/commits/efadee8e999) - Update no-deprecated-apis ESlint rule to accept configurations
8
+
3
9
  ## 4.15.6
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -40,13 +40,67 @@ module.exports = {
40
40
  + '@atlaskit/design-system/no-unsafe-design-token-usage': ['error', { 'shouldEnsureFallbackUsage': true }],
41
41
  + '@atlaskit/design-system/use-visually-hidden': 'error',
42
42
  + '@atlaskit/design-system/no-deprecated-imports': 'error',
43
- + '@atlaskit/design-system/no-deprecated-api-usage': 'error'
43
+ + '@atlaskit/design-system/no-deprecated-api': 'error',
44
44
  }
45
45
  }
46
46
  };
47
47
  ```
48
48
 
49
- Rules will where possible come with fixers.
49
+ ## Usage of '@atlaskit/design-system/no-deprecated-api'
50
+
51
+ You can use the `@atlaskit/design-system/no-deprecated-api` rule to check for deprecated API usage in your codebase. The rule can take one option - `deprecatedConfig`, if not provided, the rule will use the default config file. If provided, the rule will override the default config file and use the config file provided.
52
+ See the examples below:
53
+ [Usage with default deprecated APIs config](###Usage-with-default-deprecated-APIs-config)
54
+ [Overwrite default deprecated APIs config](###Overwrite-default-deprecated-APIs-config)
55
+
56
+ ### Default deprecated APIs config
57
+
58
+ The default config containing the deprecated APIs config for this rule. You can import the default config file from `@atlaskit/eslint-plugin-design-system`.
59
+
60
+ ```js
61
+ import { configs } from '@atlaskit/eslint-plugin-design-system';
62
+ const { deprecatedConfig } = configs;
63
+ ```
64
+
65
+ In the default config file you can find the following fields:
66
+
67
+ - `deprecatedAPI`, which is the deprecated props. Each prop has the following fields:
68
+
69
+ - `moduleSpecifier`, which is the module specifier of the package in which the prop was deprecated. For example: `@atlaskit/button`.
70
+ - `namedSpecifier`**(optional)**, which is an array of named specifiers of the package in which the prop was deprecated. For example: `Button`.
71
+ - `actionableVersion`**(optional)**, which is the version of the package in which the prop can be actioned on. For example: `1.0.0`.
72
+
73
+ ### Usage with default deprecated APIs config
74
+
75
+ Enable the rule as other rules if you want to use the default deprecated APIs config. The rule will automatically load the default config file and use it.
76
+
77
+ Enable the rule in your `.eslintrc.js` file:
78
+
79
+ ```js
80
+ rules: {
81
+ '@atlaskit/design-system/no-deprecated-api': 'error'
82
+ }
83
+ ```
84
+
85
+ ### Overwrite default deprecated APIs config
86
+
87
+ You can overwrite the default deprecated APIs to suits your needs. You can do this by providing the `deprecatedConfig` option to the rule. The option can be partial of the default config file, or a new config that contatins the required fields described in the [Default deprecated APIs config](###Default-deprecated-APIs-config) section.
88
+
89
+ The plugin also provides a `filterActionableDeprecations` util function that accepts the `deprecated APIs config` and `your root package.json` as params, and will filter the default deprecated APIs config based on the package versions listed in the package.json file, and return a list of actionable entries.
90
+ Example:
91
+
92
+ ```js
93
+ import { configs } from '@atlaskit/eslint-plugin-design-system';
94
+ import packageJson from '.path-to/package.json';
95
+
96
+ rules: {
97
+ '@atlaskit/design-system/no-deprecated-api': ['error', {
98
+ 'deprecatedConfig': filterActionableDeprecations(configs.deprecatedConfig, JSON.parse(packageJson)),
99
+ }]
100
+ }
101
+ ```
102
+
103
+ Rules may come with fixers to assist.
50
104
  For individual rules see the [`rules`](./src/rules) folder,
51
105
  however its strongly recommended to use the rules as above.
52
106
  You can read more about configuring eslint in their [documentation](https://eslint.org/docs/user-guide/configuring).
@@ -0,0 +1,33 @@
1
+ {
2
+ "cssFn": [{
3
+ "moduleSpecifier": "@atlaskit/menu"
4
+ },
5
+ {
6
+ "moduleSpecifier": "@atlaskit/side-navigation"
7
+ }
8
+ ],
9
+ "overrides": [{
10
+ "moduleSpecifier": "@atlaskit/menu"
11
+ },
12
+ {
13
+ "moduleSpecifier": "@atlaskit/side-navigation"
14
+ }
15
+ ],
16
+ "type": [{
17
+ "moduleSpecifier": "@atlaskit/inline-message"
18
+ }],
19
+ "textColor": [{
20
+ "moduleSpecifier": "@atlaskit/logo"
21
+
22
+ }],
23
+ "iconColor": [{
24
+ "moduleSpecifier": "@atlaskit/logo"
25
+ }],
26
+ "iconGradientStart": [{
27
+ "moduleSpecifier": "@atlaskit/logo"
28
+ }],
29
+ "iconGradientStop": [{
30
+ "moduleSpecifier": "@atlaskit/logo"
31
+ }]
32
+
33
+ }
package/dist/cjs/index.js CHANGED
@@ -4,7 +4,14 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
4
4
  Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
- exports.rules = exports.configs = void 0;
7
+ exports.configs = void 0;
8
+ Object.defineProperty(exports, "filterActionableDeprecations", {
9
+ enumerable: true,
10
+ get: function get() {
11
+ return _filterActionableDeprecations.filterActionableDeprecations;
12
+ }
13
+ });
14
+ exports.rules = void 0;
8
15
  var _ensureDesignTokenUsage = _interopRequireDefault(require("./rules/ensure-design-token-usage"));
9
16
  var _ensureDesignTokenUsageSpacing = _interopRequireDefault(require("./rules/ensure-design-token-usage-spacing"));
10
17
  var _iconLabel = _interopRequireDefault(require("./rules/icon-label"));
@@ -14,6 +21,7 @@ var _noDeprecatedDesignTokenUsage = _interopRequireDefault(require("./rules/no-d
14
21
  var _noDeprecatedImports = _interopRequireDefault(require("./rules/no-deprecated-imports"));
15
22
  var _noUnsafeDesignTokenUsage = _interopRequireDefault(require("./rules/no-unsafe-design-token-usage"));
16
23
  var _useVisuallyHidden = _interopRequireDefault(require("./rules/use-visually-hidden"));
24
+ var _filterActionableDeprecations = require("./rules/no-deprecated-apis/helpers/filter-actionable-deprecations");
17
25
  var rules = {
18
26
  'ensure-design-token-usage': _ensureDesignTokenUsage.default,
19
27
  'icon-label': _iconLabel.default,
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.filterActionableDeprecations = void 0;
8
+ var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
9
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
10
+ var _semver = _interopRequireDefault(require("semver"));
11
+ var _validateDeprecatedApisConfig = require("./validate-deprecated-apis-config");
12
+ var filterActionableDeprecations = function filterActionableDeprecations(originalDeprecatedConfig, rootPackageJson) {
13
+ // verify the config is valid and parse it to an object
14
+ var validatedDeprecatedConfig = (0, _validateDeprecatedApisConfig.getValidatedConfig)(originalDeprecatedConfig);
15
+
16
+ // verify the root package.json is valid and parse it to an object
17
+ var rootPackageDependencies;
18
+ try {
19
+ rootPackageDependencies = JSON.parse(rootPackageJson).dependencies;
20
+ if (!rootPackageDependencies) {
21
+ throw new Error('No dependencies found in the provided root package.json');
22
+ }
23
+ } catch (e) {
24
+ var error = e;
25
+ throw new Error("Failed to parse root package.json: ".concat(error.message));
26
+ }
27
+ var filteredConfig = {};
28
+ // filter out the deprecated APIs that are not actionable
29
+ for (var _i = 0, _Object$entries = Object.entries(validatedDeprecatedConfig); _i < _Object$entries.length; _i++) {
30
+ var _Object$entries$_i = (0, _slicedToArray2.default)(_Object$entries[_i], 2),
31
+ apiKey = _Object$entries$_i[0],
32
+ apiValues = _Object$entries$_i[1];
33
+ var filterApiValues = apiValues.filter(function (apiValue) {
34
+ var _rootPackageDependenc;
35
+ var moduleSpecifier = apiValue.moduleSpecifier,
36
+ actionableVersion = apiValue.actionableVersion;
37
+
38
+ // if actionableVersion is not provided in the deprecated APIs config, it is actionable on all versions
39
+ if (!actionableVersion) {
40
+ return true;
41
+ }
42
+ var installedVersion = (_rootPackageDependenc = rootPackageDependencies) === null || _rootPackageDependenc === void 0 ? void 0 : _rootPackageDependenc[moduleSpecifier];
43
+ var coercedInstalledVersion = _semver.default.coerce(installedVersion);
44
+ if (!coercedInstalledVersion) {
45
+ throw new Error("No valid ".concat(moduleSpecifier, " found in the dependencies of root package.json."));
46
+ }
47
+ var coercedActionableVersion = _semver.default.coerce(actionableVersion);
48
+ if (!coercedActionableVersion) {
49
+ throw new Error("Actionable version is invalid for ".concat(moduleSpecifier, " in the deprecated APIs config."));
50
+ }
51
+ return _semver.default.gte(coercedInstalledVersion, coercedActionableVersion);
52
+ });
53
+ if (filterApiValues.length > 0) {
54
+ Object.assign(filteredConfig, (0, _defineProperty2.default)({}, apiKey, filterApiValues));
55
+ }
56
+ }
57
+ return JSON.stringify(filteredConfig);
58
+ };
59
+ exports.filterActionableDeprecations = filterActionableDeprecations;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.getValidatedConfig = void 0;
8
+ var _ajv = _interopRequireDefault(require("ajv"));
9
+ var deprecatedSchema = {
10
+ type: 'object',
11
+ patternProperties: {
12
+ '.+': {
13
+ type: 'array',
14
+ items: {
15
+ type: 'object',
16
+ properties: {
17
+ moduleSpecifier: {
18
+ type: 'string'
19
+ },
20
+ namedSpecifiers: {
21
+ type: 'array',
22
+ items: {
23
+ type: 'string'
24
+ }
25
+ },
26
+ actionableVersion: {
27
+ type: 'string'
28
+ }
29
+ },
30
+ required: ['moduleSpecifier'],
31
+ additionalProperites: false
32
+ }
33
+ }
34
+ },
35
+ allowMatchingProperties: true
36
+ };
37
+ var getValidatedConfig = function getValidatedConfig(originalDeprecatedConfig) {
38
+ var parsedDeprecatedConfig = {};
39
+ try {
40
+ parsedDeprecatedConfig = JSON.parse(originalDeprecatedConfig);
41
+ } catch (e) {
42
+ var error = e;
43
+ throw new Error("Failed to parse JSON string: ".concat(error.message));
44
+ }
45
+ var ajv = new _ajv.default({
46
+ allErrors: true
47
+ });
48
+ var validate = ajv.compile(deprecatedSchema);
49
+ var valid = validate(parsedDeprecatedConfig);
50
+ if (!valid) {
51
+ var errors = validate.errors;
52
+ if (errors && errors.length) {
53
+ throw new Error("Deprecated APIs config is invalid: ".concat(errors));
54
+ } else {
55
+ throw new Error('Failed to validate deprecated APIs config with unknown error.');
56
+ }
57
+ }
58
+ return parsedDeprecatedConfig;
59
+ };
60
+ exports.getValidatedConfig = getValidatedConfig;
@@ -1,78 +1,154 @@
1
1
  "use strict";
2
2
 
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
3
4
  Object.defineProperty(exports, "__esModule", {
4
5
  value: true
5
6
  });
6
- exports.default = void 0;
7
- var _eslintCodemodUtils = require("eslint-codemod-utils");
8
- var _getImportNodeBySource = require("../utils/get-import-node-by-source");
9
- var unsafeOverridesConfig = {
10
- cssFn: ['@atlaskit/menu', '@atlaskit/side-navigation'],
11
- overrides: ['@atlaskit/drawer', '@atlaskit/menu', '@atlaskit/side-navigation'],
12
- innerRef: ['@atlaskit/banner'],
13
- isOpen: ['@atlaskit/banner'],
14
- type: ['@atlaskit/inline-message']
7
+ exports.noDeprecatedJSXAttributeMessageId = exports.name = exports.default = void 0;
8
+ var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
9
+ var _fs = _interopRequireDefault(require("fs"));
10
+ var _path = _interopRequireDefault(require("path"));
11
+ var _utils = require("@typescript-eslint/utils");
12
+ var createRule = _utils.ESLintUtils.RuleCreator(function (name) {
13
+ return name;
14
+ });
15
+ var noDeprecatedJSXAttributeMessageId = 'noDeprecatedJSXAttributes';
16
+ exports.noDeprecatedJSXAttributeMessageId = noDeprecatedJSXAttributeMessageId;
17
+ var isNodeOfType = function isNodeOfType(node, nodeType) {
18
+ return _utils.ASTUtils.isNodeOfType(nodeType)(node);
19
+ };
20
+ var isImportDeclaration = function isImportDeclaration(programStatement) {
21
+ return (programStatement === null || programStatement === void 0 ? void 0 : programStatement.type) === 'ImportDeclaration';
22
+ };
23
+ var findJSXElementName = function findJSXElementName(jsxAttributeNode) {
24
+ if (!jsxAttributeNode.parent || !isNodeOfType(jsxAttributeNode.parent, _utils.AST_NODE_TYPES.JSXOpeningElement)) {
25
+ return;
26
+ }
27
+ var openingElement = jsxAttributeNode.parent;
28
+ if (!isNodeOfType(openingElement.name, _utils.AST_NODE_TYPES.JSXIdentifier)) {
29
+ return;
30
+ }
31
+ return openingElement.name.name;
32
+ };
33
+ var getConfig = function getConfig() {
34
+ var configPath = _path.default.resolve(__dirname, '..', '..', '..', 'configs', 'deprecated.json');
35
+ var source = _fs.default.readFileSync(configPath, 'utf8');
36
+ var parsedConfig = JSON.parse(source);
37
+ return parsedConfig;
15
38
  };
16
- var unsafeOverrides = ['cssFn', 'overrides', 'innerRef', 'isOpen', 'type'];
17
- var rule = {
39
+ var name = 'no-deprecated-apis';
40
+ exports.name = name;
41
+ var rule = createRule({
42
+ name: name,
43
+ defaultOptions: [{
44
+ deprecatedConfig: getConfig()
45
+ }],
18
46
  meta: {
19
47
  type: 'suggestion',
20
48
  docs: {
21
49
  description: 'Disallow specified APIs that have been marked as deprecated and/or discouraged.',
22
- recommended: true
50
+ recommended: 'warn'
23
51
  },
24
52
  messages: {
25
- noDeprecatedApis: "The prop \"{{propName}}\" has been deprecated. It will be removed in the next major release."
26
- }
53
+ noDeprecatedJSXAttributes: 'The JSX attribute {{propName}} has been deprecated.'
54
+ },
55
+ schema: [{
56
+ type: 'object',
57
+ properties: {
58
+ deprecatedConfig: {
59
+ type: 'object',
60
+ properties: {
61
+ '.+': {
62
+ type: 'array',
63
+ items: {
64
+ type: 'object',
65
+ properties: {
66
+ moduleSpecifier: {
67
+ type: 'string'
68
+ },
69
+ namedSpecifiers: {
70
+ type: 'array',
71
+ items: {
72
+ type: 'string'
73
+ }
74
+ },
75
+ actionableVersion: {
76
+ type: 'string'
77
+ }
78
+ },
79
+ required: ['moduleSpecifier'],
80
+ additionalProperites: false
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }
86
+ }]
27
87
  },
28
- create: function create(context) {
88
+ create: function create(context, _ref) {
89
+ var _context$options$;
90
+ var _ref2 = (0, _slicedToArray2.default)(_ref, 1),
91
+ options = _ref2[0];
92
+ // Get rule configuration
93
+ var defaultDeprecatedConfig = options.deprecatedConfig;
94
+
95
+ // Get the rule configuration specified otherwise use default config.
96
+ // A bit confusing as it seems that the default options have precedence over the user specified options.
97
+ var deprecatedConfig = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || defaultDeprecatedConfig;
29
98
  return {
30
99
  // find JSX atribute - find name of attribute - get source and find relevant identifiers.
31
100
  JSXAttribute: function JSXAttribute(node) {
32
- var _node$name;
33
- if (!(0, _eslintCodemodUtils.isNodeOfType)(node, 'JSXAttribute')) {
101
+ var jsxAttributeIdentifier = node.name;
102
+ if (!isNodeOfType(jsxAttributeIdentifier, _utils.AST_NODE_TYPES.JSXIdentifier)) {
34
103
  return;
35
104
  }
36
- if (!unsafeOverrides.includes(node === null || node === void 0 ? void 0 : (_node$name = node.name) === null || _node$name === void 0 ? void 0 : _node$name.name)) {
105
+ var jsxAttributeName = jsxAttributeIdentifier.name;
106
+ if (!deprecatedConfig[jsxAttributeName]) {
37
107
  return;
38
108
  }
39
- var source = context.getSourceCode();
40
- var bannedApi = node.name.name;
41
-
42
- // traverse the tree to the nearest JSX Element and get its name
43
- var closesetJSXElement = (0, _eslintCodemodUtils.closestOfType)(node, 'JSXOpeningElement');
44
- var jsxElementName = (0, _eslintCodemodUtils.isNodeOfType)(closesetJSXElement === null || closesetJSXElement === void 0 ? void 0 : closesetJSXElement.name, 'JSXIdentifier') && closesetJSXElement.name.name;
109
+ var jsxElementName = findJSXElementName(node);
45
110
  if (!jsxElementName) {
46
111
  return;
47
112
  }
113
+ var source = context.getSourceCode();
48
114
 
49
115
  // find an import for the path of the banned api
50
- unsafeOverridesConfig[bannedApi].forEach(function (path) {
51
- var importNode = (0, _getImportNodeBySource.getImportedNodeBySource)(source, path);
116
+ deprecatedConfig[jsxAttributeName].forEach(function (importItem) {
117
+ var _importItem$namedSpec;
118
+ var importNode = source.ast.body.filter(isImportDeclaration).find(function (node) {
119
+ return node.source.value === importItem.moduleSpecifier;
120
+ });
52
121
  if (!importNode) {
53
122
  return;
54
123
  }
55
124
 
56
125
  // find an import that matches our JSX element
57
- var hasTargetNode = importNode.specifiers.some(function (node) {
126
+ var targetNode = importNode.specifiers.find(function (node) {
58
127
  return node.local.name === jsxElementName;
59
128
  });
60
- if (!hasTargetNode) {
129
+
130
+ // check if the import exists
131
+ if (!targetNode) {
61
132
  return;
62
133
  }
63
134
 
64
- // if we're here the import exists and there is a valid lint error.
135
+ // if the import has named specifiers, check if the JSX element is one of them
136
+ if (importItem !== null && importItem !== void 0 && (_importItem$namedSpec = importItem.namedSpecifiers) !== null && _importItem$namedSpec !== void 0 && _importItem$namedSpec.length && !importItem.namedSpecifiers.includes(targetNode.local.name)) {
137
+ return;
138
+ }
139
+
140
+ // if we're here, there is a valid lint error.
65
141
  context.report({
66
142
  node: node,
67
- messageId: 'noDeprecatedApis',
143
+ messageId: 'noDeprecatedJSXAttributes',
68
144
  data: {
69
- propName: bannedApi
145
+ propName: jsxAttributeName
70
146
  }
71
147
  });
72
148
  });
73
149
  }
74
150
  };
75
151
  }
76
- };
152
+ });
77
153
  var _default = rule;
78
154
  exports.default = _default;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
- "version": "4.15.6",
3
+ "version": "4.16.0",
4
4
  "sideEffects": false
5
5
  }
@@ -0,0 +1,33 @@
1
+ {
2
+ "cssFn": [{
3
+ "moduleSpecifier": "@atlaskit/menu"
4
+ },
5
+ {
6
+ "moduleSpecifier": "@atlaskit/side-navigation"
7
+ }
8
+ ],
9
+ "overrides": [{
10
+ "moduleSpecifier": "@atlaskit/menu"
11
+ },
12
+ {
13
+ "moduleSpecifier": "@atlaskit/side-navigation"
14
+ }
15
+ ],
16
+ "type": [{
17
+ "moduleSpecifier": "@atlaskit/inline-message"
18
+ }],
19
+ "textColor": [{
20
+ "moduleSpecifier": "@atlaskit/logo"
21
+
22
+ }],
23
+ "iconColor": [{
24
+ "moduleSpecifier": "@atlaskit/logo"
25
+ }],
26
+ "iconGradientStart": [{
27
+ "moduleSpecifier": "@atlaskit/logo"
28
+ }],
29
+ "iconGradientStop": [{
30
+ "moduleSpecifier": "@atlaskit/logo"
31
+ }]
32
+
33
+ }
@@ -42,4 +42,5 @@ export const configs = {
42
42
  '@atlaskit/design-system/ensure-design-token-usage-spacing': 'error'
43
43
  }
44
44
  }
45
- };
45
+ };
46
+ export { filterActionableDeprecations } from './rules/no-deprecated-apis/helpers/filter-actionable-deprecations';
@@ -0,0 +1,50 @@
1
+ import semver from 'semver';
2
+ import { getValidatedConfig } from './validate-deprecated-apis-config';
3
+ export const filterActionableDeprecations = (originalDeprecatedConfig, rootPackageJson) => {
4
+ // verify the config is valid and parse it to an object
5
+ const validatedDeprecatedConfig = getValidatedConfig(originalDeprecatedConfig);
6
+
7
+ // verify the root package.json is valid and parse it to an object
8
+ let rootPackageDependencies;
9
+ try {
10
+ rootPackageDependencies = JSON.parse(rootPackageJson).dependencies;
11
+ if (!rootPackageDependencies) {
12
+ throw new Error('No dependencies found in the provided root package.json');
13
+ }
14
+ } catch (e) {
15
+ const error = e;
16
+ throw new Error(`Failed to parse root package.json: ${error.message}`);
17
+ }
18
+ const filteredConfig = {};
19
+ // filter out the deprecated APIs that are not actionable
20
+ for (const [apiKey, apiValues] of Object.entries(validatedDeprecatedConfig)) {
21
+ const filterApiValues = apiValues.filter(apiValue => {
22
+ var _rootPackageDependenc;
23
+ const {
24
+ moduleSpecifier,
25
+ actionableVersion
26
+ } = apiValue;
27
+
28
+ // if actionableVersion is not provided in the deprecated APIs config, it is actionable on all versions
29
+ if (!actionableVersion) {
30
+ return true;
31
+ }
32
+ const installedVersion = (_rootPackageDependenc = rootPackageDependencies) === null || _rootPackageDependenc === void 0 ? void 0 : _rootPackageDependenc[moduleSpecifier];
33
+ const coercedInstalledVersion = semver.coerce(installedVersion);
34
+ if (!coercedInstalledVersion) {
35
+ throw new Error(`No valid ${moduleSpecifier} found in the dependencies of root package.json.`);
36
+ }
37
+ const coercedActionableVersion = semver.coerce(actionableVersion);
38
+ if (!coercedActionableVersion) {
39
+ throw new Error(`Actionable version is invalid for ${moduleSpecifier} in the deprecated APIs config.`);
40
+ }
41
+ return semver.gte(coercedInstalledVersion, coercedActionableVersion);
42
+ });
43
+ if (filterApiValues.length > 0) {
44
+ Object.assign(filteredConfig, {
45
+ [apiKey]: filterApiValues
46
+ });
47
+ }
48
+ }
49
+ return JSON.stringify(filteredConfig);
50
+ };
@@ -0,0 +1,54 @@
1
+ import Ajv from 'ajv';
2
+ const deprecatedSchema = {
3
+ type: 'object',
4
+ patternProperties: {
5
+ '.+': {
6
+ type: 'array',
7
+ items: {
8
+ type: 'object',
9
+ properties: {
10
+ moduleSpecifier: {
11
+ type: 'string'
12
+ },
13
+ namedSpecifiers: {
14
+ type: 'array',
15
+ items: {
16
+ type: 'string'
17
+ }
18
+ },
19
+ actionableVersion: {
20
+ type: 'string'
21
+ }
22
+ },
23
+ required: ['moduleSpecifier'],
24
+ additionalProperites: false
25
+ }
26
+ }
27
+ },
28
+ allowMatchingProperties: true
29
+ };
30
+ export const getValidatedConfig = originalDeprecatedConfig => {
31
+ let parsedDeprecatedConfig = {};
32
+ try {
33
+ parsedDeprecatedConfig = JSON.parse(originalDeprecatedConfig);
34
+ } catch (e) {
35
+ const error = e;
36
+ throw new Error(`Failed to parse JSON string: ${error.message}`);
37
+ }
38
+ const ajv = new Ajv({
39
+ allErrors: true
40
+ });
41
+ const validate = ajv.compile(deprecatedSchema);
42
+ const valid = validate(parsedDeprecatedConfig);
43
+ if (!valid) {
44
+ const {
45
+ errors
46
+ } = validate;
47
+ if (errors && errors.length) {
48
+ throw new Error(`Deprecated APIs config is invalid: ${errors}`);
49
+ } else {
50
+ throw new Error('Failed to validate deprecated APIs config with unknown error.');
51
+ }
52
+ }
53
+ return parsedDeprecatedConfig;
54
+ };
@@ -1,69 +1,135 @@
1
- import { closestOfType, isNodeOfType } from 'eslint-codemod-utils';
2
- import { getImportedNodeBySource } from '../utils/get-import-node-by-source';
3
- const unsafeOverridesConfig = {
4
- cssFn: ['@atlaskit/menu', '@atlaskit/side-navigation'],
5
- overrides: ['@atlaskit/drawer', '@atlaskit/menu', '@atlaskit/side-navigation'],
6
- innerRef: ['@atlaskit/banner'],
7
- isOpen: ['@atlaskit/banner'],
8
- type: ['@atlaskit/inline-message']
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import { AST_NODE_TYPES, ASTUtils, ESLintUtils } from '@typescript-eslint/utils';
4
+ const createRule = ESLintUtils.RuleCreator(name => name);
5
+ export const noDeprecatedJSXAttributeMessageId = 'noDeprecatedJSXAttributes';
6
+ const isNodeOfType = (node, nodeType) => ASTUtils.isNodeOfType(nodeType)(node);
7
+ const isImportDeclaration = programStatement => {
8
+ return (programStatement === null || programStatement === void 0 ? void 0 : programStatement.type) === 'ImportDeclaration';
9
9
  };
10
- const unsafeOverrides = ['cssFn', 'overrides', 'innerRef', 'isOpen', 'type'];
11
- const rule = {
10
+ const findJSXElementName = jsxAttributeNode => {
11
+ if (!jsxAttributeNode.parent || !isNodeOfType(jsxAttributeNode.parent, AST_NODE_TYPES.JSXOpeningElement)) {
12
+ return;
13
+ }
14
+ const openingElement = jsxAttributeNode.parent;
15
+ if (!isNodeOfType(openingElement.name, AST_NODE_TYPES.JSXIdentifier)) {
16
+ return;
17
+ }
18
+ return openingElement.name.name;
19
+ };
20
+ const getConfig = () => {
21
+ const configPath = path.resolve(__dirname, '..', '..', '..', 'configs', 'deprecated.json');
22
+ const source = fs.readFileSync(configPath, 'utf8');
23
+ const parsedConfig = JSON.parse(source);
24
+ return parsedConfig;
25
+ };
26
+ export const name = 'no-deprecated-apis';
27
+ const rule = createRule({
28
+ name,
29
+ defaultOptions: [{
30
+ deprecatedConfig: getConfig()
31
+ }],
12
32
  meta: {
13
33
  type: 'suggestion',
14
34
  docs: {
15
35
  description: 'Disallow specified APIs that have been marked as deprecated and/or discouraged.',
16
- recommended: true
36
+ recommended: 'warn'
17
37
  },
18
38
  messages: {
19
- noDeprecatedApis: `The prop "{{propName}}" has been deprecated. It will be removed in the next major release.`
20
- }
39
+ noDeprecatedJSXAttributes: 'The JSX attribute {{propName}} has been deprecated.'
40
+ },
41
+ schema: [{
42
+ type: 'object',
43
+ properties: {
44
+ deprecatedConfig: {
45
+ type: 'object',
46
+ properties: {
47
+ '.+': {
48
+ type: 'array',
49
+ items: {
50
+ type: 'object',
51
+ properties: {
52
+ moduleSpecifier: {
53
+ type: 'string'
54
+ },
55
+ namedSpecifiers: {
56
+ type: 'array',
57
+ items: {
58
+ type: 'string'
59
+ }
60
+ },
61
+ actionableVersion: {
62
+ type: 'string'
63
+ }
64
+ },
65
+ required: ['moduleSpecifier'],
66
+ additionalProperites: false
67
+ }
68
+ }
69
+ }
70
+ }
71
+ }
72
+ }]
21
73
  },
22
- create(context) {
74
+ create(context, [options]) {
75
+ var _context$options$;
76
+ // Get rule configuration
77
+ const {
78
+ deprecatedConfig: defaultDeprecatedConfig
79
+ } = options;
80
+
81
+ // Get the rule configuration specified otherwise use default config.
82
+ // A bit confusing as it seems that the default options have precedence over the user specified options.
83
+ const deprecatedConfig = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || defaultDeprecatedConfig;
23
84
  return {
24
85
  // find JSX atribute - find name of attribute - get source and find relevant identifiers.
25
86
  JSXAttribute(node) {
26
- var _node$name;
27
- if (!isNodeOfType(node, 'JSXAttribute')) {
87
+ const jsxAttributeIdentifier = node.name;
88
+ if (!isNodeOfType(jsxAttributeIdentifier, AST_NODE_TYPES.JSXIdentifier)) {
28
89
  return;
29
90
  }
30
- if (!unsafeOverrides.includes(node === null || node === void 0 ? void 0 : (_node$name = node.name) === null || _node$name === void 0 ? void 0 : _node$name.name)) {
91
+ const jsxAttributeName = jsxAttributeIdentifier.name;
92
+ if (!deprecatedConfig[jsxAttributeName]) {
31
93
  return;
32
94
  }
33
- const source = context.getSourceCode();
34
- const bannedApi = node.name.name;
35
-
36
- // traverse the tree to the nearest JSX Element and get its name
37
- const closesetJSXElement = closestOfType(node, 'JSXOpeningElement');
38
- const jsxElementName = isNodeOfType(closesetJSXElement === null || closesetJSXElement === void 0 ? void 0 : closesetJSXElement.name, 'JSXIdentifier') && closesetJSXElement.name.name;
95
+ const jsxElementName = findJSXElementName(node);
39
96
  if (!jsxElementName) {
40
97
  return;
41
98
  }
99
+ const source = context.getSourceCode();
42
100
 
43
101
  // find an import for the path of the banned api
44
- unsafeOverridesConfig[bannedApi].forEach(path => {
45
- const importNode = getImportedNodeBySource(source, path);
102
+ deprecatedConfig[jsxAttributeName].forEach(importItem => {
103
+ var _importItem$namedSpec;
104
+ const importNode = source.ast.body.filter(isImportDeclaration).find(node => node.source.value === importItem.moduleSpecifier);
46
105
  if (!importNode) {
47
106
  return;
48
107
  }
49
108
 
50
109
  // find an import that matches our JSX element
51
- const hasTargetNode = importNode.specifiers.some(node => node.local.name === jsxElementName);
52
- if (!hasTargetNode) {
110
+ const targetNode = importNode.specifiers.find(node => node.local.name === jsxElementName);
111
+
112
+ // check if the import exists
113
+ if (!targetNode) {
53
114
  return;
54
115
  }
55
116
 
56
- // if we're here the import exists and there is a valid lint error.
117
+ // if the import has named specifiers, check if the JSX element is one of them
118
+ if (importItem !== null && importItem !== void 0 && (_importItem$namedSpec = importItem.namedSpecifiers) !== null && _importItem$namedSpec !== void 0 && _importItem$namedSpec.length && !importItem.namedSpecifiers.includes(targetNode.local.name)) {
119
+ return;
120
+ }
121
+
122
+ // if we're here, there is a valid lint error.
57
123
  context.report({
58
- node: node,
59
- messageId: 'noDeprecatedApis',
124
+ node,
125
+ messageId: 'noDeprecatedJSXAttributes',
60
126
  data: {
61
- propName: bannedApi
127
+ propName: jsxAttributeName
62
128
  }
63
129
  });
64
130
  });
65
131
  }
66
132
  };
67
133
  }
68
- };
134
+ });
69
135
  export default rule;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
- "version": "4.15.6",
3
+ "version": "4.16.0",
4
4
  "sideEffects": false
5
5
  }
package/dist/esm/index.js CHANGED
@@ -42,4 +42,5 @@ export var configs = {
42
42
  '@atlaskit/design-system/ensure-design-token-usage-spacing': 'error'
43
43
  }
44
44
  }
45
- };
45
+ };
46
+ export { filterActionableDeprecations } from './rules/no-deprecated-apis/helpers/filter-actionable-deprecations';
@@ -0,0 +1,51 @@
1
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
2
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
3
+ import semver from 'semver';
4
+ import { getValidatedConfig } from './validate-deprecated-apis-config';
5
+ export var filterActionableDeprecations = function filterActionableDeprecations(originalDeprecatedConfig, rootPackageJson) {
6
+ // verify the config is valid and parse it to an object
7
+ var validatedDeprecatedConfig = getValidatedConfig(originalDeprecatedConfig);
8
+
9
+ // verify the root package.json is valid and parse it to an object
10
+ var rootPackageDependencies;
11
+ try {
12
+ rootPackageDependencies = JSON.parse(rootPackageJson).dependencies;
13
+ if (!rootPackageDependencies) {
14
+ throw new Error('No dependencies found in the provided root package.json');
15
+ }
16
+ } catch (e) {
17
+ var error = e;
18
+ throw new Error("Failed to parse root package.json: ".concat(error.message));
19
+ }
20
+ var filteredConfig = {};
21
+ // filter out the deprecated APIs that are not actionable
22
+ for (var _i = 0, _Object$entries = Object.entries(validatedDeprecatedConfig); _i < _Object$entries.length; _i++) {
23
+ var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
24
+ apiKey = _Object$entries$_i[0],
25
+ apiValues = _Object$entries$_i[1];
26
+ var filterApiValues = apiValues.filter(function (apiValue) {
27
+ var _rootPackageDependenc;
28
+ var moduleSpecifier = apiValue.moduleSpecifier,
29
+ actionableVersion = apiValue.actionableVersion;
30
+
31
+ // if actionableVersion is not provided in the deprecated APIs config, it is actionable on all versions
32
+ if (!actionableVersion) {
33
+ return true;
34
+ }
35
+ var installedVersion = (_rootPackageDependenc = rootPackageDependencies) === null || _rootPackageDependenc === void 0 ? void 0 : _rootPackageDependenc[moduleSpecifier];
36
+ var coercedInstalledVersion = semver.coerce(installedVersion);
37
+ if (!coercedInstalledVersion) {
38
+ throw new Error("No valid ".concat(moduleSpecifier, " found in the dependencies of root package.json."));
39
+ }
40
+ var coercedActionableVersion = semver.coerce(actionableVersion);
41
+ if (!coercedActionableVersion) {
42
+ throw new Error("Actionable version is invalid for ".concat(moduleSpecifier, " in the deprecated APIs config."));
43
+ }
44
+ return semver.gte(coercedInstalledVersion, coercedActionableVersion);
45
+ });
46
+ if (filterApiValues.length > 0) {
47
+ Object.assign(filteredConfig, _defineProperty({}, apiKey, filterApiValues));
48
+ }
49
+ }
50
+ return JSON.stringify(filteredConfig);
51
+ };
@@ -0,0 +1,52 @@
1
+ import Ajv from 'ajv';
2
+ var deprecatedSchema = {
3
+ type: 'object',
4
+ patternProperties: {
5
+ '.+': {
6
+ type: 'array',
7
+ items: {
8
+ type: 'object',
9
+ properties: {
10
+ moduleSpecifier: {
11
+ type: 'string'
12
+ },
13
+ namedSpecifiers: {
14
+ type: 'array',
15
+ items: {
16
+ type: 'string'
17
+ }
18
+ },
19
+ actionableVersion: {
20
+ type: 'string'
21
+ }
22
+ },
23
+ required: ['moduleSpecifier'],
24
+ additionalProperites: false
25
+ }
26
+ }
27
+ },
28
+ allowMatchingProperties: true
29
+ };
30
+ export var getValidatedConfig = function getValidatedConfig(originalDeprecatedConfig) {
31
+ var parsedDeprecatedConfig = {};
32
+ try {
33
+ parsedDeprecatedConfig = JSON.parse(originalDeprecatedConfig);
34
+ } catch (e) {
35
+ var error = e;
36
+ throw new Error("Failed to parse JSON string: ".concat(error.message));
37
+ }
38
+ var ajv = new Ajv({
39
+ allErrors: true
40
+ });
41
+ var validate = ajv.compile(deprecatedSchema);
42
+ var valid = validate(parsedDeprecatedConfig);
43
+ if (!valid) {
44
+ var errors = validate.errors;
45
+ if (errors && errors.length) {
46
+ throw new Error("Deprecated APIs config is invalid: ".concat(errors));
47
+ } else {
48
+ throw new Error('Failed to validate deprecated APIs config with unknown error.');
49
+ }
50
+ }
51
+ return parsedDeprecatedConfig;
52
+ };
@@ -1,71 +1,144 @@
1
- import { closestOfType, isNodeOfType } from 'eslint-codemod-utils';
2
- import { getImportedNodeBySource } from '../utils/get-import-node-by-source';
3
- var unsafeOverridesConfig = {
4
- cssFn: ['@atlaskit/menu', '@atlaskit/side-navigation'],
5
- overrides: ['@atlaskit/drawer', '@atlaskit/menu', '@atlaskit/side-navigation'],
6
- innerRef: ['@atlaskit/banner'],
7
- isOpen: ['@atlaskit/banner'],
8
- type: ['@atlaskit/inline-message']
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import fs from 'fs';
3
+ import path from 'path';
4
+ import { AST_NODE_TYPES, ASTUtils, ESLintUtils } from '@typescript-eslint/utils';
5
+ var createRule = ESLintUtils.RuleCreator(function (name) {
6
+ return name;
7
+ });
8
+ export var noDeprecatedJSXAttributeMessageId = 'noDeprecatedJSXAttributes';
9
+ var isNodeOfType = function isNodeOfType(node, nodeType) {
10
+ return ASTUtils.isNodeOfType(nodeType)(node);
9
11
  };
10
- var unsafeOverrides = ['cssFn', 'overrides', 'innerRef', 'isOpen', 'type'];
11
- var rule = {
12
+ var isImportDeclaration = function isImportDeclaration(programStatement) {
13
+ return (programStatement === null || programStatement === void 0 ? void 0 : programStatement.type) === 'ImportDeclaration';
14
+ };
15
+ var findJSXElementName = function findJSXElementName(jsxAttributeNode) {
16
+ if (!jsxAttributeNode.parent || !isNodeOfType(jsxAttributeNode.parent, AST_NODE_TYPES.JSXOpeningElement)) {
17
+ return;
18
+ }
19
+ var openingElement = jsxAttributeNode.parent;
20
+ if (!isNodeOfType(openingElement.name, AST_NODE_TYPES.JSXIdentifier)) {
21
+ return;
22
+ }
23
+ return openingElement.name.name;
24
+ };
25
+ var getConfig = function getConfig() {
26
+ var configPath = path.resolve(__dirname, '..', '..', '..', 'configs', 'deprecated.json');
27
+ var source = fs.readFileSync(configPath, 'utf8');
28
+ var parsedConfig = JSON.parse(source);
29
+ return parsedConfig;
30
+ };
31
+ export var name = 'no-deprecated-apis';
32
+ var rule = createRule({
33
+ name: name,
34
+ defaultOptions: [{
35
+ deprecatedConfig: getConfig()
36
+ }],
12
37
  meta: {
13
38
  type: 'suggestion',
14
39
  docs: {
15
40
  description: 'Disallow specified APIs that have been marked as deprecated and/or discouraged.',
16
- recommended: true
41
+ recommended: 'warn'
17
42
  },
18
43
  messages: {
19
- noDeprecatedApis: "The prop \"{{propName}}\" has been deprecated. It will be removed in the next major release."
20
- }
44
+ noDeprecatedJSXAttributes: 'The JSX attribute {{propName}} has been deprecated.'
45
+ },
46
+ schema: [{
47
+ type: 'object',
48
+ properties: {
49
+ deprecatedConfig: {
50
+ type: 'object',
51
+ properties: {
52
+ '.+': {
53
+ type: 'array',
54
+ items: {
55
+ type: 'object',
56
+ properties: {
57
+ moduleSpecifier: {
58
+ type: 'string'
59
+ },
60
+ namedSpecifiers: {
61
+ type: 'array',
62
+ items: {
63
+ type: 'string'
64
+ }
65
+ },
66
+ actionableVersion: {
67
+ type: 'string'
68
+ }
69
+ },
70
+ required: ['moduleSpecifier'],
71
+ additionalProperites: false
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
77
+ }]
21
78
  },
22
- create: function create(context) {
79
+ create: function create(context, _ref) {
80
+ var _context$options$;
81
+ var _ref2 = _slicedToArray(_ref, 1),
82
+ options = _ref2[0];
83
+ // Get rule configuration
84
+ var defaultDeprecatedConfig = options.deprecatedConfig;
85
+
86
+ // Get the rule configuration specified otherwise use default config.
87
+ // A bit confusing as it seems that the default options have precedence over the user specified options.
88
+ var deprecatedConfig = ((_context$options$ = context.options[0]) === null || _context$options$ === void 0 ? void 0 : _context$options$.deprecatedConfig) || defaultDeprecatedConfig;
23
89
  return {
24
90
  // find JSX atribute - find name of attribute - get source and find relevant identifiers.
25
91
  JSXAttribute: function JSXAttribute(node) {
26
- var _node$name;
27
- if (!isNodeOfType(node, 'JSXAttribute')) {
92
+ var jsxAttributeIdentifier = node.name;
93
+ if (!isNodeOfType(jsxAttributeIdentifier, AST_NODE_TYPES.JSXIdentifier)) {
28
94
  return;
29
95
  }
30
- if (!unsafeOverrides.includes(node === null || node === void 0 ? void 0 : (_node$name = node.name) === null || _node$name === void 0 ? void 0 : _node$name.name)) {
96
+ var jsxAttributeName = jsxAttributeIdentifier.name;
97
+ if (!deprecatedConfig[jsxAttributeName]) {
31
98
  return;
32
99
  }
33
- var source = context.getSourceCode();
34
- var bannedApi = node.name.name;
35
-
36
- // traverse the tree to the nearest JSX Element and get its name
37
- var closesetJSXElement = closestOfType(node, 'JSXOpeningElement');
38
- var jsxElementName = isNodeOfType(closesetJSXElement === null || closesetJSXElement === void 0 ? void 0 : closesetJSXElement.name, 'JSXIdentifier') && closesetJSXElement.name.name;
100
+ var jsxElementName = findJSXElementName(node);
39
101
  if (!jsxElementName) {
40
102
  return;
41
103
  }
104
+ var source = context.getSourceCode();
42
105
 
43
106
  // find an import for the path of the banned api
44
- unsafeOverridesConfig[bannedApi].forEach(function (path) {
45
- var importNode = getImportedNodeBySource(source, path);
107
+ deprecatedConfig[jsxAttributeName].forEach(function (importItem) {
108
+ var _importItem$namedSpec;
109
+ var importNode = source.ast.body.filter(isImportDeclaration).find(function (node) {
110
+ return node.source.value === importItem.moduleSpecifier;
111
+ });
46
112
  if (!importNode) {
47
113
  return;
48
114
  }
49
115
 
50
116
  // find an import that matches our JSX element
51
- var hasTargetNode = importNode.specifiers.some(function (node) {
117
+ var targetNode = importNode.specifiers.find(function (node) {
52
118
  return node.local.name === jsxElementName;
53
119
  });
54
- if (!hasTargetNode) {
120
+
121
+ // check if the import exists
122
+ if (!targetNode) {
55
123
  return;
56
124
  }
57
125
 
58
- // if we're here the import exists and there is a valid lint error.
126
+ // if the import has named specifiers, check if the JSX element is one of them
127
+ if (importItem !== null && importItem !== void 0 && (_importItem$namedSpec = importItem.namedSpecifiers) !== null && _importItem$namedSpec !== void 0 && _importItem$namedSpec.length && !importItem.namedSpecifiers.includes(targetNode.local.name)) {
128
+ return;
129
+ }
130
+
131
+ // if we're here, there is a valid lint error.
59
132
  context.report({
60
133
  node: node,
61
- messageId: 'noDeprecatedApis',
134
+ messageId: 'noDeprecatedJSXAttributes',
62
135
  data: {
63
- propName: bannedApi
136
+ propName: jsxAttributeName
64
137
  }
65
138
  });
66
139
  });
67
140
  }
68
141
  };
69
142
  }
70
- };
143
+ });
71
144
  export default rule;
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
- "version": "4.15.6",
3
+ "version": "4.16.0",
4
4
  "sideEffects": false
5
5
  }
@@ -1,7 +1,9 @@
1
1
  export declare const rules: {
2
2
  'ensure-design-token-usage': import("eslint").Rule.RuleModule;
3
3
  'icon-label': import("eslint").Rule.RuleModule;
4
- 'no-deprecated-apis': import("eslint").Rule.RuleModule;
4
+ 'no-deprecated-apis': import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleModule<string, [{
5
+ deprecatedConfig: import("./rules/no-deprecated-apis").DeprecatedConfig;
6
+ }], import("@typescript-eslint/utils/dist/ts-eslint/Rule").RuleListener>;
5
7
  'no-deprecated-design-token-usage': import("eslint").Rule.RuleModule;
6
8
  'no-deprecated-imports': import("eslint").Rule.RuleModule;
7
9
  'no-banned-imports': import("eslint").Rule.RuleModule;
@@ -34,3 +36,4 @@ export declare const configs: {
34
36
  };
35
37
  };
36
38
  };
39
+ export { filterActionableDeprecations } from './rules/no-deprecated-apis/helpers/filter-actionable-deprecations';
@@ -0,0 +1 @@
1
+ export declare const filterActionableDeprecations: (originalDeprecatedConfig: string, rootPackageJson: string) => string;
@@ -0,0 +1,2 @@
1
+ import type { DeprecatedConfig } from '../index';
2
+ export declare const getValidatedConfig: (originalDeprecatedConfig: string) => DeprecatedConfig;
@@ -1,3 +1,15 @@
1
- import type { Rule } from 'eslint';
2
- declare const rule: Rule.RuleModule;
1
+ import { TSESLint } from '@typescript-eslint/utils';
2
+ interface DeprecatedConfigEntry {
3
+ moduleSpecifier: string;
4
+ namedSpecifiers?: string[];
5
+ actionableVersion?: string;
6
+ }
7
+ export interface DeprecatedConfig {
8
+ [key: string]: DeprecatedConfigEntry[];
9
+ }
10
+ export declare const noDeprecatedJSXAttributeMessageId = "noDeprecatedJSXAttributes";
11
+ export declare const name = "no-deprecated-apis";
12
+ declare const rule: TSESLint.RuleModule<string, [{
13
+ deprecatedConfig: DeprecatedConfig;
14
+ }], TSESLint.RuleListener>;
3
15
  export default rule;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@atlaskit/eslint-plugin-design-system",
3
3
  "description": "The essential plugin for use with the Atlassian Design System.",
4
- "version": "4.15.6",
4
+ "version": "4.16.0",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "publishConfig": {
7
7
  "registry": "https://registry.npmjs.org/"
@@ -34,7 +34,10 @@
34
34
  "dependencies": {
35
35
  "@atlaskit/tokens": "^1.2.0",
36
36
  "@babel/runtime": "^7.0.0",
37
- "eslint-codemod-utils": "^1.6.3"
37
+ "@typescript-eslint/utils": "^5.48.1",
38
+ "ajv": "^6.12.6",
39
+ "eslint-codemod-utils": "^1.6.3",
40
+ "semver": "^7.3.0"
38
41
  },
39
42
  "devDependencies": {
40
43
  "@atlaskit/ds-lib": "^2.1.0",
@@ -48,6 +51,9 @@
48
51
  "tsconfig-paths": "^3.9.0",
49
52
  "typescript": "4.5.5"
50
53
  },
54
+ "scripts": {
55
+ "ak-postbuild": "cp -r configs dist"
56
+ },
51
57
  "techstack": {
52
58
  "@atlassian/frontend": {
53
59
  "import-structure": "atlassian-conventions",