eslint-plugin-package-json 0.56.2 → 0.56.4
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 +14 -2
- package/README.md +19 -7
- package/lib/createRule.d.ts +13 -4
- package/lib/createRule.js +4 -0
- package/lib/index.d.ts +4 -9
- package/lib/plugin.d.ts +4 -2
- package/lib/plugin.js +1 -2
- package/lib/rules/no-empty-fields.d.ts +15 -5
- package/lib/rules/no-redundant-files.d.ts +1 -1
- package/lib/rules/no-redundant-files.js +1 -2
- package/lib/rules/order-properties.d.ts +20 -5
- package/lib/rules/order-properties.js +5 -7
- package/lib/rules/repository-shorthand.d.ts +13 -5
- package/lib/rules/require-properties.d.ts +11 -2
- package/lib/rules/restrict-dependency-ranges.d.ts +87 -10
- package/lib/rules/restrict-dependency-ranges.js +4 -7
- package/lib/rules/sort-collections.d.ts +7 -2
- package/lib/rules/sort-collections.js +2 -5
- package/lib/rules/unique-dependencies.d.ts +1 -1
- package/lib/rules/valid-bin.d.ts +12 -4
- package/lib/rules/valid-bin.js +1 -2
- package/lib/rules/valid-local-dependency.d.ts +1 -1
- package/lib/rules/valid-local-dependency.js +1 -2
- package/lib/rules/valid-name.d.ts +1 -1
- package/lib/rules/valid-package-definition.d.ts +15 -5
- package/lib/rules/valid-package-definition.js +1 -2
- package/lib/rules/valid-properties.d.ts +1 -1
- package/lib/rules/valid-repository-directory.d.ts +1 -1
- package/lib/rules/valid-version.d.ts +1 -1
- package/lib/types/estree.d.ts +1 -3
- package/lib/utils/createSimpleRequirePropertyRule.d.ts +12 -4
- package/lib/utils/createSimpleRequirePropertyRule.js +31 -32
- package/lib/utils/createSimpleValidPropertyRule.d.ts +1 -1
- package/lib/utils/createSimpleValidPropertyRule.js +27 -29
- package/package.json +16 -18
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## [0.56.
|
|
3
|
+
## [0.56.4](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.56.3...v0.56.4) (2025-10-14)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* re-adopt jsonc-eslint-parser's RuleListener type ([#1319](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1319)) ([2c4c7c2](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/2c4c7c2591732f1b298e5e6eb279afe5f7d52cab)), closes [#000](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/000)
|
|
4
9
|
|
|
10
|
+
## [0.56.3](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.56.2...v0.56.3) (2025-09-15)
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- **plugin:** update types to be compatible with `defineConfig` ([#1245](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1245)) ([861e5e1](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/861e5e129b3a5e3455b6b2a2a26d453086f20c14)), closes [#1242](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1242)
|
|
15
|
+
|
|
16
|
+
## [0.56.2](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.56.1...v0.56.2) (2025-09-04)
|
|
5
17
|
|
|
6
18
|
### Bug Fixes
|
|
7
19
|
|
|
8
|
-
|
|
20
|
+
- improve sort-collections docs and error messages ([#1250](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1250)) ([1864376](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commit/1864376039db3db690423051b0dd8a2104395aa4)), closes [#1243](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1243) [#1243](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues/1243)
|
|
9
21
|
|
|
10
22
|
## [0.56.1](https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/compare/v0.56.0...v0.56.1) (2025-08-31)
|
|
11
23
|
|
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
<p align="center">
|
|
9
9
|
<!-- prettier-ignore-start -->
|
|
10
10
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
|
11
|
-
<a href="#contributors" target="_blank"><img alt="👪 All Contributors:
|
|
11
|
+
<a href="#contributors" target="_blank"><img alt="👪 All Contributors: 30" src="https://img.shields.io/badge/%F0%9F%91%AA_all_contributors-30-21bb42.svg" /></a>
|
|
12
12
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
|
13
13
|
<!-- prettier-ignore-end -->
|
|
14
14
|
<a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/blob/main/.github/CODE_OF_CONDUCT.md" target="_blank"><img alt="🤝 Code of Conduct: Kept" src="https://img.shields.io/badge/%F0%9F%A4%9D_code_of_conduct-kept-21bb42" /></a>
|
|
@@ -130,10 +130,21 @@ export default {
|
|
|
130
130
|
|
|
131
131
|
#### `enforceForPrivate`
|
|
132
132
|
|
|
133
|
-
**Type:** `boolean`
|
|
133
|
+
- **Type:** `boolean`
|
|
134
|
+
- **Default:** [see below]
|
|
134
135
|
|
|
135
|
-
|
|
136
|
-
|
|
136
|
+
When a package.json file has a `"private": true` field, it indicates that the package will not be published to npm (or another online registry).
|
|
137
|
+
Some fields that are nice to have in public packages become less relevant when a package is private.
|
|
138
|
+
This option determines whether `require-*` rules, if used, should enforce the presence of the corresponding property in package.json files that have `"private": true`.
|
|
139
|
+
|
|
140
|
+
By default, this is:
|
|
141
|
+
|
|
142
|
+
- `false` for [`require-name`](docs/rules/require-name.md) and [`require-version`](docs/rules/require-version.md).
|
|
143
|
+
- `true` for every other `require-*` rule.
|
|
144
|
+
|
|
145
|
+
By specifying this setting as `true` or `false`, it will override the defaults and apply the setting for ALL rules.
|
|
146
|
+
In that case, either all `require-*` rules will be applied to private packages or no `require-*` rules will be applied to private packages.
|
|
147
|
+
Even then, you can override the setting again at the rule level, by using the rule's `ignorePrivate` option, which will take precedence over this global setting.
|
|
137
148
|
|
|
138
149
|
### Usage Alongside Prettier
|
|
139
150
|
|
|
@@ -249,7 +260,7 @@ Thanks! 🗂
|
|
|
249
260
|
<td align="center" valign="top" width="14.28%"><a href="https://davidlj95.com"><img src="https://avatars.githubusercontent.com/u/8050648?v=4?s=100" width="100px;" alt="David LJ"/><br /><sub><b>David LJ</b></sub></a><br /><a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=davidlj95" title="Documentation">📖</a></td>
|
|
250
261
|
<td align="center" valign="top" width="14.28%"><a href="http://lishaduck.github.io"><img src="https://avatars.githubusercontent.com/u/88557639?v=4?s=100" width="100px;" alt="Eli"/><br /><sub><b>Eli</b></sub></a><br /><a href="#ideas-lishaduck" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3Alishaduck" title="Bug reports">🐛</a></td>
|
|
251
262
|
<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>
|
|
252
|
-
<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/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=Zamiell" title="Code">💻</a> <a href="#ideas-Zamiell" title="Ideas, Planning, & Feedback">🤔</a></td>
|
|
263
|
+
<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/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=Zamiell" title="Code">💻</a> <a href="#ideas-Zamiell" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3AZamiell" title="Bug reports">🐛</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=Zamiell" title="Documentation">📖</a></td>
|
|
253
264
|
<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/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=zetlen" title="Code">💻</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3Azetlen" title="Bug reports">🐛</a> <a href="https://github.com/JoshuaKGoldberg/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>
|
|
254
265
|
<td align="center" valign="top" width="14.28%"><a href="https://piranna.github.io/"><img src="https://avatars.githubusercontent.com/u/532414?v=4?s=100" width="100px;" alt="Jesús Leganés-Combarro"/><br /><sub><b>Jesús Leganés-Combarro</b></sub></a><br /><a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=piranna" title="Code">💻</a></td>
|
|
255
266
|
<td align="center" valign="top" width="14.28%"><a href="http://www.joshuakgoldberg.com/"><img src="https://avatars.githubusercontent.com/u/3335181?v=4?s=100" width="100px;" alt="Josh Goldberg ✨"/><br /><sub><b>Josh Goldberg ✨</b></sub></a><br /><a href="#tool-JoshuaKGoldberg" title="Tools">🔧</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3AJoshuaKGoldberg" title="Bug reports">🐛</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=JoshuaKGoldberg" title="Code">💻</a> <a href="#infra-JoshuaKGoldberg" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=JoshuaKGoldberg" title="Documentation">📖</a> <a href="#maintenance-JoshuaKGoldberg" title="Maintenance">🚧</a> <a href="#ideas-JoshuaKGoldberg" title="Ideas, Planning, & Feedback">🤔</a> <a href="#content-JoshuaKGoldberg" title="Content">🖋</a> <a href="#projectManagement-JoshuaKGoldberg" title="Project Management">📆</a></td>
|
|
@@ -259,20 +270,21 @@ Thanks! 🗂
|
|
|
259
270
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/KristjanESPERANTO"><img src="https://avatars.githubusercontent.com/u/35647502?v=4?s=100" width="100px;" alt="Kristjan ESPERANTO"/><br /><sub><b>Kristjan ESPERANTO</b></sub></a><br /><a href="#ideas-kristjanesperanto" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3Akristjanesperanto" title="Bug reports">🐛</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=kristjanesperanto" title="Code">💻</a></td>
|
|
260
271
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/lo1tuma"><img src="https://avatars.githubusercontent.com/u/169170?v=4?s=100" width="100px;" alt="Mathias Schreck"/><br /><sub><b>Mathias Schreck</b></sub></a><br /><a href="#ideas-lo1tuma" title="Ideas, Planning, & Feedback">🤔</a></td>
|
|
261
272
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Cellule"><img src="https://avatars.githubusercontent.com/u/4157103?v=4?s=100" width="100px;" alt="Michael "Mike" Ferris"/><br /><sub><b>Michael "Mike" Ferris</b></sub></a><br /><a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=cellule" title="Code">💻</a></td>
|
|
273
|
+
<td align="center" valign="top" width="14.28%"><a href="https://morrisoncole.co.uk"><img src="https://avatars.githubusercontent.com/u/963368?v=4?s=100" width="100px;" alt="Morrison Cole"/><br /><sub><b>Morrison Cole</b></sub></a><br /><a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3AMorrisonCole" title="Bug reports">🐛</a></td>
|
|
262
274
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/nschonni"><img src="https://avatars.githubusercontent.com/u/1297909?v=4?s=100" width="100px;" alt="Nick Schonning"/><br /><sub><b>Nick Schonning</b></sub></a><br /><a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=nschonni" title="Code">💻</a></td>
|
|
263
275
|
<td align="center" valign="top" width="14.28%"><a href="https://github.com/rakleed"><img src="https://avatars.githubusercontent.com/u/19418601?v=4?s=100" width="100px;" alt="Pavel"/><br /><sub><b>Pavel</b></sub></a><br /><a href="#ideas-rakleed" title="Ideas, Planning, & Feedback">🤔</a> <a href="#tool-rakleed" title="Tools">🔧</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=rakleed" title="Documentation">📖</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=rakleed" title="Code">💻</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3Arakleed" title="Bug reports">🐛</a></td>
|
|
264
|
-
<td align="center" valign="top" width="14.28%"><a href="https://sasial.dev"><img src="https://avatars.githubusercontent.com/u/44125644?v=4?s=100" width="100px;" alt="Sasial"/><br /><sub><b>Sasial</b></sub></a><br /><a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=sasial-dev" title="Code">💻</a></td>
|
|
265
276
|
</tr>
|
|
266
277
|
<tr>
|
|
278
|
+
<td align="center" valign="top" width="14.28%"><a href="https://sasial.dev"><img src="https://avatars.githubusercontent.com/u/44125644?v=4?s=100" width="100px;" alt="Sasial"/><br /><sub><b>Sasial</b></sub></a><br /><a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=sasial-dev" title="Code">💻</a></td>
|
|
267
279
|
<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/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=sirugh" title="Code">💻</a></td>
|
|
268
280
|
<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/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3Ahyoban" title="Bug reports">🐛</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=hyoban" title="Code">💻</a> <a href="#ideas-hyoban" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=hyoban" title="Documentation">📖</a></td>
|
|
269
281
|
<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/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3Aota-meshi" title="Bug reports">🐛</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=ota-meshi" title="Code">💻</a></td>
|
|
270
282
|
<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/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3Ab3rnhard" title="Bug reports">🐛</a></td>
|
|
271
283
|
<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/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=chouchouji" title="Code">💻</a></td>
|
|
272
284
|
<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/JoshuaKGoldberg/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/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3Amichaelfaith" title="Bug reports">🐛</a> <a href="#tool-michaelfaith" title="Tools">🔧</a> <a href="https://github.com/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=michaelfaith" title="Documentation">📖</a></td>
|
|
273
|
-
<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/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=roottool" title="Code">💻</a></td>
|
|
274
285
|
</tr>
|
|
275
286
|
<tr>
|
|
287
|
+
<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/JoshuaKGoldberg/eslint-plugin-package-json/commits?author=roottool" title="Code">💻</a></td>
|
|
276
288
|
<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/JoshuaKGoldberg/eslint-plugin-package-json/issues?q=author%3Asunnytsang1998" title="Bug reports">🐛</a></td>
|
|
277
289
|
</tr>
|
|
278
290
|
</tbody>
|
package/lib/createRule.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { AST, RuleListener } from "jsonc-eslint-parser";
|
|
2
2
|
import * as ESTree from "estree";
|
|
3
|
+
import { FromSchema, JSONSchema } from "json-schema-to-ts";
|
|
3
4
|
import { AST as AST$1, Rule, SourceCode } from "eslint";
|
|
4
5
|
|
|
5
6
|
//#region src/createRule.d.ts
|
|
@@ -31,15 +32,23 @@ interface PackageJsonRuleContext<Options extends unknown[] = unknown[]> extends
|
|
|
31
32
|
};
|
|
32
33
|
sourceCode: PackageJsonSourceCode;
|
|
33
34
|
}
|
|
34
|
-
interface PackageJsonRuleModule<Options extends unknown[] = unknown[]> {
|
|
35
|
+
interface PackageJsonRuleModule<Options extends unknown[] = unknown[], Schema extends JSONSchema[] = JSONSchema[]> {
|
|
35
36
|
create(context: PackageJsonRuleContext<Options>): RuleListener;
|
|
36
|
-
meta: Rule.RuleMetaData
|
|
37
|
+
meta: Omit<Rule.RuleMetaData, "defaultOptions" | "schema"> & {
|
|
38
|
+
defaultOptions?: NoInfer<Options>;
|
|
39
|
+
schema?: Schema;
|
|
40
|
+
};
|
|
37
41
|
}
|
|
38
42
|
interface PackageJsonSourceCode extends SourceCode {
|
|
39
43
|
ast: PackageJsonAst;
|
|
40
44
|
}
|
|
41
|
-
|
|
45
|
+
type InferJsonSchemasTupleType<T extends JSONSchema[]> = { [K in keyof T]?: FromSchema<T[K]> };
|
|
46
|
+
/**
|
|
47
|
+
* Rule options type is inferred from the JSON schema by [json-schema-to-ts](https://www.npmjs.com/package/json-schema-to-ts).
|
|
48
|
+
* If you're not satisfied with the inferred type, you may specify it manually in the first type parameter.
|
|
49
|
+
*/
|
|
50
|
+
declare function createRule<OptionsOverride extends unknown[] = never, const Schema extends JSONSchema[] = JSONSchema[], _OptionsResolved extends unknown[] = ([OptionsOverride] extends [never] ? InferJsonSchemasTupleType<Schema> : OptionsOverride)>(rule: PackageJsonRuleModule<_OptionsResolved, Schema> & {
|
|
42
51
|
name: string;
|
|
43
|
-
}): PackageJsonRuleModule<
|
|
52
|
+
}): PackageJsonRuleModule<_OptionsResolved, Schema>;
|
|
44
53
|
//#endregion
|
|
45
54
|
export { JsonAstBodyExpression, JsonAstBodyProperty, JsonAstBodyStatement, PackageJsonAst, PackageJsonPluginSettings, PackageJsonRuleContext, PackageJsonRuleModule, PackageJsonSourceCode, createRule };
|
package/lib/createRule.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { isPackageJson } from "./utils/isPackageJson.js";
|
|
2
2
|
|
|
3
3
|
//#region src/createRule.ts
|
|
4
|
+
/**
|
|
5
|
+
* Rule options type is inferred from the JSON schema by [json-schema-to-ts](https://www.npmjs.com/package/json-schema-to-ts).
|
|
6
|
+
* If you're not satisfied with the inferred type, you may specify it manually in the first type parameter.
|
|
7
|
+
*/
|
|
4
8
|
function createRule(rule) {
|
|
5
9
|
return {
|
|
6
10
|
create(context) {
|
package/lib/index.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { PackageJsonPluginSettings, PackageJsonRuleModule } from "./createRule.js";
|
|
2
2
|
import { plugin } from "./plugin.js";
|
|
3
3
|
import * as jsonc_eslint_parser0 from "jsonc-eslint-parser";
|
|
4
|
+
import * as json_schema_to_ts0 from "json-schema-to-ts";
|
|
5
|
+
import * as eslint0 from "eslint";
|
|
4
6
|
|
|
5
7
|
//#region src/index.d.ts
|
|
6
|
-
declare const rules: Record<string, PackageJsonRuleModule<unknown[]>>;
|
|
8
|
+
declare const rules: Record<string, PackageJsonRuleModule<unknown[], json_schema_to_ts0.JSONSchema[]>>;
|
|
7
9
|
declare const configs: {
|
|
8
10
|
"legacy-recommended": {
|
|
9
11
|
plugins: string[];
|
|
@@ -20,14 +22,7 @@ declare const configs: {
|
|
|
20
22
|
};
|
|
21
23
|
name: string;
|
|
22
24
|
plugins: {
|
|
23
|
-
readonly "package-json":
|
|
24
|
-
configs: /*elided*/any;
|
|
25
|
-
meta: {
|
|
26
|
-
name: string;
|
|
27
|
-
version: string;
|
|
28
|
-
};
|
|
29
|
-
rules: Record<string, PackageJsonRuleModule<unknown[]>>;
|
|
30
|
-
};
|
|
25
|
+
readonly "package-json": eslint0.ESLint.Plugin;
|
|
31
26
|
};
|
|
32
27
|
rules: {
|
|
33
28
|
"package-json/valid-package-definition": ["error", {
|
package/lib/plugin.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { PackageJsonRuleModule } from "./createRule.js";
|
|
2
2
|
import * as parserJsonc from "jsonc-eslint-parser";
|
|
3
|
+
import * as json_schema_to_ts0 from "json-schema-to-ts";
|
|
4
|
+
import { ESLint } from "eslint";
|
|
3
5
|
|
|
4
6
|
//#region src/plugin.d.ts
|
|
5
7
|
declare const plugin: {
|
|
@@ -19,7 +21,7 @@ declare const plugin: {
|
|
|
19
21
|
};
|
|
20
22
|
name: string;
|
|
21
23
|
plugins: {
|
|
22
|
-
readonly "package-json":
|
|
24
|
+
readonly "package-json": ESLint.Plugin;
|
|
23
25
|
};
|
|
24
26
|
rules: {
|
|
25
27
|
"package-json/valid-package-definition": ["error", {
|
|
@@ -32,7 +34,7 @@ declare const plugin: {
|
|
|
32
34
|
name: string;
|
|
33
35
|
version: string;
|
|
34
36
|
};
|
|
35
|
-
rules: Record<string, PackageJsonRuleModule<unknown[]>>;
|
|
37
|
+
rules: Record<string, PackageJsonRuleModule<unknown[], json_schema_to_ts0.JSONSchema[]>>;
|
|
36
38
|
};
|
|
37
39
|
//#endregion
|
|
38
40
|
export { plugin };
|
package/lib/plugin.js
CHANGED
|
@@ -17,8 +17,7 @@ import { createRequire } from "node:module";
|
|
|
17
17
|
import * as parserJsonc from "jsonc-eslint-parser";
|
|
18
18
|
|
|
19
19
|
//#region src/plugin.ts
|
|
20
|
-
const
|
|
21
|
-
const { name, version } = require("../package.json");
|
|
20
|
+
const { name, version } = createRequire(import.meta.url)("../package.json");
|
|
22
21
|
const rules$2 = {
|
|
23
22
|
"no-empty-fields": rule,
|
|
24
23
|
"no-redundant-files": rule$1,
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { PackageJsonRuleModule } from "../createRule.js";
|
|
2
2
|
|
|
3
3
|
//#region src/rules/no-empty-fields.d.ts
|
|
4
|
-
|
|
5
|
-
ignoreProperties?: string[];
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
declare const rule: PackageJsonRuleModule<[({
|
|
5
|
+
ignoreProperties?: string[] | undefined;
|
|
6
|
+
} | undefined)?], [{
|
|
7
|
+
readonly additionalProperties: false;
|
|
8
|
+
readonly properties: {
|
|
9
|
+
readonly ignoreProperties: {
|
|
10
|
+
readonly description: "Array of top-level properties to ignore.";
|
|
11
|
+
readonly items: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
};
|
|
14
|
+
readonly type: "array";
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
readonly type: "object";
|
|
18
|
+
}]>;
|
|
9
19
|
//#endregion
|
|
10
20
|
export { rule };
|
|
@@ -73,8 +73,7 @@ const rule = createRule({
|
|
|
73
73
|
messageId: "unnecessaryBin"
|
|
74
74
|
}];
|
|
75
75
|
for (const validation of validations) for (const fileToCheck of validation.files) for (const [index, fileEntry] of files.entries()) if (isNotNullish(fileEntry) && isJSONStringLiteral(fileEntry)) {
|
|
76
|
-
|
|
77
|
-
if (regex?.test(fileToCheck)) report(files, index, validation.messageId);
|
|
76
|
+
if (getCachedLocalFileRegex(fileEntry.value)?.test(fileToCheck)) report(files, index, validation.messageId);
|
|
78
77
|
}
|
|
79
78
|
}
|
|
80
79
|
};
|
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
import { PackageJsonRuleModule } from "../createRule.js";
|
|
2
2
|
|
|
3
3
|
//#region src/rules/order-properties.d.ts
|
|
4
|
-
|
|
5
|
-
order
|
|
6
|
-
}?]
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
declare const rule: PackageJsonRuleModule<[({
|
|
5
|
+
order?: "sort-package-json" | "legacy" | string[] | undefined;
|
|
6
|
+
} | undefined)?], [{
|
|
7
|
+
readonly additionalProperties: false;
|
|
8
|
+
readonly properties: {
|
|
9
|
+
readonly order: {
|
|
10
|
+
readonly anyOf: readonly [{
|
|
11
|
+
readonly enum: readonly ["legacy", "sort-package-json"];
|
|
12
|
+
readonly type: readonly ["string"];
|
|
13
|
+
}, {
|
|
14
|
+
readonly items: {
|
|
15
|
+
readonly type: readonly ["string"];
|
|
16
|
+
};
|
|
17
|
+
readonly type: readonly ["array"];
|
|
18
|
+
}];
|
|
19
|
+
readonly description: "Specifies the sorting order of top-level properties.";
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
readonly type: "object";
|
|
23
|
+
}]>;
|
|
9
24
|
//#endregion
|
|
10
25
|
export { rule };
|
|
@@ -39,18 +39,16 @@ const rule = createRule({
|
|
|
39
39
|
create(context) {
|
|
40
40
|
return { "Program:exit"() {
|
|
41
41
|
const { ast, text } = context.sourceCode;
|
|
42
|
-
const options = {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const requiredOrder = options.order === "legacy" ? standardOrderLegacy : options.order === "sort-package-json" ? sortOrder : options.order;
|
|
42
|
+
const options = { ...context.options[0] };
|
|
43
|
+
options.order ??= "sort-package-json";
|
|
44
|
+
const { order } = options;
|
|
45
|
+
const requiredOrder = order === "legacy" ? standardOrderLegacy : order === "sort-package-json" ? sortOrder : order;
|
|
47
46
|
const json = JSON.parse(text);
|
|
48
47
|
const orderedSource = sortObjectKeys(json, [...requiredOrder, ...Object.keys(json)]);
|
|
49
48
|
const orderedKeys = Object.keys(orderedSource);
|
|
50
49
|
const { properties } = ast.body[0].expression;
|
|
51
50
|
for (let i = 0; i < properties.length; i += 1) {
|
|
52
|
-
const
|
|
53
|
-
const { value } = property;
|
|
51
|
+
const { value } = properties[i].key;
|
|
54
52
|
if (value === orderedKeys[i]) continue;
|
|
55
53
|
context.report({
|
|
56
54
|
data: { property: value },
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import { PackageJsonRuleModule } from "../createRule.js";
|
|
2
2
|
|
|
3
3
|
//#region src/rules/repository-shorthand.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
declare const rule: PackageJsonRuleModule<[({
|
|
5
|
+
form?: "object" | "shorthand" | undefined;
|
|
6
|
+
} | undefined)?], [{
|
|
7
|
+
readonly additionalProperties: false;
|
|
8
|
+
readonly properties: {
|
|
9
|
+
readonly form: {
|
|
10
|
+
readonly description: "Specifies which repository form to enforce.";
|
|
11
|
+
readonly enum: readonly ["object", "shorthand"];
|
|
12
|
+
readonly type: readonly ["string"];
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
readonly type: "object";
|
|
16
|
+
}]>;
|
|
9
17
|
//#endregion
|
|
10
18
|
export { rule };
|
|
@@ -3,8 +3,17 @@ import { PackageJsonRuleModule } from "../createRule.js";
|
|
|
3
3
|
//#region src/rules/require-properties.d.ts
|
|
4
4
|
declare const rules: {
|
|
5
5
|
[k: string]: PackageJsonRuleModule<[({
|
|
6
|
-
ignorePrivate
|
|
7
|
-
} | undefined)?]
|
|
6
|
+
ignorePrivate: boolean;
|
|
7
|
+
} | undefined)?], [{
|
|
8
|
+
readonly additionalProperties: false;
|
|
9
|
+
readonly properties: {
|
|
10
|
+
readonly ignorePrivate: {
|
|
11
|
+
readonly default: boolean;
|
|
12
|
+
readonly type: "boolean";
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
readonly type: "object";
|
|
16
|
+
}]>;
|
|
8
17
|
};
|
|
9
18
|
//#endregion
|
|
10
19
|
export { rules };
|
|
@@ -1,15 +1,92 @@
|
|
|
1
1
|
import { PackageJsonRuleModule } from "../createRule.js";
|
|
2
2
|
|
|
3
3
|
//#region src/rules/restrict-dependency-ranges.d.ts
|
|
4
|
-
|
|
5
|
-
forDependencyTypes?: string[];
|
|
6
|
-
forPackages?: string[];
|
|
7
|
-
forVersions?: string;
|
|
8
|
-
rangeType:
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
4
|
+
declare const rule: PackageJsonRuleModule<[({
|
|
5
|
+
forDependencyTypes?: string[] | undefined;
|
|
6
|
+
forPackages?: string[] | undefined;
|
|
7
|
+
forVersions?: string | undefined;
|
|
8
|
+
rangeType: "caret" | "pin" | "tilde" | ("caret" | "pin" | "tilde")[];
|
|
9
|
+
} | {
|
|
10
|
+
forDependencyTypes?: string[] | undefined;
|
|
11
|
+
forPackages?: string[] | undefined;
|
|
12
|
+
forVersions?: string | undefined;
|
|
13
|
+
rangeType: "caret" | "pin" | "tilde" | ("caret" | "pin" | "tilde")[];
|
|
14
|
+
}[] | undefined)?], [{
|
|
15
|
+
readonly oneOf: readonly [{
|
|
16
|
+
readonly additionalProperties: false;
|
|
17
|
+
readonly properties: {
|
|
18
|
+
readonly forDependencyTypes: {
|
|
19
|
+
readonly description: "Apply a range type restriction for an entire group of dependencies by which type of dependencies they belong to.";
|
|
20
|
+
readonly items: {
|
|
21
|
+
readonly enum: string[];
|
|
22
|
+
};
|
|
23
|
+
readonly type: "array";
|
|
24
|
+
};
|
|
25
|
+
readonly forPackages: {
|
|
26
|
+
readonly description: "The exact name of a package, or a regex pattern used to match a group of packages by name.";
|
|
27
|
+
readonly items: {
|
|
28
|
+
readonly type: "string";
|
|
29
|
+
};
|
|
30
|
+
readonly type: "array";
|
|
31
|
+
};
|
|
32
|
+
readonly forVersions: {
|
|
33
|
+
readonly description: "Apply a restriction to a specific semver range.";
|
|
34
|
+
readonly type: "string";
|
|
35
|
+
};
|
|
36
|
+
readonly rangeType: {
|
|
37
|
+
readonly description: "Identifies which range type or types you want to apply to packages that match any of the other match options (or all dependencies if no other options are provided).";
|
|
38
|
+
readonly oneOf: readonly [{
|
|
39
|
+
readonly enum: readonly ["caret", "pin", "tilde"];
|
|
40
|
+
}, {
|
|
41
|
+
readonly items: {
|
|
42
|
+
readonly enum: readonly ["caret", "pin", "tilde"];
|
|
43
|
+
};
|
|
44
|
+
readonly type: "array";
|
|
45
|
+
}];
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
readonly required: readonly ["rangeType"];
|
|
49
|
+
readonly type: "object";
|
|
50
|
+
}, {
|
|
51
|
+
readonly description: "Array of configuration options, specifying range requirements.";
|
|
52
|
+
readonly items: {
|
|
53
|
+
readonly additionalProperties: false;
|
|
54
|
+
readonly properties: {
|
|
55
|
+
readonly forDependencyTypes: {
|
|
56
|
+
readonly description: "Apply a range type restriction for an entire group of dependencies by which type of dependencies they belong to.";
|
|
57
|
+
readonly items: {
|
|
58
|
+
readonly enum: string[];
|
|
59
|
+
};
|
|
60
|
+
readonly type: "array";
|
|
61
|
+
};
|
|
62
|
+
readonly forPackages: {
|
|
63
|
+
readonly description: "The exact name of a package, or a regex pattern used to match a group of packages by name.";
|
|
64
|
+
readonly items: {
|
|
65
|
+
readonly type: "string";
|
|
66
|
+
};
|
|
67
|
+
readonly type: "array";
|
|
68
|
+
};
|
|
69
|
+
readonly forVersions: {
|
|
70
|
+
readonly description: "Apply a restriction to a specific semver range.";
|
|
71
|
+
readonly type: "string";
|
|
72
|
+
};
|
|
73
|
+
readonly rangeType: {
|
|
74
|
+
readonly description: "Identifies which range type or types you want to apply to packages that match any of the other match options (or all dependencies if no other options are provided).";
|
|
75
|
+
readonly oneOf: readonly [{
|
|
76
|
+
readonly enum: readonly ["caret", "pin", "tilde"];
|
|
77
|
+
}, {
|
|
78
|
+
readonly items: {
|
|
79
|
+
readonly enum: readonly ["caret", "pin", "tilde"];
|
|
80
|
+
};
|
|
81
|
+
readonly type: "array";
|
|
82
|
+
}];
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
readonly required: readonly ["rangeType"];
|
|
86
|
+
readonly type: "object";
|
|
87
|
+
};
|
|
88
|
+
readonly type: "array";
|
|
89
|
+
}];
|
|
90
|
+
}]>;
|
|
14
91
|
//#endregion
|
|
15
92
|
export { rule };
|
|
@@ -73,8 +73,7 @@ const capitalize = (str) => {
|
|
|
73
73
|
const rule = createRule({
|
|
74
74
|
create(context) {
|
|
75
75
|
if (!context.options[0]) return {};
|
|
76
|
-
const
|
|
77
|
-
const optionsArray = optionsProvided.map((option) => ({
|
|
76
|
+
const optionsArray = (Array.isArray(context.options[0]) ? [...context.options[0]].reverse() : [context.options[0]]).map((option) => ({
|
|
78
77
|
...option,
|
|
79
78
|
forPackages: option.forPackages?.map((pattern) => new RegExp(pattern)),
|
|
80
79
|
rangeTypes: Array.isArray(option.rangeType) ? option.rangeType : [option.rangeType]
|
|
@@ -93,8 +92,7 @@ const rule = createRule({
|
|
|
93
92
|
for (const options of optionsArray) {
|
|
94
93
|
if (options.forDependencyTypes && !options.forDependencyTypes.includes(dependencyType)) continue;
|
|
95
94
|
if (options.forPackages) {
|
|
96
|
-
|
|
97
|
-
if (!isMatch) continue;
|
|
95
|
+
if (!options.forPackages.some((packageNameRegex) => packageNameRegex.test(name))) continue;
|
|
98
96
|
}
|
|
99
97
|
if (options.forVersions && (/^workspace:[^~*]?$/.test(version) || version !== "*" && !semver.satisfies(version.replace(/(?:workspace:)?[^~]?/, ""), options.forVersions))) continue;
|
|
100
98
|
const rangeTypes = options.rangeTypes;
|
|
@@ -106,14 +104,13 @@ const rule = createRule({
|
|
|
106
104
|
});
|
|
107
105
|
break;
|
|
108
106
|
}
|
|
109
|
-
|
|
107
|
+
if (!rangeTypes.find((rangeType) => {
|
|
110
108
|
switch (rangeType) {
|
|
111
109
|
case "caret": return isCaretRange;
|
|
112
110
|
case "pin": return isPinned;
|
|
113
111
|
case "tilde": return isTildeRange;
|
|
114
112
|
}
|
|
115
|
-
})
|
|
116
|
-
if (!rangeTypeMatch) context.report({
|
|
113
|
+
})) context.report({
|
|
117
114
|
data: { rangeTypes: rangeTypes.join(", ") },
|
|
118
115
|
messageId: "wrongRangeType",
|
|
119
116
|
node: property.value,
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { PackageJsonRuleModule } from "../createRule.js";
|
|
2
2
|
|
|
3
3
|
//#region src/rules/sort-collections.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
declare const rule: PackageJsonRuleModule<[(string[] | undefined)?], [{
|
|
5
|
+
readonly description: "Array of package properties to require sorting.";
|
|
6
|
+
readonly items: {
|
|
7
|
+
readonly type: "string";
|
|
8
|
+
};
|
|
9
|
+
readonly type: "array";
|
|
10
|
+
}]>;
|
|
6
11
|
//#endregion
|
|
7
12
|
export { rule };
|
|
@@ -27,14 +27,11 @@ const rule = createRule({
|
|
|
27
27
|
const currentOrder = collection.properties;
|
|
28
28
|
let desiredOrder;
|
|
29
29
|
if (keyPartsReversed.at(-1) !== "scripts") desiredOrder = currentOrder.slice().sort((a, b) => {
|
|
30
|
-
|
|
31
|
-
const bKey = b.key.value;
|
|
32
|
-
return aKey > bKey ? 1 : -1;
|
|
30
|
+
return a.key.value > b.key.value ? 1 : -1;
|
|
33
31
|
});
|
|
34
32
|
else {
|
|
35
33
|
const scriptsSource = context.sourceCode.getText(node);
|
|
36
|
-
const
|
|
37
|
-
const { scripts: sortedScripts } = sortPackageJson(minimalJson);
|
|
34
|
+
const { scripts: sortedScripts } = sortPackageJson(JSON.parse(`{${scriptsSource}}`));
|
|
38
35
|
const propertyNodeMap = Object.fromEntries(collection.properties.map((prop) => [prop.key.value, prop]));
|
|
39
36
|
desiredOrder = Object.keys(sortedScripts).map((prop) => propertyNodeMap[prop]);
|
|
40
37
|
}
|
package/lib/rules/valid-bin.d.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import { PackageJsonRuleModule } from "../createRule.js";
|
|
2
2
|
|
|
3
3
|
//#region src/rules/valid-bin.d.ts
|
|
4
|
-
|
|
5
|
-
enforceCase
|
|
6
|
-
}?]
|
|
7
|
-
|
|
4
|
+
declare const rule: PackageJsonRuleModule<[({
|
|
5
|
+
enforceCase?: boolean | undefined;
|
|
6
|
+
} | undefined)?], [{
|
|
7
|
+
readonly additionalProperties: false;
|
|
8
|
+
readonly properties: {
|
|
9
|
+
readonly enforceCase: {
|
|
10
|
+
readonly description: "Enforce that the bin's keys should be in kebab case.";
|
|
11
|
+
readonly type: "boolean";
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
readonly type: "object";
|
|
15
|
+
}]>;
|
|
8
16
|
//#endregion
|
|
9
17
|
export { rule };
|
package/lib/rules/valid-bin.js
CHANGED
|
@@ -9,8 +9,7 @@ const rule = createRule({
|
|
|
9
9
|
const shouldEnforceCase = !!context.options[0]?.enforceCase;
|
|
10
10
|
return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=bin]"(node) {
|
|
11
11
|
const binValueNode = node.value;
|
|
12
|
-
const
|
|
13
|
-
const errors = validateBin(binValue);
|
|
12
|
+
const errors = validateBin(JSON.parse(context.sourceCode.getText(binValueNode)));
|
|
14
13
|
if (errors.length) context.report({
|
|
15
14
|
data: { errors: formatErrors(errors) },
|
|
16
15
|
messageId: "validationError",
|
|
@@ -9,8 +9,7 @@ const linkRegex = /^link:/;
|
|
|
9
9
|
const rule = createRule({
|
|
10
10
|
create(context) {
|
|
11
11
|
return { "Program:exit"() {
|
|
12
|
-
const
|
|
13
|
-
const { dependencies, devDependencies, peerDependencies } = original;
|
|
12
|
+
const { dependencies, devDependencies, peerDependencies } = JSON.parse(context.sourceCode.text);
|
|
14
13
|
const depObjs = [
|
|
15
14
|
Object.entries(dependencies ?? {}),
|
|
16
15
|
Object.entries(peerDependencies ?? {}),
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
import { PackageJsonRuleModule } from "../createRule.js";
|
|
2
2
|
|
|
3
3
|
//#region src/rules/valid-package-definition.d.ts
|
|
4
|
-
|
|
5
|
-
ignoreProperties?: string[];
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
declare const rule: PackageJsonRuleModule<[({
|
|
5
|
+
ignoreProperties?: string[] | undefined;
|
|
6
|
+
} | undefined)?], [{
|
|
7
|
+
readonly additionalProperties: false;
|
|
8
|
+
readonly properties: {
|
|
9
|
+
readonly ignoreProperties: {
|
|
10
|
+
readonly description: "Array of top-level package properties to ignore.";
|
|
11
|
+
readonly items: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
};
|
|
14
|
+
readonly type: "array";
|
|
15
|
+
};
|
|
16
|
+
};
|
|
17
|
+
readonly type: "object";
|
|
18
|
+
}]>;
|
|
9
19
|
//#endregion
|
|
10
20
|
export { rule };
|
|
@@ -12,8 +12,7 @@ const rule = createRule({
|
|
|
12
12
|
create(context) {
|
|
13
13
|
const ignoreProperties = context.options[0]?.ignoreProperties ?? [];
|
|
14
14
|
return { "Program:exit"() {
|
|
15
|
-
const
|
|
16
|
-
const usableErrors = validation.errors?.filter((error) => {
|
|
15
|
+
const usableErrors = validate(context.sourceCode.text).errors?.filter((error) => {
|
|
17
16
|
return isUsableError(error.message) && !ignoreProperties.includes(error.field);
|
|
18
17
|
}) ?? [];
|
|
19
18
|
for (const error of usableErrors) if (error.message) context.report({
|
|
@@ -3,7 +3,7 @@ import { PackageJsonRuleModule } from "../createRule.js";
|
|
|
3
3
|
//#region src/rules/valid-properties.d.ts
|
|
4
4
|
/** All basic valid- flavor rules */
|
|
5
5
|
declare const rules: {
|
|
6
|
-
[k: string]: PackageJsonRuleModule<
|
|
6
|
+
[k: string]: PackageJsonRuleModule<[], []>;
|
|
7
7
|
};
|
|
8
8
|
//#endregion
|
|
9
9
|
export { rules };
|
package/lib/types/estree.d.ts
CHANGED
|
@@ -11,9 +11,6 @@ interface CreateRequirePropertyRuleOptions {
|
|
|
11
11
|
*/
|
|
12
12
|
isRecommended?: boolean;
|
|
13
13
|
}
|
|
14
|
-
type Options = [{
|
|
15
|
-
ignorePrivate?: boolean;
|
|
16
|
-
}?];
|
|
17
14
|
/**
|
|
18
15
|
* Given a top-level property name, create a rule that requires that property to be present.
|
|
19
16
|
* Optionally, include it in the recommended config.
|
|
@@ -24,7 +21,18 @@ declare const createSimpleRequirePropertyRule: (propertyName: string, {
|
|
|
24
21
|
ignorePrivateDefault,
|
|
25
22
|
isRecommended
|
|
26
23
|
}?: CreateRequirePropertyRuleOptions) => {
|
|
27
|
-
rule: PackageJsonRuleModule<
|
|
24
|
+
rule: PackageJsonRuleModule<[({
|
|
25
|
+
ignorePrivate: boolean;
|
|
26
|
+
} | undefined)?], [{
|
|
27
|
+
readonly additionalProperties: false;
|
|
28
|
+
readonly properties: {
|
|
29
|
+
readonly ignorePrivate: {
|
|
30
|
+
readonly default: boolean;
|
|
31
|
+
readonly type: "boolean";
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
readonly type: "object";
|
|
35
|
+
}]>;
|
|
28
36
|
ruleName: string;
|
|
29
37
|
};
|
|
30
38
|
//#endregion
|
|
@@ -10,39 +10,38 @@ import { isJSONStringLiteral } from "./predicates.js";
|
|
|
10
10
|
*/
|
|
11
11
|
const createSimpleRequirePropertyRule = (propertyName, { ignorePrivateDefault = false, isRecommended } = {}) => {
|
|
12
12
|
const ruleName = `require-${propertyName}`;
|
|
13
|
-
const rule = createRule({
|
|
14
|
-
create(context) {
|
|
15
|
-
const enforceForPrivate = context.settings.packageJson?.enforceForPrivate;
|
|
16
|
-
const ignorePrivate = context.options[0]?.ignorePrivate ?? (typeof enforceForPrivate === "boolean" ? !enforceForPrivate : ignorePrivateDefault);
|
|
17
|
-
return { "Program > JSONExpressionStatement > JSONObjectExpression"(node) {
|
|
18
|
-
if (ignorePrivate && node.properties.some((property) => isJSONStringLiteral(property.key) && property.key.value === "private" && property.value.type === "JSONLiteral" && property.value.value === true)) return;
|
|
19
|
-
if (!node.properties.some((property) => isJSONStringLiteral(property.key) && property.key.value === propertyName)) context.report({
|
|
20
|
-
data: { property: propertyName },
|
|
21
|
-
messageId: "missing",
|
|
22
|
-
node: context.sourceCode.ast
|
|
23
|
-
});
|
|
24
|
-
} };
|
|
25
|
-
},
|
|
26
|
-
meta: {
|
|
27
|
-
docs: {
|
|
28
|
-
description: `Requires the \`${propertyName}\` property to be present.`,
|
|
29
|
-
recommended: isRecommended
|
|
30
|
-
},
|
|
31
|
-
messages: { missing: "Property '{{property}}' is required." },
|
|
32
|
-
schema: [{
|
|
33
|
-
additionalProperties: false,
|
|
34
|
-
properties: { ignorePrivate: {
|
|
35
|
-
default: ignorePrivateDefault,
|
|
36
|
-
type: "boolean"
|
|
37
|
-
} },
|
|
38
|
-
type: "object"
|
|
39
|
-
}],
|
|
40
|
-
type: "suggestion"
|
|
41
|
-
},
|
|
42
|
-
name: ruleName
|
|
43
|
-
});
|
|
44
13
|
return {
|
|
45
|
-
rule
|
|
14
|
+
rule: createRule({
|
|
15
|
+
create(context) {
|
|
16
|
+
const enforceForPrivate = context.settings.packageJson?.enforceForPrivate;
|
|
17
|
+
const ignorePrivate = context.options[0]?.ignorePrivate ?? (typeof enforceForPrivate === "boolean" ? !enforceForPrivate : ignorePrivateDefault);
|
|
18
|
+
return { "Program > JSONExpressionStatement > JSONObjectExpression"(node) {
|
|
19
|
+
if (ignorePrivate && node.properties.some((property) => isJSONStringLiteral(property.key) && property.key.value === "private" && property.value.type === "JSONLiteral" && property.value.value === true)) return;
|
|
20
|
+
if (!node.properties.some((property) => isJSONStringLiteral(property.key) && property.key.value === propertyName)) context.report({
|
|
21
|
+
data: { property: propertyName },
|
|
22
|
+
messageId: "missing",
|
|
23
|
+
node: context.sourceCode.ast
|
|
24
|
+
});
|
|
25
|
+
} };
|
|
26
|
+
},
|
|
27
|
+
meta: {
|
|
28
|
+
docs: {
|
|
29
|
+
description: `Requires the \`${propertyName}\` property to be present.`,
|
|
30
|
+
recommended: isRecommended
|
|
31
|
+
},
|
|
32
|
+
messages: { missing: "Property '{{property}}' is required." },
|
|
33
|
+
schema: [{
|
|
34
|
+
additionalProperties: false,
|
|
35
|
+
properties: { ignorePrivate: {
|
|
36
|
+
default: ignorePrivateDefault,
|
|
37
|
+
type: "boolean"
|
|
38
|
+
} },
|
|
39
|
+
type: "object"
|
|
40
|
+
}],
|
|
41
|
+
type: "suggestion"
|
|
42
|
+
},
|
|
43
|
+
name: ruleName
|
|
44
|
+
}),
|
|
46
45
|
ruleName
|
|
47
46
|
};
|
|
48
47
|
};
|
|
@@ -9,7 +9,7 @@ type ValidationFunction = (value: unknown) => string[];
|
|
|
9
9
|
* to create a more complex rule, create it in its own file.
|
|
10
10
|
*/
|
|
11
11
|
declare const createSimpleValidPropertyRule: (propertyName: string, validationFunction: ValidationFunction, aliases?: string[]) => {
|
|
12
|
-
rule: PackageJsonRuleModule<
|
|
12
|
+
rule: PackageJsonRuleModule<[], []>;
|
|
13
13
|
ruleName: string;
|
|
14
14
|
};
|
|
15
15
|
//#endregion
|
|
@@ -11,36 +11,34 @@ import { formatErrors } from "./formatErrors.js";
|
|
|
11
11
|
const createSimpleValidPropertyRule = (propertyName, validationFunction, aliases = []) => {
|
|
12
12
|
const ruleName = `valid-${propertyName}`;
|
|
13
13
|
const propertyNames = [propertyName, ...aliases];
|
|
14
|
-
const rule = createRule({
|
|
15
|
-
create(context) {
|
|
16
|
-
return propertyNames.reduce((acc, name) => {
|
|
17
|
-
acc[`Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=${name}]`] = (node) => {
|
|
18
|
-
const valueNode = node.value;
|
|
19
|
-
const value = JSON.parse(context.sourceCode.getText(valueNode));
|
|
20
|
-
const errors = validationFunction(value);
|
|
21
|
-
if (errors.length) context.report({
|
|
22
|
-
data: { errors: formatErrors(errors) },
|
|
23
|
-
messageId: "validationError",
|
|
24
|
-
node: valueNode
|
|
25
|
-
});
|
|
26
|
-
};
|
|
27
|
-
return acc;
|
|
28
|
-
}, {});
|
|
29
|
-
},
|
|
30
|
-
meta: {
|
|
31
|
-
docs: {
|
|
32
|
-
category: "Best Practices",
|
|
33
|
-
description: `Enforce that the \`${propertyName}\`${aliases.length ? ` (also: ${aliases.map((alias) => `\`${alias}\``).join(", ")})` : ""} property is valid.`,
|
|
34
|
-
recommended: true
|
|
35
|
-
},
|
|
36
|
-
messages: { validationError: `Invalid ${propertyName}: {{ errors }}` },
|
|
37
|
-
schema: [],
|
|
38
|
-
type: "problem"
|
|
39
|
-
},
|
|
40
|
-
name: ruleName
|
|
41
|
-
});
|
|
42
14
|
return {
|
|
43
|
-
rule
|
|
15
|
+
rule: createRule({
|
|
16
|
+
create(context) {
|
|
17
|
+
return propertyNames.reduce((acc, name) => {
|
|
18
|
+
acc[`Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=${name}]`] = (node) => {
|
|
19
|
+
const valueNode = node.value;
|
|
20
|
+
const errors = validationFunction(JSON.parse(context.sourceCode.getText(valueNode)));
|
|
21
|
+
if (errors.length) context.report({
|
|
22
|
+
data: { errors: formatErrors(errors) },
|
|
23
|
+
messageId: "validationError",
|
|
24
|
+
node: valueNode
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
return acc;
|
|
28
|
+
}, {});
|
|
29
|
+
},
|
|
30
|
+
meta: {
|
|
31
|
+
docs: {
|
|
32
|
+
category: "Best Practices",
|
|
33
|
+
description: `Enforce that the \`${propertyName}\`${aliases.length ? ` (also: ${aliases.map((alias) => `\`${alias}\``).join(", ")})` : ""} property is valid.`,
|
|
34
|
+
recommended: true
|
|
35
|
+
},
|
|
36
|
+
messages: { validationError: `Invalid ${propertyName}: {{ errors }}` },
|
|
37
|
+
schema: [],
|
|
38
|
+
type: "problem"
|
|
39
|
+
},
|
|
40
|
+
name: ruleName
|
|
41
|
+
}),
|
|
44
42
|
ruleName
|
|
45
43
|
};
|
|
46
44
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-package-json",
|
|
3
|
-
"version": "0.56.
|
|
3
|
+
"version": "0.56.4",
|
|
4
4
|
"description": "Rules for consistent, readable, and valid package.json files. 🗂️",
|
|
5
5
|
"homepage": "https://github.com/JoshuaKGoldberg/eslint-plugin-package-json#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -35,7 +35,6 @@
|
|
|
35
35
|
"lint:docs": "eslint-doc-generator --check",
|
|
36
36
|
"lint:knip": "knip",
|
|
37
37
|
"lint:md": "markdownlint \"**/*.md\" \".github/**/*.md\" --rules sentences-per-line",
|
|
38
|
-
"lint:packages": "pnpm dedupe --check",
|
|
39
38
|
"prepare": "husky",
|
|
40
39
|
"test": "vitest",
|
|
41
40
|
"typecheck": "tsc"
|
|
@@ -57,9 +56,8 @@
|
|
|
57
56
|
},
|
|
58
57
|
"devDependencies": {
|
|
59
58
|
"@eslint-community/eslint-plugin-eslint-comments": "4.5.0",
|
|
60
|
-
"@eslint/js": "9.
|
|
59
|
+
"@eslint/js": "9.37.0",
|
|
61
60
|
"@release-it/conventional-changelog": "10.0.0",
|
|
62
|
-
"@types/eslint-plugin-markdown": "2.0.2",
|
|
63
61
|
"@types/estree": "1.0.7",
|
|
64
62
|
"@types/node": "22.18.0",
|
|
65
63
|
"@types/semver": "7.7.0",
|
|
@@ -68,21 +66,21 @@
|
|
|
68
66
|
"@vitest/coverage-v8": "3.2.0",
|
|
69
67
|
"@vitest/eslint-plugin": "1.3.3",
|
|
70
68
|
"console-fail-test": "0.5.0",
|
|
71
|
-
"eslint": "9.
|
|
72
|
-
"eslint-doc-generator": "2.
|
|
69
|
+
"eslint": "9.37.0",
|
|
70
|
+
"eslint-doc-generator": "2.3.0",
|
|
73
71
|
"eslint-plugin-eslint-plugin": "7.0.0",
|
|
74
|
-
"eslint-plugin-jsdoc": "
|
|
75
|
-
"eslint-plugin-jsonc": "2.
|
|
76
|
-
"eslint-plugin-markdown": "5.1.0",
|
|
72
|
+
"eslint-plugin-jsdoc": "60.8.0",
|
|
73
|
+
"eslint-plugin-jsonc": "2.21.0",
|
|
77
74
|
"eslint-plugin-n": "17.21.0",
|
|
78
75
|
"eslint-plugin-perfectionist": "4.15.0",
|
|
79
76
|
"eslint-plugin-regexp": "2.10.0",
|
|
80
|
-
"eslint-plugin-yml": "1.
|
|
77
|
+
"eslint-plugin-yml": "1.19.0",
|
|
81
78
|
"husky": "9.1.7",
|
|
82
|
-
"jiti": "2.
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
79
|
+
"jiti": "2.6.0",
|
|
80
|
+
"json-schema-to-ts": "3.1.1",
|
|
81
|
+
"jsonc-eslint-parser": "2.4.1",
|
|
82
|
+
"knip": "5.64.0",
|
|
83
|
+
"lint-staged": "16.2.0",
|
|
86
84
|
"markdownlint": "0.38.0",
|
|
87
85
|
"markdownlint-cli": "0.45.0",
|
|
88
86
|
"prettier": "3.6.0",
|
|
@@ -91,18 +89,18 @@
|
|
|
91
89
|
"prettier-plugin-sh": "0.18.0",
|
|
92
90
|
"release-it": "19.0.1",
|
|
93
91
|
"sentences-per-line": "0.3.0",
|
|
94
|
-
"tsdown": "0.
|
|
92
|
+
"tsdown": "0.15.0",
|
|
95
93
|
"typescript": "5.9.2",
|
|
96
|
-
"typescript-eslint": "8.
|
|
94
|
+
"typescript-eslint": "8.46.0",
|
|
97
95
|
"vitest": "3.2.0"
|
|
98
96
|
},
|
|
99
97
|
"peerDependencies": {
|
|
100
98
|
"eslint": ">=8.0.0",
|
|
101
99
|
"jsonc-eslint-parser": "^2.0.0"
|
|
102
100
|
},
|
|
103
|
-
"packageManager": "pnpm@10.
|
|
101
|
+
"packageManager": "pnpm@10.18.0",
|
|
104
102
|
"engines": {
|
|
105
|
-
"node": "
|
|
103
|
+
"node": "^20.19.0 || >=22.12.0"
|
|
106
104
|
},
|
|
107
105
|
"publishConfig": {
|
|
108
106
|
"provenance": true
|