eslint-plugin-package-json 1.6.2 → 1.7.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.
@@ -1,4 +1,4 @@
1
- import { t as plugin$1 } from "../plugin-C-Z8sf5g.mjs";
1
+ import { t as plugin$1 } from "../plugin-Dzfp9IK7.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-C-Z8sf5g.mjs";
1
+ import { t as plugin } from "./plugin-Dzfp9IK7.mjs";
2
2
  //#region src/index.ts
3
3
  const rules = plugin.rules;
4
4
  const configs = plugin.configs;
@@ -9,7 +9,9 @@ import sortPackageJson, { sortOrder } from "sort-package-json";
9
9
  import { execFileSync } from "node:child_process";
10
10
  import semver from "semver";
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
+ import fs from "node:fs";
12
13
  import path from "node:path";
14
+ import process from "node:process";
13
15
  import { sep } from "node:path/posix";
14
16
  import { findRootSync } from "@altano/repository-tools";
15
17
  //#region src/utils/predicates/isJSONStringLiteral.ts
@@ -242,12 +244,21 @@ const rule$16 = createRule({
242
244
  //#endregion
243
245
  //#region src/rules/no-local-dependencies.ts
244
246
  const isLocalDependency = (value) => value.startsWith("file:") || value.startsWith("link:") || value.startsWith("./") || value.startsWith("../") || value.startsWith(".\\") || value.startsWith("..\\");
247
+ const getBundledDependencyNames = (value) => {
248
+ const names = /* @__PURE__ */ new Set();
249
+ if (value?.type === "JSONArrayExpression") for (const element of value.elements.filter(isNotNullish).filter(isJSONStringLiteral)) names.add(element.value);
250
+ return names;
251
+ };
245
252
  const rule$15 = createRule({
246
253
  create(context) {
247
254
  const ignorePrivate = context.options[0]?.ignorePrivate ?? true;
248
255
  let isPrivate = false;
249
256
  let dependencyNodes = [];
257
+ const bundleDependencyValues = /* @__PURE__ */ new Map();
250
258
  return {
259
+ "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral]:matches([key.value=bundleDependencies], [key.value=bundledDependencies])"(node) {
260
+ bundleDependencyValues.set(node.key.value, node.value);
261
+ },
251
262
  "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.type=JSONLiteral][value.type=JSONLiteral][key.value=private]"(node) {
252
263
  if (node.value.value === true) isPrivate = true;
253
264
  },
@@ -256,7 +267,13 @@ const rule$15 = createRule({
256
267
  },
257
268
  "Program:exit"() {
258
269
  if (ignorePrivate && isPrivate) return;
270
+ let bundleDependenciesValue = bundleDependencyValues.get("bundleDependencies");
271
+ if (!(bundleDependenciesValue && (bundleDependenciesValue.type !== "JSONLiteral" || Boolean(bundleDependenciesValue.value)))) bundleDependenciesValue = bundleDependencyValues.get("bundledDependencies");
272
+ if (bundleDependenciesValue?.type === "JSONLiteral" && bundleDependenciesValue.value === true) return;
273
+ const bundledDependencyNames = getBundledDependencyNames(bundleDependenciesValue);
259
274
  for (const dependencyPropertyNode of dependencyNodes) {
275
+ const dependencyKey = dependencyPropertyNode.key;
276
+ if (isJSONStringLiteral(dependencyKey) && bundledDependencyNames.has(dependencyKey.value)) continue;
260
277
  const dependencyValue = dependencyPropertyNode.value;
261
278
  if (isJSONStringLiteral(dependencyValue) && isLocalDependency(dependencyValue.value)) context.report({
262
279
  data: { name: dependencyValue.value },
@@ -845,10 +862,40 @@ const DEPENDENCY_TYPES = [
845
862
  "peerDependencies"
846
863
  ];
847
864
  const RANGE_TYPES = [
848
- "caret",
849
- "pin",
850
- "tilde"
865
+ {
866
+ symbol: "^",
867
+ alias: "caret",
868
+ workspaceSymbol: "^"
869
+ },
870
+ {
871
+ alias: "pin",
872
+ workspaceSymbol: "*"
873
+ },
874
+ {
875
+ symbol: "~",
876
+ alias: "tilde",
877
+ workspaceSymbol: "~"
878
+ },
879
+ {
880
+ symbol: "<",
881
+ alias: "lt"
882
+ },
883
+ {
884
+ symbol: "<=",
885
+ alias: "le"
886
+ },
887
+ {
888
+ symbol: ">",
889
+ alias: "gt"
890
+ },
891
+ {
892
+ symbol: ">=",
893
+ alias: "ge"
894
+ }
851
895
  ];
896
+ const SYMBOLS = RANGE_TYPES.filter((rangeType) => "symbol" in rangeType).map((rangeType) => rangeType.symbol);
897
+ const RANGE_NAMES = RANGE_TYPES.map((rangeType) => rangeType.alias);
898
+ const SYMBOLS_AND_RANGE_NAMES = [...SYMBOLS, ...RANGE_NAMES];
852
899
  const schemaOptions = {
853
900
  additionalProperties: false,
854
901
  properties: {
@@ -868,8 +915,8 @@ const schemaOptions = {
868
915
  },
869
916
  rangeType: {
870
917
  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).",
871
- oneOf: [{ enum: RANGE_TYPES }, {
872
- items: { enum: RANGE_TYPES },
918
+ oneOf: [{ enum: SYMBOLS_AND_RANGE_NAMES }, {
919
+ items: { enum: SYMBOLS_AND_RANGE_NAMES },
873
920
  type: "array"
874
921
  }]
875
922
  }
@@ -877,33 +924,37 @@ const schemaOptions = {
877
924
  required: ["rangeType"],
878
925
  type: "object"
879
926
  };
880
- const SYMBOLS = {
881
- caret: "^",
882
- pin: "",
883
- tilde: "~"
927
+ const normalizeRangeType = (rangeTypeOrSymbol) => RANGE_TYPES.find((rangeType) => "symbol" in rangeType && rangeType.symbol === rangeTypeOrSymbol || rangeType.alias === rangeTypeOrSymbol);
928
+ /** @returns `undefined` if workspace versions are not supported for the specified {@link rangeType} */
929
+ const getWorkspaceVersionForRange = (rangeType) => {
930
+ if ("workspaceSymbol" in rangeType) return `workspace:${rangeType.workspaceSymbol}`;
884
931
  };
932
+ /** For displaying a range type in a user-facing way (ie. an error message). */
933
+ const displayRangeType = (rangeType) => "symbol" in rangeType ? rangeType.symbol : rangeType.alias;
934
+ const ROLLING_WORKSPACE_REGEX = /^workspace:[~^*]$/;
935
+ const isRollingWorkspaceSpec = (version) => ROLLING_WORKSPACE_REGEX.test(version);
936
+ const CHANGE_VERSION_RANGE_REGEX = /^(workspace:)?(\^|~|<=?|>=?)?/;
885
937
  /**
886
938
  * Given the original version, update it to use the correct range type.
887
939
  */
888
940
  const changeVersionRange = (version, rangeType) => {
889
- if (/^workspace:[~^*]$/.test(version)) switch (rangeType) {
890
- case "caret": return "workspace:^";
891
- case "pin": return "workspace:*";
892
- default: return "workspace:~";
941
+ if (isRollingWorkspaceSpec(version)) {
942
+ const result = getWorkspaceVersionForRange(rangeType);
943
+ if (result !== void 0) return result;
893
944
  }
894
- return version.replace(/^(workspace:)?(\^|~|<=?|>=?)?/, `$1${SYMBOLS[rangeType]}`);
945
+ const replaceWith = "symbol" in rangeType ? rangeType.symbol : "";
946
+ return version.replace(CHANGE_VERSION_RANGE_REGEX, `$1${replaceWith}`);
895
947
  };
948
+ const IS_VERSION_SUPPORTED_REGEX = /^workspace:/;
896
949
  /**
897
950
  * Check if the version is in a form that this rule supports.
898
951
  */
899
952
  const isVersionSupported = (version) => {
900
- if (/^workspace:[*^~]$/.test(version)) return true;
901
- const rawVersion = version.replace(/^workspace:/, "");
953
+ if (isRollingWorkspaceSpec(version)) return true;
954
+ const rawVersion = version.replace(IS_VERSION_SUPPORTED_REGEX, "");
902
955
  return !!semver.validRange(rawVersion);
903
956
  };
904
- const capitalize = (str) => {
905
- return str.charAt(0).toUpperCase() + str.slice(1);
906
- };
957
+ const POSSIBLE_WORKSPACE_SPEC_REGEX = /(?:workspace:)?[^~]?/;
907
958
  const rule$9 = createRule({
908
959
  create(context) {
909
960
  if (!context.options[0]) return {};
@@ -920,39 +971,41 @@ const rule$9 = createRule({
920
971
  const name = property.key.value;
921
972
  const version = property.value.value;
922
973
  if (!isVersionSupported(version)) continue;
923
- const isPinned = !!semver.parse(version) || version === "workspace:*";
924
- const isTildeRange = !!semver.validRange(version) && version.startsWith("~") || version.startsWith("workspace:~");
925
- const isCaretRange = !!semver.validRange(version) && version.startsWith("^") || version.startsWith("workspace:^");
974
+ const doesRangeTypeMatch = (rangeType) => {
975
+ if ("symbol" in rangeType && semver.validRange(version)) return version.startsWith(rangeType.symbol);
976
+ if (rangeType.alias === "pin" && (!!semver.parse(version) || version === "workspace:*" || version === "workspace:")) return true;
977
+ if (version.startsWith("workspace:")) {
978
+ const workspaceVersion = getWorkspaceVersionForRange(rangeType);
979
+ return workspaceVersion === void 0 || version.startsWith(workspaceVersion);
980
+ }
981
+ return false;
982
+ };
926
983
  for (const options of optionsArray) {
927
984
  if (options.forDependencyTypes && !options.forDependencyTypes.includes(dependencyType)) continue;
928
985
  if (options.forPackages) {
929
986
  if (!options.forPackages.some((packageNameRegex) => packageNameRegex.test(name))) continue;
930
987
  }
931
- if (options.forVersions && (/^workspace:[^~*]?$/.test(version) || version !== "*" && !semver.satisfies(version.replace(/(?:workspace:)?[^~]?/, ""), options.forVersions))) continue;
932
- const rangeTypes = options.rangeTypes;
988
+ if (options.forVersions && (isRollingWorkspaceSpec(version) || version !== "*" && !semver.satisfies(version.replace(POSSIBLE_WORKSPACE_SPEC_REGEX, ""), options.forVersions))) continue;
989
+ const rangeTypes = options.rangeTypes.map(normalizeRangeType);
990
+ const validRangeTypes = rangeTypes.map(displayRangeType).join(", ");
933
991
  if (version === "*") {
934
992
  context.report({
935
- data: { rangeTypes: rangeTypes.join(", ") },
993
+ data: { rangeTypes: validRangeTypes },
936
994
  messageId: "wrongRangeType",
937
995
  node: property.value
938
996
  });
939
997
  break;
940
998
  }
941
- if (!rangeTypes.some((rangeType) => {
942
- switch (rangeType) {
943
- case "caret": return isCaretRange;
944
- case "pin": return isPinned;
945
- case "tilde": return isTildeRange;
946
- }
947
- })) context.report({
948
- data: { rangeTypes: rangeTypes.join(", ") },
999
+ if (!rangeTypes.some(doesRangeTypeMatch)) context.report({
1000
+ data: { rangeTypes: validRangeTypes },
949
1001
  messageId: "wrongRangeType",
950
1002
  node: property.value,
951
1003
  suggest: rangeTypes.map((rangeType) => ({
952
1004
  fix(fixer) {
953
1005
  return fixer.replaceText(property.value, `"${changeVersionRange(version, rangeType)}"`);
954
1006
  },
955
- messageId: `changeTo${capitalize(rangeType)}`
1007
+ messageId: rangeType.alias === "pin" ? "changeToPin" : "changeTo",
1008
+ data: rangeType.alias === "pin" ? void 0 : { rangeType: displayRangeType(rangeType) }
956
1009
  }))
957
1010
  });
958
1011
  break;
@@ -965,9 +1018,8 @@ const rule$9 = createRule({
965
1018
  docs: { description: "Restricts the range of dependencies to allow or disallow specific types of ranges." },
966
1019
  hasSuggestions: true,
967
1020
  messages: {
968
- changeToCaret: "Change to use a caret range.",
969
1021
  changeToPin: "Pin the version.",
970
- changeToTilde: "Change to use a tilde range.",
1022
+ changeTo: "Change to use a {{rangeType}} range",
971
1023
  wrongRangeType: "This dependency is using the wrong range type. Acceptable range type(s): {{rangeTypes}}"
972
1024
  },
973
1025
  schema: [{ oneOf: [schemaOptions, {
@@ -1099,23 +1151,26 @@ const rule$7 = createRule({
1099
1151
  });
1100
1152
  //#endregion
1101
1153
  //#region src/rules/scripts-name-casing.ts
1102
- const BUILT_IN_SCRIPTS_IN_CAMEL_CASE = /* @__PURE__ */ new Set(["prepublishOnly"]);
1154
+ const BUILT_IN_SCRIPTS_IN_CAMEL_CASE = /* @__PURE__ */ new Set(["prepublishOnly", "pnpm:devPreinstall"]);
1103
1155
  const rule$6 = createRule({
1104
1156
  create(context) {
1157
+ const { ignoreNames = [], ignorePatterns = [] } = context.options[0] ?? {};
1158
+ const ignoreRegexes = ignorePatterns.map((pattern) => new RegExp(pattern));
1159
+ const isIgnored = (name) => ignoreNames.includes(name) || ignoreRegexes.some((regex) => regex.test(name));
1105
1160
  return { "Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=scripts]"(node) {
1106
1161
  if (node.value.type === "JSONObjectExpression") for (const property of node.value.properties) {
1107
1162
  const keyNode = property.key;
1108
1163
  const key = keyNode.value;
1109
- if (BUILT_IN_SCRIPTS_IN_CAMEL_CASE.has(key)) continue;
1110
- const kebabCaseKey = key.split(":").map((segment) => kebabCase(segment)).join(":");
1111
- if (kebabCaseKey !== key) context.report({
1164
+ if (BUILT_IN_SCRIPTS_IN_CAMEL_CASE.has(key) || isIgnored(key)) continue;
1165
+ const kebabCaseKey = (key.startsWith(".") ? key.slice(1) : key).split(":").map((segment) => kebabCase(segment)).join(":");
1166
+ if (kebabCaseKey !== (key.startsWith(".") ? key.slice(1) : key)) context.report({
1112
1167
  data: { property: key },
1113
1168
  messageId: "invalidCase",
1114
1169
  node: keyNode,
1115
1170
  suggest: [{
1116
1171
  data: { property: key },
1117
1172
  fix: (fixer) => {
1118
- return fixer.replaceText(keyNode, JSON.stringify(kebabCaseKey));
1173
+ return fixer.replaceText(keyNode, JSON.stringify(key.startsWith(".") ? `.${kebabCaseKey}` : kebabCaseKey));
1119
1174
  },
1120
1175
  messageId: "convertToKebabCase"
1121
1176
  }]
@@ -1124,6 +1179,7 @@ const rule$6 = createRule({
1124
1179
  } };
1125
1180
  },
1126
1181
  meta: {
1182
+ defaultOptions: [{}],
1127
1183
  docs: {
1128
1184
  category: "Stylistic",
1129
1185
  description: "Enforce that names for `scripts` are in kebab case (optionally separated by colons)."
@@ -1133,7 +1189,22 @@ const rule$6 = createRule({
1133
1189
  convertToKebabCase: "Convert {{ property }} to kebab case.",
1134
1190
  invalidCase: "Script name {{ property }} should be in kebab case."
1135
1191
  },
1136
- schema: [],
1192
+ schema: [{
1193
+ additionalProperties: false,
1194
+ properties: {
1195
+ ignoreNames: {
1196
+ items: { type: ["string"] },
1197
+ type: ["array"],
1198
+ description: "Specific script names to ignore."
1199
+ },
1200
+ ignorePatterns: {
1201
+ items: { type: ["string"] },
1202
+ type: ["array"],
1203
+ description: "Regex patterns for script names to ignore."
1204
+ }
1205
+ },
1206
+ type: "object"
1207
+ }],
1137
1208
  type: "suggestion"
1138
1209
  },
1139
1210
  name: "scripts-name-casing"
@@ -1543,6 +1614,130 @@ const createSimpleValidPropertyRule = (propertyName, validationFunction, aliases
1543
1614
  ruleName
1544
1615
  };
1545
1616
  };
1617
+ //#endregion
1618
+ //#region src/utils/packageManager/constants.ts
1619
+ const AGENTS = [
1620
+ "npm",
1621
+ "yarn",
1622
+ "pnpm",
1623
+ "bun",
1624
+ "deno",
1625
+ "nub",
1626
+ "aube"
1627
+ ];
1628
+ const LOCK_FILES = {
1629
+ "aube-lock.yaml": "aube",
1630
+ "aube-workspace.yaml": "aube",
1631
+ "bun.lock": "bun",
1632
+ "bun.lockb": "bun",
1633
+ "deno.lock": "deno",
1634
+ "nub.lock": "nub",
1635
+ "pnpm-lock.yaml": "pnpm",
1636
+ "pnpm-workspace.yaml": "pnpm",
1637
+ "yarn.lock": "yarn",
1638
+ "package-lock.json": "npm",
1639
+ "npm-shrinkwrap.json": "npm"
1640
+ };
1641
+ //#endregion
1642
+ //#region src/utils/packageManager/detectPackageManager.ts
1643
+ let packageManagerCache;
1644
+ const userAgentRegex = /^(.+?)\/(\S+)?/;
1645
+ function getPackageManagerFromUserAgent() {
1646
+ const userAgentMatch = process.env.npm_config_user_agent?.match(userAgentRegex);
1647
+ if (userAgentMatch) {
1648
+ const name = userAgentMatch[1];
1649
+ const version = userAgentMatch[2];
1650
+ if (AGENTS.includes(name)) return {
1651
+ name,
1652
+ version
1653
+ };
1654
+ }
1655
+ return null;
1656
+ }
1657
+ function setPackageManagerCache(result) {
1658
+ packageManagerCache = result;
1659
+ return packageManagerCache;
1660
+ }
1661
+ function* lookup(cwd = process.cwd()) {
1662
+ let directory = path.resolve(cwd);
1663
+ const { root } = path.parse(directory);
1664
+ while (directory && directory !== root) {
1665
+ yield directory;
1666
+ directory = path.dirname(directory);
1667
+ }
1668
+ }
1669
+ function parsePackageJson(filepath) {
1670
+ if (!filepath || !fs.existsSync(filepath)) return null;
1671
+ return handlePackageManager(filepath);
1672
+ }
1673
+ /**
1674
+ * Detects the package manager used in the project.
1675
+ * @returns The detected package manager or `null` if not found.
1676
+ */
1677
+ function detectPackageManager() {
1678
+ if (packageManagerCache) return packageManagerCache;
1679
+ const cwd = process.cwd();
1680
+ const strategies = [
1681
+ "lockfile",
1682
+ "packageManager-field",
1683
+ "user-agent"
1684
+ ];
1685
+ for (const directory of lookup(cwd)) for (const strategy of strategies) switch (strategy) {
1686
+ case "lockfile":
1687
+ if (fs.existsSync(path.join(directory, "rush.json"))) return setPackageManagerCache({ name: "pnpm" });
1688
+ for (const lock of Object.keys(LOCK_FILES)) if (fs.existsSync(path.join(directory, lock))) {
1689
+ const name = LOCK_FILES[lock];
1690
+ return setPackageManagerCache(parsePackageJson(path.join(directory, "package.json")) ?? { name });
1691
+ }
1692
+ break;
1693
+ case "packageManager-field": {
1694
+ const result = parsePackageJson(path.join(directory, "package.json"));
1695
+ if (result) return setPackageManagerCache(result);
1696
+ break;
1697
+ }
1698
+ case "user-agent": {
1699
+ const result = getPackageManagerFromUserAgent();
1700
+ if (result) return setPackageManagerCache(result);
1701
+ break;
1702
+ }
1703
+ }
1704
+ return null;
1705
+ }
1706
+ function getNameAndVersion(pkg) {
1707
+ const normalizeVersion = (version) => version?.match(/\d+(?:\.\d+){0,2}/)?.[0] ?? version;
1708
+ if (typeof pkg.packageManager === "string") {
1709
+ const [name, version] = pkg.packageManager.replace(/^\^/, "").split("@", 2);
1710
+ return {
1711
+ name,
1712
+ version: normalizeVersion(version)
1713
+ };
1714
+ }
1715
+ if (typeof pkg.devEngines?.packageManager?.name === "string") return {
1716
+ name: pkg.devEngines.packageManager.name,
1717
+ version: normalizeVersion(pkg.devEngines.packageManager.version)
1718
+ };
1719
+ }
1720
+ function handlePackageManager(filepath) {
1721
+ try {
1722
+ const content = fs.readFileSync(filepath, "utf8");
1723
+ const nameAndVer = getNameAndVersion(JSON.parse(content));
1724
+ if (nameAndVer) return {
1725
+ name: nameAndVer.name,
1726
+ version: nameAndVer.version
1727
+ };
1728
+ } catch {}
1729
+ return null;
1730
+ }
1731
+ //#endregion
1732
+ //#region src/rules/valid-properties.ts
1733
+ const packageManagerAwareValidateDependencies = (value) => {
1734
+ const result = detectPackageManager();
1735
+ if (result?.name === "pnpm") {
1736
+ const version = result.version;
1737
+ if (!version || semver.gte(version, "11.1.0")) return validateDependencies(value, { allowNamedRegistries: true });
1738
+ }
1739
+ return validateDependencies(value);
1740
+ };
1546
1741
  /** All basic valid- flavor rules */
1547
1742
  const rules$1 = Object.fromEntries([
1548
1743
  ["bin", validateBin],
@@ -1556,8 +1751,8 @@ const rules$1 = Object.fromEntries([
1556
1751
  ["contributors", validateContributors],
1557
1752
  ["cpu", validateCpu],
1558
1753
  ["description", validateDescription],
1559
- ["dependencies", validateDependencies],
1560
- ["devDependencies", validateDependencies],
1754
+ ["dependencies", packageManagerAwareValidateDependencies],
1755
+ ["devDependencies", packageManagerAwareValidateDependencies],
1561
1756
  ["devEngines", validateDevEngines],
1562
1757
  ["directories", validateDirectories],
1563
1758
  ["engines", validateEngines],
@@ -1611,7 +1806,7 @@ const pathEndsWith = (parent, child) => {
1611
1806
  let pathToCheck = "";
1612
1807
  return segments.reverse().some((segment) => {
1613
1808
  pathToCheck = path.join(segment, pathToCheck);
1614
- if (pathToCheck === child) return true;
1809
+ return pathToCheck === child;
1615
1810
  });
1616
1811
  };
1617
1812
  let repoRootCache = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-package-json",
3
- "version": "1.6.2",
3
+ "version": "1.7.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": {
@@ -51,7 +51,7 @@
51
51
  "eslint-fix-utils": "~0.4.3",
52
52
  "eslint-json-compat-utils": "^0.2.3",
53
53
  "jsonc-eslint-parser": "^3.1.0",
54
- "package-json-validator": "^1.5.0",
54
+ "package-json-validator": "^1.6.0",
55
55
  "semver": "^7.7.3",
56
56
  "sort-object-keys": "^2.0.0",
57
57
  "sort-package-json": "^4.0.0"
@@ -67,28 +67,28 @@
67
67
  "@eslint/markdown": "8.0.1",
68
68
  "@ianvs/prettier-plugin-sort-imports": "4.7.1",
69
69
  "@types/node": "24.13.0",
70
- "@types/semver": "7.7.1",
70
+ "@types/semver": "7.8.0",
71
71
  "@typescript/native": "npm:typescript@7.0.2",
72
72
  "@vitest/coverage-v8": "4.1.8",
73
73
  "@vitest/eslint-plugin": "1.6.20",
74
- "astro": "7.1.0",
74
+ "astro": "7.2.0",
75
75
  "astro-og-canvas": "0.13.0",
76
76
  "canvaskit-wasm": "0.41.1",
77
77
  "console-fail-test": "0.6.0",
78
- "eslint": "10.7.0",
78
+ "eslint": "10.8.0",
79
79
  "eslint-doc-generator": "3.7.0",
80
- "eslint-plugin-eslint-plugin": "7.5.0",
81
- "eslint-plugin-jsdoc": "63.2.0",
82
- "eslint-plugin-jsonc": "3.3.0",
80
+ "eslint-plugin-eslint-plugin": "7.6.0",
81
+ "eslint-plugin-jsdoc": "63.3.0",
82
+ "eslint-plugin-jsonc": "3.4.0",
83
83
  "eslint-plugin-n": "18.2.1",
84
84
  "eslint-plugin-node-dependencies": "2.2.0",
85
85
  "eslint-plugin-perfectionist": "5.10.0",
86
86
  "eslint-plugin-regexp": "3.1.0",
87
- "eslint-plugin-unicorn": "72.0.0",
88
- "eslint-plugin-yml": "3.6.0",
87
+ "eslint-plugin-unicorn": "73.0.0",
88
+ "eslint-plugin-yml": "3.8.0",
89
89
  "jiti": "2.7.0",
90
90
  "json-schema-to-ts": "3.1.1",
91
- "knip": "6.29.0",
91
+ "knip": "6.32.0",
92
92
  "prettier": "3.9.0",
93
93
  "prettier-plugin-curly": "0.4.1",
94
94
  "prettier-plugin-packagejson": "3.0.2",
@@ -99,7 +99,7 @@
99
99
  "starlight-auto-sidebar": "0.4.0",
100
100
  "tsdown": "0.22.2",
101
101
  "typescript": "npm:@typescript/typescript6@6.0.2",
102
- "typescript-eslint": "8.65.0",
102
+ "typescript-eslint": "8.66.0",
103
103
  "vitest": "4.1.8"
104
104
  },
105
105
  "peerDependencies": {