eslint-plugin-package-json 0.2.0 → 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.
package/.eslintrc CHANGED
@@ -5,7 +5,7 @@
5
5
  },
6
6
  "extends": ["eslint:recommended"],
7
7
  "parserOptions": {
8
- "ecmaVersion": 6,
8
+ "ecmaVersion": 2021,
9
9
  "sourceType": "module"
10
10
  }
11
11
  }
package/README.md CHANGED
@@ -4,47 +4,46 @@ Rules for valid, consistent, and readable package.json files
4
4
 
5
5
  ## Installation
6
6
 
7
- You'll first need to install [ESLint](http://eslint.org):
7
+ You'll first need to install [ESLint](http://eslint.org) >=8 and `eslint-plugin-package-json`:
8
8
 
9
- ```
10
- $ npm i eslint --save-dev
11
- ```
12
-
13
- Next, install `eslint-plugin-package-json`:
14
-
15
- ```
16
- $ npm install eslint-plugin-package-json --save-dev
9
+ ```shell
10
+ $ npm install eslint eslint-plugin-package-json --save-dev
17
11
  ```
18
12
 
19
13
  **Note:** If you installed ESLint globally (using the `-g` flag) then you must also install `eslint-plugin-package-json` globally.
20
14
 
21
15
  ## Usage
22
16
 
23
- Add `package-json` to the plugins section of your `.eslintrc` configuration file. You can omit the `eslint-plugin-` prefix:
24
-
25
- ```json
26
- {
27
- "plugins": ["package-json"]
28
- }
29
- ```
30
-
31
- Use the prepackaged config by adding an "extends" property, or appending to an existing "extends" property:
32
-
33
- ```json
34
- {
35
- "extends": ["eslint:recommended", "plugin:package-json/recommended"],
36
- "plugins": ["package-json"]
37
- }
17
+ Add an override to your ESLint configuration file that specifies this plugin, [`jsonc-eslint-parser`](https://github.com/ota-meshi/jsonc-eslint-parser) and its recommended rules for your `package.json` file:
18
+
19
+ ```js
20
+ module.exports = {
21
+ overrides: [
22
+ {
23
+ extends: ['plugin:package-json/recommended'],
24
+ files: ['package.json'],
25
+ parser: 'jsonc-eslint-parser'
26
+ plugins: ['package-json']
27
+ }
28
+ ]
29
+ };
38
30
  ```
39
31
 
40
32
  Or, individually configure the rules you want to use under the rules section.
41
33
 
42
- ```json
43
- {
44
- "rules": {
45
- "package-json/rule-name": 2
46
- }
47
- }
34
+ ```js
35
+ module.exports = {
36
+ overrides: [
37
+ {
38
+ files: ['package.json'],
39
+ parser: 'jsonc-eslint-parser'
40
+ plugins: ['package-json'],
41
+ rules: {
42
+ 'package-json/valid-package-def': 'error'
43
+ }
44
+ }
45
+ ]
46
+ };
48
47
  ```
49
48
 
50
49
  ## Supported Rules
@@ -0,0 +1,17 @@
1
+ const isPackageJson = filePath =>
2
+ filePath.endsWith('/package.json') || filePath === 'package.json';
3
+
4
+ function createRule(rule) {
5
+ return {
6
+ ...rule,
7
+ create(context) {
8
+ if (!isPackageJson(context.filename)) {
9
+ return {};
10
+ }
11
+
12
+ return rule.create(context);
13
+ }
14
+ };
15
+ }
16
+
17
+ module.exports.createRule = createRule;
package/lib/index.js CHANGED
@@ -1,34 +1,19 @@
1
1
  'use strict';
2
2
 
3
- //------------------------------------------------------------------------------
4
- // Requirements
5
- //------------------------------------------------------------------------------
3
+ const orderProperties = require('./rules/order-properties');
4
+ const sortCollections = require('./rules/sort-collections');
5
+ const validLocalDependency = require('./rules/valid-local-dependency');
6
+ const validPackageDef = require('./rules/valid-package-def');
6
7
 
7
- var requireIndex = require('requireindex');
8
-
9
- //------------------------------------------------------------------------------
10
- // Plugin Definition
11
- //------------------------------------------------------------------------------
12
-
13
- // import all rules in lib/rules
14
- module.exports.rules = requireIndex(__dirname + '/rules');
15
-
16
- // import processors
17
- const PackageJsonProcessor = require('./processors/PackageJsonProcessor');
18
- module.exports.processors = {
19
- // adapted from https://github.com/godaddy/eslint-plugin-i18n-json
20
- // thank you!
21
- '.json': PackageJsonProcessor
22
- // add your processors here
23
- };
24
-
25
- module.exports.configs = {
26
- recommended: {
27
- rules: {
28
- 'package-json/sort-collections': 'error',
29
- 'package-json/order-properties': 'warn',
30
- 'package-json/valid-package-def': 'error',
31
- 'package-json/valid-local-dependency': 'error'
8
+ module.exports = {
9
+ configs: {
10
+ recommended: {
11
+ rules: {
12
+ 'order-properties': orderProperties,
13
+ 'sort-collections': sortCollections,
14
+ 'valid-local-dependency': validLocalDependency,
15
+ 'valid-package-def': validPackageDef
16
+ }
32
17
  }
33
18
  }
34
19
  };
@@ -1,16 +1,12 @@
1
1
  'use strict';
2
- const disparity = require('disparity');
2
+ const { createRule } = require('../createRule');
3
3
  const sortPackageJson = require('sort-package-json');
4
- const {
5
- isPackageJson,
6
- extractPackageObjectFromAST
7
- } = require('../processors/PackageJsonProcessor');
8
4
 
9
5
  //------------------------------------------------------------------------------
10
6
  // Rule Definition
11
7
  //------------------------------------------------------------------------------
12
8
 
13
- const standardOrder = [
9
+ const standardOrderLegacy = [
14
10
  'name',
15
11
  'version',
16
12
  'private',
@@ -41,7 +37,7 @@ const standardOrder = [
41
37
  'cpu'
42
38
  ];
43
39
 
44
- module.exports = {
40
+ module.exports = createRule({
45
41
  meta: {
46
42
  docs: {
47
43
  description:
@@ -49,7 +45,7 @@ module.exports = {
49
45
  category: 'Best Practices',
50
46
  recommended: true
51
47
  },
52
- fixable: 'code', // or "code" or "whitespace"
48
+ fixable: 'code',
53
49
  schema: [
54
50
  {
55
51
  type: 'object',
@@ -75,50 +71,44 @@ module.exports = {
75
71
 
76
72
  create(context) {
77
73
  return {
78
- 'Program:exit': node => {
74
+ 'Program:exit'() {
75
+ const { ast, text } = context.sourceCode;
76
+
79
77
  const options = context.options[0] || { order: 'legacy' };
80
- if (!isPackageJson(context.getFilename())) {
81
- return;
82
- }
83
- const sourceCode = context.getSourceCode();
84
- const packageRoot = extractPackageObjectFromAST(node);
85
- const original = JSON.parse(sourceCode.getText(packageRoot));
86
78
  const requiredOrder =
87
- options.order === 'legacy' ? standardOrder : options.order;
88
-
79
+ options.order === 'legacy'
80
+ ? standardOrderLegacy
81
+ : options.order;
89
82
  const orderedSource = sortPackageJson(
90
- original,
83
+ JSON.parse(text),
91
84
  requiredOrder === 'sort-package-json'
92
85
  ? undefined
93
86
  : {
94
87
  sortOrder: requiredOrder
95
88
  }
96
89
  );
90
+ const orderedKeys = Object.keys(orderedSource);
97
91
 
98
- const diff = disparity.unified(
99
- JSON.stringify(orderedSource, null, 2),
100
- JSON.stringify(original, null, 2)
101
- );
102
- if (diff) {
103
- context.report({
104
- node: packageRoot,
105
- message:
106
- 'Package top-level properties are not ordered in the NPM standard way:\n\n{{ diff }}',
107
- data: {
108
- diff: diff
109
- .split('\n')
110
- .slice(3)
111
- .join('\n')
112
- },
113
- fix(fixer) {
114
- return fixer.replaceText(
115
- node,
116
- JSON.stringify(orderedSource, null, 2) + `\n`
117
- );
118
- }
119
- });
92
+ const { properties } = ast.body[0].expression;
93
+
94
+ for (let i = 0; i < properties.length; i += 1) {
95
+ if (properties[i].value !== orderedKeys[i]) {
96
+ context.report({
97
+ node: context.sourceCode.ast,
98
+ message:
99
+ 'Package top-level properties are not ordered in the npm standard way. Run the ESLint auto-fixer to correct.',
100
+ fix(fixer) {
101
+ return fixer.replaceText(
102
+ context.sourceCode.ast,
103
+ JSON.stringify(orderedSource, null, 2) +
104
+ `\n`
105
+ );
106
+ }
107
+ });
108
+ }
109
+ break;
120
110
  }
121
111
  }
122
112
  };
123
113
  }
124
- };
114
+ });
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
- const { isPackageJson } = require('../processors/PackageJsonProcessor');
2
+
3
+ const { createRule } = require('../createRule');
3
4
 
4
5
  //------------------------------------------------------------------------------
5
6
  // Rule Definition
@@ -11,7 +12,7 @@ const defaultCollections = [
11
12
  'peerDependencies',
12
13
  'config'
13
14
  ];
14
- module.exports = {
15
+ module.exports = createRule({
15
16
  meta: {
16
17
  docs: {
17
18
  description:
@@ -30,16 +31,13 @@ module.exports = {
30
31
  ]
31
32
  },
32
33
 
33
- create: function(context) {
34
+ create(context) {
34
35
  const toSort = context.options[0] || defaultCollections;
35
36
  return {
36
- 'Property:exit': node => {
37
- if (!isPackageJson(context.getFilename())) {
38
- return;
39
- }
37
+ 'JSONProperty:exit'(node) {
40
38
  const collection = node.value;
41
39
  if (
42
- collection.type === 'ObjectExpression' &&
40
+ collection.type === 'JSONObjectExpression' &&
43
41
  toSort.includes(node.key.value)
44
42
  ) {
45
43
  const currentOrder = collection.properties;
@@ -85,4 +83,4 @@ module.exports = {
85
83
  }
86
84
  };
87
85
  }
88
- };
86
+ });
@@ -4,35 +4,26 @@
4
4
  */
5
5
  'use strict';
6
6
  const path = require('path');
7
- const {
8
- isPackageJson,
9
- extractPackageObjectFromAST
10
- } = require('../processors/PackageJsonProcessor');
7
+ const { createRule } = require('../createRule');
11
8
 
12
9
  //------------------------------------------------------------------------------
13
10
  // Rule Definition
14
11
  //------------------------------------------------------------------------------
15
12
 
16
- module.exports = {
13
+ module.exports = createRule({
17
14
  meta: {
18
15
  docs: {
19
16
  description:
20
17
  'Checks existence of local dependencies in the package.json',
21
18
  category: 'Best Practices',
22
19
  recommended: true
23
- },
24
- fixable: null // or "code" or "whitespace"
20
+ }
25
21
  },
26
22
 
27
23
  create: function(context) {
28
24
  return {
29
- 'Program:exit': node => {
30
- if (!isPackageJson(context.getFilename())) {
31
- return;
32
- }
33
- const sourceCode = context.getSourceCode();
34
- const packageRoot = extractPackageObjectFromAST(node);
35
- const original = JSON.parse(sourceCode.getText(packageRoot));
25
+ 'Program:exit'() {
26
+ const original = JSON.parse(context.sourceCode.text);
36
27
  const {
37
28
  dependencies,
38
29
  peerDependencies,
@@ -59,13 +50,13 @@ module.exports = {
59
50
  try {
60
51
  if (!require.resolve(filePath)) {
61
52
  context.report({
62
- node: packageRoot,
53
+ node: context.sourceCode.ast,
63
54
  message: `The package ${key} does not exist given the specified path: ${value}.`
64
55
  });
65
56
  }
66
57
  } catch (e) {
67
58
  context.report({
68
- node: packageRoot,
59
+ node: context.sourceCode.ast,
69
60
  message: `The package ${key} does not exist given the specified path: ${value}.`
70
61
  });
71
62
  }
@@ -82,4 +73,4 @@ module.exports = {
82
73
  }
83
74
  };
84
75
  }
85
- };
76
+ });
@@ -1,9 +1,6 @@
1
1
  'use strict';
2
2
  const { PJV: PackageValidator } = require('package-json-validator');
3
- const {
4
- isPackageJson,
5
- extractPackageObjectFromAST
6
- } = require('../processors/PackageJsonProcessor');
3
+ const { createRule } = require('../createRule');
7
4
 
8
5
  //------------------------------------------------------------------------------
9
6
  // Rule Definition
@@ -21,41 +18,32 @@ const unusedErrorPatterns = [
21
18
  const isUsableError = errorText =>
22
19
  unusedErrorPatterns.every(pattern => !pattern.test(errorText));
23
20
 
24
- module.exports = {
21
+ module.exports = createRule({
25
22
  meta: {
26
23
  docs: {
27
24
  description:
28
25
  'Enforce that package.json has all properties required by NPM spec',
29
26
  category: 'Best Practices',
30
27
  recommended: true
31
- },
32
- fixable: null // or "code" or "whitespace"
28
+ }
33
29
  },
34
30
 
35
31
  create: function(context) {
36
32
  return {
37
- 'Program:exit': node => {
38
- if (!isPackageJson(context.getFilename())) {
39
- return;
40
- }
41
- const packageRoot = extractPackageObjectFromAST(node);
42
-
43
- const { critical, errors } = PackageValidator.validate(
44
- context.getSourceCode().getText(packageRoot)
33
+ 'Program:exit'() {
34
+ const { errors } = PackageValidator.validate(
35
+ context.sourceCode.text
45
36
  );
46
37
 
47
- if (critical || errors) {
48
- const allErrors = [...(critical || []), ...errors];
49
- allErrors.filter(isUsableError).forEach(
50
- message =>
51
- message &&
52
- context.report({
53
- node: packageRoot,
54
- message
55
- })
56
- );
57
- }
38
+ (errors || []).filter(isUsableError).forEach(
39
+ message =>
40
+ message &&
41
+ context.report({
42
+ node: context.sourceCode.ast,
43
+ message
44
+ })
45
+ );
58
46
  }
59
47
  };
60
48
  }
61
- };
49
+ });
package/package.json CHANGED
@@ -1,53 +1,53 @@
1
1
  {
2
- "name": "eslint-plugin-package-json",
3
- "version": "0.2.0",
4
- "description": "Rules for valid, consistent, and readable package.json files",
5
- "keywords": [
6
- "eslint",
7
- "eslintplugin",
8
- "eslint-plugin",
9
- "magento"
10
- ],
11
- "author": "James Zetlen <zetlen@gmail.com>",
12
- "license": "MIT",
13
- "main": "lib/index.js",
14
- "homepage": "https://github.com/zetlen/eslint-plugin-package-json#readme",
15
- "repository": {
16
- "type": "git",
17
- "url": "git+https://github.com/zetlen/eslint-plugin-package-json/issues"
18
- },
19
- "bugs": {
20
- "url": "https://github.com/zetlen/eslint-plugin-package-json/issues"
21
- },
22
- "scripts": {
23
- "test": "nyc --reporter=lcov --reporter=text mocha tests --recursive",
24
- "test:debug": "mocha --inspect-brk tests --recursive",
25
- "test:watch": "mocha tests --recursive --watch",
26
- "pretest": "npm run format",
27
- "format": "prettier --ignore-path .gitignore --write \"**/*.{js,css,md}\" && eslint ./**/*.js"
28
- },
29
- "devDependencies": {
30
- "eslint": "^5.8.0",
31
- "lodash": "^4.17.15",
32
- "mocha": "^6.2.0",
33
- "nyc": "^14.1.1",
34
- "prettier": "^1.18.2"
35
- },
36
- "dependencies": {
37
- "disparity": "^3.2.0",
38
- "package-json-validator": "^0.6.3",
39
- "requireindex": "^1.2.0",
40
- "sort-package-json": "^1.57.0"
41
- },
42
- "peerDependencies": {
43
- "eslint": ">=4.7.0"
44
- },
45
- "engines": {
46
- "node": ">=8.0.0"
47
- },
48
- "nyc": {
49
- "include": [
50
- "lib/**"
51
- ]
52
- }
2
+ "name": "eslint-plugin-package-json",
3
+ "version": "0.3.0",
4
+ "description": "Rules for valid, consistent, and readable package.json files",
5
+ "keywords": [
6
+ "eslint",
7
+ "eslintplugin",
8
+ "eslint-plugin",
9
+ "magento"
10
+ ],
11
+ "author": "James Zetlen <zetlen@gmail.com>",
12
+ "license": "MIT",
13
+ "main": "lib/index.js",
14
+ "homepage": "https://github.com/zetlen/eslint-plugin-package-json#readme",
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/zetlen/eslint-plugin-package-json/issues"
18
+ },
19
+ "bugs": {
20
+ "url": "https://github.com/zetlen/eslint-plugin-package-json/issues"
21
+ },
22
+ "scripts": {
23
+ "test": "nyc --reporter=lcov --reporter=text mocha tests --recursive",
24
+ "test:debug": "mocha --inspect-brk tests --recursive",
25
+ "test:watch": "mocha tests --recursive --watch",
26
+ "pretest": "npm run format",
27
+ "format": "prettier --ignore-path .gitignore --write \"**/*.{js,css,md}\" && eslint ./**/*.js"
28
+ },
29
+ "devDependencies": {
30
+ "eslint": "^8.49.0",
31
+ "jsonc-eslint-parser": "^2.3.0",
32
+ "lodash": "^4.17.15",
33
+ "mocha": "^6.2.0",
34
+ "nyc": "^14.1.1",
35
+ "prettier": "^1.18.2"
36
+ },
37
+ "dependencies": {
38
+ "package-json-validator": "^0.6.3",
39
+ "sort-package-json": "^1.57.0"
40
+ },
41
+ "peerDependencies": {
42
+ "eslint": ">=8.0.0",
43
+ "jsonc-eslint-parser": "^2.0.0"
44
+ },
45
+ "engines": {
46
+ "node": ">=18.0.0"
47
+ },
48
+ "nyc": {
49
+ "include": [
50
+ "lib/**"
51
+ ]
52
+ }
53
53
  }