eslint-plugin-package-json 1.8.1 → 1.9.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 CHANGED
@@ -50,6 +50,7 @@ See [Getting Started](https://eslint-plugin-package-json.dev/getting-started) fo
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
52
  | [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. | | | 💡 |
53
+ | [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
54
  | [restrict-private-properties](https://eslint-plugin-package-json.dev/rules/restrict-private-properties) | Disallows unnecessary properties in private packages. | | 🔧 | 💡 |
54
55
  | [restrict-top-level-properties](https://eslint-plugin-package-json.dev/rules/restrict-top-level-properties) | Disallows specified top-level properties in package.json. | | | 💡 |
55
56
  | [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 +210,7 @@ Thanks! 🍻
209
210
  </tr>
210
211
  <tr>
211
212
  <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>
213
+ <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
214
  <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
215
  <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
216
  <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>
@@ -1,4 +1,4 @@
1
- import { t as plugin$1 } from "../plugin-DlF-r5D9.mjs";
1
+ import { t as plugin$1 } from "../plugin-2AyGRwRO.mjs";
2
2
  import { toCompatRule } from "eslint-json-compat-utils";
3
3
  //#region src/experimental/plugin.ts
4
4
  const language = "json/json";
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as plugin } from "./plugin-DlF-r5D9.mjs";
1
+ import { t as plugin } from "./plugin-2AyGRwRO.mjs";
2
2
  //#region src/index.ts
3
3
  const rules = plugin.rules;
4
4
  const configs = plugin.configs;
@@ -55,7 +55,7 @@ function createRule(rule) {
55
55
  }
56
56
  //#endregion
57
57
  //#region src/rules/bin-name-casing.ts
58
- const rule$19 = createRule({
58
+ const rule$20 = createRule({
59
59
  create(context) {
60
60
  return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=bin]"(node) {
61
61
  if (node.value.type === "JSONObjectExpression") for (const property of node.value.properties) {
@@ -97,7 +97,7 @@ function isImplicitFormat(node) {
97
97
  if (node.type === "JSONLiteral") return true;
98
98
  return node.properties.every((property) => !isJSONStringLiteral(property.key) || !property.key.value.startsWith("."));
99
99
  }
100
- const rule$18 = createRule({
100
+ const rule$19 = createRule({
101
101
  create(context) {
102
102
  const [{ prefer = "explicit" } = {}] = context.options;
103
103
  function validateForExplicit(node) {
@@ -200,7 +200,7 @@ const getTopLevelProperty = (node) => {
200
200
  return n.type === "JSONProperty" ? n.key : void 0;
201
201
  };
202
202
  const defaultIgnoreProperties = ["files"];
203
- const rule$17 = createRule({
203
+ const rule$18 = createRule({
204
204
  create(context) {
205
205
  const ignoreProperties = new Set(context.options[0]?.ignoreProperties ?? defaultIgnoreProperties);
206
206
  return {
@@ -256,7 +256,7 @@ const getBundledDependencyNames = (value) => {
256
256
  if (value?.type === "JSONArrayExpression") for (const element of value.elements.filter(isNotNullish).filter(isJSONStringLiteral)) names.add(element.value);
257
257
  return names;
258
258
  };
259
- const rule$16 = createRule({
259
+ const rule$17 = createRule({
260
260
  create(context) {
261
261
  const ignorePrivate = context.options[0]?.ignorePrivate ?? true;
262
262
  let isPrivate = false;
@@ -327,7 +327,7 @@ const getCachedLocalFileRegex = (filename) => {
327
327
  return regex;
328
328
  }
329
329
  };
330
- const rule$15 = createRule({
330
+ const rule$16 = createRule({
331
331
  create(context) {
332
332
  const entryCache = {
333
333
  bin: [],
@@ -404,7 +404,7 @@ const rule$15 = createRule({
404
404
  });
405
405
  //#endregion
406
406
  //#region src/rules/no-redundant-publishConfig.ts
407
- const rule$14 = createRule({
407
+ const rule$15 = createRule({
408
408
  create(context) {
409
409
  let packageName;
410
410
  let publishConfigAccessProperty;
@@ -450,7 +450,7 @@ const rule$14 = createRule({
450
450
  });
451
451
  //#endregion
452
452
  //#region src/rules/order-properties.ts
453
- const rule$13 = createRule({
453
+ const rule$14 = createRule({
454
454
  create(context) {
455
455
  return { "Program:exit"() {
456
456
  const { ast, text } = context.sourceCode;
@@ -510,7 +510,7 @@ const rule$13 = createRule({
510
510
  //#region src/rules/prefer-rolling-workspace-spec.ts
511
511
  const rollingWorkspaceSpecRegex = /^workspace:[*^~]?$/;
512
512
  const convertibleSpecRegex = /^(workspace:[~^])/;
513
- const rule$12 = createRule({
513
+ const rule$13 = createRule({
514
514
  create(context) {
515
515
  const { ignoreDependencies = [], ignorePatterns = [] } = context.options[0] ?? {};
516
516
  const ignoreRegexes = ignorePatterns.map((pattern) => new RegExp(pattern));
@@ -608,7 +608,7 @@ const createUrl = (shorthand) => {
608
608
  }
609
609
  return `${providerUrls.github}${shorthand}`;
610
610
  };
611
- const rule$11 = createRule({
611
+ const rule$12 = createRule({
612
612
  create(context) {
613
613
  const [{ form = "object" } = {}] = context.options;
614
614
  function validateRepositoryForObject(node) {
@@ -687,7 +687,7 @@ const rule$11 = createRule({
687
687
  });
688
688
  //#endregion
689
689
  //#region src/rules/require-attribution.ts
690
- const rule$10 = createRule({
690
+ const rule$11 = createRule({
691
691
  create(context) {
692
692
  const preferContributorsOnly = context.options[0]?.preferContributorsOnly ?? false;
693
693
  const ignorePrivate = context.options[0]?.ignorePrivate ?? true;
@@ -929,7 +929,7 @@ const rules$2 = Object.fromEntries([
929
929
  }));
930
930
  //#endregion
931
931
  //#region src/rules/restrict-dependency-ranges.ts
932
- const DEPENDENCY_TYPES = [
932
+ const DEPENDENCY_TYPES$1 = [
933
933
  "dependencies",
934
934
  "devDependencies",
935
935
  "optionalDependencies",
@@ -975,7 +975,7 @@ const schemaOptions = {
975
975
  properties: {
976
976
  forDependencyTypes: {
977
977
  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 },
978
+ items: { enum: DEPENDENCY_TYPES$1 },
979
979
  type: "array"
980
980
  },
981
981
  forPackages: {
@@ -1029,7 +1029,7 @@ const isVersionSupported = (version) => {
1029
1029
  return !!semver.validRange(rawVersion);
1030
1030
  };
1031
1031
  const POSSIBLE_WORKSPACE_SPEC_REGEX = /(?:workspace:)?[^~]?/;
1032
- const rule$9 = createRule({
1032
+ const rule$10 = createRule({
1033
1033
  create(context) {
1034
1034
  if (!context.options[0]) return {};
1035
1035
  const optionsArray = (Array.isArray(context.options[0]) ? context.options[0].toReversed() : [context.options[0]]).map((option) => ({
@@ -1039,7 +1039,7 @@ const rule$9 = createRule({
1039
1039
  }));
1040
1040
  return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral][value.type=JSONObjectExpression]"(node) {
1041
1041
  const dependencyType = node.key.value;
1042
- if (!DEPENDENCY_TYPES.includes(dependencyType)) return;
1042
+ if (!DEPENDENCY_TYPES$1.includes(dependencyType)) return;
1043
1043
  for (const property of node.value.properties) {
1044
1044
  if (!isJSONStringLiteral(property.key) || !isJSONStringLiteral(property.value)) continue;
1045
1045
  const name = property.key.value;
@@ -1106,6 +1106,73 @@ const rule$9 = createRule({
1106
1106
  name: "restrict-dependency-ranges"
1107
1107
  });
1108
1108
  //#endregion
1109
+ //#region src/rules/restrict-dist-tags.ts
1110
+ const DEPENDENCY_TYPES = [
1111
+ "dependencies",
1112
+ "devDependencies",
1113
+ "optionalDependencies",
1114
+ "peerDependencies"
1115
+ ];
1116
+ const DEFAULT_ALLOWED_TAGS = [
1117
+ "latest",
1118
+ "dev",
1119
+ "next",
1120
+ "alpha",
1121
+ "beta",
1122
+ "canary",
1123
+ "rc"
1124
+ ];
1125
+ const distTagPattern = /^[A-Z0-9][\w.-]*$/i;
1126
+ function isDistTag(value) {
1127
+ return !semver.validRange(value) && distTagPattern.test(value);
1128
+ }
1129
+ const rule$9 = createRule({
1130
+ create(context) {
1131
+ const { allowed = DEFAULT_ALLOWED_TAGS, allowedFor } = context.options[0] ?? {};
1132
+ return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral][value.type=JSONObjectExpression]"(node) {
1133
+ const dependencyType = node.key.value;
1134
+ if (!DEPENDENCY_TYPES.includes(dependencyType)) return;
1135
+ for (const property of node.value.properties) {
1136
+ if (!isJSONStringLiteral(property.key) || !isJSONStringLiteral(property.value)) continue;
1137
+ const spec = property.value.value;
1138
+ if (!isDistTag(spec)) continue;
1139
+ if ((allowedFor === void 0 || allowedFor.includes(dependencyType)) && allowed.includes(spec)) continue;
1140
+ context.report({
1141
+ data: {
1142
+ dependencyType,
1143
+ tag: spec
1144
+ },
1145
+ messageId: "disallowedDistTag",
1146
+ node: property.value
1147
+ });
1148
+ }
1149
+ } };
1150
+ },
1151
+ meta: {
1152
+ defaultOptions: [{ allowed: DEFAULT_ALLOWED_TAGS }],
1153
+ docs: { description: "Restricts dependency dist-tags to an allowed list and selected dependency types." },
1154
+ messages: { disallowedDistTag: "The \"{{ tag }}\" dist-tag is not allowed for {{ dependencyType }}." },
1155
+ schema: [{
1156
+ type: "object",
1157
+ properties: {
1158
+ allowed: {
1159
+ description: "Dist-tags allowed in dependency specifications.",
1160
+ type: "array",
1161
+ items: { type: "string" }
1162
+ },
1163
+ allowedFor: {
1164
+ description: "Dependency sections where the allowed dist-tags may be used.",
1165
+ type: "array",
1166
+ items: { enum: DEPENDENCY_TYPES }
1167
+ }
1168
+ },
1169
+ additionalProperties: false
1170
+ }],
1171
+ type: "problem"
1172
+ },
1173
+ name: "restrict-dist-tags"
1174
+ });
1175
+ //#endregion
1109
1176
  //#region src/rules/restrict-private-properties.ts
1110
1177
  const defaultBlockedProperties = ["files", "publishConfig"];
1111
1178
  const rule$8 = createRule({
@@ -1940,18 +2007,19 @@ const rule = createRule({
1940
2007
  //#region src/plugin.ts
1941
2008
  const require = createRequire(import.meta.url);
1942
2009
  const rules = {
1943
- "bin-name-casing": rule$19,
1944
- "exports-subpaths-style": rule$18,
1945
- "no-empty-fields": rule$17,
1946
- "no-local-dependencies": rule$16,
1947
- "no-redundant-files": rule$15,
1948
- "no-redundant-publishConfig": rule$14,
1949
- "order-properties": rule$13,
1950
- "prefer-rolling-workspace-spec": rule$12,
1951
- "require-attribution": rule$10,
2010
+ "bin-name-casing": rule$20,
2011
+ "exports-subpaths-style": rule$19,
2012
+ "no-empty-fields": rule$18,
2013
+ "no-local-dependencies": rule$17,
2014
+ "no-redundant-files": rule$16,
2015
+ "no-redundant-publishConfig": rule$15,
2016
+ "order-properties": rule$14,
2017
+ "prefer-rolling-workspace-spec": rule$13,
2018
+ "require-attribution": rule$11,
1952
2019
  ...rules$2,
1953
- "repository-shorthand": rule$11,
1954
- "restrict-dependency-ranges": rule$9,
2020
+ "repository-shorthand": rule$12,
2021
+ "restrict-dependency-ranges": rule$10,
2022
+ "restrict-dist-tags": rule$9,
1955
2023
  "restrict-private-properties": rule$8,
1956
2024
  "restrict-top-level-properties": rule$7,
1957
2025
  "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.8.1",
3
+ "version": "1.9.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": {
@@ -61,7 +61,7 @@
61
61
  "@astrojs/markdown-satteri": "0.4.1",
62
62
  "@astrojs/starlight": "0.42.0",
63
63
  "@catppuccin/starlight": "2.1.0",
64
- "@eslint-community/eslint-plugin-eslint-comments": "4.8.0",
64
+ "@eslint-community/eslint-plugin-eslint-comments": "4.8.1",
65
65
  "@eslint/js": "10.0.1",
66
66
  "@eslint/json": "2.1.0",
67
67
  "@eslint/markdown": "8.0.3",
@@ -69,7 +69,7 @@
69
69
  "@types/node": "24.13.4",
70
70
  "@types/semver": "7.8.0",
71
71
  "@typescript/native": "npm:typescript@7.0.2",
72
- "@vitest/coverage-v8": "5.0.0",
72
+ "@vitest/coverage-v8": "5.0.1",
73
73
  "@vitest/eslint-plugin": "1.6.27",
74
74
  "astro": "7.3.2",
75
75
  "astro-og-canvas": "0.13.1",
@@ -78,7 +78,7 @@
78
78
  "eslint": "10.10.0",
79
79
  "eslint-doc-generator": "3.7.1",
80
80
  "eslint-plugin-eslint-plugin": "7.6.2",
81
- "eslint-plugin-jsdoc": "64.3.8",
81
+ "eslint-plugin-jsdoc": "64.4.0",
82
82
  "eslint-plugin-jsonc": "3.4.2",
83
83
  "eslint-plugin-n": "18.3.0",
84
84
  "eslint-plugin-node-dependencies": "2.2.0",
@@ -101,7 +101,7 @@
101
101
  "tsdown": "0.23.0",
102
102
  "typescript": "npm:@typescript/typescript6@6.0.2",
103
103
  "typescript-eslint": "8.70.0",
104
- "vitest": "5.0.0"
104
+ "vitest": "5.0.1"
105
105
  },
106
106
  "peerDependencies": {
107
107
  "@eslint/json": ">=1.0.0",