eslint-plugin-package-json 0.15.1 → 0.15.3

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.
@@ -44,6 +44,12 @@ const rule = (0, import_createRule.createRule)({
44
44
  });
45
45
  return;
46
46
  }
47
+ const privateField = node.parent.properties.find(
48
+ (p) => p.key.type === "JSONLiteral" && p.key.value === "private"
49
+ );
50
+ if (privateField && privateField.value.type === "JSONLiteral" && (privateField.value.value === true || privateField.value.value === "true")) {
51
+ return;
52
+ }
47
53
  const { errors, warnings } = (0, import_validate_npm_package_name.default)(node.value.value);
48
54
  const complaints = [...errors ?? [], ...warnings ?? []];
49
55
  if (!complaints.length) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/rules/valid-name.ts"],"sourcesContent":["import type { AST as JsonAST } from \"jsonc-eslint-parser\";\n\nimport * as ESTree from \"estree\";\nimport validate from \"validate-npm-package-name\";\n\nimport { createRule } from \"../createRule.js\";\n\nexport const rule = createRule({\n\tcreate(context) {\n\t\treturn {\n\t\t\t\"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=name]\"(\n\t\t\t\tnode: JsonAST.JSONProperty,\n\t\t\t) {\n\t\t\t\tif (\n\t\t\t\t\tnode.value.type !== \"JSONLiteral\" ||\n\t\t\t\t\ttypeof node.value.value !== \"string\"\n\t\t\t\t) {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tmessageId: \"type\",\n\t\t\t\t\t\tnode: node.value as unknown as ESTree.Node,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst { errors, warnings } = validate(node.value.value);\n\t\t\t\tconst complaints = [...(errors ?? []), ...(warnings ?? [])];\n\t\t\t\tif (!complaints.length) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontext.report({\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcomplaints: complaints\n\t\t\t\t\t\t\t.map((error) => error.substring(0, error.length))\n\t\t\t\t\t\t\t.join(\"; \"),\n\t\t\t\t\t},\n\t\t\t\t\tmessageId: \"invalid\",\n\t\t\t\t\tnode: node.value as unknown as ESTree.Node,\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t},\n\n\tmeta: {\n\t\tdocs: {\n\t\t\tcategory: \"Best Practices\",\n\t\t\tdescription:\n\t\t\t\t\"Enforce that package names are valid npm package names\",\n\t\t\trecommended: true,\n\t\t},\n\t\tmessages: {\n\t\t\tinvalid: \"Invalid npm package name: {{ complaints }}.\",\n\t\t\ttype: '\"name\" should be a string.',\n\t\t},\n\t},\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,uCAAqB;AAErB,wBAA2B;AAEpB,MAAM,WAAO,8BAAW;AAAA,EAC9B,OAAO,SAAS;AACf,WAAO;AAAA,MACN,0FACC,MACC;AACD,YACC,KAAK,MAAM,SAAS,iBACpB,OAAO,KAAK,MAAM,UAAU,UAC3B;AACD,kBAAQ,OAAO;AAAA,YACd,WAAW;AAAA,YACX,MAAM,KAAK;AAAA,UACZ,CAAC;AACD;AAAA,QACD;AAEA,cAAM,EAAE,QAAQ,SAAS,QAAI,iCAAAA,SAAS,KAAK,MAAM,KAAK;AACtD,cAAM,aAAa,CAAC,GAAI,UAAU,CAAC,GAAI,GAAI,YAAY,CAAC,CAAE;AAC1D,YAAI,CAAC,WAAW,QAAQ;AACvB;AAAA,QACD;AAEA,gBAAQ,OAAO;AAAA,UACd,MAAM;AAAA,YACL,YAAY,WACV,IAAI,CAAC,UAAU,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,EAC/C,KAAK,IAAI;AAAA,UACZ;AAAA,UACA,WAAW;AAAA,UACX,MAAM,KAAK;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM;AAAA,IACL,MAAM;AAAA,MACL,UAAU;AAAA,MACV,aACC;AAAA,MACD,aAAa;AAAA,IACd;AAAA,IACA,UAAU;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IACP;AAAA,EACD;AACD,CAAC;","names":["validate"]}
1
+ {"version":3,"sources":["../../src/rules/valid-name.ts"],"sourcesContent":["import type { AST as JsonAST } from \"jsonc-eslint-parser\";\n\nimport * as ESTree from \"estree\";\nimport validate from \"validate-npm-package-name\";\n\nimport { createRule } from \"../createRule.js\";\n\nexport const rule = createRule({\n\tcreate(context) {\n\t\treturn {\n\t\t\t\"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=name]\"(\n\t\t\t\tnode: JsonAST.JSONProperty,\n\t\t\t) {\n\t\t\t\tif (\n\t\t\t\t\tnode.value.type !== \"JSONLiteral\" ||\n\t\t\t\t\ttypeof node.value.value !== \"string\"\n\t\t\t\t) {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tmessageId: \"type\",\n\t\t\t\t\t\tnode: node.value as unknown as ESTree.Node,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst privateField = node.parent.properties.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.key.type === \"JSONLiteral\" &&\n\t\t\t\t\t\tp.key.value === \"private\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\tprivateField &&\n\t\t\t\t\tprivateField.value.type === \"JSONLiteral\" &&\n\t\t\t\t\t(privateField.value.value === true ||\n\t\t\t\t\t\tprivateField.value.value === \"true\")\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst { errors, warnings } = validate(node.value.value);\n\t\t\t\tconst complaints = [...(errors ?? []), ...(warnings ?? [])];\n\t\t\t\tif (!complaints.length) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontext.report({\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcomplaints: complaints\n\t\t\t\t\t\t\t.map((error) => error.substring(0, error.length))\n\t\t\t\t\t\t\t.join(\"; \"),\n\t\t\t\t\t},\n\t\t\t\t\tmessageId: \"invalid\",\n\t\t\t\t\tnode: node.value as unknown as ESTree.Node,\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t},\n\n\tmeta: {\n\t\tdocs: {\n\t\t\tcategory: \"Best Practices\",\n\t\t\tdescription:\n\t\t\t\t\"Enforce that package names are valid npm package names\",\n\t\t\trecommended: true,\n\t\t},\n\t\tmessages: {\n\t\t\tinvalid: \"Invalid npm package name: {{ complaints }}.\",\n\t\t\ttype: '\"name\" should be a string.',\n\t\t},\n\t},\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,uCAAqB;AAErB,wBAA2B;AAEpB,MAAM,WAAO,8BAAW;AAAA,EAC9B,OAAO,SAAS;AACf,WAAO;AAAA,MACN,0FACC,MACC;AACD,YACC,KAAK,MAAM,SAAS,iBACpB,OAAO,KAAK,MAAM,UAAU,UAC3B;AACD,kBAAQ,OAAO;AAAA,YACd,WAAW;AAAA,YACX,MAAM,KAAK;AAAA,UACZ,CAAC;AACD;AAAA,QACD;AAEA,cAAM,eAAe,KAAK,OAAO,WAAW;AAAA,UAC3C,CAAC,MACA,EAAE,IAAI,SAAS,iBACf,EAAE,IAAI,UAAU;AAAA,QAClB;AACA,YACC,gBACA,aAAa,MAAM,SAAS,kBAC3B,aAAa,MAAM,UAAU,QAC7B,aAAa,MAAM,UAAU,SAC7B;AACD;AAAA,QACD;AAEA,cAAM,EAAE,QAAQ,SAAS,QAAI,iCAAAA,SAAS,KAAK,MAAM,KAAK;AACtD,cAAM,aAAa,CAAC,GAAI,UAAU,CAAC,GAAI,GAAI,YAAY,CAAC,CAAE;AAC1D,YAAI,CAAC,WAAW,QAAQ;AACvB;AAAA,QACD;AAEA,gBAAQ,OAAO;AAAA,UACd,MAAM;AAAA,YACL,YAAY,WACV,IAAI,CAAC,UAAU,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,EAC/C,KAAK,IAAI;AAAA,UACZ;AAAA,UACA,WAAW;AAAA,UACX,MAAM,KAAK;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM;AAAA,IACL,MAAM;AAAA,MACL,UAAU;AAAA,MACV,aACC;AAAA,MACD,aAAa;AAAA,IACd;AAAA,IACA,UAAU;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IACP;AAAA,EACD;AACD,CAAC;","names":["validate"]}
@@ -11,6 +11,12 @@ const rule = createRule({
11
11
  });
12
12
  return;
13
13
  }
14
+ const privateField = node.parent.properties.find(
15
+ (p) => p.key.type === "JSONLiteral" && p.key.value === "private"
16
+ );
17
+ if (privateField && privateField.value.type === "JSONLiteral" && (privateField.value.value === true || privateField.value.value === "true")) {
18
+ return;
19
+ }
14
20
  const { errors, warnings } = validate(node.value.value);
15
21
  const complaints = [...errors ?? [], ...warnings ?? []];
16
22
  if (!complaints.length) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/rules/valid-name.ts"],"sourcesContent":["import type { AST as JsonAST } from \"jsonc-eslint-parser\";\n\nimport * as ESTree from \"estree\";\nimport validate from \"validate-npm-package-name\";\n\nimport { createRule } from \"../createRule.js\";\n\nexport const rule = createRule({\n\tcreate(context) {\n\t\treturn {\n\t\t\t\"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=name]\"(\n\t\t\t\tnode: JsonAST.JSONProperty,\n\t\t\t) {\n\t\t\t\tif (\n\t\t\t\t\tnode.value.type !== \"JSONLiteral\" ||\n\t\t\t\t\ttypeof node.value.value !== \"string\"\n\t\t\t\t) {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tmessageId: \"type\",\n\t\t\t\t\t\tnode: node.value as unknown as ESTree.Node,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst { errors, warnings } = validate(node.value.value);\n\t\t\t\tconst complaints = [...(errors ?? []), ...(warnings ?? [])];\n\t\t\t\tif (!complaints.length) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontext.report({\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcomplaints: complaints\n\t\t\t\t\t\t\t.map((error) => error.substring(0, error.length))\n\t\t\t\t\t\t\t.join(\"; \"),\n\t\t\t\t\t},\n\t\t\t\t\tmessageId: \"invalid\",\n\t\t\t\t\tnode: node.value as unknown as ESTree.Node,\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t},\n\n\tmeta: {\n\t\tdocs: {\n\t\t\tcategory: \"Best Practices\",\n\t\t\tdescription:\n\t\t\t\t\"Enforce that package names are valid npm package names\",\n\t\t\trecommended: true,\n\t\t},\n\t\tmessages: {\n\t\t\tinvalid: \"Invalid npm package name: {{ complaints }}.\",\n\t\t\ttype: '\"name\" should be a string.',\n\t\t},\n\t},\n});\n"],"mappings":"AAGA,OAAO,cAAc;AAErB,SAAS,kBAAkB;AAEpB,MAAM,OAAO,WAAW;AAAA,EAC9B,OAAO,SAAS;AACf,WAAO;AAAA,MACN,0FACC,MACC;AACD,YACC,KAAK,MAAM,SAAS,iBACpB,OAAO,KAAK,MAAM,UAAU,UAC3B;AACD,kBAAQ,OAAO;AAAA,YACd,WAAW;AAAA,YACX,MAAM,KAAK;AAAA,UACZ,CAAC;AACD;AAAA,QACD;AAEA,cAAM,EAAE,QAAQ,SAAS,IAAI,SAAS,KAAK,MAAM,KAAK;AACtD,cAAM,aAAa,CAAC,GAAI,UAAU,CAAC,GAAI,GAAI,YAAY,CAAC,CAAE;AAC1D,YAAI,CAAC,WAAW,QAAQ;AACvB;AAAA,QACD;AAEA,gBAAQ,OAAO;AAAA,UACd,MAAM;AAAA,YACL,YAAY,WACV,IAAI,CAAC,UAAU,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,EAC/C,KAAK,IAAI;AAAA,UACZ;AAAA,UACA,WAAW;AAAA,UACX,MAAM,KAAK;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM;AAAA,IACL,MAAM;AAAA,MACL,UAAU;AAAA,MACV,aACC;AAAA,MACD,aAAa;AAAA,IACd;AAAA,IACA,UAAU;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IACP;AAAA,EACD;AACD,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/rules/valid-name.ts"],"sourcesContent":["import type { AST as JsonAST } from \"jsonc-eslint-parser\";\n\nimport * as ESTree from \"estree\";\nimport validate from \"validate-npm-package-name\";\n\nimport { createRule } from \"../createRule.js\";\n\nexport const rule = createRule({\n\tcreate(context) {\n\t\treturn {\n\t\t\t\"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=name]\"(\n\t\t\t\tnode: JsonAST.JSONProperty,\n\t\t\t) {\n\t\t\t\tif (\n\t\t\t\t\tnode.value.type !== \"JSONLiteral\" ||\n\t\t\t\t\ttypeof node.value.value !== \"string\"\n\t\t\t\t) {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tmessageId: \"type\",\n\t\t\t\t\t\tnode: node.value as unknown as ESTree.Node,\n\t\t\t\t\t});\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst privateField = node.parent.properties.find(\n\t\t\t\t\t(p) =>\n\t\t\t\t\t\tp.key.type === \"JSONLiteral\" &&\n\t\t\t\t\t\tp.key.value === \"private\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\tprivateField &&\n\t\t\t\t\tprivateField.value.type === \"JSONLiteral\" &&\n\t\t\t\t\t(privateField.value.value === true ||\n\t\t\t\t\t\tprivateField.value.value === \"true\")\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst { errors, warnings } = validate(node.value.value);\n\t\t\t\tconst complaints = [...(errors ?? []), ...(warnings ?? [])];\n\t\t\t\tif (!complaints.length) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tcontext.report({\n\t\t\t\t\tdata: {\n\t\t\t\t\t\tcomplaints: complaints\n\t\t\t\t\t\t\t.map((error) => error.substring(0, error.length))\n\t\t\t\t\t\t\t.join(\"; \"),\n\t\t\t\t\t},\n\t\t\t\t\tmessageId: \"invalid\",\n\t\t\t\t\tnode: node.value as unknown as ESTree.Node,\n\t\t\t\t});\n\t\t\t},\n\t\t};\n\t},\n\n\tmeta: {\n\t\tdocs: {\n\t\t\tcategory: \"Best Practices\",\n\t\t\tdescription:\n\t\t\t\t\"Enforce that package names are valid npm package names\",\n\t\t\trecommended: true,\n\t\t},\n\t\tmessages: {\n\t\t\tinvalid: \"Invalid npm package name: {{ complaints }}.\",\n\t\t\ttype: '\"name\" should be a string.',\n\t\t},\n\t},\n});\n"],"mappings":"AAGA,OAAO,cAAc;AAErB,SAAS,kBAAkB;AAEpB,MAAM,OAAO,WAAW;AAAA,EAC9B,OAAO,SAAS;AACf,WAAO;AAAA,MACN,0FACC,MACC;AACD,YACC,KAAK,MAAM,SAAS,iBACpB,OAAO,KAAK,MAAM,UAAU,UAC3B;AACD,kBAAQ,OAAO;AAAA,YACd,WAAW;AAAA,YACX,MAAM,KAAK;AAAA,UACZ,CAAC;AACD;AAAA,QACD;AAEA,cAAM,eAAe,KAAK,OAAO,WAAW;AAAA,UAC3C,CAAC,MACA,EAAE,IAAI,SAAS,iBACf,EAAE,IAAI,UAAU;AAAA,QAClB;AACA,YACC,gBACA,aAAa,MAAM,SAAS,kBAC3B,aAAa,MAAM,UAAU,QAC7B,aAAa,MAAM,UAAU,SAC7B;AACD;AAAA,QACD;AAEA,cAAM,EAAE,QAAQ,SAAS,IAAI,SAAS,KAAK,MAAM,KAAK;AACtD,cAAM,aAAa,CAAC,GAAI,UAAU,CAAC,GAAI,GAAI,YAAY,CAAC,CAAE;AAC1D,YAAI,CAAC,WAAW,QAAQ;AACvB;AAAA,QACD;AAEA,gBAAQ,OAAO;AAAA,UACd,MAAM;AAAA,YACL,YAAY,WACV,IAAI,CAAC,UAAU,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,EAC/C,KAAK,IAAI;AAAA,UACZ;AAAA,UACA,WAAW;AAAA,UACX,MAAM,KAAK;AAAA,QACZ,CAAC;AAAA,MACF;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM;AAAA,IACL,MAAM;AAAA,MACL,UAAU;AAAA,MACV,aACC;AAAA,MACD,aAAa;AAAA,IACd;AAAA,IACA,UAAU;AAAA,MACT,SAAS;AAAA,MACT,MAAM;AAAA,IACP;AAAA,EACD;AACD,CAAC;","names":[]}
@@ -31,9 +31,23 @@ __export(valid_repository_directory_exports, {
31
31
  rule: () => rule
32
32
  });
33
33
  module.exports = __toCommonJS(valid_repository_directory_exports);
34
+ var import_findRootSync = require("@altano/repository-tools/findRootSync.cjs");
34
35
  var path = __toESM(require("node:path"));
35
36
  var import_createRule = require("../createRule.js");
36
37
  var import_findPropertyWithKeyValue = require("../utils/findPropertyWithKeyValue.js");
38
+ function pathEndsWith(parent, child) {
39
+ const segments = parent.split(path.sep);
40
+ if (parent === child) {
41
+ return true;
42
+ }
43
+ let pathToCheck = "";
44
+ return segments.reverse().some((segment) => {
45
+ pathToCheck = path.join(segment, pathToCheck);
46
+ if (pathToCheck === child) {
47
+ return true;
48
+ }
49
+ });
50
+ }
37
51
  const rule = (0, import_createRule.createRule)({
38
52
  create(context) {
39
53
  return {
@@ -46,23 +60,42 @@ const rule = (0, import_createRule.createRule)({
46
60
  return;
47
61
  }
48
62
  const directoryValue = directoryProperty.value.value;
49
- const expected = path.normalize(path.dirname(context.filename));
50
- if (path.normalize(directoryValue) !== expected) {
51
- context.report({
52
- messageId: "mismatched",
53
- node: directoryProperty.value,
54
- suggest: [
55
- {
56
- fix(fixer) {
57
- return fixer.replaceText(
58
- directoryProperty.value,
59
- `"${expected}"`
60
- );
61
- },
62
- messageId: "replace"
63
- }
64
- ]
65
- });
63
+ const fileDirectory = path.normalize(
64
+ path.dirname(context.filename)
65
+ );
66
+ const repositoryRoot = (0, import_findRootSync.findRootSync)(fileDirectory);
67
+ if (repositoryRoot == null) {
68
+ if (!pathEndsWith(
69
+ fileDirectory,
70
+ path.normalize(directoryValue)
71
+ )) {
72
+ context.report({
73
+ messageId: "mismatched",
74
+ node: directoryProperty.value
75
+ });
76
+ }
77
+ } else {
78
+ const expected = path.relative(
79
+ repositoryRoot,
80
+ fileDirectory
81
+ );
82
+ if (expected !== directoryValue) {
83
+ context.report({
84
+ messageId: "mismatched",
85
+ node: directoryProperty.value,
86
+ suggest: [
87
+ {
88
+ fix(fixer) {
89
+ return fixer.replaceText(
90
+ directoryProperty.value,
91
+ `"${expected}"`
92
+ );
93
+ },
94
+ messageId: "replace"
95
+ }
96
+ ]
97
+ });
98
+ }
66
99
  }
67
100
  }
68
101
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/rules/valid-repository-directory.ts"],"sourcesContent":["import type { AST as JsonAST } from \"jsonc-eslint-parser\";\n\nimport * as ESTree from \"estree\";\nimport * as path from \"node:path\";\n\nimport { createRule } from \"../createRule.js\";\nimport { findPropertyWithKeyValue } from \"../utils/findPropertyWithKeyValue.js\";\n\nexport const rule = createRule({\n\tcreate(context) {\n\t\treturn {\n\t\t\t\"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=repository][value.type=JSONObjectExpression]\"(\n\t\t\t\tnode: JsonAST.JSONProperty & {\n\t\t\t\t\tvalue: JsonAST.JSONObjectExpression;\n\t\t\t\t},\n\t\t\t) {\n\t\t\t\tconst directoryProperty = findPropertyWithKeyValue(\n\t\t\t\t\tnode.value.properties,\n\t\t\t\t\t\"directory\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\tdirectoryProperty?.value.type !== \"JSONLiteral\" ||\n\t\t\t\t\ttypeof directoryProperty.value.value !== \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst directoryValue = directoryProperty.value.value;\n\t\t\t\tconst expected = path.normalize(path.dirname(context.filename));\n\n\t\t\t\tif (path.normalize(directoryValue) !== expected) {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tmessageId: \"mismatched\",\n\t\t\t\t\t\tnode: directoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\tsuggest: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\t\t\t\treturn fixer.replaceText(\n\t\t\t\t\t\t\t\t\t\tdirectoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\t\t\t\t\t`\"${expected}\"`,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tmessageId: \"replace\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t},\n\n\tmeta: {\n\t\tdocs: {\n\t\t\tcategory: \"Best Practices\",\n\t\t\tdescription:\n\t\t\t\t\"Enforce that if repository directory is specified, it matches the path to the package.json file\",\n\t\t\trecommended: true,\n\t\t},\n\t\thasSuggestions: true,\n\t\tmessages: {\n\t\t\tmismatched: \"Directory does not match package.json directory.\",\n\t\t\treplace: \"Replace with '{{ expected }}'.\",\n\t\t},\n\t},\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,WAAsB;AAEtB,wBAA2B;AAC3B,sCAAyC;AAElC,MAAM,WAAO,8BAAW;AAAA,EAC9B,OAAO,SAAS;AACf,WAAO;AAAA,MACN,iIACC,MAGC;AACD,cAAM,wBAAoB;AAAA,UACzB,KAAK,MAAM;AAAA,UACX;AAAA,QACD;AACA,YACC,mBAAmB,MAAM,SAAS,iBAClC,OAAO,kBAAkB,MAAM,UAAU,UACxC;AACD;AAAA,QACD;AAEA,cAAM,iBAAiB,kBAAkB,MAAM;AAC/C,cAAM,WAAW,KAAK,UAAU,KAAK,QAAQ,QAAQ,QAAQ,CAAC;AAE9D,YAAI,KAAK,UAAU,cAAc,MAAM,UAAU;AAChD,kBAAQ,OAAO;AAAA,YACd,WAAW;AAAA,YACX,MAAM,kBAAkB;AAAA,YACxB,SAAS;AAAA,cACR;AAAA,gBACC,IAAI,OAAO;AACV,yBAAO,MAAM;AAAA,oBACZ,kBAAkB;AAAA,oBAClB,IAAI,QAAQ;AAAA,kBACb;AAAA,gBACD;AAAA,gBACA,WAAW;AAAA,cACZ;AAAA,YACD;AAAA,UACD,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM;AAAA,IACL,MAAM;AAAA,MACL,UAAU;AAAA,MACV,aACC;AAAA,MACD,aAAa;AAAA,IACd;AAAA,IACA,gBAAgB;AAAA,IAChB,UAAU;AAAA,MACT,YAAY;AAAA,MACZ,SAAS;AAAA,IACV;AAAA,EACD;AACD,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/rules/valid-repository-directory.ts"],"sourcesContent":["import type { AST as JsonAST } from \"jsonc-eslint-parser\";\n\nimport { findRootSync } from \"@altano/repository-tools/findRootSync.cjs\";\nimport * as ESTree from \"estree\";\nimport * as path from \"node:path\";\n\nimport { createRule } from \"../createRule.js\";\nimport { findPropertyWithKeyValue } from \"../utils/findPropertyWithKeyValue.js\";\n\n/**\n * Checks if the child path appears at the end of the parent path. e.g.\n *\n * '/a/b/c', 'c' => true\n * '/a/b/c', 'b/c' => true\n * '/a/b/c', 'b' => false\n * '/a/b/c', 'd' => false\n */\nfunction pathEndsWith(parent: string, child: string): boolean {\n\tconst segments = parent.split(path.sep);\n\n\tif (parent === child) {\n\t\t// the directory specified was the full, absolute path to the\n\t\t// package.json\n\t\treturn true;\n\t}\n\n\t// work backwards from the end, adding another path segment to each check\n\tlet pathToCheck = \"\";\n\treturn segments.reverse().some((segment) => {\n\t\tpathToCheck = path.join(segment, pathToCheck);\n\t\tif (pathToCheck === child) {\n\t\t\treturn true;\n\t\t}\n\t});\n}\n\nexport const rule = createRule({\n\tcreate(context) {\n\t\treturn {\n\t\t\t\"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=repository][value.type=JSONObjectExpression]\"(\n\t\t\t\tnode: JsonAST.JSONProperty & {\n\t\t\t\t\tvalue: JsonAST.JSONObjectExpression;\n\t\t\t\t},\n\t\t\t) {\n\t\t\t\tconst directoryProperty = findPropertyWithKeyValue(\n\t\t\t\t\tnode.value.properties,\n\t\t\t\t\t\"directory\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\tdirectoryProperty?.value.type !== \"JSONLiteral\" ||\n\t\t\t\t\ttypeof directoryProperty.value.value !== \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst directoryValue = directoryProperty.value.value;\n\t\t\t\tconst fileDirectory = path.normalize(\n\t\t\t\t\tpath.dirname(context.filename),\n\t\t\t\t);\n\t\t\t\tconst repositoryRoot = findRootSync(fileDirectory);\n\n\t\t\t\tif (repositoryRoot == null) {\n\t\t\t\t\t// Since we couldn't determine the repository root, we can't\n\t\t\t\t\t// rigorously determine the validity of the directory value.\n\t\t\t\t\t// But, we can at least make sure the directory value\n\t\t\t\t\t// appears at the end of the package.json file path. For\n\t\t\t\t\t// example:\n\t\t\t\t\t//\n\t\t\t\t\t// if /a/b/c/package.json has the value: directory: \"b/c\"\n\t\t\t\t\t// it will validate\n\t\t\t\t\t//\n\t\t\t\t\t// if /a/b/c/package.json has the value: directory: \"b/d\"\n\t\t\t\t\t// it will NOT validate\n\t\t\t\t\t//\n\t\t\t\t\t// This ensures that the directory value is at least\n\t\t\t\t\t// partially correct.\n\t\t\t\t\tif (\n\t\t\t\t\t\t!pathEndsWith(\n\t\t\t\t\t\t\tfileDirectory,\n\t\t\t\t\t\t\tpath.normalize(directoryValue),\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontext.report({\n\t\t\t\t\t\t\tmessageId: \"mismatched\",\n\t\t\t\t\t\t\tnode: directoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Get the relative path from repository root to\n\t\t\t\t\t// package.json. For example:\n\t\t\t\t\t//\n\t\t\t\t\t// Simple case (root package.json):\n\t\t\t\t\t// repositoryRoot: '~/src/project'\n\t\t\t\t\t// filename: '~/src/project/package.json',\n\t\t\t\t\t// fileDirectory: '~/src/project',\n\t\t\t\t\t// expected: '' (directory should be undefined or empty)\n\t\t\t\t\t//\n\t\t\t\t\t// Monorepo case (nested package.json):\n\t\t\t\t\t// repositoryRoot: '~/src/project'\n\t\t\t\t\t// filename: '~/src/project/packages/packageA/package.json',\n\t\t\t\t\t// fileDirectory: '~/src/project/packages/packageA',\n\t\t\t\t\t// expected: 'packages/packageA'\n\t\t\t\t\t//\n\t\t\t\t\tconst expected = path.relative(\n\t\t\t\t\t\trepositoryRoot,\n\t\t\t\t\t\tfileDirectory,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (expected !== directoryValue) {\n\t\t\t\t\t\tcontext.report({\n\t\t\t\t\t\t\tmessageId: \"mismatched\",\n\t\t\t\t\t\t\tnode: directoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\t\tsuggest: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\t\t\t\t\treturn fixer.replaceText(\n\t\t\t\t\t\t\t\t\t\t\tdirectoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\t\t\t\t\t\t`\"${expected}\"`,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tmessageId: \"replace\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t},\n\n\tmeta: {\n\t\tdocs: {\n\t\t\tcategory: \"Best Practices\",\n\t\t\tdescription:\n\t\t\t\t\"Enforce that if repository directory is specified, it matches the path to the package.json file\",\n\t\t\trecommended: true,\n\t\t},\n\t\thasSuggestions: true,\n\t\tmessages: {\n\t\t\tmismatched: \"Directory does not match package.json directory.\",\n\t\t\treplace: \"Replace with '{{ expected }}'.\",\n\t\t},\n\t},\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,0BAA6B;AAE7B,WAAsB;AAEtB,wBAA2B;AAC3B,sCAAyC;AAUzC,SAAS,aAAa,QAAgB,OAAwB;AAC7D,QAAM,WAAW,OAAO,MAAM,KAAK,GAAG;AAEtC,MAAI,WAAW,OAAO;AAGrB,WAAO;AAAA,EACR;AAGA,MAAI,cAAc;AAClB,SAAO,SAAS,QAAQ,EAAE,KAAK,CAAC,YAAY;AAC3C,kBAAc,KAAK,KAAK,SAAS,WAAW;AAC5C,QAAI,gBAAgB,OAAO;AAC1B,aAAO;AAAA,IACR;AAAA,EACD,CAAC;AACF;AAEO,MAAM,WAAO,8BAAW;AAAA,EAC9B,OAAO,SAAS;AACf,WAAO;AAAA,MACN,iIACC,MAGC;AACD,cAAM,wBAAoB;AAAA,UACzB,KAAK,MAAM;AAAA,UACX;AAAA,QACD;AACA,YACC,mBAAmB,MAAM,SAAS,iBAClC,OAAO,kBAAkB,MAAM,UAAU,UACxC;AACD;AAAA,QACD;AAEA,cAAM,iBAAiB,kBAAkB,MAAM;AAC/C,cAAM,gBAAgB,KAAK;AAAA,UAC1B,KAAK,QAAQ,QAAQ,QAAQ;AAAA,QAC9B;AACA,cAAM,qBAAiB,kCAAa,aAAa;AAEjD,YAAI,kBAAkB,MAAM;AAe3B,cACC,CAAC;AAAA,YACA;AAAA,YACA,KAAK,UAAU,cAAc;AAAA,UAC9B,GACC;AACD,oBAAQ,OAAO;AAAA,cACd,WAAW;AAAA,cACX,MAAM,kBAAkB;AAAA,YACzB,CAAC;AAAA,UACF;AAAA,QACD,OAAO;AAgBN,gBAAM,WAAW,KAAK;AAAA,YACrB;AAAA,YACA;AAAA,UACD;AAEA,cAAI,aAAa,gBAAgB;AAChC,oBAAQ,OAAO;AAAA,cACd,WAAW;AAAA,cACX,MAAM,kBAAkB;AAAA,cACxB,SAAS;AAAA,gBACR;AAAA,kBACC,IAAI,OAAO;AACV,2BAAO,MAAM;AAAA,sBACZ,kBAAkB;AAAA,sBAClB,IAAI,QAAQ;AAAA,oBACb;AAAA,kBACD;AAAA,kBACA,WAAW;AAAA,gBACZ;AAAA,cACD;AAAA,YACD,CAAC;AAAA,UACF;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM;AAAA,IACL,MAAM;AAAA,MACL,UAAU;AAAA,MACV,aACC;AAAA,MACD,aAAa;AAAA,IACd;AAAA,IACA,gBAAgB;AAAA,IAChB,UAAU;AAAA,MACT,YAAY;AAAA,MACZ,SAAS;AAAA,IACV;AAAA,EACD;AACD,CAAC;","names":[]}
@@ -1,6 +1,20 @@
1
+ import { findRootSync } from "@altano/repository-tools/findRootSync.cjs";
1
2
  import * as path from "node:path";
2
3
  import { createRule } from "../createRule.js";
3
4
  import { findPropertyWithKeyValue } from "../utils/findPropertyWithKeyValue.js";
5
+ function pathEndsWith(parent, child) {
6
+ const segments = parent.split(path.sep);
7
+ if (parent === child) {
8
+ return true;
9
+ }
10
+ let pathToCheck = "";
11
+ return segments.reverse().some((segment) => {
12
+ pathToCheck = path.join(segment, pathToCheck);
13
+ if (pathToCheck === child) {
14
+ return true;
15
+ }
16
+ });
17
+ }
4
18
  const rule = createRule({
5
19
  create(context) {
6
20
  return {
@@ -13,23 +27,42 @@ const rule = createRule({
13
27
  return;
14
28
  }
15
29
  const directoryValue = directoryProperty.value.value;
16
- const expected = path.normalize(path.dirname(context.filename));
17
- if (path.normalize(directoryValue) !== expected) {
18
- context.report({
19
- messageId: "mismatched",
20
- node: directoryProperty.value,
21
- suggest: [
22
- {
23
- fix(fixer) {
24
- return fixer.replaceText(
25
- directoryProperty.value,
26
- `"${expected}"`
27
- );
28
- },
29
- messageId: "replace"
30
- }
31
- ]
32
- });
30
+ const fileDirectory = path.normalize(
31
+ path.dirname(context.filename)
32
+ );
33
+ const repositoryRoot = findRootSync(fileDirectory);
34
+ if (repositoryRoot == null) {
35
+ if (!pathEndsWith(
36
+ fileDirectory,
37
+ path.normalize(directoryValue)
38
+ )) {
39
+ context.report({
40
+ messageId: "mismatched",
41
+ node: directoryProperty.value
42
+ });
43
+ }
44
+ } else {
45
+ const expected = path.relative(
46
+ repositoryRoot,
47
+ fileDirectory
48
+ );
49
+ if (expected !== directoryValue) {
50
+ context.report({
51
+ messageId: "mismatched",
52
+ node: directoryProperty.value,
53
+ suggest: [
54
+ {
55
+ fix(fixer) {
56
+ return fixer.replaceText(
57
+ directoryProperty.value,
58
+ `"${expected}"`
59
+ );
60
+ },
61
+ messageId: "replace"
62
+ }
63
+ ]
64
+ });
65
+ }
33
66
  }
34
67
  }
35
68
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/rules/valid-repository-directory.ts"],"sourcesContent":["import type { AST as JsonAST } from \"jsonc-eslint-parser\";\n\nimport * as ESTree from \"estree\";\nimport * as path from \"node:path\";\n\nimport { createRule } from \"../createRule.js\";\nimport { findPropertyWithKeyValue } from \"../utils/findPropertyWithKeyValue.js\";\n\nexport const rule = createRule({\n\tcreate(context) {\n\t\treturn {\n\t\t\t\"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=repository][value.type=JSONObjectExpression]\"(\n\t\t\t\tnode: JsonAST.JSONProperty & {\n\t\t\t\t\tvalue: JsonAST.JSONObjectExpression;\n\t\t\t\t},\n\t\t\t) {\n\t\t\t\tconst directoryProperty = findPropertyWithKeyValue(\n\t\t\t\t\tnode.value.properties,\n\t\t\t\t\t\"directory\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\tdirectoryProperty?.value.type !== \"JSONLiteral\" ||\n\t\t\t\t\ttypeof directoryProperty.value.value !== \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst directoryValue = directoryProperty.value.value;\n\t\t\t\tconst expected = path.normalize(path.dirname(context.filename));\n\n\t\t\t\tif (path.normalize(directoryValue) !== expected) {\n\t\t\t\t\tcontext.report({\n\t\t\t\t\t\tmessageId: \"mismatched\",\n\t\t\t\t\t\tnode: directoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\tsuggest: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\t\t\t\treturn fixer.replaceText(\n\t\t\t\t\t\t\t\t\t\tdirectoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\t\t\t\t\t`\"${expected}\"`,\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tmessageId: \"replace\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t},\n\n\tmeta: {\n\t\tdocs: {\n\t\t\tcategory: \"Best Practices\",\n\t\t\tdescription:\n\t\t\t\t\"Enforce that if repository directory is specified, it matches the path to the package.json file\",\n\t\t\trecommended: true,\n\t\t},\n\t\thasSuggestions: true,\n\t\tmessages: {\n\t\t\tmismatched: \"Directory does not match package.json directory.\",\n\t\t\treplace: \"Replace with '{{ expected }}'.\",\n\t\t},\n\t},\n});\n"],"mappings":"AAGA,YAAY,UAAU;AAEtB,SAAS,kBAAkB;AAC3B,SAAS,gCAAgC;AAElC,MAAM,OAAO,WAAW;AAAA,EAC9B,OAAO,SAAS;AACf,WAAO;AAAA,MACN,iIACC,MAGC;AACD,cAAM,oBAAoB;AAAA,UACzB,KAAK,MAAM;AAAA,UACX;AAAA,QACD;AACA,YACC,mBAAmB,MAAM,SAAS,iBAClC,OAAO,kBAAkB,MAAM,UAAU,UACxC;AACD;AAAA,QACD;AAEA,cAAM,iBAAiB,kBAAkB,MAAM;AAC/C,cAAM,WAAW,KAAK,UAAU,KAAK,QAAQ,QAAQ,QAAQ,CAAC;AAE9D,YAAI,KAAK,UAAU,cAAc,MAAM,UAAU;AAChD,kBAAQ,OAAO;AAAA,YACd,WAAW;AAAA,YACX,MAAM,kBAAkB;AAAA,YACxB,SAAS;AAAA,cACR;AAAA,gBACC,IAAI,OAAO;AACV,yBAAO,MAAM;AAAA,oBACZ,kBAAkB;AAAA,oBAClB,IAAI,QAAQ;AAAA,kBACb;AAAA,gBACD;AAAA,gBACA,WAAW;AAAA,cACZ;AAAA,YACD;AAAA,UACD,CAAC;AAAA,QACF;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM;AAAA,IACL,MAAM;AAAA,MACL,UAAU;AAAA,MACV,aACC;AAAA,MACD,aAAa;AAAA,IACd;AAAA,IACA,gBAAgB;AAAA,IAChB,UAAU;AAAA,MACT,YAAY;AAAA,MACZ,SAAS;AAAA,IACV;AAAA,EACD;AACD,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/rules/valid-repository-directory.ts"],"sourcesContent":["import type { AST as JsonAST } from \"jsonc-eslint-parser\";\n\nimport { findRootSync } from \"@altano/repository-tools/findRootSync.cjs\";\nimport * as ESTree from \"estree\";\nimport * as path from \"node:path\";\n\nimport { createRule } from \"../createRule.js\";\nimport { findPropertyWithKeyValue } from \"../utils/findPropertyWithKeyValue.js\";\n\n/**\n * Checks if the child path appears at the end of the parent path. e.g.\n *\n * '/a/b/c', 'c' => true\n * '/a/b/c', 'b/c' => true\n * '/a/b/c', 'b' => false\n * '/a/b/c', 'd' => false\n */\nfunction pathEndsWith(parent: string, child: string): boolean {\n\tconst segments = parent.split(path.sep);\n\n\tif (parent === child) {\n\t\t// the directory specified was the full, absolute path to the\n\t\t// package.json\n\t\treturn true;\n\t}\n\n\t// work backwards from the end, adding another path segment to each check\n\tlet pathToCheck = \"\";\n\treturn segments.reverse().some((segment) => {\n\t\tpathToCheck = path.join(segment, pathToCheck);\n\t\tif (pathToCheck === child) {\n\t\t\treturn true;\n\t\t}\n\t});\n}\n\nexport const rule = createRule({\n\tcreate(context) {\n\t\treturn {\n\t\t\t\"Program > JSONExpressionStatement > JSONObjectExpression > JSONProperty[key.value=repository][value.type=JSONObjectExpression]\"(\n\t\t\t\tnode: JsonAST.JSONProperty & {\n\t\t\t\t\tvalue: JsonAST.JSONObjectExpression;\n\t\t\t\t},\n\t\t\t) {\n\t\t\t\tconst directoryProperty = findPropertyWithKeyValue(\n\t\t\t\t\tnode.value.properties,\n\t\t\t\t\t\"directory\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\tdirectoryProperty?.value.type !== \"JSONLiteral\" ||\n\t\t\t\t\ttypeof directoryProperty.value.value !== \"string\"\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst directoryValue = directoryProperty.value.value;\n\t\t\t\tconst fileDirectory = path.normalize(\n\t\t\t\t\tpath.dirname(context.filename),\n\t\t\t\t);\n\t\t\t\tconst repositoryRoot = findRootSync(fileDirectory);\n\n\t\t\t\tif (repositoryRoot == null) {\n\t\t\t\t\t// Since we couldn't determine the repository root, we can't\n\t\t\t\t\t// rigorously determine the validity of the directory value.\n\t\t\t\t\t// But, we can at least make sure the directory value\n\t\t\t\t\t// appears at the end of the package.json file path. For\n\t\t\t\t\t// example:\n\t\t\t\t\t//\n\t\t\t\t\t// if /a/b/c/package.json has the value: directory: \"b/c\"\n\t\t\t\t\t// it will validate\n\t\t\t\t\t//\n\t\t\t\t\t// if /a/b/c/package.json has the value: directory: \"b/d\"\n\t\t\t\t\t// it will NOT validate\n\t\t\t\t\t//\n\t\t\t\t\t// This ensures that the directory value is at least\n\t\t\t\t\t// partially correct.\n\t\t\t\t\tif (\n\t\t\t\t\t\t!pathEndsWith(\n\t\t\t\t\t\t\tfileDirectory,\n\t\t\t\t\t\t\tpath.normalize(directoryValue),\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tcontext.report({\n\t\t\t\t\t\t\tmessageId: \"mismatched\",\n\t\t\t\t\t\t\tnode: directoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Get the relative path from repository root to\n\t\t\t\t\t// package.json. For example:\n\t\t\t\t\t//\n\t\t\t\t\t// Simple case (root package.json):\n\t\t\t\t\t// repositoryRoot: '~/src/project'\n\t\t\t\t\t// filename: '~/src/project/package.json',\n\t\t\t\t\t// fileDirectory: '~/src/project',\n\t\t\t\t\t// expected: '' (directory should be undefined or empty)\n\t\t\t\t\t//\n\t\t\t\t\t// Monorepo case (nested package.json):\n\t\t\t\t\t// repositoryRoot: '~/src/project'\n\t\t\t\t\t// filename: '~/src/project/packages/packageA/package.json',\n\t\t\t\t\t// fileDirectory: '~/src/project/packages/packageA',\n\t\t\t\t\t// expected: 'packages/packageA'\n\t\t\t\t\t//\n\t\t\t\t\tconst expected = path.relative(\n\t\t\t\t\t\trepositoryRoot,\n\t\t\t\t\t\tfileDirectory,\n\t\t\t\t\t);\n\n\t\t\t\t\tif (expected !== directoryValue) {\n\t\t\t\t\t\tcontext.report({\n\t\t\t\t\t\t\tmessageId: \"mismatched\",\n\t\t\t\t\t\t\tnode: directoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\t\tsuggest: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\tfix(fixer) {\n\t\t\t\t\t\t\t\t\t\treturn fixer.replaceText(\n\t\t\t\t\t\t\t\t\t\t\tdirectoryProperty.value as unknown as ESTree.Node,\n\t\t\t\t\t\t\t\t\t\t\t`\"${expected}\"`,\n\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tmessageId: \"replace\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t},\n\n\tmeta: {\n\t\tdocs: {\n\t\t\tcategory: \"Best Practices\",\n\t\t\tdescription:\n\t\t\t\t\"Enforce that if repository directory is specified, it matches the path to the package.json file\",\n\t\t\trecommended: true,\n\t\t},\n\t\thasSuggestions: true,\n\t\tmessages: {\n\t\t\tmismatched: \"Directory does not match package.json directory.\",\n\t\t\treplace: \"Replace with '{{ expected }}'.\",\n\t\t},\n\t},\n});\n"],"mappings":"AAEA,SAAS,oBAAoB;AAE7B,YAAY,UAAU;AAEtB,SAAS,kBAAkB;AAC3B,SAAS,gCAAgC;AAUzC,SAAS,aAAa,QAAgB,OAAwB;AAC7D,QAAM,WAAW,OAAO,MAAM,KAAK,GAAG;AAEtC,MAAI,WAAW,OAAO;AAGrB,WAAO;AAAA,EACR;AAGA,MAAI,cAAc;AAClB,SAAO,SAAS,QAAQ,EAAE,KAAK,CAAC,YAAY;AAC3C,kBAAc,KAAK,KAAK,SAAS,WAAW;AAC5C,QAAI,gBAAgB,OAAO;AAC1B,aAAO;AAAA,IACR;AAAA,EACD,CAAC;AACF;AAEO,MAAM,OAAO,WAAW;AAAA,EAC9B,OAAO,SAAS;AACf,WAAO;AAAA,MACN,iIACC,MAGC;AACD,cAAM,oBAAoB;AAAA,UACzB,KAAK,MAAM;AAAA,UACX;AAAA,QACD;AACA,YACC,mBAAmB,MAAM,SAAS,iBAClC,OAAO,kBAAkB,MAAM,UAAU,UACxC;AACD;AAAA,QACD;AAEA,cAAM,iBAAiB,kBAAkB,MAAM;AAC/C,cAAM,gBAAgB,KAAK;AAAA,UAC1B,KAAK,QAAQ,QAAQ,QAAQ;AAAA,QAC9B;AACA,cAAM,iBAAiB,aAAa,aAAa;AAEjD,YAAI,kBAAkB,MAAM;AAe3B,cACC,CAAC;AAAA,YACA;AAAA,YACA,KAAK,UAAU,cAAc;AAAA,UAC9B,GACC;AACD,oBAAQ,OAAO;AAAA,cACd,WAAW;AAAA,cACX,MAAM,kBAAkB;AAAA,YACzB,CAAC;AAAA,UACF;AAAA,QACD,OAAO;AAgBN,gBAAM,WAAW,KAAK;AAAA,YACrB;AAAA,YACA;AAAA,UACD;AAEA,cAAI,aAAa,gBAAgB;AAChC,oBAAQ,OAAO;AAAA,cACd,WAAW;AAAA,cACX,MAAM,kBAAkB;AAAA,cACxB,SAAS;AAAA,gBACR;AAAA,kBACC,IAAI,OAAO;AACV,2BAAO,MAAM;AAAA,sBACZ,kBAAkB;AAAA,sBAClB,IAAI,QAAQ;AAAA,oBACb;AAAA,kBACD;AAAA,kBACA,WAAW;AAAA,gBACZ;AAAA,cACD;AAAA,YACD,CAAC;AAAA,UACF;AAAA,QACD;AAAA,MACD;AAAA,IACD;AAAA,EACD;AAAA,EAEA,MAAM;AAAA,IACL,MAAM;AAAA,MACL,UAAU;AAAA,MACV,aACC;AAAA,MACD,aAAa;AAAA,IACd;AAAA,IACA,gBAAgB;AAAA,IAChB,UAAU;AAAA,MACT,YAAY;AAAA,MACZ,SAAS;AAAA,IACV;AAAA,EACD;AACD,CAAC;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-package-json",
3
- "version": "0.15.1",
3
+ "version": "0.15.3",
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": {
@@ -58,6 +58,7 @@
58
58
  "*": "prettier --ignore-unknown --write"
59
59
  },
60
60
  "dependencies": {
61
+ "@altano/repository-tools": "^0.1.1",
61
62
  "detect-indent": "6.1.0",
62
63
  "detect-newline": "3.1.0",
63
64
  "package-json-validator": "^0.6.5",
@@ -70,7 +71,7 @@
70
71
  "@release-it/conventional-changelog": "^8.0.1",
71
72
  "@types/eslint": "^8.56.2",
72
73
  "@types/estree": "^1.0.5",
73
- "@types/node": "^20.11.5",
74
+ "@types/node": "^22.0.0",
74
75
  "@types/package-json-validator": "^0.6.1",
75
76
  "@types/semver": "^7.5.6",
76
77
  "@types/sort-object-keys": "^1.1.3",
@@ -78,7 +79,7 @@
78
79
  "@typescript-eslint/eslint-plugin": "^7.0.0",
79
80
  "@typescript-eslint/parser": "^7.0.0",
80
81
  "@vitest/coverage-v8": "^1.2.1",
81
- "console-fail-test": "^0.2.3",
82
+ "console-fail-test": "^0.5.0",
82
83
  "cspell": "^8.3.2",
83
84
  "eslint": "^8.56.0",
84
85
  "eslint-doc-generator": "^1.6.2",
@@ -115,7 +116,7 @@
115
116
  "eslint": ">=8.0.0",
116
117
  "jsonc-eslint-parser": "^2.0.0"
117
118
  },
118
- "packageManager": "pnpm@9.4.0",
119
+ "packageManager": "pnpm@9.7.1",
119
120
  "engines": {
120
121
  "node": ">=18"
121
122
  },