repopo 0.8.0 → 0.10.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.
Files changed (141) hide show
  1. package/CHANGELOG.md +67 -0
  2. package/THIRD-PARTY-LICENSES.txt +4 -3
  3. package/esm/adapters/fluidFramework.js +8 -3
  4. package/esm/adapters/fluidFramework.js.map +1 -1
  5. package/esm/baseCommand.d.ts.map +1 -1
  6. package/esm/baseCommand.js +2 -1
  7. package/esm/baseCommand.js.map +1 -1
  8. package/esm/commands/check.d.ts +1 -0
  9. package/esm/commands/check.d.ts.map +1 -1
  10. package/esm/commands/check.js +114 -52
  11. package/esm/commands/check.js.map +1 -1
  12. package/esm/commands/list.d.ts.map +1 -1
  13. package/esm/commands/list.js +3 -1
  14. package/esm/commands/list.js.map +1 -1
  15. package/esm/config.d.ts +19 -4
  16. package/esm/config.d.ts.map +1 -1
  17. package/esm/config.js +2 -3
  18. package/esm/config.js.map +1 -1
  19. package/esm/generators.d.ts +30 -2
  20. package/esm/generators.d.ts.map +1 -1
  21. package/esm/generators.js +31 -1
  22. package/esm/generators.js.map +1 -1
  23. package/esm/index.d.ts +14 -4
  24. package/esm/index.d.ts.map +1 -1
  25. package/esm/index.js +17 -2
  26. package/esm/index.js.map +1 -1
  27. package/esm/makePolicy.d.ts +74 -3
  28. package/esm/makePolicy.d.ts.map +1 -1
  29. package/esm/makePolicy.js +87 -13
  30. package/esm/makePolicy.js.map +1 -1
  31. package/esm/perf.d.ts +3 -2
  32. package/esm/perf.d.ts.map +1 -1
  33. package/esm/perf.js +2 -2
  34. package/esm/perf.js.map +1 -1
  35. package/esm/policies/ConditionalScripts.d.ts +94 -0
  36. package/esm/policies/ConditionalScripts.d.ts.map +1 -0
  37. package/esm/policies/ConditionalScripts.js +144 -0
  38. package/esm/policies/ConditionalScripts.js.map +1 -0
  39. package/esm/policies/ExactScripts.d.ts +51 -0
  40. package/esm/policies/ExactScripts.d.ts.map +1 -0
  41. package/esm/policies/ExactScripts.js +107 -0
  42. package/esm/policies/ExactScripts.js.map +1 -0
  43. package/esm/policies/HtmlFileHeaders.d.ts +1 -1
  44. package/esm/policies/HtmlFileHeaders.d.ts.map +1 -1
  45. package/esm/policies/HtmlFileHeaders.js +11 -7
  46. package/esm/policies/HtmlFileHeaders.js.map +1 -1
  47. package/esm/policies/JsTsFileHeaders.d.ts +1 -1
  48. package/esm/policies/JsTsFileHeaders.d.ts.map +1 -1
  49. package/esm/policies/JsTsFileHeaders.js +11 -7
  50. package/esm/policies/JsTsFileHeaders.js.map +1 -1
  51. package/esm/policies/LicenseFileExists.d.ts.map +1 -1
  52. package/esm/policies/LicenseFileExists.js +22 -18
  53. package/esm/policies/LicenseFileExists.js.map +1 -1
  54. package/esm/policies/MutuallyExclusiveScripts.d.ts +46 -0
  55. package/esm/policies/MutuallyExclusiveScripts.d.ts.map +1 -0
  56. package/esm/policies/MutuallyExclusiveScripts.js +52 -0
  57. package/esm/policies/MutuallyExclusiveScripts.js.map +1 -0
  58. package/esm/policies/NoJsFileExtensions.d.ts.map +1 -1
  59. package/esm/policies/NoJsFileExtensions.js +16 -12
  60. package/esm/policies/NoJsFileExtensions.js.map +1 -1
  61. package/esm/policies/NoLargeBinaryFiles.d.ts.map +1 -1
  62. package/esm/policies/NoLargeBinaryFiles.js +35 -31
  63. package/esm/policies/NoLargeBinaryFiles.js.map +1 -1
  64. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +1 -1
  65. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
  66. package/esm/policies/NoPrivateWorkspaceDependencies.js +53 -45
  67. package/esm/policies/NoPrivateWorkspaceDependencies.js.map +1 -1
  68. package/esm/policies/PackageAllowedScopes.d.ts +1 -1
  69. package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
  70. package/esm/policies/PackageAllowedScopes.js +45 -40
  71. package/esm/policies/PackageAllowedScopes.js.map +1 -1
  72. package/esm/policies/PackageEsmType.d.ts +1 -1
  73. package/esm/policies/PackageEsmType.d.ts.map +1 -1
  74. package/esm/policies/PackageEsmType.js +48 -44
  75. package/esm/policies/PackageEsmType.js.map +1 -1
  76. package/esm/policies/PackageFolderName.d.ts +1 -1
  77. package/esm/policies/PackageFolderName.d.ts.map +1 -1
  78. package/esm/policies/PackageFolderName.js +38 -34
  79. package/esm/policies/PackageFolderName.js.map +1 -1
  80. package/esm/policies/PackageJsonProperties.d.ts +1 -1
  81. package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
  82. package/esm/policies/PackageJsonProperties.js +36 -31
  83. package/esm/policies/PackageJsonProperties.js.map +1 -1
  84. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts +1 -1
  85. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
  86. package/esm/policies/PackageJsonRepoDirectoryProperty.js +41 -38
  87. package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
  88. package/esm/policies/PackageJsonSorted.d.ts +1 -1
  89. package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
  90. package/esm/policies/PackageJsonSorted.js +40 -36
  91. package/esm/policies/PackageJsonSorted.js.map +1 -1
  92. package/esm/policies/PackageLicense.d.ts +1 -1
  93. package/esm/policies/PackageLicense.d.ts.map +1 -1
  94. package/esm/policies/PackageLicense.js +58 -54
  95. package/esm/policies/PackageLicense.js.map +1 -1
  96. package/esm/policies/PackagePrivateField.d.ts +1 -1
  97. package/esm/policies/PackagePrivateField.d.ts.map +1 -1
  98. package/esm/policies/PackagePrivateField.js +58 -54
  99. package/esm/policies/PackagePrivateField.js.map +1 -1
  100. package/esm/policies/PackageReadme.d.ts +1 -1
  101. package/esm/policies/PackageReadme.d.ts.map +1 -1
  102. package/esm/policies/PackageReadme.js +30 -26
  103. package/esm/policies/PackageReadme.js.map +1 -1
  104. package/esm/policies/PackageScripts.d.ts +1 -1
  105. package/esm/policies/PackageScripts.d.ts.map +1 -1
  106. package/esm/policies/PackageScripts.js +39 -35
  107. package/esm/policies/PackageScripts.js.map +1 -1
  108. package/esm/policies/PackageTestScripts.d.ts +1 -1
  109. package/esm/policies/PackageTestScripts.d.ts.map +1 -1
  110. package/esm/policies/PackageTestScripts.js +46 -40
  111. package/esm/policies/PackageTestScripts.js.map +1 -1
  112. package/esm/policies/RequiredGitignorePatterns.d.ts.map +1 -1
  113. package/esm/policies/RequiredGitignorePatterns.js +20 -15
  114. package/esm/policies/RequiredGitignorePatterns.js.map +1 -1
  115. package/esm/policies/RequiredScripts.d.ts +71 -0
  116. package/esm/policies/RequiredScripts.d.ts.map +1 -0
  117. package/esm/policies/RequiredScripts.js +120 -0
  118. package/esm/policies/RequiredScripts.js.map +1 -0
  119. package/esm/policies/ScriptContains.d.ts +64 -0
  120. package/esm/policies/ScriptContains.d.ts.map +1 -0
  121. package/esm/policies/ScriptContains.js +62 -0
  122. package/esm/policies/ScriptContains.js.map +1 -0
  123. package/esm/policies.d.ts +6 -1
  124. package/esm/policies.d.ts.map +1 -1
  125. package/esm/policies.js +18 -0
  126. package/esm/policies.js.map +1 -1
  127. package/esm/policy.d.ts +193 -74
  128. package/esm/policy.d.ts.map +1 -1
  129. package/esm/policy.js +110 -19
  130. package/esm/policy.js.map +1 -1
  131. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +49 -2
  132. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
  133. package/esm/policyDefiners/defineFileHeaderPolicy.js +21 -4
  134. package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
  135. package/esm/policyDefiners/definePackagePolicy.d.ts +57 -3
  136. package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
  137. package/esm/policyDefiners/definePackagePolicy.js +50 -5
  138. package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
  139. package/esm/tsdoc-metadata.json +1 -1
  140. package/oclif.manifest.json +1 -1
  141. package/package.json +6 -4
@@ -1,5 +1,6 @@
1
1
  import { updatePackageJsonFile } from "@tylerbu/cli-api";
2
- import { join } from "pathe";
2
+ import { call } from "effection";
3
+ import { resolve as resolvePath } from "pathe";
3
4
  import { sortPackageJson } from "sort-package-json";
4
5
  import { definePackagePolicy } from "../policyDefiners/definePackagePolicy.js";
5
6
  /**
@@ -7,48 +8,51 @@ import { definePackagePolicy } from "../policyDefiners/definePackagePolicy.js";
7
8
  *
8
9
  * @alpha
9
10
  */
10
- export const PackageJsonSorted = definePackagePolicy("PackageJsonSorted", async (json, { file, root, resolve }) => {
11
- const sortedJson = sortPackageJson(json);
12
- const isSorted = JSON.stringify(sortedJson) === JSON.stringify(json);
13
- if (isSorted) {
14
- return true;
15
- }
16
- if (resolve) {
17
- try {
18
- // biome-ignore lint/nursery/noShadow: no need to use the shadowed variable
19
- await updatePackageJsonFile(join(root, file), (json) => json, {
20
- sort: true,
21
- });
22
- const result = {
23
- name: PackageJsonSorted.name,
24
- file,
25
- resolved: true,
26
- errorMessages: [],
27
- };
28
- return result;
11
+ export const PackageJsonSorted = definePackagePolicy({
12
+ name: "PackageJsonSorted",
13
+ description: "Ensures package.json files are sorted consistently using sort-package-json.",
14
+ handler: function* (json, { file, root, resolve }) {
15
+ const sortedJson = sortPackageJson(json);
16
+ const isSorted = JSON.stringify(sortedJson) === JSON.stringify(json);
17
+ if (isSorted) {
18
+ return true;
29
19
  }
30
- catch (error) {
20
+ if (resolve) {
21
+ try {
22
+ yield* call(() => updatePackageJsonFile(resolvePath(root, file), (pkgJson) => pkgJson, {
23
+ sort: true,
24
+ }));
25
+ const result = {
26
+ name: PackageJsonSorted.name,
27
+ file,
28
+ resolved: true,
29
+ errorMessages: [],
30
+ };
31
+ return result;
32
+ }
33
+ catch (error) {
34
+ const result = {
35
+ name: PackageJsonSorted.name,
36
+ file,
37
+ resolved: false,
38
+ autoFixable: true,
39
+ errorMessages: [
40
+ error.message,
41
+ error.stack ?? "",
42
+ ],
43
+ };
44
+ return result;
45
+ }
46
+ }
47
+ else {
31
48
  const result = {
32
49
  name: PackageJsonSorted.name,
33
50
  file,
34
- resolved: false,
35
51
  autoFixable: true,
36
- errorMessages: [
37
- error.message,
38
- error.stack ?? "",
39
- ],
52
+ errorMessages: [],
40
53
  };
41
54
  return result;
42
55
  }
43
- }
44
- else {
45
- const result = {
46
- name: PackageJsonSorted.name,
47
- file,
48
- autoFixable: true,
49
- errorMessages: [],
50
- };
51
- return result;
52
- }
56
+ },
53
57
  });
54
58
  //# sourceMappingURL=PackageJsonSorted.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageJsonSorted.js","sourceRoot":"","sources":["../../src/policies/PackageJsonSorted.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAE/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CACnD,mBAAmB,EACnB,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;IACvC,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAErE,IAAI,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACb,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACb,IAAI,CAAC;YACJ,2EAA2E;YAC3E,MAAM,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;gBAC7D,IAAI,EAAE,IAAI;aACV,CAAC,CAAC;YACH,MAAM,MAAM,GAAoB;gBAC/B,IAAI,EAAE,iBAAiB,CAAC,IAAI;gBAC5B,IAAI;gBACJ,QAAQ,EAAE,IAAI;gBACd,aAAa,EAAE,EAAE;aACjB,CAAC;YACF,OAAO,MAAM,CAAC;QACf,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACzB,MAAM,MAAM,GAAoB;gBAC/B,IAAI,EAAE,iBAAiB,CAAC,IAAI;gBAC5B,IAAI;gBACJ,QAAQ,EAAE,KAAK;gBACf,WAAW,EAAE,IAAI;gBACjB,aAAa,EAAE;oBACb,KAAe,CAAC,OAAO;oBACvB,KAAe,CAAC,KAAK,IAAI,EAAE;iBAC5B;aACD,CAAC;YACF,OAAO,MAAM,CAAC;QACf,CAAC;IACF,CAAC;SAAM,CAAC;QACP,MAAM,MAAM,GAAkB;YAC7B,IAAI,EAAE,iBAAiB,CAAC,IAAI;YAC5B,IAAI;YACJ,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE,EAAE;SACjB,CAAC;QACF,OAAO,MAAM,CAAC;IACf,CAAC;AACF,CAAC,CACD,CAAC","sourcesContent":["import { updatePackageJsonFile } from \"@tylerbu/cli-api\";\nimport { join } from \"pathe\";\nimport { sortPackageJson } from \"sort-package-json\";\nimport type { PolicyFailure, PolicyFixResult } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * A repo policy that checks if package.json files in the repo are sorted using sort-package-json.\n *\n * @alpha\n */\nexport const PackageJsonSorted = definePackagePolicy(\n\t\"PackageJsonSorted\",\n\tasync (json, { file, root, resolve }) => {\n\t\tconst sortedJson = sortPackageJson(json);\n\t\tconst isSorted = JSON.stringify(sortedJson) === JSON.stringify(json);\n\n\t\tif (isSorted) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (resolve) {\n\t\t\ttry {\n\t\t\t\t// biome-ignore lint/nursery/noShadow: no need to use the shadowed variable\n\t\t\t\tawait updatePackageJsonFile(join(root, file), (json) => json, {\n\t\t\t\t\tsort: true,\n\t\t\t\t});\n\t\t\t\tconst result: PolicyFixResult = {\n\t\t\t\t\tname: PackageJsonSorted.name,\n\t\t\t\t\tfile,\n\t\t\t\t\tresolved: true,\n\t\t\t\t\terrorMessages: [],\n\t\t\t\t};\n\t\t\t\treturn result;\n\t\t\t} catch (error: unknown) {\n\t\t\t\tconst result: PolicyFixResult = {\n\t\t\t\t\tname: PackageJsonSorted.name,\n\t\t\t\t\tfile,\n\t\t\t\t\tresolved: false,\n\t\t\t\t\tautoFixable: true,\n\t\t\t\t\terrorMessages: [\n\t\t\t\t\t\t(error as Error).message,\n\t\t\t\t\t\t(error as Error).stack ?? \"\",\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t\treturn result;\n\t\t\t}\n\t\t} else {\n\t\t\tconst result: PolicyFailure = {\n\t\t\t\tname: PackageJsonSorted.name,\n\t\t\t\tfile,\n\t\t\t\tautoFixable: true,\n\t\t\t\terrorMessages: [],\n\t\t\t};\n\t\t\treturn result;\n\t\t}\n\t},\n);\n"]}
1
+ {"version":3,"file":"PackageJsonSorted.js","sourceRoot":"","sources":["../../src/policies/PackageJsonSorted.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAE/E;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;IACpD,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACV,6EAA6E;IAC9E,OAAO,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE;QAChD,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAErE,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI,OAAO,EAAE,CAAC;YACb,IAAI,CAAC;gBACJ,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,CAChB,qBAAqB,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE;oBACpE,IAAI,EAAE,IAAI;iBACV,CAAC,CACF,CAAC;gBACF,MAAM,MAAM,GAAoB;oBAC/B,IAAI,EAAE,iBAAiB,CAAC,IAAI;oBAC5B,IAAI;oBACJ,QAAQ,EAAE,IAAI;oBACd,aAAa,EAAE,EAAE;iBACjB,CAAC;gBACF,OAAO,MAAM,CAAC;YACf,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAoB;oBAC/B,IAAI,EAAE,iBAAiB,CAAC,IAAI;oBAC5B,IAAI;oBACJ,QAAQ,EAAE,KAAK;oBACf,WAAW,EAAE,IAAI;oBACjB,aAAa,EAAE;wBACb,KAAe,CAAC,OAAO;wBACvB,KAAe,CAAC,KAAK,IAAI,EAAE;qBAC5B;iBACD,CAAC;gBACF,OAAO,MAAM,CAAC;YACf,CAAC;QACF,CAAC;aAAM,CAAC;YACP,MAAM,MAAM,GAAkB;gBAC7B,IAAI,EAAE,iBAAiB,CAAC,IAAI;gBAC5B,IAAI;gBACJ,WAAW,EAAE,IAAI;gBACjB,aAAa,EAAE,EAAE;aACjB,CAAC;YACF,OAAO,MAAM,CAAC;QACf,CAAC;IACF,CAAC;CACD,CAAC,CAAC","sourcesContent":["import { updatePackageJsonFile } from \"@tylerbu/cli-api\";\nimport { call } from \"effection\";\nimport { resolve as resolvePath } from \"pathe\";\nimport { sortPackageJson } from \"sort-package-json\";\nimport type { PolicyFailure, PolicyFixResult } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * A repo policy that checks if package.json files in the repo are sorted using sort-package-json.\n *\n * @alpha\n */\nexport const PackageJsonSorted = definePackagePolicy({\n\tname: \"PackageJsonSorted\",\n\tdescription:\n\t\t\"Ensures package.json files are sorted consistently using sort-package-json.\",\n\thandler: function* (json, { file, root, resolve }) {\n\t\tconst sortedJson = sortPackageJson(json);\n\t\tconst isSorted = JSON.stringify(sortedJson) === JSON.stringify(json);\n\n\t\tif (isSorted) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (resolve) {\n\t\t\ttry {\n\t\t\t\tyield* call(() =>\n\t\t\t\t\tupdatePackageJsonFile(resolvePath(root, file), (pkgJson) => pkgJson, {\n\t\t\t\t\t\tsort: true,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tconst result: PolicyFixResult = {\n\t\t\t\t\tname: PackageJsonSorted.name,\n\t\t\t\t\tfile,\n\t\t\t\t\tresolved: true,\n\t\t\t\t\terrorMessages: [],\n\t\t\t\t};\n\t\t\t\treturn result;\n\t\t\t} catch (error: unknown) {\n\t\t\t\tconst result: PolicyFixResult = {\n\t\t\t\t\tname: PackageJsonSorted.name,\n\t\t\t\t\tfile,\n\t\t\t\t\tresolved: false,\n\t\t\t\t\tautoFixable: true,\n\t\t\t\t\terrorMessages: [\n\t\t\t\t\t\t(error as Error).message,\n\t\t\t\t\t\t(error as Error).stack ?? \"\",\n\t\t\t\t\t],\n\t\t\t\t};\n\t\t\t\treturn result;\n\t\t\t}\n\t\t} else {\n\t\t\tconst result: PolicyFailure = {\n\t\t\t\tname: PackageJsonSorted.name,\n\t\t\t\tfile,\n\t\t\t\tautoFixable: true,\n\t\t\t\terrorMessages: [],\n\t\t\t};\n\t\t\treturn result;\n\t\t}\n\t},\n});\n"]}
@@ -57,5 +57,5 @@ export interface PackageLicenseSettings {
57
57
  *
58
58
  * @alpha
59
59
  */
60
- export declare const PackageLicense: import("../policy.js").PolicyDefinition<PackageLicenseSettings | undefined>;
60
+ export declare const PackageLicense: import("../policy.js").PolicyShape<PackageLicenseSettings | undefined>;
61
61
  //# sourceMappingURL=PackageLicense.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageLicense.d.ts","sourceRoot":"","sources":["../../src/policies/PackageLicense.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AA8CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,cAAc,6EAoFzB,CAAC"}
1
+ {"version":3,"file":"PackageLicense.d.ts","sourceRoot":"","sources":["../../src/policies/PackageLicense.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AA8CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,cAAc,wEA0FzB,CAAC"}
@@ -71,61 +71,65 @@ async function copyLicenseFile(rootLicensePath, packageLicensePath, policyName,
71
71
  *
72
72
  * @alpha
73
73
  */
74
- export const PackageLicense = definePackagePolicy("PackageLicense", async (json, { file, root, resolve, config }) => {
75
- const skipPrivate = config?.skipPrivate ?? true;
76
- const licenseFileName = config?.licenseFileName ?? DEFAULT_LICENSE_FILE_NAME;
77
- // Skip private packages if configured to do so
78
- if (skipPrivate && json.private === true) {
79
- return true;
80
- }
81
- const packageName = json.name ?? "unknown";
82
- // file is an absolute path, get the directory containing package.json
83
- const packageDir = path.dirname(file);
84
- const packageLicensePath = path.join(packageDir, licenseFileName);
85
- const rootLicensePath = path.join(root, licenseFileName);
86
- // Check if root LICENSE exists
87
- if (!existsSync(rootLicensePath)) {
88
- return {
89
- name: POLICY_NAME,
90
- file,
91
- autoFixable: false,
92
- errorMessages: [
93
- `Cannot validate package LICENSE: root ${licenseFileName} file not found`,
94
- ],
95
- };
96
- }
97
- // Check if package LICENSE exists
98
- if (!existsSync(packageLicensePath)) {
99
- if (resolve) {
100
- return await copyLicenseFile(rootLicensePath, packageLicensePath, POLICY_NAME, file, packageName, licenseFileName, true);
74
+ export const PackageLicense = definePackagePolicy({
75
+ name: "PackageLicense",
76
+ description: "Ensures each package has a LICENSE file that matches the root repository LICENSE.",
77
+ handler: async (json, { file, root, resolve, config }) => {
78
+ const skipPrivate = config?.skipPrivate ?? true;
79
+ const licenseFileName = config?.licenseFileName ?? DEFAULT_LICENSE_FILE_NAME;
80
+ // Skip private packages if configured to do so
81
+ if (skipPrivate && json.private === true) {
82
+ return true;
101
83
  }
102
- return {
103
- name: POLICY_NAME,
104
- file,
105
- autoFixable: true,
106
- errorMessages: [
107
- `${licenseFileName} file missing for package "${packageName}"`,
108
- ],
109
- };
110
- }
111
- // Compare package LICENSE with root LICENSE
112
- const [packageLicenseContent, rootLicenseContent] = await Promise.all([
113
- readFile(packageLicensePath, "utf-8"),
114
- readFile(rootLicensePath, "utf-8"),
115
- ]);
116
- if (packageLicenseContent !== rootLicenseContent) {
117
- if (resolve) {
118
- return await copyLicenseFile(rootLicensePath, packageLicensePath, POLICY_NAME, file, packageName, licenseFileName, false);
84
+ const packageName = json.name ?? "unknown";
85
+ // file is an absolute path, get the directory containing package.json
86
+ const packageDir = path.dirname(file);
87
+ const packageLicensePath = path.join(packageDir, licenseFileName);
88
+ const rootLicensePath = path.join(root, licenseFileName);
89
+ // Check if root LICENSE exists
90
+ if (!existsSync(rootLicensePath)) {
91
+ return {
92
+ name: POLICY_NAME,
93
+ file,
94
+ autoFixable: false,
95
+ errorMessages: [
96
+ `Cannot validate package LICENSE: root ${licenseFileName} file not found`,
97
+ ],
98
+ };
119
99
  }
120
- return {
121
- name: POLICY_NAME,
122
- file,
123
- autoFixable: true,
124
- errorMessages: [
125
- `${licenseFileName} file in package "${packageName}" doesn't match root ${licenseFileName}`,
126
- ],
127
- };
128
- }
129
- return true;
100
+ // Check if package LICENSE exists
101
+ if (!existsSync(packageLicensePath)) {
102
+ if (resolve) {
103
+ return await copyLicenseFile(rootLicensePath, packageLicensePath, POLICY_NAME, file, packageName, licenseFileName, true);
104
+ }
105
+ return {
106
+ name: POLICY_NAME,
107
+ file,
108
+ autoFixable: true,
109
+ errorMessages: [
110
+ `${licenseFileName} file missing for package "${packageName}"`,
111
+ ],
112
+ };
113
+ }
114
+ // Compare package LICENSE with root LICENSE
115
+ const [packageLicenseContent, rootLicenseContent] = await Promise.all([
116
+ readFile(packageLicensePath, "utf-8"),
117
+ readFile(rootLicensePath, "utf-8"),
118
+ ]);
119
+ if (packageLicenseContent !== rootLicenseContent) {
120
+ if (resolve) {
121
+ return await copyLicenseFile(rootLicensePath, packageLicensePath, POLICY_NAME, file, packageName, licenseFileName, false);
122
+ }
123
+ return {
124
+ name: POLICY_NAME,
125
+ file,
126
+ autoFixable: true,
127
+ errorMessages: [
128
+ `${licenseFileName} file in package "${packageName}" doesn't match root ${licenseFileName}`,
129
+ ],
130
+ };
131
+ }
132
+ return true;
133
+ },
130
134
  });
131
135
  //# sourceMappingURL=PackageLicense.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageLicense.js","sourceRoot":"","sources":["../../src/policies/PackageLicense.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { copyFile, readFile } from \"node:fs/promises\";\nimport path from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFixResult } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * Policy settings for the PackageLicense repo policy.\n *\n * @alpha\n */\nexport interface PackageLicenseSettings {\n\t/**\n\t * Whether to skip validation for private packages.\n\t *\n\t * @defaultValue true\n\t *\n\t * @remarks\n\t *\n\t * Private packages (those with `private: true` in package.json) are typically\n\t * not published and may not need a LICENSE file. Set to `false` to require\n\t * LICENSE files for all packages.\n\t */\n\tskipPrivate?: boolean;\n\n\t/**\n\t * The name of the LICENSE file to look for and sync.\n\t *\n\t * @defaultValue \"LICENSE\"\n\t */\n\tlicenseFileName?: string;\n}\n\nconst DEFAULT_LICENSE_FILE_NAME = \"LICENSE\";\nconst POLICY_NAME = \"PackageLicense\";\n\n/**\n * Copies the root LICENSE file to the package directory.\n * @returns A PolicyFixResult indicating success or failure.\n */\nasync function copyLicenseFile(\n\trootLicensePath: string,\n\tpackageLicensePath: string,\n\tpolicyName: string,\n\tfile: string,\n\tpackageName: string,\n\tlicenseFileName: string,\n\tisCreate: boolean,\n): Promise<PolicyFixResult> {\n\ttry {\n\t\tawait copyFile(rootLicensePath, packageLicensePath);\n\t\treturn {\n\t\t\tname: policyName,\n\t\t\tfile,\n\t\t\tresolved: true,\n\t\t\tautoFixable: true,\n\t\t\terrorMessages: [\n\t\t\t\tisCreate\n\t\t\t\t\t? `Created ${licenseFileName} file for package \"${packageName}\"`\n\t\t\t\t\t: `Updated ${licenseFileName} file for package \"${packageName}\" to match root`,\n\t\t\t],\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tname: policyName,\n\t\t\tfile,\n\t\t\tresolved: false,\n\t\t\tautoFixable: true,\n\t\t\terrorMessages: [\n\t\t\t\tisCreate\n\t\t\t\t\t? `Failed to copy ${licenseFileName} to package \"${packageName}\"`\n\t\t\t\t\t: `Failed to update ${licenseFileName} for package \"${packageName}\"`,\n\t\t\t],\n\t\t};\n\t}\n}\n\n/**\n * A repo policy that ensures each package has a LICENSE file that matches the root LICENSE.\n *\n * @remarks\n *\n * This policy is essential for monorepos where individual packages are published\n * to npm. Each published package should include a LICENSE file, and it should\n * match the root repository's LICENSE to ensure consistent licensing.\n *\n * The policy:\n * 1. Checks if a LICENSE file exists in the package directory\n * 2. Compares it with the root LICENSE file\n * 3. Can auto-fix by copying the root LICENSE to the package directory\n *\n * By default, private packages are skipped since they're not published.\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageLicense } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * // Use defaults (skip private, look for LICENSE)\n * makePolicy(PackageLicense),\n *\n * // Or require LICENSE for all packages including private\n * makePolicy(PackageLicense, { skipPrivate: false }),\n * ],\n * };\n * ```\n *\n * @alpha\n */\nexport const PackageLicense = definePackagePolicy<\n\tPackageJson,\n\tPackageLicenseSettings | undefined\n>(\"PackageLicense\", async (json, { file, root, resolve, config }) => {\n\tconst skipPrivate = config?.skipPrivate ?? true;\n\tconst licenseFileName = config?.licenseFileName ?? DEFAULT_LICENSE_FILE_NAME;\n\n\t// Skip private packages if configured to do so\n\tif (skipPrivate && json.private === true) {\n\t\treturn true;\n\t}\n\n\tconst packageName = json.name ?? \"unknown\";\n\t// file is an absolute path, get the directory containing package.json\n\tconst packageDir = path.dirname(file);\n\tconst packageLicensePath = path.join(packageDir, licenseFileName);\n\tconst rootLicensePath = path.join(root, licenseFileName);\n\n\t// Check if root LICENSE exists\n\tif (!existsSync(rootLicensePath)) {\n\t\treturn {\n\t\t\tname: POLICY_NAME,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages: [\n\t\t\t\t`Cannot validate package LICENSE: root ${licenseFileName} file not found`,\n\t\t\t],\n\t\t};\n\t}\n\n\t// Check if package LICENSE exists\n\tif (!existsSync(packageLicensePath)) {\n\t\tif (resolve) {\n\t\t\treturn await copyLicenseFile(\n\t\t\t\trootLicensePath,\n\t\t\t\tpackageLicensePath,\n\t\t\t\tPOLICY_NAME,\n\t\t\t\tfile,\n\t\t\t\tpackageName,\n\t\t\t\tlicenseFileName,\n\t\t\t\ttrue,\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tname: POLICY_NAME,\n\t\t\tfile,\n\t\t\tautoFixable: true,\n\t\t\terrorMessages: [\n\t\t\t\t`${licenseFileName} file missing for package \"${packageName}\"`,\n\t\t\t],\n\t\t};\n\t}\n\n\t// Compare package LICENSE with root LICENSE\n\tconst [packageLicenseContent, rootLicenseContent] = await Promise.all([\n\t\treadFile(packageLicensePath, \"utf-8\"),\n\t\treadFile(rootLicensePath, \"utf-8\"),\n\t]);\n\n\tif (packageLicenseContent !== rootLicenseContent) {\n\t\tif (resolve) {\n\t\t\treturn await copyLicenseFile(\n\t\t\t\trootLicensePath,\n\t\t\t\tpackageLicensePath,\n\t\t\t\tPOLICY_NAME,\n\t\t\t\tfile,\n\t\t\t\tpackageName,\n\t\t\t\tlicenseFileName,\n\t\t\t\tfalse,\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tname: POLICY_NAME,\n\t\t\tfile,\n\t\t\tautoFixable: true,\n\t\t\terrorMessages: [\n\t\t\t\t`${licenseFileName} file in package \"${packageName}\" doesn't match root ${licenseFileName}`,\n\t\t\t],\n\t\t};\n\t}\n\n\treturn true;\n});\n"]}
1
+ {"version":3,"file":"PackageLicense.js","sourceRoot":"","sources":["../../src/policies/PackageLicense.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync } from \"node:fs\";\nimport { copyFile, readFile } from \"node:fs/promises\";\nimport path from \"pathe\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFixResult } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * Policy settings for the PackageLicense repo policy.\n *\n * @alpha\n */\nexport interface PackageLicenseSettings {\n\t/**\n\t * Whether to skip validation for private packages.\n\t *\n\t * @defaultValue true\n\t *\n\t * @remarks\n\t *\n\t * Private packages (those with `private: true` in package.json) are typically\n\t * not published and may not need a LICENSE file. Set to `false` to require\n\t * LICENSE files for all packages.\n\t */\n\tskipPrivate?: boolean;\n\n\t/**\n\t * The name of the LICENSE file to look for and sync.\n\t *\n\t * @defaultValue \"LICENSE\"\n\t */\n\tlicenseFileName?: string;\n}\n\nconst DEFAULT_LICENSE_FILE_NAME = \"LICENSE\";\nconst POLICY_NAME = \"PackageLicense\";\n\n/**\n * Copies the root LICENSE file to the package directory.\n * @returns A PolicyFixResult indicating success or failure.\n */\nasync function copyLicenseFile(\n\trootLicensePath: string,\n\tpackageLicensePath: string,\n\tpolicyName: string,\n\tfile: string,\n\tpackageName: string,\n\tlicenseFileName: string,\n\tisCreate: boolean,\n): Promise<PolicyFixResult> {\n\ttry {\n\t\tawait copyFile(rootLicensePath, packageLicensePath);\n\t\treturn {\n\t\t\tname: policyName,\n\t\t\tfile,\n\t\t\tresolved: true,\n\t\t\tautoFixable: true,\n\t\t\terrorMessages: [\n\t\t\t\tisCreate\n\t\t\t\t\t? `Created ${licenseFileName} file for package \"${packageName}\"`\n\t\t\t\t\t: `Updated ${licenseFileName} file for package \"${packageName}\" to match root`,\n\t\t\t],\n\t\t};\n\t} catch {\n\t\treturn {\n\t\t\tname: policyName,\n\t\t\tfile,\n\t\t\tresolved: false,\n\t\t\tautoFixable: true,\n\t\t\terrorMessages: [\n\t\t\t\tisCreate\n\t\t\t\t\t? `Failed to copy ${licenseFileName} to package \"${packageName}\"`\n\t\t\t\t\t: `Failed to update ${licenseFileName} for package \"${packageName}\"`,\n\t\t\t],\n\t\t};\n\t}\n}\n\n/**\n * A repo policy that ensures each package has a LICENSE file that matches the root LICENSE.\n *\n * @remarks\n *\n * This policy is essential for monorepos where individual packages are published\n * to npm. Each published package should include a LICENSE file, and it should\n * match the root repository's LICENSE to ensure consistent licensing.\n *\n * The policy:\n * 1. Checks if a LICENSE file exists in the package directory\n * 2. Compares it with the root LICENSE file\n * 3. Can auto-fix by copying the root LICENSE to the package directory\n *\n * By default, private packages are skipped since they're not published.\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackageLicense } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * // Use defaults (skip private, look for LICENSE)\n * makePolicy(PackageLicense),\n *\n * // Or require LICENSE for all packages including private\n * makePolicy(PackageLicense, { skipPrivate: false }),\n * ],\n * };\n * ```\n *\n * @alpha\n */\nexport const PackageLicense = definePackagePolicy<\n\tPackageJson,\n\tPackageLicenseSettings | undefined\n>({\n\tname: \"PackageLicense\",\n\tdescription:\n\t\t\"Ensures each package has a LICENSE file that matches the root repository LICENSE.\",\n\thandler: async (json, { file, root, resolve, config }) => {\n\t\tconst skipPrivate = config?.skipPrivate ?? true;\n\t\tconst licenseFileName =\n\t\t\tconfig?.licenseFileName ?? DEFAULT_LICENSE_FILE_NAME;\n\n\t\t// Skip private packages if configured to do so\n\t\tif (skipPrivate && json.private === true) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst packageName = json.name ?? \"unknown\";\n\t\t// file is an absolute path, get the directory containing package.json\n\t\tconst packageDir = path.dirname(file);\n\t\tconst packageLicensePath = path.join(packageDir, licenseFileName);\n\t\tconst rootLicensePath = path.join(root, licenseFileName);\n\n\t\t// Check if root LICENSE exists\n\t\tif (!existsSync(rootLicensePath)) {\n\t\t\treturn {\n\t\t\t\tname: POLICY_NAME,\n\t\t\t\tfile,\n\t\t\t\tautoFixable: false,\n\t\t\t\terrorMessages: [\n\t\t\t\t\t`Cannot validate package LICENSE: root ${licenseFileName} file not found`,\n\t\t\t\t],\n\t\t\t};\n\t\t}\n\n\t\t// Check if package LICENSE exists\n\t\tif (!existsSync(packageLicensePath)) {\n\t\t\tif (resolve) {\n\t\t\t\treturn await copyLicenseFile(\n\t\t\t\t\trootLicensePath,\n\t\t\t\t\tpackageLicensePath,\n\t\t\t\t\tPOLICY_NAME,\n\t\t\t\t\tfile,\n\t\t\t\t\tpackageName,\n\t\t\t\t\tlicenseFileName,\n\t\t\t\t\ttrue,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tname: POLICY_NAME,\n\t\t\t\tfile,\n\t\t\t\tautoFixable: true,\n\t\t\t\terrorMessages: [\n\t\t\t\t\t`${licenseFileName} file missing for package \"${packageName}\"`,\n\t\t\t\t],\n\t\t\t};\n\t\t}\n\n\t\t// Compare package LICENSE with root LICENSE\n\t\tconst [packageLicenseContent, rootLicenseContent] = await Promise.all([\n\t\t\treadFile(packageLicensePath, \"utf-8\"),\n\t\t\treadFile(rootLicensePath, \"utf-8\"),\n\t\t]);\n\n\t\tif (packageLicenseContent !== rootLicenseContent) {\n\t\t\tif (resolve) {\n\t\t\t\treturn await copyLicenseFile(\n\t\t\t\t\trootLicensePath,\n\t\t\t\t\tpackageLicensePath,\n\t\t\t\t\tPOLICY_NAME,\n\t\t\t\t\tfile,\n\t\t\t\t\tpackageName,\n\t\t\t\t\tlicenseFileName,\n\t\t\t\t\tfalse,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tname: POLICY_NAME,\n\t\t\t\tfile,\n\t\t\t\tautoFixable: true,\n\t\t\t\terrorMessages: [\n\t\t\t\t\t`${licenseFileName} file in package \"${packageName}\" doesn't match root ${licenseFileName}`,\n\t\t\t\t],\n\t\t\t};\n\t\t}\n\n\t\treturn true;\n\t},\n});\n"]}
@@ -120,5 +120,5 @@ export interface PackagePrivateFieldConfig {
120
120
  *
121
121
  * @alpha
122
122
  */
123
- export declare const PackagePrivateField: import("../policy.js").PolicyDefinition<PackagePrivateFieldConfig | undefined>;
123
+ export declare const PackagePrivateField: import("../policy.js").PolicyShape<PackagePrivateFieldConfig | undefined>;
124
124
  //# sourceMappingURL=PackagePrivateField.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackagePrivateField.d.ts","sourceRoot":"","sources":["../../src/policies/PackagePrivateField.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,yBAAyB;IACzC;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAEtB;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACpD;AA+DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,mBAAmB,gFA0E9B,CAAC"}
1
+ {"version":3,"file":"PackagePrivateField.d.ts","sourceRoot":"","sources":["../../src/policies/PackagePrivateField.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,yBAAyB;IACzC;;;;;;;;;;;;;;;OAeG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;;;;;;;;;;;;OAeG;IACH,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IAEtB;;;;;;;;OAQG;IACH,iBAAiB,CAAC,EAAE,SAAS,GAAG,QAAQ,GAAG,QAAQ,CAAC;CACpD;AA+DD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,mBAAmB,2EA+E9B,CAAC"}
@@ -93,63 +93,67 @@ function getRequiredPrivateState(packageName, config) {
93
93
  *
94
94
  * @alpha
95
95
  */
96
- export const PackagePrivateField = definePackagePolicy("PackagePrivateField", async (json, { file, config, resolve }) => {
97
- // If no config provided, skip validation
98
- if (config === undefined) {
99
- return true;
100
- }
101
- const packageName = json.name;
102
- // Skip packages without a name (shouldn't happen in practice)
103
- if (packageName === undefined) {
104
- return true;
105
- }
106
- // Skip the root package (typically named "root" in monorepos)
107
- if (packageName === "root") {
108
- return true;
109
- }
110
- const requiredState = getRequiredPrivateState(packageName, config);
111
- // If "ignore", the package can be either private or public
112
- if (requiredState === IGNORE_PRIVATE_STATE) {
113
- return true;
114
- }
115
- const currentlyPrivate = json.private === true;
116
- // Check if the current state matches the required state
117
- if (requiredState === currentlyPrivate) {
118
- return true;
119
- }
120
- // State mismatch - build error message
121
- const errorMessage = requiredState === true
122
- ? `Package "${packageName}" must be marked private. Add "private": true to package.json.`
123
- : `Package "${packageName}" must not be marked private. Remove "private": true from package.json to allow publishing.`;
124
- const failResult = {
125
- name: PackagePrivateField.name,
126
- file,
127
- autoFixable: true,
128
- errorMessages: [errorMessage],
129
- };
130
- if (resolve) {
131
- const fixResult = {
132
- ...failResult,
133
- resolved: false,
96
+ export const PackagePrivateField = definePackagePolicy({
97
+ name: "PackagePrivateField",
98
+ description: "Enforces the private field in package.json based on package scope or name patterns.",
99
+ handler: async (json, { file, config, resolve }) => {
100
+ // If no config provided, skip validation
101
+ if (config === undefined) {
102
+ return true;
103
+ }
104
+ const packageName = json.name;
105
+ // Skip packages without a name (shouldn't happen in practice)
106
+ if (packageName === undefined) {
107
+ return true;
108
+ }
109
+ // Skip the root package (typically named "root" in monorepos)
110
+ if (packageName === "root") {
111
+ return true;
112
+ }
113
+ const requiredState = getRequiredPrivateState(packageName, config);
114
+ // If "ignore", the package can be either private or public
115
+ if (requiredState === IGNORE_PRIVATE_STATE) {
116
+ return true;
117
+ }
118
+ const currentlyPrivate = json.private === true;
119
+ // Check if the current state matches the required state
120
+ if (requiredState === currentlyPrivate) {
121
+ return true;
122
+ }
123
+ // State mismatch - build error message
124
+ const errorMessage = requiredState === true
125
+ ? `Package "${packageName}" must be marked private. Add "private": true to package.json.`
126
+ : `Package "${packageName}" must not be marked private. Remove "private": true from package.json to allow publishing.`;
127
+ const failResult = {
128
+ name: PackagePrivateField.name,
129
+ file,
130
+ autoFixable: true,
131
+ errorMessages: [errorMessage],
134
132
  };
135
- try {
136
- if (requiredState === true) {
137
- // Add private: true
138
- json.private = true;
133
+ if (resolve) {
134
+ const fixResult = {
135
+ ...failResult,
136
+ resolved: false,
137
+ };
138
+ try {
139
+ if (requiredState === true) {
140
+ // Add private: true
141
+ json.private = true;
142
+ }
143
+ else {
144
+ // Remove private field
145
+ delete json.private;
146
+ }
147
+ await writeJson(file, json, { spaces: "\t" });
148
+ fixResult.resolved = true;
139
149
  }
140
- else {
141
- // Remove private field
142
- delete json.private;
150
+ catch {
151
+ fixResult.resolved = false;
152
+ fixResult.errorMessages = [`Failed to update ${file}`];
143
153
  }
144
- await writeJson(file, json, { spaces: "\t" });
145
- fixResult.resolved = true;
154
+ return fixResult;
146
155
  }
147
- catch {
148
- fixResult.resolved = false;
149
- fixResult.errorMessages = [`Failed to update ${file}`];
150
- }
151
- return fixResult;
152
- }
153
- return failResult;
156
+ return failResult;
157
+ },
154
158
  });
155
159
  //# sourceMappingURL=PackagePrivateField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackagePrivateField.js","sourceRoot":"","sources":["../../src/policies/PackagePrivateField.ts"],"names":[],"mappings":"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","sourcesContent":["import jsonfile from \"jsonfile\";\nimport picomatch from \"picomatch\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure, PolicyFixResult } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\nconst { writeFile: writeJson } = jsonfile;\n\n/**\n * Sentinel value indicating that the package's private status should not be enforced.\n * This is more explicit than using `undefined` to represent \"ignore\".\n */\nconst IGNORE_PRIVATE_STATE = \"ignore\" as const;\n\n/**\n * The required private state for a package.\n * - `true`: Package must have `private: true`\n * - `false`: Package must NOT have `private: true`\n * - `\"ignore\"`: No enforcement - package can be either private or public\n */\ntype RequiredPrivateState = boolean | typeof IGNORE_PRIVATE_STATE;\n\n/**\n * Configuration for the PackagePrivateField policy.\n *\n * This policy enforces that packages are correctly marked as private or public based on\n * their scope or name. This is essential for monorepos where some packages should be\n * published to npm while others should remain internal.\n *\n * All pattern matching uses glob patterns via picomatch.\n *\n * @example\n * ```typescript\n * const config: PackagePrivateFieldConfig = {\n * // Packages in myorg scope must be published (private: false or absent)\n * mustPublish: [\"@myorg/*\"],\n * // Packages in internal scope must be private\n * mustBePrivate: [\"@internal/*\"],\n * // Packages in experimental scope can choose\n * mayPublish: [\"@experimental/*\"],\n * };\n * ```\n *\n * @alpha\n */\nexport interface PackagePrivateFieldConfig {\n\t/**\n\t * A list of glob patterns for packages that must be published.\n\t *\n\t * Packages matching these patterns must NOT have `private: true` in their package.json.\n\t * If they do, the policy will fail and can auto-fix by removing the private field.\n\t *\n\t * @remarks\n\t *\n\t * Uses glob patterns via picomatch. Use \"@scope/*\" to match all packages in a scope,\n\t * or use exact package names.\n\t *\n\t * @example\n\t * ```typescript\n\t * mustPublish: [\"@fluidframework/*\", \"@fluid-tools/*\", \"tinylicious\"]\n\t * ```\n\t */\n\tmustPublish?: string[];\n\n\t/**\n\t * A list of glob patterns for packages that must be private.\n\t *\n\t * Packages matching these patterns must have `private: true` in their package.json.\n\t * If they don't, the policy will fail and can auto-fix by adding `private: true`.\n\t *\n\t * @remarks\n\t *\n\t * Uses glob patterns via picomatch (see mustPublish for pattern examples).\n\t *\n\t * @example\n\t * ```typescript\n\t * mustBePrivate: [\"@fluid-internal/*\", \"@fluid-private/*\"]\n\t * ```\n\t */\n\tmustBePrivate?: string[];\n\n\t/**\n\t * A list of glob patterns for packages that may optionally be published.\n\t *\n\t * Packages matching these patterns can choose whether to be private or public.\n\t * The policy will not enforce either state for these packages.\n\t *\n\t * @remarks\n\t *\n\t * Uses glob patterns via picomatch (see mustPublish for pattern examples).\n\t * Packages not matching any list default to requiring `private: true`.\n\t *\n\t * @example\n\t * ```typescript\n\t * mayPublish: [\"@fluid-experimental/*\"]\n\t * ```\n\t */\n\tmayPublish?: string[];\n\n\t/**\n\t * Default behavior for packages that don't match any of the above lists.\n\t *\n\t * - `\"private\"` (default): Unmatched packages must have `private: true`\n\t * - `\"public\"`: Unmatched packages must NOT have `private: true`\n\t * - `\"ignore\"`: No enforcement for unmatched packages\n\t *\n\t * @defaultValue \"private\"\n\t */\n\tunmatchedPackages?: \"private\" | \"public\" | \"ignore\";\n}\n\n/**\n * Check if a package name matches any pattern in the list.\n *\n * Supports glob patterns via picomatch. Use patterns like:\n * - \"@myorg/\\*\" - matches all packages in the myorg scope\n * - \"my-package\" - exact match\n * - \"my-*\" - matches my-foo, my-bar, etc.\n *\n * @param packageName - The package name to check (e.g., `@myorg/foo`)\n * @param patterns - List of glob patterns or exact package names\n * @returns `true` if the package matches any pattern\n */\nfunction matchesAnyPattern(\n\tpackageName: string,\n\tpatterns: string[] | undefined,\n): boolean {\n\tif (patterns === undefined || patterns.length === 0) {\n\t\treturn false;\n\t}\n\n\treturn picomatch.isMatch(packageName, patterns);\n}\n\n/**\n * Determine what the private field should be for a package.\n *\n * @returns `true` if package must be private, `false` if must be public, `\"ignore\"` if either is ok\n */\nfunction getRequiredPrivateState(\n\tpackageName: string,\n\tconfig: PackagePrivateFieldConfig,\n): RequiredPrivateState {\n\t// Check mustPublish first - these packages must NOT be private\n\tif (matchesAnyPattern(packageName, config.mustPublish)) {\n\t\treturn false;\n\t}\n\n\t// Check mustBePrivate - these packages MUST be private\n\tif (matchesAnyPattern(packageName, config.mustBePrivate)) {\n\t\treturn true;\n\t}\n\n\t// Check mayPublish - these packages can be either\n\tif (matchesAnyPattern(packageName, config.mayPublish)) {\n\t\treturn IGNORE_PRIVATE_STATE;\n\t}\n\n\t// Default behavior for unmatched packages\n\tconst unmatchedBehavior = config.unmatchedPackages ?? \"private\";\n\tswitch (unmatchedBehavior) {\n\t\tcase \"private\":\n\t\t\treturn true;\n\t\tcase \"public\":\n\t\t\treturn false;\n\t\tcase \"ignore\":\n\t\t\treturn IGNORE_PRIVATE_STATE;\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown unmatchedPackages value: ${unmatchedBehavior}`);\n\t}\n}\n\n/**\n * A policy that enforces the `private` field in package.json based on package scope or name.\n *\n * This policy is essential for monorepos where publishing control is important:\n *\n * - Prevent accidental publishing of internal packages\n * - Ensure public packages don't have `private: true` blocking publishing\n * - Allow experimental packages to choose their own publishing status\n *\n * @remarks\n *\n * The policy evaluates packages in the following order:\n *\n * 1. If the package matches `mustPublish`, it must NOT have `private: true`\n * 2. If the package matches `mustBePrivate`, it MUST have `private: true`\n * 3. If the package matches `mayPublish`, no enforcement is applied\n * 4. Otherwise, the `unmatchedPackages` setting determines behavior (defaults to requiring private)\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackagePrivateField } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * makePolicy(PackagePrivateField, {\n * mustPublish: [\"@myorg/*\"],\n * mustBePrivate: [\"@internal/*\"],\n * mayPublish: [\"@experimental/*\"],\n * unmatchedPackages: \"private\",\n * }),\n * ],\n * };\n * ```\n *\n * @alpha\n */\nexport const PackagePrivateField = definePackagePolicy<\n\tPackageJson,\n\tPackagePrivateFieldConfig | undefined\n>(\"PackagePrivateField\", async (json, { file, config, resolve }) => {\n\t// If no config provided, skip validation\n\tif (config === undefined) {\n\t\treturn true;\n\t}\n\n\tconst packageName = json.name;\n\n\t// Skip packages without a name (shouldn't happen in practice)\n\tif (packageName === undefined) {\n\t\treturn true;\n\t}\n\n\t// Skip the root package (typically named \"root\" in monorepos)\n\tif (packageName === \"root\") {\n\t\treturn true;\n\t}\n\n\tconst requiredState = getRequiredPrivateState(packageName, config);\n\n\t// If \"ignore\", the package can be either private or public\n\tif (requiredState === IGNORE_PRIVATE_STATE) {\n\t\treturn true;\n\t}\n\n\tconst currentlyPrivate = json.private === true;\n\n\t// Check if the current state matches the required state\n\tif (requiredState === currentlyPrivate) {\n\t\treturn true;\n\t}\n\n\t// State mismatch - build error message\n\tconst errorMessage =\n\t\trequiredState === true\n\t\t\t? `Package \"${packageName}\" must be marked private. Add \"private\": true to package.json.`\n\t\t\t: `Package \"${packageName}\" must not be marked private. Remove \"private\": true from package.json to allow publishing.`;\n\n\tconst failResult: PolicyFailure = {\n\t\tname: PackagePrivateField.name,\n\t\tfile,\n\t\tautoFixable: true,\n\t\terrorMessages: [errorMessage],\n\t};\n\n\tif (resolve) {\n\t\tconst fixResult: PolicyFixResult = {\n\t\t\t...failResult,\n\t\t\tresolved: false,\n\t\t};\n\n\t\ttry {\n\t\t\tif (requiredState === true) {\n\t\t\t\t// Add private: true\n\t\t\t\tjson.private = true;\n\t\t\t} else {\n\t\t\t\t// Remove private field\n\t\t\t\tdelete json.private;\n\t\t\t}\n\n\t\t\tawait writeJson(file, json, { spaces: \"\\t\" });\n\t\t\tfixResult.resolved = true;\n\t\t} catch {\n\t\t\tfixResult.resolved = false;\n\t\t\tfixResult.errorMessages = [`Failed to update ${file}`];\n\t\t}\n\n\t\treturn fixResult;\n\t}\n\n\treturn failResult;\n});\n"]}
1
+ {"version":3,"file":"PackagePrivateField.js","sourceRoot":"","sources":["../../src/policies/PackagePrivateField.ts"],"names":[],"mappings":"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","sourcesContent":["import jsonfile from \"jsonfile\";\nimport picomatch from \"picomatch\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure, PolicyFixResult } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\nconst { writeFile: writeJson } = jsonfile;\n\n/**\n * Sentinel value indicating that the package's private status should not be enforced.\n * This is more explicit than using `undefined` to represent \"ignore\".\n */\nconst IGNORE_PRIVATE_STATE = \"ignore\" as const;\n\n/**\n * The required private state for a package.\n * - `true`: Package must have `private: true`\n * - `false`: Package must NOT have `private: true`\n * - `\"ignore\"`: No enforcement - package can be either private or public\n */\ntype RequiredPrivateState = boolean | typeof IGNORE_PRIVATE_STATE;\n\n/**\n * Configuration for the PackagePrivateField policy.\n *\n * This policy enforces that packages are correctly marked as private or public based on\n * their scope or name. This is essential for monorepos where some packages should be\n * published to npm while others should remain internal.\n *\n * All pattern matching uses glob patterns via picomatch.\n *\n * @example\n * ```typescript\n * const config: PackagePrivateFieldConfig = {\n * // Packages in myorg scope must be published (private: false or absent)\n * mustPublish: [\"@myorg/*\"],\n * // Packages in internal scope must be private\n * mustBePrivate: [\"@internal/*\"],\n * // Packages in experimental scope can choose\n * mayPublish: [\"@experimental/*\"],\n * };\n * ```\n *\n * @alpha\n */\nexport interface PackagePrivateFieldConfig {\n\t/**\n\t * A list of glob patterns for packages that must be published.\n\t *\n\t * Packages matching these patterns must NOT have `private: true` in their package.json.\n\t * If they do, the policy will fail and can auto-fix by removing the private field.\n\t *\n\t * @remarks\n\t *\n\t * Uses glob patterns via picomatch. Use \"@scope/*\" to match all packages in a scope,\n\t * or use exact package names.\n\t *\n\t * @example\n\t * ```typescript\n\t * mustPublish: [\"@fluidframework/*\", \"@fluid-tools/*\", \"tinylicious\"]\n\t * ```\n\t */\n\tmustPublish?: string[];\n\n\t/**\n\t * A list of glob patterns for packages that must be private.\n\t *\n\t * Packages matching these patterns must have `private: true` in their package.json.\n\t * If they don't, the policy will fail and can auto-fix by adding `private: true`.\n\t *\n\t * @remarks\n\t *\n\t * Uses glob patterns via picomatch (see mustPublish for pattern examples).\n\t *\n\t * @example\n\t * ```typescript\n\t * mustBePrivate: [\"@fluid-internal/*\", \"@fluid-private/*\"]\n\t * ```\n\t */\n\tmustBePrivate?: string[];\n\n\t/**\n\t * A list of glob patterns for packages that may optionally be published.\n\t *\n\t * Packages matching these patterns can choose whether to be private or public.\n\t * The policy will not enforce either state for these packages.\n\t *\n\t * @remarks\n\t *\n\t * Uses glob patterns via picomatch (see mustPublish for pattern examples).\n\t * Packages not matching any list default to requiring `private: true`.\n\t *\n\t * @example\n\t * ```typescript\n\t * mayPublish: [\"@fluid-experimental/*\"]\n\t * ```\n\t */\n\tmayPublish?: string[];\n\n\t/**\n\t * Default behavior for packages that don't match any of the above lists.\n\t *\n\t * - `\"private\"` (default): Unmatched packages must have `private: true`\n\t * - `\"public\"`: Unmatched packages must NOT have `private: true`\n\t * - `\"ignore\"`: No enforcement for unmatched packages\n\t *\n\t * @defaultValue \"private\"\n\t */\n\tunmatchedPackages?: \"private\" | \"public\" | \"ignore\";\n}\n\n/**\n * Check if a package name matches any pattern in the list.\n *\n * Supports glob patterns via picomatch. Use patterns like:\n * - \"@myorg/\\*\" - matches all packages in the myorg scope\n * - \"my-package\" - exact match\n * - \"my-*\" - matches my-foo, my-bar, etc.\n *\n * @param packageName - The package name to check (e.g., `@myorg/foo`)\n * @param patterns - List of glob patterns or exact package names\n * @returns `true` if the package matches any pattern\n */\nfunction matchesAnyPattern(\n\tpackageName: string,\n\tpatterns: string[] | undefined,\n): boolean {\n\tif (patterns === undefined || patterns.length === 0) {\n\t\treturn false;\n\t}\n\n\treturn picomatch.isMatch(packageName, patterns);\n}\n\n/**\n * Determine what the private field should be for a package.\n *\n * @returns `true` if package must be private, `false` if must be public, `\"ignore\"` if either is ok\n */\nfunction getRequiredPrivateState(\n\tpackageName: string,\n\tconfig: PackagePrivateFieldConfig,\n): RequiredPrivateState {\n\t// Check mustPublish first - these packages must NOT be private\n\tif (matchesAnyPattern(packageName, config.mustPublish)) {\n\t\treturn false;\n\t}\n\n\t// Check mustBePrivate - these packages MUST be private\n\tif (matchesAnyPattern(packageName, config.mustBePrivate)) {\n\t\treturn true;\n\t}\n\n\t// Check mayPublish - these packages can be either\n\tif (matchesAnyPattern(packageName, config.mayPublish)) {\n\t\treturn IGNORE_PRIVATE_STATE;\n\t}\n\n\t// Default behavior for unmatched packages\n\tconst unmatchedBehavior = config.unmatchedPackages ?? \"private\";\n\tswitch (unmatchedBehavior) {\n\t\tcase \"private\":\n\t\t\treturn true;\n\t\tcase \"public\":\n\t\t\treturn false;\n\t\tcase \"ignore\":\n\t\t\treturn IGNORE_PRIVATE_STATE;\n\t\tdefault:\n\t\t\tthrow new Error(`Unknown unmatchedPackages value: ${unmatchedBehavior}`);\n\t}\n}\n\n/**\n * A policy that enforces the `private` field in package.json based on package scope or name.\n *\n * This policy is essential for monorepos where publishing control is important:\n *\n * - Prevent accidental publishing of internal packages\n * - Ensure public packages don't have `private: true` blocking publishing\n * - Allow experimental packages to choose their own publishing status\n *\n * @remarks\n *\n * The policy evaluates packages in the following order:\n *\n * 1. If the package matches `mustPublish`, it must NOT have `private: true`\n * 2. If the package matches `mustBePrivate`, it MUST have `private: true`\n * 3. If the package matches `mayPublish`, no enforcement is applied\n * 4. Otherwise, the `unmatchedPackages` setting determines behavior (defaults to requiring private)\n *\n * @example\n * ```typescript\n * import { makePolicy } from \"repopo\";\n * import { PackagePrivateField } from \"repopo/policies\";\n *\n * const config: RepopoConfig = {\n * policies: [\n * makePolicy(PackagePrivateField, {\n * mustPublish: [\"@myorg/*\"],\n * mustBePrivate: [\"@internal/*\"],\n * mayPublish: [\"@experimental/*\"],\n * unmatchedPackages: \"private\",\n * }),\n * ],\n * };\n * ```\n *\n * @alpha\n */\nexport const PackagePrivateField = definePackagePolicy<\n\tPackageJson,\n\tPackagePrivateFieldConfig | undefined\n>({\n\tname: \"PackagePrivateField\",\n\tdescription:\n\t\t\"Enforces the private field in package.json based on package scope or name patterns.\",\n\thandler: async (json, { file, config, resolve }) => {\n\t\t// If no config provided, skip validation\n\t\tif (config === undefined) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst packageName = json.name;\n\n\t\t// Skip packages without a name (shouldn't happen in practice)\n\t\tif (packageName === undefined) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Skip the root package (typically named \"root\" in monorepos)\n\t\tif (packageName === \"root\") {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst requiredState = getRequiredPrivateState(packageName, config);\n\n\t\t// If \"ignore\", the package can be either private or public\n\t\tif (requiredState === IGNORE_PRIVATE_STATE) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst currentlyPrivate = json.private === true;\n\n\t\t// Check if the current state matches the required state\n\t\tif (requiredState === currentlyPrivate) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// State mismatch - build error message\n\t\tconst errorMessage =\n\t\t\trequiredState === true\n\t\t\t\t? `Package \"${packageName}\" must be marked private. Add \"private\": true to package.json.`\n\t\t\t\t: `Package \"${packageName}\" must not be marked private. Remove \"private\": true from package.json to allow publishing.`;\n\n\t\tconst failResult: PolicyFailure = {\n\t\t\tname: PackagePrivateField.name,\n\t\t\tfile,\n\t\t\tautoFixable: true,\n\t\t\terrorMessages: [errorMessage],\n\t\t};\n\n\t\tif (resolve) {\n\t\t\tconst fixResult: PolicyFixResult = {\n\t\t\t\t...failResult,\n\t\t\t\tresolved: false,\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\tif (requiredState === true) {\n\t\t\t\t\t// Add private: true\n\t\t\t\t\tjson.private = true;\n\t\t\t\t} else {\n\t\t\t\t\t// Remove private field\n\t\t\t\t\tdelete json.private;\n\t\t\t\t}\n\n\t\t\t\tawait writeJson(file, json, { spaces: \"\\t\" });\n\t\t\t\tfixResult.resolved = true;\n\t\t\t} catch {\n\t\t\t\tfixResult.resolved = false;\n\t\t\t\tfixResult.errorMessages = [`Failed to update ${file}`];\n\t\t\t}\n\n\t\t\treturn fixResult;\n\t\t}\n\n\t\treturn failResult;\n\t},\n});\n"]}
@@ -73,5 +73,5 @@ export interface PackageReadmeSettings {
73
73
  *
74
74
  * @alpha
75
75
  */
76
- export declare const PackageReadme: import("../policy.js").PolicyDefinition<PackageReadmeSettings | undefined>;
76
+ export declare const PackageReadme: import("../policy.js").PolicyShape<PackageReadmeSettings | undefined>;
77
77
  //# sourceMappingURL=PackageReadme.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageReadme.d.ts","sourceRoot":"","sources":["../../src/policies/PackageReadme.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAkMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,aAAa,4EAuCxB,CAAC"}
1
+ {"version":3,"file":"PackageReadme.d.ts","sourceRoot":"","sources":["../../src/policies/PackageReadme.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;;;;OASG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAE/B;;;;;;;;;;;;OAYG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAkMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,aAAa,uEA4CxB,CAAC"}
@@ -179,31 +179,35 @@ async function validateExistingReadme(ctx) {
179
179
  *
180
180
  * @alpha
181
181
  */
182
- export const PackageReadme = definePackagePolicy("PackageReadme", async (json, { file, resolve, config }) => {
183
- const skipPrivate = config?.skipPrivate ?? true;
184
- const requireMatchingTitle = config?.requireMatchingTitle ?? true;
185
- const requiredContent = config?.requiredContent;
186
- // Skip private packages if configured to do so
187
- if (skipPrivate && json.private === true) {
188
- return true;
189
- }
190
- const packageName = json.name ?? "unknown";
191
- const packageDir = path.dirname(file);
192
- const readmePath = path.join(packageDir, "README.md");
193
- // Check if README exists
194
- if (!existsSync(readmePath)) {
195
- return await handleMissingReadme(readmePath, packageName, file, resolve, requiredContent);
196
- }
197
- // README exists, validate content
198
- const readmeContent = await readFile(readmePath, "utf-8");
199
- return await validateExistingReadme({
200
- readmePath,
201
- readmeContent,
202
- packageName,
203
- file,
204
- resolve,
205
- requireMatchingTitle,
206
- requiredContent,
207
- });
182
+ export const PackageReadme = definePackagePolicy({
183
+ name: "PackageReadme",
184
+ description: "Ensures each package has a README.md file with proper title and required content.",
185
+ handler: async (json, { file, resolve, config }) => {
186
+ const skipPrivate = config?.skipPrivate ?? true;
187
+ const requireMatchingTitle = config?.requireMatchingTitle ?? true;
188
+ const requiredContent = config?.requiredContent;
189
+ // Skip private packages if configured to do so
190
+ if (skipPrivate && json.private === true) {
191
+ return true;
192
+ }
193
+ const packageName = json.name ?? "unknown";
194
+ const packageDir = path.dirname(file);
195
+ const readmePath = path.join(packageDir, "README.md");
196
+ // Check if README exists
197
+ if (!existsSync(readmePath)) {
198
+ return await handleMissingReadme(readmePath, packageName, file, resolve, requiredContent);
199
+ }
200
+ // README exists, validate content
201
+ const readmeContent = await readFile(readmePath, "utf-8");
202
+ return await validateExistingReadme({
203
+ readmePath,
204
+ readmeContent,
205
+ packageName,
206
+ file,
207
+ resolve,
208
+ requireMatchingTitle,
209
+ requiredContent,
210
+ });
211
+ },
208
212
  });
209
213
  //# sourceMappingURL=PackageReadme.js.map