eslint-plugin-package-json 1.7.1 → 1.8.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
@@ -46,6 +46,7 @@ See [Getting Started](https://eslint-plugin-package-json.dev/getting-started) fo
46
46
  | [no-redundant-files](https://eslint-plugin-package-json.dev/rules/no-redundant-files) | Prevents adding unnecessary / redundant files. | ✅ | | 💡 |
47
47
  | [no-redundant-publishConfig](https://eslint-plugin-package-json.dev/rules/no-redundant-publishConfig) | Warns when publishConfig.access is used in unscoped packages. | ✅ | | 💡 |
48
48
  | [order-properties](https://eslint-plugin-package-json.dev/rules/order-properties) | Enforces that package properties are declared in a consistent order. | 🎨 | 🔧 | |
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. | | | 💡 |
49
50
  | [repository-shorthand](https://eslint-plugin-package-json.dev/rules/repository-shorthand) | Enforce either object or shorthand declaration for repository. | ✅ | 🔧 | |
50
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. | ✅ | | 💡 |
51
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. | | | 💡 |
@@ -1,4 +1,4 @@
1
- import { t as plugin$1 } from "../plugin-BG90Pf7y.mjs";
1
+ import { t as plugin$1 } from "../plugin-Ciw4gT9_.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-BG90Pf7y.mjs";
1
+ import { t as plugin } from "./plugin-Ciw4gT9_.mjs";
2
2
  //#region src/index.ts
3
3
  const rules = plugin.rules;
4
4
  const configs = plugin.configs;
@@ -6,8 +6,8 @@ import detectIndent from "detect-indent";
6
6
  import { detectNewlineGraceful } from "detect-newline";
7
7
  import sortObjectKeys from "sort-object-keys";
8
8
  import sortPackageJson, { sortOrder } from "sort-package-json";
9
- import { execFileSync } from "node:child_process";
10
9
  import semver from "semver";
10
+ import { execFileSync } from "node:child_process";
11
11
  import { validateAuthor, validateBin, validateBrowser, validateBugs, validateBundleDependencies, validateConfig, validateContributors, validateCpu, validateDependencies, validateDescription, validateDevEngines, validateDirectories, validateEngines, validateExports, validateFiles, validateFunding, validateGypfile, validateHomepage, validateKeywords, validateLibc, validateLicense, validateMain, validateMan, validateName, validateOs, validatePackageManager, validatePeerDependenciesMeta, validatePrivate, validatePublishConfig, validateRepository, validateScripts, validateSideEffects, validateType, validateVersion, validateWorkspaces } from "package-json-validator";
12
12
  import fs from "node:fs";
13
13
  import path from "node:path";
@@ -50,7 +50,7 @@ function createRule(rule) {
50
50
  }
51
51
  //#endregion
52
52
  //#region src/rules/bin-name-casing.ts
53
- const rule$18 = createRule({
53
+ const rule$19 = createRule({
54
54
  create(context) {
55
55
  return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=bin]"(node) {
56
56
  if (node.value.type === "JSONObjectExpression") for (const property of node.value.properties) {
@@ -92,7 +92,7 @@ function isImplicitFormat(node) {
92
92
  if (node.type === "JSONLiteral") return true;
93
93
  return node.properties.every((property) => !isJSONStringLiteral(property.key) || !property.key.value.startsWith("."));
94
94
  }
95
- const rule$17 = createRule({
95
+ const rule$18 = createRule({
96
96
  create(context) {
97
97
  const [{ prefer = "explicit" } = {}] = context.options;
98
98
  function validateForExplicit(node) {
@@ -193,7 +193,7 @@ const getTopLevelProperty = (node) => {
193
193
  return n.type === "JSONProperty" ? n.key : void 0;
194
194
  };
195
195
  const defaultIgnoreProperties = ["files"];
196
- const rule$16 = createRule({
196
+ const rule$17 = createRule({
197
197
  create(context) {
198
198
  const ignoreProperties = new Set(context.options[0]?.ignoreProperties ?? defaultIgnoreProperties);
199
199
  return {
@@ -249,7 +249,7 @@ const getBundledDependencyNames = (value) => {
249
249
  if (value?.type === "JSONArrayExpression") for (const element of value.elements.filter(isNotNullish).filter(isJSONStringLiteral)) names.add(element.value);
250
250
  return names;
251
251
  };
252
- const rule$15 = createRule({
252
+ const rule$16 = createRule({
253
253
  create(context) {
254
254
  const ignorePrivate = context.options[0]?.ignorePrivate ?? true;
255
255
  let isPrivate = false;
@@ -320,7 +320,7 @@ const getCachedLocalFileRegex = (filename) => {
320
320
  return regex;
321
321
  }
322
322
  };
323
- const rule$14 = createRule({
323
+ const rule$15 = createRule({
324
324
  create(context) {
325
325
  const entryCache = {
326
326
  bin: [],
@@ -397,7 +397,7 @@ const rule$14 = createRule({
397
397
  });
398
398
  //#endregion
399
399
  //#region src/rules/no-redundant-publishConfig.ts
400
- const rule$13 = createRule({
400
+ const rule$14 = createRule({
401
401
  create(context) {
402
402
  let packageName;
403
403
  let publishConfigAccessProperty;
@@ -443,7 +443,7 @@ const rule$13 = createRule({
443
443
  });
444
444
  //#endregion
445
445
  //#region src/rules/order-properties.ts
446
- const rule$12 = createRule({
446
+ const rule$13 = createRule({
447
447
  create(context) {
448
448
  return { "Program:exit"() {
449
449
  const { ast, text } = context.sourceCode;
@@ -500,6 +500,73 @@ const rule$12 = createRule({
500
500
  name: "order-properties"
501
501
  });
502
502
  //#endregion
503
+ //#region src/rules/prefer-rolling-workspace-spec.ts
504
+ const rollingWorkspaceSpecRegex = /^workspace:[*^~]?$/;
505
+ const convertibleSpecRegex = /^(workspace:[~^])/;
506
+ const rule$12 = createRule({
507
+ create(context) {
508
+ const { ignoreDependencies = [], ignorePatterns = [] } = context.options[0] ?? {};
509
+ const ignoreRegexes = ignorePatterns.map((pattern) => new RegExp(pattern));
510
+ const isIgnored = (name) => ignoreDependencies.includes(name) || ignoreRegexes.some((regex) => regex.test(name));
511
+ return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral]:matches([key.value=dependencies], [key.value=devDependencies])"(node) {
512
+ if (node.value.type === "JSONObjectExpression") for (const property of node.value.properties) {
513
+ const key = property.key.value;
514
+ if (isIgnored(key)) continue;
515
+ const valueNode = property.value;
516
+ if (!isJSONStringLiteral(valueNode) || !valueNode.value.startsWith("workspace:")) continue;
517
+ const dependencySpec = valueNode.value;
518
+ if (!rollingWorkspaceSpecRegex.test(dependencySpec)) {
519
+ let conversion;
520
+ const convertibleMatch = convertibleSpecRegex.exec(dependencySpec);
521
+ const rawVersion = dependencySpec.replace("workspace:", "");
522
+ if (convertibleMatch) conversion = convertibleMatch[1];
523
+ else if (semver.parse(rawVersion)) conversion = "workspace:*";
524
+ context.report({
525
+ messageId: "nonRollingWorkspaceSpec",
526
+ node: valueNode,
527
+ suggest: conversion ? [{
528
+ fix: (fixer) => {
529
+ return fixer.replaceText(valueNode, JSON.stringify(conversion));
530
+ },
531
+ messageId: "convertToRolling"
532
+ }] : void 0
533
+ });
534
+ }
535
+ }
536
+ } };
537
+ },
538
+ meta: {
539
+ defaultOptions: [{}],
540
+ docs: {
541
+ category: "Best Practices",
542
+ description: "Require that dependencies declared with workspace protocol use a rolling workspace spec instead of a specific semver range."
543
+ },
544
+ hasSuggestions: true,
545
+ messages: {
546
+ convertToRolling: "Convert to rolling workspace spec",
547
+ nonRollingWorkspaceSpec: "Workspace spec should not include specific semver range. Use a rolling workspace spec instead."
548
+ },
549
+ schema: [{
550
+ additionalProperties: false,
551
+ properties: {
552
+ ignoreDependencies: {
553
+ items: { type: ["string"] },
554
+ type: ["array"],
555
+ description: "Specific dependencies to ignore."
556
+ },
557
+ ignorePatterns: {
558
+ items: { type: ["string"] },
559
+ type: ["array"],
560
+ description: "Regex patterns for dependency names to ignore."
561
+ }
562
+ },
563
+ type: "object"
564
+ }],
565
+ type: "suggestion"
566
+ },
567
+ name: "prefer-rolling-workspace-spec"
568
+ });
569
+ //#endregion
503
570
  //#region src/utils/findPropertyWithKeyValue.ts
504
571
  function findPropertyWithKeyValue(properties, value) {
505
572
  return properties.find((property) => property.key.type === "JSONLiteral" && property.key.value === value);
@@ -1864,13 +1931,14 @@ const rule = createRule({
1864
1931
  //#region src/plugin.ts
1865
1932
  const require = createRequire(import.meta.url);
1866
1933
  const rules = {
1867
- "bin-name-casing": rule$18,
1868
- "exports-subpaths-style": rule$17,
1869
- "no-empty-fields": rule$16,
1870
- "no-local-dependencies": rule$15,
1871
- "no-redundant-files": rule$14,
1872
- "no-redundant-publishConfig": rule$13,
1873
- "order-properties": rule$12,
1934
+ "bin-name-casing": rule$19,
1935
+ "exports-subpaths-style": rule$18,
1936
+ "no-empty-fields": rule$17,
1937
+ "no-local-dependencies": rule$16,
1938
+ "no-redundant-files": rule$15,
1939
+ "no-redundant-publishConfig": rule$14,
1940
+ "order-properties": rule$13,
1941
+ "prefer-rolling-workspace-spec": rule$12,
1874
1942
  "require-attribution": rule$10,
1875
1943
  ...rules$2,
1876
1944
  "repository-shorthand": rule$11,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-package-json",
3
- "version": "1.7.1",
3
+ "version": "1.8.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": {
@@ -73,22 +73,23 @@
73
73
  "@vitest/eslint-plugin": "1.6.20",
74
74
  "astro": "7.2.0",
75
75
  "astro-og-canvas": "0.13.0",
76
- "canvaskit-wasm": "0.41.1",
76
+ "canvaskit-wasm": "0.42.0",
77
77
  "console-fail-test": "0.6.0",
78
- "eslint": "10.8.0",
78
+ "eslint": "10.9.0",
79
79
  "eslint-doc-generator": "3.7.0",
80
80
  "eslint-plugin-eslint-plugin": "7.6.0",
81
- "eslint-plugin-jsdoc": "64.0.0",
81
+ "eslint-plugin-jsdoc": "64.2.0",
82
82
  "eslint-plugin-jsonc": "3.4.0",
83
- "eslint-plugin-n": "18.2.1",
83
+ "eslint-plugin-n": "18.3.0",
84
84
  "eslint-plugin-node-dependencies": "2.2.0",
85
85
  "eslint-plugin-perfectionist": "5.10.0",
86
- "eslint-plugin-regexp": "3.1.0",
86
+ "eslint-plugin-regexp": "3.2.0",
87
87
  "eslint-plugin-unicorn": "73.0.0",
88
88
  "eslint-plugin-yml": "3.8.0",
89
89
  "jiti": "2.7.0",
90
90
  "json-schema-to-ts": "3.1.1",
91
91
  "knip": "6.32.0",
92
+ "pkg-pr-new": "0.0.87",
92
93
  "prettier": "3.9.0",
93
94
  "prettier-plugin-curly": "0.4.1",
94
95
  "prettier-plugin-packagejson": "3.0.2",
@@ -99,7 +100,7 @@
99
100
  "starlight-auto-sidebar": "0.4.0",
100
101
  "tsdown": "0.22.2",
101
102
  "typescript": "npm:@typescript/typescript6@6.0.2",
102
- "typescript-eslint": "8.66.0",
103
+ "typescript-eslint": "8.68.0",
103
104
  "vitest": "4.1.8"
104
105
  },
105
106
  "peerDependencies": {