eslint-plugin-package-json 1.8.1 โ 1.10.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/README.md +6 -3
- package/dist/experimental/index.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{plugin-DlF-r5D9.mjs โ plugin-BfdzXm-J.mjs} +207 -69
- package/package.json +16 -15
package/README.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<p align="center">
|
|
16
16
|
<!-- prettier-ignore-start -->
|
|
17
17
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
18
|
-
<a href="#contributors" target="_blank"><img alt="๐ช All Contributors:
|
|
18
|
+
<a href="#contributors" target="_blank"><img alt="๐ช All Contributors: 45" src="https://img.shields.io/badge/%F0%9F%91%AA_all_contributors-45-21bb42.svg" /></a>
|
|
19
19
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
20
20
|
<!-- prettier-ignore-end -->
|
|
21
21
|
<a href="https://codecov.io/gh/michaelfaith/eslint-plugin-package-json" target="_blank"><img alt="๐งช Coverage" src="https://img.shields.io/codecov/c/github/michaelfaith/eslint-plugin-package-json?label=%F0%9F%A7%AA%20coverage" /></a>
|
|
@@ -49,7 +49,9 @@ See [Getting Started](https://eslint-plugin-package-json.dev/getting-started) fo
|
|
|
49
49
|
| [prefer-rolling-workspace-spec](https://eslint-plugin-package-json.dev/rules/prefer-rolling-workspace-spec) | Require that dependencies declared with workspace protocol use a rolling workspace spec instead of a specific semver range. | | | ๐ก |
|
|
50
50
|
| [repository-shorthand](https://eslint-plugin-package-json.dev/rules/repository-shorthand) | Enforce either object or shorthand declaration for repository. | โ
| ๐ง | |
|
|
51
51
|
| [require-attribution](https://eslint-plugin-package-json.dev/rules/require-attribution) | Ensures that proper attribution is included, requiring that either `author` or `contributors` is defined, and that if `contributors` is present, it should include at least one contributor. | โ
| | ๐ก |
|
|
52
|
+
| [require-package-json-export](https://eslint-plugin-package-json.dev/rules/require-package-json-export) | Ensures that if a package specifies `exports` (or `publishConfig.exports`), an explicit `package.json` export is included. | | | ๐ก |
|
|
52
53
|
| [restrict-dependency-ranges](https://eslint-plugin-package-json.dev/rules/restrict-dependency-ranges) | Restricts the range of dependencies to allow or disallow specific types of ranges. | | | ๐ก |
|
|
54
|
+
| [restrict-dist-tags](https://eslint-plugin-package-json.dev/rules/restrict-dist-tags) | Restricts dependency dist-tags to an allowed list and selected dependency types. | | | |
|
|
53
55
|
| [restrict-private-properties](https://eslint-plugin-package-json.dev/rules/restrict-private-properties) | Disallows unnecessary properties in private packages. | | ๐ง | ๐ก |
|
|
54
56
|
| [restrict-top-level-properties](https://eslint-plugin-package-json.dev/rules/restrict-top-level-properties) | Disallows specified top-level properties in package.json. | | | ๐ก |
|
|
55
57
|
| [scripts-name-casing](https://eslint-plugin-package-json.dev/rules/scripts-name-casing) | Enforce that names for `scripts` are in kebab case (optionally separated by colons). | ๐จ | | ๐ก |
|
|
@@ -209,7 +211,7 @@ Thanks! ๐ป
|
|
|
209
211
|
</tr>
|
|
210
212
|
<tr>
|
|
211
213
|
<td align="center" valign="top" width="14.28%"><a href="http://heggria.site"><img src="https://avatars.githubusercontent.com/u/34475327?v=4?s=100" width="100px;" alt="Heggria"/><br /><sub><b>Heggria</b></sub></a><br /><a href="#ideas-heggria" title="Ideas, Planning, & Feedback">๐ค</a></td>
|
|
212
|
-
<td align="center" valign="top" width="14.28%"><a href="https://hirok.io"><img src="https://avatars.githubusercontent.com/u/1075694?v=4?s=100" width="100px;" alt="Hiroki Osame"/><br /><sub><b>Hiroki Osame</b></sub></a><br /><a href="#ideas-privatenumber" title="Ideas, Planning, & Feedback">๐ค</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=privatenumber" title="Code">๐ป</a></td>
|
|
214
|
+
<td align="center" valign="top" width="14.28%"><a href="https://hirok.io"><img src="https://avatars.githubusercontent.com/u/1075694?v=4?s=100" width="100px;" alt="Hiroki Osame"/><br /><sub><b>Hiroki Osame</b></sub></a><br /><a href="#ideas-privatenumber" title="Ideas, Planning, & Feedback">๐ค</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=privatenumber" title="Code">๐ป</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3Aprivatenumber" title="Bug reports">๐</a></td>
|
|
213
215
|
<td align="center" valign="top" width="14.28%"><a href="https://vanyauhalin.me/"><img src="https://avatars.githubusercontent.com/u/56481109?v=4?s=100" width="100px;" alt="Ivan Uhalin"/><br /><sub><b>Ivan Uhalin</b></sub></a><br /><a href="#ideas-vanyauhalin" title="Ideas, Planning, & Feedback">๐ค</a></td>
|
|
214
216
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Zamiell"><img src="https://avatars.githubusercontent.com/u/5511220?v=4?s=100" width="100px;" alt="James"/><br /><sub><b>James</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=Zamiell" title="Code">๐ป</a> <a href="#ideas-Zamiell" title="Ideas, Planning, & Feedback">๐ค</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3AZamiell" title="Bug reports">๐</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=Zamiell" title="Documentation">๐</a></td>
|
|
215
217
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/zetlen"><img src="https://avatars.githubusercontent.com/u/1643758?v=4?s=100" width="100px;" alt="James Zetlen"/><br /><sub><b>James Zetlen</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=zetlen" title="Code">๐ป</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3Azetlen" title="Bug reports">๐</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=zetlen" title="Documentation">๐</a> <a href="#infra-zetlen" title="Infrastructure (Hosting, Build-Tools, etc)">๐</a> <a href="#maintenance-zetlen" title="Maintenance">๐ง</a> <a href="#tool-zetlen" title="Tools">๐ง</a></td>
|
|
@@ -237,13 +239,14 @@ Thanks! ๐ป
|
|
|
237
239
|
<tr>
|
|
238
240
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sirugh"><img src="https://avatars.githubusercontent.com/u/1278869?v=4?s=100" width="100px;" alt="Stephen"/><br /><sub><b>Stephen</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=sirugh" title="Code">๐ป</a></td>
|
|
239
241
|
<td align="center" valign="top" width="14.28%"><a href="https://hyoban.cc"><img src="https://avatars.githubusercontent.com/u/38493346?v=4?s=100" width="100px;" alt="Stephen Zhou"/><br /><sub><b>Stephen Zhou</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3Ahyoban" title="Bug reports">๐</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=hyoban" title="Code">๐ป</a> <a href="#ideas-hyoban" title="Ideas, Planning, & Feedback">๐ค</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=hyoban" title="Documentation">๐</a></td>
|
|
242
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/thernstig"><img src="https://avatars.githubusercontent.com/u/30827238?v=4?s=100" width="100px;" alt="Tobias Hernstig"/><br /><sub><b>Tobias Hernstig</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3Athernstig" title="Bug reports">๐</a></td>
|
|
240
243
|
<td align="center" valign="top" width="14.28%"><a href="https://www.wesleytodd.com/"><img src="https://avatars.githubusercontent.com/u/1027776?v=4?s=100" width="100px;" alt="Wes Todd"/><br /><sub><b>Wes Todd</b></sub></a><br /><a href="#ideas-wesleytodd" title="Ideas, Planning, & Feedback">๐ค</a></td>
|
|
241
244
|
<td align="center" valign="top" width="14.28%"><a href="https://ota-meshi.github.io/"><img src="https://avatars.githubusercontent.com/u/16508807?v=4?s=100" width="100px;" alt="Yosuke Ota"/><br /><sub><b>Yosuke Ota</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3Aota-meshi" title="Bug reports">๐</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=ota-meshi" title="Code">๐ป</a></td>
|
|
242
245
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/b3rnhard"><img src="https://avatars.githubusercontent.com/u/10774404?v=4?s=100" width="100px;" alt="b3rnhard"/><br /><sub><b>b3rnhard</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3Ab3rnhard" title="Bug reports">๐</a></td>
|
|
243
246
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/chouchouji"><img src="https://avatars.githubusercontent.com/u/70570907?v=4?s=100" width="100px;" alt="chouchouji"/><br /><sub><b>chouchouji</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=chouchouji" title="Code">๐ป</a></td>
|
|
244
|
-
<td align="center" valign="top" width="14.28%"><a href="https://github.com/michaelfaith"><img src="https://avatars.githubusercontent.com/u/8071845?v=4?s=100" width="100px;" alt="michael faith"/><br /><sub><b>michael faith</b></sub></a><br /><a href="#infra-michaelfaith" title="Infrastructure (Hosting, Build-Tools, etc)">๐</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=michaelfaith" title="Code">๐ป</a> <a href="#maintenance-michaelfaith" title="Maintenance">๐ง</a> <a href="#ideas-michaelfaith" title="Ideas, Planning, & Feedback">๐ค</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3Amichaelfaith" title="Bug reports">๐</a> <a href="#tool-michaelfaith" title="Tools">๐ง</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=michaelfaith" title="Documentation">๐</a> <a href="#projectManagement-michaelfaith" title="Project Management">๐</a></td>
|
|
245
247
|
</tr>
|
|
246
248
|
<tr>
|
|
249
|
+
<td align="center" valign="top" width="14.28%"><a href="https://github.com/michaelfaith"><img src="https://avatars.githubusercontent.com/u/8071845?v=4?s=100" width="100px;" alt="michael faith"/><br /><sub><b>michael faith</b></sub></a><br /><a href="#infra-michaelfaith" title="Infrastructure (Hosting, Build-Tools, etc)">๐</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=michaelfaith" title="Code">๐ป</a> <a href="#maintenance-michaelfaith" title="Maintenance">๐ง</a> <a href="#ideas-michaelfaith" title="Ideas, Planning, & Feedback">๐ค</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3Amichaelfaith" title="Bug reports">๐</a> <a href="#tool-michaelfaith" title="Tools">๐ง</a> <a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=michaelfaith" title="Documentation">๐</a> <a href="#projectManagement-michaelfaith" title="Project Management">๐</a></td>
|
|
247
250
|
<td align="center" valign="top" width="14.28%"><a href="https://roottool.vercel.app"><img src="https://avatars.githubusercontent.com/u/11808736?v=4?s=100" width="100px;" alt="roottool"/><br /><sub><b>roottool</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/commits?author=roottool" title="Code">๐ป</a></td>
|
|
248
251
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/sunnytsang1998"><img src="https://avatars.githubusercontent.com/u/207208443?v=4?s=100" width="100px;" alt="sunnytsang1998"/><br /><sub><b>sunnytsang1998</b></sub></a><br /><a href="https://github.com/michaelfaith/eslint-plugin-package-json/issues?q=author%3Asunnytsang1998" title="Bug reports">๐</a></td>
|
|
249
252
|
</tr>
|
package/dist/index.mjs
CHANGED
|
@@ -41,8 +41,7 @@ function createRule(rule) {
|
|
|
41
41
|
const ruleGroup = rule.meta.docs?.ruleGroup;
|
|
42
42
|
return {
|
|
43
43
|
create(context) {
|
|
44
|
-
|
|
45
|
-
return rule.create(context);
|
|
44
|
+
return isPackageJson(context.filename) ? rule.create(context) : {};
|
|
46
45
|
},
|
|
47
46
|
meta: {
|
|
48
47
|
...rule.meta,
|
|
@@ -55,7 +54,7 @@ function createRule(rule) {
|
|
|
55
54
|
}
|
|
56
55
|
//#endregion
|
|
57
56
|
//#region src/rules/bin-name-casing.ts
|
|
58
|
-
const rule$
|
|
57
|
+
const rule$21 = createRule({
|
|
59
58
|
create(context) {
|
|
60
59
|
return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=bin]"(node) {
|
|
61
60
|
if (node.value.type === "JSONObjectExpression") for (const property of node.value.properties) {
|
|
@@ -93,17 +92,16 @@ const rule$19 = createRule({
|
|
|
93
92
|
});
|
|
94
93
|
//#endregion
|
|
95
94
|
//#region src/rules/exports-subpaths-style.ts
|
|
96
|
-
function isImplicitFormat(node) {
|
|
97
|
-
|
|
98
|
-
return node.properties.every((property) => !isJSONStringLiteral(property.key) || !property.key.value.startsWith("."));
|
|
95
|
+
function isImplicitFormat$1(node) {
|
|
96
|
+
return node.type === "JSONLiteral" ? true : node.properties.every((property) => !isJSONStringLiteral(property.key) || !property.key.value.startsWith("."));
|
|
99
97
|
}
|
|
100
|
-
const rule$
|
|
98
|
+
const rule$20 = createRule({
|
|
101
99
|
create(context) {
|
|
102
100
|
const [{ prefer = "explicit" } = {}] = context.options;
|
|
103
101
|
function validateForExplicit(node) {
|
|
104
102
|
const { value } = node;
|
|
105
103
|
if (isJSONNullLiteral(value)) return;
|
|
106
|
-
if (value.type !== "JSONLiteral" && value.type !== "JSONObjectExpression" || !isImplicitFormat(value)) return;
|
|
104
|
+
if (value.type !== "JSONLiteral" && value.type !== "JSONObjectExpression" || !isImplicitFormat$1(value)) return;
|
|
107
105
|
context.report({
|
|
108
106
|
fix(fixer) {
|
|
109
107
|
const valueText = context.sourceCode.getText(value);
|
|
@@ -200,25 +198,21 @@ const getTopLevelProperty = (node) => {
|
|
|
200
198
|
return n.type === "JSONProperty" ? n.key : void 0;
|
|
201
199
|
};
|
|
202
200
|
const defaultIgnoreProperties = ["files"];
|
|
203
|
-
const rule$
|
|
201
|
+
const rule$19 = createRule({
|
|
204
202
|
create(context) {
|
|
205
203
|
const ignoreProperties = new Set(context.options[0]?.ignoreProperties ?? defaultIgnoreProperties);
|
|
206
204
|
return {
|
|
207
205
|
JSONArrayExpression(node) {
|
|
208
206
|
const topLevelProperty = getTopLevelProperty(node);
|
|
209
|
-
if (!topLevelProperty) return;
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if (!ignoreProperties.has(topLevelPropertyName)) report(context, getNode(node));
|
|
213
|
-
}
|
|
207
|
+
if (!topLevelProperty || node.elements.length) return;
|
|
208
|
+
const topLevelPropertyName = topLevelProperty.value;
|
|
209
|
+
if (!ignoreProperties.has(topLevelPropertyName)) report(context, getNode(node));
|
|
214
210
|
},
|
|
215
211
|
JSONObjectExpression(node) {
|
|
216
212
|
const topLevelProperty = getTopLevelProperty(node);
|
|
217
|
-
if (!topLevelProperty) return;
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
if (!ignoreProperties.has(topLevelPropertyName)) report(context, getNode(node));
|
|
221
|
-
}
|
|
213
|
+
if (!topLevelProperty || node.properties.length) return;
|
|
214
|
+
const topLevelPropertyName = topLevelProperty.value;
|
|
215
|
+
if (!ignoreProperties.has(topLevelPropertyName)) report(context, getNode(node));
|
|
222
216
|
}
|
|
223
217
|
};
|
|
224
218
|
},
|
|
@@ -256,7 +250,7 @@ const getBundledDependencyNames = (value) => {
|
|
|
256
250
|
if (value?.type === "JSONArrayExpression") for (const element of value.elements.filter(isNotNullish).filter(isJSONStringLiteral)) names.add(element.value);
|
|
257
251
|
return names;
|
|
258
252
|
};
|
|
259
|
-
const rule$
|
|
253
|
+
const rule$18 = createRule({
|
|
260
254
|
create(context) {
|
|
261
255
|
const ignorePrivate = context.options[0]?.ignorePrivate ?? true;
|
|
262
256
|
let isPrivate = false;
|
|
@@ -327,7 +321,7 @@ const getCachedLocalFileRegex = (filename) => {
|
|
|
327
321
|
return regex;
|
|
328
322
|
}
|
|
329
323
|
};
|
|
330
|
-
const rule$
|
|
324
|
+
const rule$17 = createRule({
|
|
331
325
|
create(context) {
|
|
332
326
|
const entryCache = {
|
|
333
327
|
bin: [],
|
|
@@ -404,7 +398,7 @@ const rule$15 = createRule({
|
|
|
404
398
|
});
|
|
405
399
|
//#endregion
|
|
406
400
|
//#region src/rules/no-redundant-publishConfig.ts
|
|
407
|
-
const rule$
|
|
401
|
+
const rule$16 = createRule({
|
|
408
402
|
create(context) {
|
|
409
403
|
let packageName;
|
|
410
404
|
let publishConfigAccessProperty;
|
|
@@ -450,7 +444,7 @@ const rule$14 = createRule({
|
|
|
450
444
|
});
|
|
451
445
|
//#endregion
|
|
452
446
|
//#region src/rules/order-properties.ts
|
|
453
|
-
const rule$
|
|
447
|
+
const rule$15 = createRule({
|
|
454
448
|
create(context) {
|
|
455
449
|
return { "Program:exit"() {
|
|
456
450
|
const { ast, text } = context.sourceCode;
|
|
@@ -510,7 +504,7 @@ const rule$13 = createRule({
|
|
|
510
504
|
//#region src/rules/prefer-rolling-workspace-spec.ts
|
|
511
505
|
const rollingWorkspaceSpecRegex = /^workspace:[*^~]?$/;
|
|
512
506
|
const convertibleSpecRegex = /^(workspace:[~^])/;
|
|
513
|
-
const rule$
|
|
507
|
+
const rule$14 = createRule({
|
|
514
508
|
create(context) {
|
|
515
509
|
const { ignoreDependencies = [], ignorePatterns = [] } = context.options[0] ?? {};
|
|
516
510
|
const ignoreRegexes = ignorePatterns.map((pattern) => new RegExp(pattern));
|
|
@@ -608,14 +602,13 @@ const createUrl = (shorthand) => {
|
|
|
608
602
|
}
|
|
609
603
|
return `${providerUrls.github}${shorthand}`;
|
|
610
604
|
};
|
|
611
|
-
const rule$
|
|
605
|
+
const rule$13 = createRule({
|
|
612
606
|
create(context) {
|
|
613
607
|
const [{ form = "object" } = {}] = context.options;
|
|
614
608
|
function validateRepositoryForObject(node) {
|
|
615
609
|
if (isJSONStringLiteral(node.value)) context.report({
|
|
616
610
|
fix(fixer) {
|
|
617
|
-
|
|
618
|
-
return fixer.replaceText(node.value, JSON.stringify({
|
|
611
|
+
return !isJSONStringLiteral(node.value) || node.value.value.split("/").filter(Boolean).length !== 2 ? null : fixer.replaceText(node.value, JSON.stringify({
|
|
619
612
|
type: "git",
|
|
620
613
|
url: createUrl(node.value.value)
|
|
621
614
|
}, null, 2));
|
|
@@ -687,7 +680,7 @@ const rule$11 = createRule({
|
|
|
687
680
|
});
|
|
688
681
|
//#endregion
|
|
689
682
|
//#region src/rules/require-attribution.ts
|
|
690
|
-
const rule$
|
|
683
|
+
const rule$12 = createRule({
|
|
691
684
|
create(context) {
|
|
692
685
|
const preferContributorsOnly = context.options[0]?.preferContributorsOnly ?? false;
|
|
693
686
|
const ignorePrivate = context.options[0]?.ignorePrivate ?? true;
|
|
@@ -774,6 +767,86 @@ const rule$10 = createRule({
|
|
|
774
767
|
name: "require-attribution"
|
|
775
768
|
});
|
|
776
769
|
//#endregion
|
|
770
|
+
//#region src/utils/increaseIndent.ts
|
|
771
|
+
const increaseIndent = (original, additional) => original.split("\n").join(`\n${additional}`);
|
|
772
|
+
//#endregion
|
|
773
|
+
//#region src/rules/require-package-json-export.ts
|
|
774
|
+
function isImplicitFormat(node) {
|
|
775
|
+
return node.properties.every((property) => !isJSONStringLiteral(property.key) || !property.key.value.startsWith("."));
|
|
776
|
+
}
|
|
777
|
+
const rule$11 = createRule({
|
|
778
|
+
create(context) {
|
|
779
|
+
let publishConfigExportsValueNode;
|
|
780
|
+
let exportsValueNode;
|
|
781
|
+
return {
|
|
782
|
+
"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=exports]"(node) {
|
|
783
|
+
if (node.value.type === "JSONObjectExpression" || isJSONStringLiteral(node.value)) exportsValueNode = node.value;
|
|
784
|
+
},
|
|
785
|
+
"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=publishConfig] > JSONObjectExpression > JSONProperty[key.value=exports]"(node) {
|
|
786
|
+
if (node.value.type === "JSONObjectExpression" || isJSONStringLiteral(node.value)) publishConfigExportsValueNode = node.value;
|
|
787
|
+
},
|
|
788
|
+
"Program:exit"() {
|
|
789
|
+
const exportsNode = publishConfigExportsValueNode ?? exportsValueNode;
|
|
790
|
+
if (!exportsNode) return;
|
|
791
|
+
const isPublishConfig = !!publishConfigExportsValueNode;
|
|
792
|
+
const { text } = context.sourceCode;
|
|
793
|
+
const { indent, type } = detectIndent(text);
|
|
794
|
+
const indentUnit = type === "tab" ? " " : indent || " ";
|
|
795
|
+
const extraIndent = isPublishConfig ? `${indentUnit}${indentUnit}` : indentUnit;
|
|
796
|
+
if (isJSONStringLiteral(exportsNode) || isImplicitFormat(exportsNode)) {
|
|
797
|
+
context.report({
|
|
798
|
+
messageId: "missing",
|
|
799
|
+
node: exportsNode,
|
|
800
|
+
suggest: [{
|
|
801
|
+
messageId: "addExport",
|
|
802
|
+
fix(fixer) {
|
|
803
|
+
const valueText = context.sourceCode.getText(exportsNode);
|
|
804
|
+
const fixedValue = increaseIndent(JSON.stringify({
|
|
805
|
+
".": JSON.parse(valueText),
|
|
806
|
+
"./package.json": "./package.json"
|
|
807
|
+
}, null, indentUnit), extraIndent);
|
|
808
|
+
return fixer.replaceText(exportsNode, fixedValue);
|
|
809
|
+
}
|
|
810
|
+
}]
|
|
811
|
+
});
|
|
812
|
+
return;
|
|
813
|
+
}
|
|
814
|
+
if (exportsNode.properties.some((property) => isJSONStringLiteral(property.key) && property.key.value === "./package.json")) return;
|
|
815
|
+
context.report({
|
|
816
|
+
messageId: "missing",
|
|
817
|
+
node: exportsNode,
|
|
818
|
+
suggest: [{
|
|
819
|
+
messageId: "addExport",
|
|
820
|
+
fix(fixer) {
|
|
821
|
+
const valueText = context.sourceCode.getText(exportsNode);
|
|
822
|
+
const existingExports = JSON.parse(valueText);
|
|
823
|
+
const fixedValue = increaseIndent(JSON.stringify({
|
|
824
|
+
...existingExports,
|
|
825
|
+
"./package.json": "./package.json"
|
|
826
|
+
}, null, indentUnit), extraIndent);
|
|
827
|
+
return fixer.replaceText(exportsNode, fixedValue);
|
|
828
|
+
}
|
|
829
|
+
}]
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
};
|
|
833
|
+
},
|
|
834
|
+
meta: {
|
|
835
|
+
docs: {
|
|
836
|
+
category: "Best Practices",
|
|
837
|
+
description: "Ensures that if a package specifies `exports` (or `publishConfig.exports`), an explicit `package.json` export is included."
|
|
838
|
+
},
|
|
839
|
+
hasSuggestions: true,
|
|
840
|
+
messages: {
|
|
841
|
+
missing: "An export for the package.json is required, and missing.",
|
|
842
|
+
addExport: "Add package.json export."
|
|
843
|
+
},
|
|
844
|
+
schema: [],
|
|
845
|
+
type: "suggestion"
|
|
846
|
+
},
|
|
847
|
+
name: "require-package-json-export"
|
|
848
|
+
});
|
|
849
|
+
//#endregion
|
|
777
850
|
//#region src/utils/createSimpleRequirePropertyRule.ts
|
|
778
851
|
/**
|
|
779
852
|
* Given a top-level property name, create a rule that requires that property to be present.
|
|
@@ -790,21 +863,20 @@ const createSimpleRequirePropertyRule = (propertyName, { category, fixValue, ign
|
|
|
790
863
|
const ignorePrivate = context.options[0]?.ignorePrivate ?? (typeof enforceForPrivate === "boolean" ? !enforceForPrivate : ignorePrivateDefault);
|
|
791
864
|
return { "Program > JSONExpressionStatement > JSONObjectExpression"(node) {
|
|
792
865
|
if (ignorePrivate && node.properties.some((property) => isJSONStringLiteral(property.key) && property.key.value === "private" && property.value.type === "JSONLiteral" && property.value.value === true)) return;
|
|
793
|
-
if (node.properties.
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
}
|
|
866
|
+
if (node.properties.some((property) => isJSONStringLiteral(property.key) && property.key.value === propertyName)) return;
|
|
867
|
+
const resolvedValue = typeof fixValue === "function" ? fixValue() : fixValue;
|
|
868
|
+
context.report({
|
|
869
|
+
data: { property: propertyName },
|
|
870
|
+
fix: resolvedValue === void 0 ? void 0 : function* (fixer) {
|
|
871
|
+
yield fixer.insertTextAfterRange([0, 1], `\n "${propertyName}": ${JSON.stringify(resolvedValue, null, 2).split("\n").join("\n ")}`);
|
|
872
|
+
yield node.properties.length > 0 ? fixer.insertTextAfterRange([0, 1], ",") : fixer.insertTextAfterRange([0, 1], "\n");
|
|
873
|
+
},
|
|
874
|
+
loc: {
|
|
875
|
+
column: 0,
|
|
876
|
+
line: 1
|
|
877
|
+
},
|
|
878
|
+
messageId: "missing"
|
|
879
|
+
});
|
|
808
880
|
} };
|
|
809
881
|
},
|
|
810
882
|
meta: {
|
|
@@ -929,7 +1001,7 @@ const rules$2 = Object.fromEntries([
|
|
|
929
1001
|
}));
|
|
930
1002
|
//#endregion
|
|
931
1003
|
//#region src/rules/restrict-dependency-ranges.ts
|
|
932
|
-
const DEPENDENCY_TYPES = [
|
|
1004
|
+
const DEPENDENCY_TYPES$1 = [
|
|
933
1005
|
"dependencies",
|
|
934
1006
|
"devDependencies",
|
|
935
1007
|
"optionalDependencies",
|
|
@@ -975,7 +1047,7 @@ const schemaOptions = {
|
|
|
975
1047
|
properties: {
|
|
976
1048
|
forDependencyTypes: {
|
|
977
1049
|
description: "Apply a range type restriction for an entire group of dependencies by which type of dependencies they belong to.",
|
|
978
|
-
items: { enum: DEPENDENCY_TYPES },
|
|
1050
|
+
items: { enum: DEPENDENCY_TYPES$1 },
|
|
979
1051
|
type: "array"
|
|
980
1052
|
},
|
|
981
1053
|
forPackages: {
|
|
@@ -1001,7 +1073,7 @@ const schemaOptions = {
|
|
|
1001
1073
|
const normalizeRangeType = (rangeTypeOrSymbol) => RANGE_TYPES.find((rangeType) => "symbol" in rangeType && rangeType.symbol === rangeTypeOrSymbol || rangeType.alias === rangeTypeOrSymbol);
|
|
1002
1074
|
/** @returns `undefined` if workspace versions are not supported for the specified {@link rangeType} */
|
|
1003
1075
|
const getWorkspaceVersionForRange = (rangeType) => {
|
|
1004
|
-
|
|
1076
|
+
return "workspaceSymbol" in rangeType ? `workspace:${rangeType.workspaceSymbol}` : void 0;
|
|
1005
1077
|
};
|
|
1006
1078
|
/** For displaying a range type in a user-facing way (ie. an error message). */
|
|
1007
1079
|
const displayRangeType = (rangeType) => "symbol" in rangeType ? rangeType.symbol : rangeType.alias;
|
|
@@ -1029,7 +1101,7 @@ const isVersionSupported = (version) => {
|
|
|
1029
1101
|
return !!semver.validRange(rawVersion);
|
|
1030
1102
|
};
|
|
1031
1103
|
const POSSIBLE_WORKSPACE_SPEC_REGEX = /(?:workspace:)?[^~]?/;
|
|
1032
|
-
const rule$
|
|
1104
|
+
const rule$10 = createRule({
|
|
1033
1105
|
create(context) {
|
|
1034
1106
|
if (!context.options[0]) return {};
|
|
1035
1107
|
const optionsArray = (Array.isArray(context.options[0]) ? context.options[0].toReversed() : [context.options[0]]).map((option) => ({
|
|
@@ -1039,7 +1111,7 @@ const rule$9 = createRule({
|
|
|
1039
1111
|
}));
|
|
1040
1112
|
return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral][value.type=JSONObjectExpression]"(node) {
|
|
1041
1113
|
const dependencyType = node.key.value;
|
|
1042
|
-
if (!DEPENDENCY_TYPES.includes(dependencyType)) return;
|
|
1114
|
+
if (!DEPENDENCY_TYPES$1.includes(dependencyType)) return;
|
|
1043
1115
|
for (const property of node.value.properties) {
|
|
1044
1116
|
if (!isJSONStringLiteral(property.key) || !isJSONStringLiteral(property.value)) continue;
|
|
1045
1117
|
const name = property.key.value;
|
|
@@ -1106,6 +1178,73 @@ const rule$9 = createRule({
|
|
|
1106
1178
|
name: "restrict-dependency-ranges"
|
|
1107
1179
|
});
|
|
1108
1180
|
//#endregion
|
|
1181
|
+
//#region src/rules/restrict-dist-tags.ts
|
|
1182
|
+
const DEPENDENCY_TYPES = [
|
|
1183
|
+
"dependencies",
|
|
1184
|
+
"devDependencies",
|
|
1185
|
+
"optionalDependencies",
|
|
1186
|
+
"peerDependencies"
|
|
1187
|
+
];
|
|
1188
|
+
const DEFAULT_ALLOWED_TAGS = [
|
|
1189
|
+
"latest",
|
|
1190
|
+
"dev",
|
|
1191
|
+
"next",
|
|
1192
|
+
"alpha",
|
|
1193
|
+
"beta",
|
|
1194
|
+
"canary",
|
|
1195
|
+
"rc"
|
|
1196
|
+
];
|
|
1197
|
+
const distTagPattern = /^[A-Z0-9][\w.-]*$/i;
|
|
1198
|
+
function isDistTag(value) {
|
|
1199
|
+
return !semver.validRange(value) && distTagPattern.test(value);
|
|
1200
|
+
}
|
|
1201
|
+
const rule$9 = createRule({
|
|
1202
|
+
create(context) {
|
|
1203
|
+
const { allowed = DEFAULT_ALLOWED_TAGS, allowedFor } = context.options[0] ?? {};
|
|
1204
|
+
return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral][value.type=JSONObjectExpression]"(node) {
|
|
1205
|
+
const dependencyType = node.key.value;
|
|
1206
|
+
if (!DEPENDENCY_TYPES.includes(dependencyType)) return;
|
|
1207
|
+
for (const property of node.value.properties) {
|
|
1208
|
+
if (!isJSONStringLiteral(property.key) || !isJSONStringLiteral(property.value)) continue;
|
|
1209
|
+
const spec = property.value.value;
|
|
1210
|
+
if (!isDistTag(spec)) continue;
|
|
1211
|
+
if ((allowedFor === void 0 || allowedFor.includes(dependencyType)) && allowed.includes(spec)) continue;
|
|
1212
|
+
context.report({
|
|
1213
|
+
data: {
|
|
1214
|
+
dependencyType,
|
|
1215
|
+
tag: spec
|
|
1216
|
+
},
|
|
1217
|
+
messageId: "disallowedDistTag",
|
|
1218
|
+
node: property.value
|
|
1219
|
+
});
|
|
1220
|
+
}
|
|
1221
|
+
} };
|
|
1222
|
+
},
|
|
1223
|
+
meta: {
|
|
1224
|
+
defaultOptions: [{ allowed: DEFAULT_ALLOWED_TAGS }],
|
|
1225
|
+
docs: { description: "Restricts dependency dist-tags to an allowed list and selected dependency types." },
|
|
1226
|
+
messages: { disallowedDistTag: "The \"{{ tag }}\" dist-tag is not allowed for {{ dependencyType }}." },
|
|
1227
|
+
schema: [{
|
|
1228
|
+
type: "object",
|
|
1229
|
+
properties: {
|
|
1230
|
+
allowed: {
|
|
1231
|
+
description: "Dist-tags allowed in dependency specifications.",
|
|
1232
|
+
type: "array",
|
|
1233
|
+
items: { type: "string" }
|
|
1234
|
+
},
|
|
1235
|
+
allowedFor: {
|
|
1236
|
+
description: "Dependency sections where the allowed dist-tags may be used.",
|
|
1237
|
+
type: "array",
|
|
1238
|
+
items: { enum: DEPENDENCY_TYPES }
|
|
1239
|
+
}
|
|
1240
|
+
},
|
|
1241
|
+
additionalProperties: false
|
|
1242
|
+
}],
|
|
1243
|
+
type: "problem"
|
|
1244
|
+
},
|
|
1245
|
+
name: "restrict-dist-tags"
|
|
1246
|
+
});
|
|
1247
|
+
//#endregion
|
|
1109
1248
|
//#region src/rules/restrict-private-properties.ts
|
|
1110
1249
|
const defaultBlockedProperties = ["files", "publishConfig"];
|
|
1111
1250
|
const rule$8 = createRule({
|
|
@@ -1325,8 +1464,7 @@ const rule$5 = createRule({
|
|
|
1325
1464
|
const bKey = b.key.value;
|
|
1326
1465
|
const ai = rank(aKey);
|
|
1327
1466
|
const bi = rank(bKey);
|
|
1328
|
-
|
|
1329
|
-
return naturalCompare(aKey, bKey);
|
|
1467
|
+
return ai === bi ? naturalCompare(aKey, bKey) : ai - bi;
|
|
1330
1468
|
});
|
|
1331
1469
|
if (currentOrder.some((property, i) => desiredOrder[i] !== property)) context.report({
|
|
1332
1470
|
data: { key },
|
|
@@ -1490,10 +1628,9 @@ const rule$3 = createRule({
|
|
|
1490
1628
|
if (!dependencyPropertyNames.has(node.key.value)) return;
|
|
1491
1629
|
const nodeValueType = node.value.type;
|
|
1492
1630
|
if (nodeValueType === "JSONArrayExpression") check(node.value.elements, (element) => element);
|
|
1493
|
-
if (nodeValueType
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
}
|
|
1631
|
+
if (nodeValueType !== "JSONObjectExpression") return;
|
|
1632
|
+
check(node.value.properties.map((property) => property.key), (property) => property.parent);
|
|
1633
|
+
if (trackForCrossGroupUniqueness.includes(node.key.value)) dependenciesCache[node.key.value] = node.value.properties;
|
|
1497
1634
|
},
|
|
1498
1635
|
"Program:exit"() {
|
|
1499
1636
|
const dependencyNames = new Set(dependenciesCache.dependencies.map((node) => node.key).filter(isJSONStringLiteral).map((dependencyNameNode) => dependencyNameNode.value));
|
|
@@ -1743,8 +1880,7 @@ function* lookup(cwd = process.cwd()) {
|
|
|
1743
1880
|
}
|
|
1744
1881
|
}
|
|
1745
1882
|
function parsePackageJson(filepath) {
|
|
1746
|
-
|
|
1747
|
-
return handlePackageManager(filepath);
|
|
1883
|
+
return !filepath || !fs.existsSync(filepath) ? null : handlePackageManager(filepath);
|
|
1748
1884
|
}
|
|
1749
1885
|
/**
|
|
1750
1886
|
* Detects the package manager used in the project.
|
|
@@ -1788,10 +1924,10 @@ function getNameAndVersion(pkg) {
|
|
|
1788
1924
|
version: normalizeVersion(version)
|
|
1789
1925
|
};
|
|
1790
1926
|
}
|
|
1791
|
-
|
|
1927
|
+
return typeof pkg.devEngines?.packageManager?.name === "string" ? {
|
|
1792
1928
|
name: pkg.devEngines.packageManager.name,
|
|
1793
1929
|
version: normalizeVersion(pkg.devEngines.packageManager.version)
|
|
1794
|
-
};
|
|
1930
|
+
} : void 0;
|
|
1795
1931
|
}
|
|
1796
1932
|
function handlePackageManager(filepath) {
|
|
1797
1933
|
try {
|
|
@@ -1940,18 +2076,20 @@ const rule = createRule({
|
|
|
1940
2076
|
//#region src/plugin.ts
|
|
1941
2077
|
const require = createRequire(import.meta.url);
|
|
1942
2078
|
const rules = {
|
|
1943
|
-
"bin-name-casing": rule$
|
|
1944
|
-
"exports-subpaths-style": rule$
|
|
1945
|
-
"no-empty-fields": rule$
|
|
1946
|
-
"no-local-dependencies": rule$
|
|
1947
|
-
"no-redundant-files": rule$
|
|
1948
|
-
"no-redundant-publishConfig": rule$
|
|
1949
|
-
"order-properties": rule$
|
|
1950
|
-
"prefer-rolling-workspace-spec": rule$
|
|
1951
|
-
"require-attribution": rule$
|
|
2079
|
+
"bin-name-casing": rule$21,
|
|
2080
|
+
"exports-subpaths-style": rule$20,
|
|
2081
|
+
"no-empty-fields": rule$19,
|
|
2082
|
+
"no-local-dependencies": rule$18,
|
|
2083
|
+
"no-redundant-files": rule$17,
|
|
2084
|
+
"no-redundant-publishConfig": rule$16,
|
|
2085
|
+
"order-properties": rule$15,
|
|
2086
|
+
"prefer-rolling-workspace-spec": rule$14,
|
|
2087
|
+
"require-attribution": rule$12,
|
|
2088
|
+
"require-package-json-export": rule$11,
|
|
1952
2089
|
...rules$2,
|
|
1953
|
-
"repository-shorthand": rule$
|
|
1954
|
-
"restrict-dependency-ranges": rule$
|
|
2090
|
+
"repository-shorthand": rule$13,
|
|
2091
|
+
"restrict-dependency-ranges": rule$10,
|
|
2092
|
+
"restrict-dist-tags": rule$9,
|
|
1955
2093
|
"restrict-private-properties": rule$8,
|
|
1956
2094
|
"restrict-top-level-properties": rule$7,
|
|
1957
2095
|
"scripts-name-casing": rule$6,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-package-json",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "Rules for consistent, readable, and valid package.json files. ๐๏ธ",
|
|
5
5
|
"homepage": "https://github.com/michaelfaith/eslint-plugin-package-json#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -36,7 +36,8 @@
|
|
|
36
36
|
"./experimental": {
|
|
37
37
|
"types": "./dist/experimental/index.d.mts",
|
|
38
38
|
"default": "./dist/experimental/index.mjs"
|
|
39
|
-
}
|
|
39
|
+
},
|
|
40
|
+
"./package.json": "./package.json"
|
|
40
41
|
},
|
|
41
42
|
"main": "dist/index.mjs",
|
|
42
43
|
"files": [
|
|
@@ -59,38 +60,38 @@
|
|
|
59
60
|
"devDependencies": {
|
|
60
61
|
"@astrojs/check": "0.9.10",
|
|
61
62
|
"@astrojs/markdown-satteri": "0.4.1",
|
|
62
|
-
"@astrojs/starlight": "0.42.
|
|
63
|
+
"@astrojs/starlight": "0.42.2",
|
|
63
64
|
"@catppuccin/starlight": "2.1.0",
|
|
64
|
-
"@eslint-community/eslint-plugin-eslint-comments": "4.8.
|
|
65
|
+
"@eslint-community/eslint-plugin-eslint-comments": "4.8.1",
|
|
65
66
|
"@eslint/js": "10.0.1",
|
|
66
67
|
"@eslint/json": "2.1.0",
|
|
67
68
|
"@eslint/markdown": "8.0.3",
|
|
68
69
|
"@ianvs/prettier-plugin-sort-imports": "4.7.1",
|
|
69
|
-
"@types/node": "24.13.
|
|
70
|
+
"@types/node": "24.13.6",
|
|
70
71
|
"@types/semver": "7.8.0",
|
|
71
72
|
"@typescript/native": "npm:typescript@7.0.2",
|
|
72
|
-
"@vitest/coverage-v8": "5.0.
|
|
73
|
+
"@vitest/coverage-v8": "5.0.1",
|
|
73
74
|
"@vitest/eslint-plugin": "1.6.27",
|
|
74
|
-
"astro": "7.3.
|
|
75
|
-
"astro-og-canvas": "0.13.
|
|
75
|
+
"astro": "7.3.3",
|
|
76
|
+
"astro-og-canvas": "0.13.2",
|
|
76
77
|
"canvaskit-wasm": "0.42.0",
|
|
77
78
|
"console-fail-test": "0.6.1",
|
|
78
|
-
"eslint": "10.
|
|
79
|
+
"eslint": "10.11.0",
|
|
79
80
|
"eslint-doc-generator": "3.7.1",
|
|
80
81
|
"eslint-plugin-eslint-plugin": "7.6.2",
|
|
81
|
-
"eslint-plugin-jsdoc": "64.
|
|
82
|
+
"eslint-plugin-jsdoc": "64.5.4",
|
|
82
83
|
"eslint-plugin-jsonc": "3.4.2",
|
|
83
84
|
"eslint-plugin-n": "18.3.0",
|
|
84
85
|
"eslint-plugin-node-dependencies": "2.2.0",
|
|
85
|
-
"eslint-plugin-perfectionist": "5.11.
|
|
86
|
+
"eslint-plugin-perfectionist": "5.11.1",
|
|
86
87
|
"eslint-plugin-regexp": "3.3.0",
|
|
87
|
-
"eslint-plugin-unicorn": "
|
|
88
|
+
"eslint-plugin-unicorn": "75.0.0",
|
|
88
89
|
"eslint-plugin-yml": "3.8.1",
|
|
89
90
|
"jiti": "2.7.0",
|
|
90
91
|
"json-schema-to-ts": "3.1.1",
|
|
91
|
-
"knip": "6.
|
|
92
|
+
"knip": "6.37.0",
|
|
92
93
|
"pkg-pr-new": "0.0.88",
|
|
93
|
-
"prettier": "3.9.
|
|
94
|
+
"prettier": "3.9.8",
|
|
94
95
|
"prettier-plugin-curly": "0.4.1",
|
|
95
96
|
"prettier-plugin-packagejson": "3.0.2",
|
|
96
97
|
"prettier-plugin-sh": "0.19.0",
|
|
@@ -101,7 +102,7 @@
|
|
|
101
102
|
"tsdown": "0.23.0",
|
|
102
103
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
103
104
|
"typescript-eslint": "8.70.0",
|
|
104
|
-
"vitest": "5.0.
|
|
105
|
+
"vitest": "5.0.1"
|
|
105
106
|
},
|
|
106
107
|
"peerDependencies": {
|
|
107
108
|
"@eslint/json": ">=1.0.0",
|