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 +1 -1
- package/README.md +29 -30
- package/lib/createRule.js +17 -0
- package/lib/index.js +13 -28
- package/lib/rules/order-properties.js +31 -41
- package/lib/rules/sort-collections.js +7 -9
- package/lib/rules/valid-local-dependency.js +8 -17
- package/lib/rules/valid-package-def.js +15 -27
- package/package.json +51 -51
- package/tests/lib/rules/order-properties.js +209 -209
- package/tests/lib/rules/ruleTester.js +7 -0
- package/tests/lib/rules/sort-collections.js +12 -13
- package/tests/lib/rules/valid-local-dependency.js +19 -20
- package/tests/lib/rules/valid-package-def.js +5 -6
- package/lib/processors/PackageJsonProcessor.js +0 -63
- package/tests/lib/index.js +0 -157
- package/tests/lib/processors/PackageJsonProcessor.js +0 -159
package/.eslintrc
CHANGED
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
|
|
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
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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
|
-
```
|
|
43
|
-
{
|
|
44
|
-
|
|
45
|
-
|
|
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
|
-
|
|
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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
|
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
|
|
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',
|
|
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'
|
|
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'
|
|
88
|
-
|
|
79
|
+
options.order === 'legacy'
|
|
80
|
+
? standardOrderLegacy
|
|
81
|
+
: options.order;
|
|
89
82
|
const orderedSource = sortPackageJson(
|
|
90
|
-
|
|
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
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
|
-
|
|
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
|
|
34
|
+
create(context) {
|
|
34
35
|
const toSort = context.options[0] || defaultCollections;
|
|
35
36
|
return {
|
|
36
|
-
'
|
|
37
|
-
if (!isPackageJson(context.getFilename())) {
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
37
|
+
'JSONProperty:exit'(node) {
|
|
40
38
|
const collection = node.value;
|
|
41
39
|
if (
|
|
42
|
-
collection.type === '
|
|
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'
|
|
30
|
-
|
|
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:
|
|
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:
|
|
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'
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
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
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
}
|