repopo 0.9.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 (83) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/esm/commands/check.d.ts +1 -0
  3. package/esm/commands/check.d.ts.map +1 -1
  4. package/esm/commands/check.js +48 -11
  5. package/esm/commands/check.js.map +1 -1
  6. package/esm/config.d.ts +19 -4
  7. package/esm/config.d.ts.map +1 -1
  8. package/esm/config.js +2 -3
  9. package/esm/config.js.map +1 -1
  10. package/esm/index.d.ts +2 -2
  11. package/esm/index.d.ts.map +1 -1
  12. package/esm/index.js +6 -1
  13. package/esm/index.js.map +1 -1
  14. package/esm/makePolicy.d.ts +50 -8
  15. package/esm/makePolicy.d.ts.map +1 -1
  16. package/esm/makePolicy.js +64 -4
  17. package/esm/makePolicy.js.map +1 -1
  18. package/esm/policies/ConditionalScripts.d.ts +94 -0
  19. package/esm/policies/ConditionalScripts.d.ts.map +1 -0
  20. package/esm/policies/ConditionalScripts.js +144 -0
  21. package/esm/policies/ConditionalScripts.js.map +1 -0
  22. package/esm/policies/ExactScripts.d.ts +51 -0
  23. package/esm/policies/ExactScripts.d.ts.map +1 -0
  24. package/esm/policies/ExactScripts.js +107 -0
  25. package/esm/policies/ExactScripts.js.map +1 -0
  26. package/esm/policies/HtmlFileHeaders.d.ts +1 -1
  27. package/esm/policies/HtmlFileHeaders.d.ts.map +1 -1
  28. package/esm/policies/JsTsFileHeaders.d.ts +1 -1
  29. package/esm/policies/JsTsFileHeaders.d.ts.map +1 -1
  30. package/esm/policies/MutuallyExclusiveScripts.d.ts +46 -0
  31. package/esm/policies/MutuallyExclusiveScripts.d.ts.map +1 -0
  32. package/esm/policies/MutuallyExclusiveScripts.js +52 -0
  33. package/esm/policies/MutuallyExclusiveScripts.js.map +1 -0
  34. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +1 -1
  35. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
  36. package/esm/policies/PackageAllowedScopes.d.ts +1 -1
  37. package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
  38. package/esm/policies/PackageEsmType.d.ts +1 -1
  39. package/esm/policies/PackageEsmType.d.ts.map +1 -1
  40. package/esm/policies/PackageFolderName.d.ts +1 -1
  41. package/esm/policies/PackageFolderName.d.ts.map +1 -1
  42. package/esm/policies/PackageJsonProperties.d.ts +1 -1
  43. package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
  44. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts +1 -1
  45. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
  46. package/esm/policies/PackageJsonSorted.d.ts +1 -1
  47. package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
  48. package/esm/policies/PackageLicense.d.ts +1 -1
  49. package/esm/policies/PackageLicense.d.ts.map +1 -1
  50. package/esm/policies/PackagePrivateField.d.ts +1 -1
  51. package/esm/policies/PackagePrivateField.d.ts.map +1 -1
  52. package/esm/policies/PackageReadme.d.ts +1 -1
  53. package/esm/policies/PackageReadme.d.ts.map +1 -1
  54. package/esm/policies/PackageScripts.d.ts +1 -1
  55. package/esm/policies/PackageScripts.d.ts.map +1 -1
  56. package/esm/policies/PackageTestScripts.d.ts +1 -1
  57. package/esm/policies/PackageTestScripts.d.ts.map +1 -1
  58. package/esm/policies/RequiredScripts.d.ts +71 -0
  59. package/esm/policies/RequiredScripts.d.ts.map +1 -0
  60. package/esm/policies/RequiredScripts.js +120 -0
  61. package/esm/policies/RequiredScripts.js.map +1 -0
  62. package/esm/policies/ScriptContains.d.ts +64 -0
  63. package/esm/policies/ScriptContains.d.ts.map +1 -0
  64. package/esm/policies/ScriptContains.js +62 -0
  65. package/esm/policies/ScriptContains.js.map +1 -0
  66. package/esm/policies.d.ts +6 -1
  67. package/esm/policies.d.ts.map +1 -1
  68. package/esm/policies.js +18 -0
  69. package/esm/policies.js.map +1 -1
  70. package/esm/policy.d.ts +180 -86
  71. package/esm/policy.d.ts.map +1 -1
  72. package/esm/policy.js +103 -21
  73. package/esm/policy.js.map +1 -1
  74. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +7 -2
  75. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
  76. package/esm/policyDefiners/defineFileHeaderPolicy.js +5 -0
  77. package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
  78. package/esm/policyDefiners/definePackagePolicy.d.ts +18 -5
  79. package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
  80. package/esm/policyDefiners/definePackagePolicy.js +14 -4
  81. package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
  82. package/oclif.manifest.json +1 -1
  83. package/package.json +1 -1
@@ -0,0 +1,94 @@
1
+ /**
2
+ * A required script entry for conditional requirements. Can be either:
3
+ * - A string (script name only, no default value)
4
+ * - An object with a single key-value pair (script name → default value for auto-fix)
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * // Script must exist, no auto-fix available
9
+ * "test"
10
+ *
11
+ * // Script must exist, auto-fix will add this value if missing
12
+ * { clean: "rimraf dist" }
13
+ * ```
14
+ *
15
+ * @alpha
16
+ */
17
+ export type ConditionalScriptEntry = string | Record<string, string>;
18
+ /**
19
+ * Configuration for a conditional script requirement.
20
+ *
21
+ * @alpha
22
+ */
23
+ export interface ConditionalScriptRule {
24
+ /**
25
+ * The script that triggers the requirement.
26
+ * If this script exists, then `requires` must also exist.
27
+ */
28
+ ifPresent: string;
29
+ /**
30
+ * Scripts that must be present if `ifPresent` script exists.
31
+ *
32
+ * @remarks
33
+ * Each entry can be:
34
+ * - A string: Script must exist, no auto-fix available
35
+ * - An object `{ scriptName: "default value" }`: Script must exist, auto-fix adds the
36
+ * default value if missing
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * requires: ["test", { clean: "rimraf dist" }]
41
+ * ```
42
+ */
43
+ requires: ConditionalScriptEntry[];
44
+ }
45
+ /**
46
+ * Configuration for the ConditionalScripts policy.
47
+ *
48
+ * @alpha
49
+ */
50
+ export interface ConditionalScriptsConfig {
51
+ /**
52
+ * Conditional script requirements. If a script is present, other scripts must also exist.
53
+ *
54
+ * @remarks
55
+ * This is useful for enforcing that packages with a "build" script also have a "clean" script,
56
+ * or packages with "test" also have "test:coverage".
57
+ *
58
+ * @example
59
+ * ```typescript
60
+ * rules: [
61
+ * { ifPresent: "build", requires: [{ clean: "rimraf dist" }] },
62
+ * { ifPresent: "test", requires: ["test:coverage"] },
63
+ * ]
64
+ * ```
65
+ */
66
+ rules: ConditionalScriptRule[];
67
+ }
68
+ /**
69
+ * A policy that validates conditional script requirements in package.json.
70
+ *
71
+ * @remarks
72
+ * Use this policy when you want to enforce that the presence of one script
73
+ * requires other scripts to also exist. For example, if "build" exists,
74
+ * then "clean" must also exist.
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * import { policy } from "repopo";
79
+ * import { ConditionalScripts } from "repopo/policies";
80
+ *
81
+ * policy(ConditionalScripts, {
82
+ * rules: [
83
+ * // If "build" exists, "clean" must also exist (with auto-fix default)
84
+ * { ifPresent: "build", requires: [{ clean: "rimraf dist" }] },
85
+ * // If "test" exists, "test:coverage" must also exist (no auto-fix)
86
+ * { ifPresent: "test", requires: ["test:coverage"] },
87
+ * ],
88
+ * })
89
+ * ```
90
+ *
91
+ * @alpha
92
+ */
93
+ export declare const ConditionalScripts: import("../policy.js").PolicyShape<ConditionalScriptsConfig | undefined>;
94
+ //# sourceMappingURL=ConditionalScripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConditionalScripts.d.ts","sourceRoot":"","sources":["../../src/policies/ConditionalScripts.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,sBAAsB,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErE;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACrC;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,sBAAsB,EAAE,CAAC;CACnC;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACxC;;;;;;;;;;;;;;OAcG;IACH,KAAK,EAAE,qBAAqB,EAAE,CAAC;CAC/B;AAiHD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,kBAAkB,0EAuE7B,CAAC"}
@@ -0,0 +1,144 @@
1
+ import jsonfile from "jsonfile";
2
+ import { definePackagePolicy } from "../policyDefiners/definePackagePolicy.js";
3
+ const POLICY_NAME = "ConditionalScripts";
4
+ /**
5
+ * Extracts script name and optional default value from a ConditionalScriptEntry.
6
+ */
7
+ function parseEntry(entry) {
8
+ if (typeof entry === "string") {
9
+ return { name: entry };
10
+ }
11
+ const keys = Object.keys(entry);
12
+ if (keys.length !== 1) {
13
+ throw new Error(`Invalid conditional script entry: expected single key-value pair, got ${keys.length} keys`);
14
+ }
15
+ // biome-ignore lint/style/noNonNullAssertion: we verified length is 1
16
+ const name = keys[0];
17
+ const defaultValue = entry[name];
18
+ return defaultValue !== undefined ? { name, defaultValue } : { name };
19
+ }
20
+ function validateConditionalRules(scripts, rules) {
21
+ const violations = [];
22
+ const missingWithDefaults = [];
23
+ const seenMissing = new Set();
24
+ for (const rule of rules) {
25
+ // Skip if the triggering script doesn't exist
26
+ if (!Object.hasOwn(scripts, rule.ifPresent)) {
27
+ continue;
28
+ }
29
+ const missingScripts = [];
30
+ for (const entry of rule.requires) {
31
+ const { name, defaultValue } = parseEntry(entry);
32
+ if (!Object.hasOwn(scripts, name)) {
33
+ missingScripts.push(name);
34
+ if (defaultValue !== undefined && !seenMissing.has(name)) {
35
+ missingWithDefaults.push({ name, defaultValue });
36
+ seenMissing.add(name);
37
+ }
38
+ }
39
+ }
40
+ if (missingScripts.length > 0) {
41
+ violations.push({
42
+ triggerScript: rule.ifPresent,
43
+ missingScripts,
44
+ });
45
+ }
46
+ }
47
+ return { violations, missingWithDefaults };
48
+ }
49
+ function formatViolationErrors(violations) {
50
+ return violations.map((v) => `Script "${v.triggerScript}" is present, but required companion script(s) missing: ${v.missingScripts.join(", ")}`);
51
+ }
52
+ async function fixMissingScripts(json, file, missingWithDefaults, existingScripts) {
53
+ const updatedScripts = {};
54
+ // Copy existing scripts
55
+ for (const [key, value] of Object.entries(existingScripts)) {
56
+ if (value !== undefined) {
57
+ updatedScripts[key] = value;
58
+ }
59
+ }
60
+ // Add missing scripts with defaults
61
+ const fixedScripts = [];
62
+ for (const { name, defaultValue } of missingWithDefaults) {
63
+ updatedScripts[name] = defaultValue;
64
+ fixedScripts.push(name);
65
+ }
66
+ await jsonfile.writeFile(file, { ...json, scripts: updatedScripts }, { spaces: 2 });
67
+ return fixedScripts;
68
+ }
69
+ /**
70
+ * A policy that validates conditional script requirements in package.json.
71
+ *
72
+ * @remarks
73
+ * Use this policy when you want to enforce that the presence of one script
74
+ * requires other scripts to also exist. For example, if "build" exists,
75
+ * then "clean" must also exist.
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * import { policy } from "repopo";
80
+ * import { ConditionalScripts } from "repopo/policies";
81
+ *
82
+ * policy(ConditionalScripts, {
83
+ * rules: [
84
+ * // If "build" exists, "clean" must also exist (with auto-fix default)
85
+ * { ifPresent: "build", requires: [{ clean: "rimraf dist" }] },
86
+ * // If "test" exists, "test:coverage" must also exist (no auto-fix)
87
+ * { ifPresent: "test", requires: ["test:coverage"] },
88
+ * ],
89
+ * })
90
+ * ```
91
+ *
92
+ * @alpha
93
+ */
94
+ export const ConditionalScripts = definePackagePolicy({
95
+ name: POLICY_NAME,
96
+ description: "Validates that if certain scripts exist, other required scripts must also exist.",
97
+ handler: async (json, { file, resolve, config }) => {
98
+ if (config === undefined || config.rules.length === 0) {
99
+ return true;
100
+ }
101
+ const scripts = json.scripts ?? {};
102
+ const validation = validateConditionalRules(scripts, config.rules);
103
+ if (validation.violations.length === 0) {
104
+ return true;
105
+ }
106
+ const errors = formatViolationErrors(validation.violations);
107
+ const hasAutoFixableErrors = validation.missingWithDefaults.length > 0;
108
+ if (resolve && hasAutoFixableErrors) {
109
+ try {
110
+ const fixedScripts = await fixMissingScripts(json, file, validation.missingWithDefaults, scripts);
111
+ // Re-validate after fix to check for remaining errors
112
+ const updatedScripts = { ...scripts };
113
+ for (const name of fixedScripts) {
114
+ const entry = validation.missingWithDefaults.find((m) => m.name === name);
115
+ if (entry) {
116
+ updatedScripts[name] = entry.defaultValue;
117
+ }
118
+ }
119
+ const revalidation = validateConditionalRules(updatedScripts, config.rules);
120
+ const remainingErrors = formatViolationErrors(revalidation.violations);
121
+ return {
122
+ name: POLICY_NAME,
123
+ file,
124
+ resolved: remainingErrors.length === 0,
125
+ errorMessages: remainingErrors.length > 0
126
+ ? [
127
+ `Fixed scripts: ${fixedScripts.join(", ")}. Remaining errors:\n${remainingErrors.join("\n")}`,
128
+ ]
129
+ : [`Fixed scripts: ${fixedScripts.join(", ")}`],
130
+ };
131
+ }
132
+ catch {
133
+ // Fall through to return regular failure
134
+ }
135
+ }
136
+ return {
137
+ name: POLICY_NAME,
138
+ file,
139
+ autoFixable: hasAutoFixableErrors,
140
+ errorMessages: errors,
141
+ };
142
+ },
143
+ });
144
+ //# sourceMappingURL=ConditionalScripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConditionalScripts.js","sourceRoot":"","sources":["../../src/policies/ConditionalScripts.ts"],"names":[],"mappings":"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","sourcesContent":["import jsonfile from \"jsonfile\";\nimport type { PackageJson } from \"type-fest\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * A required script entry for conditional requirements. Can be either:\n * - A string (script name only, no default value)\n * - An object with a single key-value pair (script name → default value for auto-fix)\n *\n * @example\n * ```typescript\n * // Script must exist, no auto-fix available\n * \"test\"\n *\n * // Script must exist, auto-fix will add this value if missing\n * { clean: \"rimraf dist\" }\n * ```\n *\n * @alpha\n */\nexport type ConditionalScriptEntry = string | Record<string, string>;\n\n/**\n * Configuration for a conditional script requirement.\n *\n * @alpha\n */\nexport interface ConditionalScriptRule {\n\t/**\n\t * The script that triggers the requirement.\n\t * If this script exists, then `requires` must also exist.\n\t */\n\tifPresent: string;\n\n\t/**\n\t * Scripts that must be present if `ifPresent` script exists.\n\t *\n\t * @remarks\n\t * Each entry can be:\n\t * - A string: Script must exist, no auto-fix available\n\t * - An object `{ scriptName: \"default value\" }`: Script must exist, auto-fix adds the\n\t * default value if missing\n\t *\n\t * @example\n\t * ```typescript\n\t * requires: [\"test\", { clean: \"rimraf dist\" }]\n\t * ```\n\t */\n\trequires: ConditionalScriptEntry[];\n}\n\n/**\n * Configuration for the ConditionalScripts policy.\n *\n * @alpha\n */\nexport interface ConditionalScriptsConfig {\n\t/**\n\t * Conditional script requirements. If a script is present, other scripts must also exist.\n\t *\n\t * @remarks\n\t * This is useful for enforcing that packages with a \"build\" script also have a \"clean\" script,\n\t * or packages with \"test\" also have \"test:coverage\".\n\t *\n\t * @example\n\t * ```typescript\n\t * rules: [\n\t * { ifPresent: \"build\", requires: [{ clean: \"rimraf dist\" }] },\n\t * { ifPresent: \"test\", requires: [\"test:coverage\"] },\n\t * ]\n\t * ```\n\t */\n\trules: ConditionalScriptRule[];\n}\n\nconst POLICY_NAME = \"ConditionalScripts\";\n\ninterface ParsedEntry {\n\tname: string;\n\tdefaultValue?: string;\n}\n\n/**\n * Extracts script name and optional default value from a ConditionalScriptEntry.\n */\nfunction parseEntry(entry: ConditionalScriptEntry): ParsedEntry {\n\tif (typeof entry === \"string\") {\n\t\treturn { name: entry };\n\t}\n\tconst keys = Object.keys(entry);\n\tif (keys.length !== 1) {\n\t\tthrow new Error(\n\t\t\t`Invalid conditional script entry: expected single key-value pair, got ${keys.length} keys`,\n\t\t);\n\t}\n\t// biome-ignore lint/style/noNonNullAssertion: we verified length is 1\n\tconst name = keys[0]!;\n\tconst defaultValue = entry[name];\n\treturn defaultValue !== undefined ? { name, defaultValue } : { name };\n}\n\ninterface RuleViolation {\n\ttriggerScript: string;\n\tmissingScripts: string[];\n}\n\ninterface ValidationResult {\n\tviolations: RuleViolation[];\n\tmissingWithDefaults: Array<{ name: string; defaultValue: string }>;\n}\n\nfunction validateConditionalRules(\n\tscripts: Record<string, string | undefined>,\n\trules: ConditionalScriptRule[],\n): ValidationResult {\n\tconst violations: RuleViolation[] = [];\n\tconst missingWithDefaults: Array<{ name: string; defaultValue: string }> = [];\n\tconst seenMissing = new Set<string>();\n\n\tfor (const rule of rules) {\n\t\t// Skip if the triggering script doesn't exist\n\t\tif (!Object.hasOwn(scripts, rule.ifPresent)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst missingScripts: string[] = [];\n\t\tfor (const entry of rule.requires) {\n\t\t\tconst { name, defaultValue } = parseEntry(entry);\n\t\t\tif (!Object.hasOwn(scripts, name)) {\n\t\t\t\tmissingScripts.push(name);\n\t\t\t\tif (defaultValue !== undefined && !seenMissing.has(name)) {\n\t\t\t\t\tmissingWithDefaults.push({ name, defaultValue });\n\t\t\t\t\tseenMissing.add(name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (missingScripts.length > 0) {\n\t\t\tviolations.push({\n\t\t\t\ttriggerScript: rule.ifPresent,\n\t\t\t\tmissingScripts,\n\t\t\t});\n\t\t}\n\t}\n\n\treturn { violations, missingWithDefaults };\n}\n\nfunction formatViolationErrors(violations: RuleViolation[]): string[] {\n\treturn violations.map(\n\t\t(v) =>\n\t\t\t`Script \"${v.triggerScript}\" is present, but required companion script(s) missing: ${v.missingScripts.join(\", \")}`,\n\t);\n}\n\nasync function fixMissingScripts(\n\tjson: PackageJson,\n\tfile: string,\n\tmissingWithDefaults: Array<{ name: string; defaultValue: string }>,\n\texistingScripts: Record<string, string | undefined>,\n): Promise<string[]> {\n\tconst updatedScripts: Record<string, string> = {};\n\n\t// Copy existing scripts\n\tfor (const [key, value] of Object.entries(existingScripts)) {\n\t\tif (value !== undefined) {\n\t\t\tupdatedScripts[key] = value;\n\t\t}\n\t}\n\n\t// Add missing scripts with defaults\n\tconst fixedScripts: string[] = [];\n\tfor (const { name, defaultValue } of missingWithDefaults) {\n\t\tupdatedScripts[name] = defaultValue;\n\t\tfixedScripts.push(name);\n\t}\n\n\tawait jsonfile.writeFile(\n\t\tfile,\n\t\t{ ...json, scripts: updatedScripts },\n\t\t{ spaces: 2 },\n\t);\n\n\treturn fixedScripts;\n}\n\n/**\n * A policy that validates conditional script requirements in package.json.\n *\n * @remarks\n * Use this policy when you want to enforce that the presence of one script\n * requires other scripts to also exist. For example, if \"build\" exists,\n * then \"clean\" must also exist.\n *\n * @example\n * ```typescript\n * import { policy } from \"repopo\";\n * import { ConditionalScripts } from \"repopo/policies\";\n *\n * policy(ConditionalScripts, {\n * rules: [\n * // If \"build\" exists, \"clean\" must also exist (with auto-fix default)\n * { ifPresent: \"build\", requires: [{ clean: \"rimraf dist\" }] },\n * // If \"test\" exists, \"test:coverage\" must also exist (no auto-fix)\n * { ifPresent: \"test\", requires: [\"test:coverage\"] },\n * ],\n * })\n * ```\n *\n * @alpha\n */\nexport const ConditionalScripts = definePackagePolicy<\n\tPackageJson,\n\tConditionalScriptsConfig | undefined\n>({\n\tname: POLICY_NAME,\n\tdescription:\n\t\t\"Validates that if certain scripts exist, other required scripts must also exist.\",\n\thandler: async (json, { file, resolve, config }) => {\n\t\tif (config === undefined || config.rules.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst scripts = json.scripts ?? {};\n\t\tconst validation = validateConditionalRules(scripts, config.rules);\n\n\t\tif (validation.violations.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst errors = formatViolationErrors(validation.violations);\n\t\tconst hasAutoFixableErrors = validation.missingWithDefaults.length > 0;\n\n\t\tif (resolve && hasAutoFixableErrors) {\n\t\t\ttry {\n\t\t\t\tconst fixedScripts = await fixMissingScripts(\n\t\t\t\t\tjson,\n\t\t\t\t\tfile,\n\t\t\t\t\tvalidation.missingWithDefaults,\n\t\t\t\t\tscripts,\n\t\t\t\t);\n\n\t\t\t\t// Re-validate after fix to check for remaining errors\n\t\t\t\tconst updatedScripts = { ...scripts };\n\t\t\t\tfor (const name of fixedScripts) {\n\t\t\t\t\tconst entry = validation.missingWithDefaults.find(\n\t\t\t\t\t\t(m) => m.name === name,\n\t\t\t\t\t);\n\t\t\t\t\tif (entry) {\n\t\t\t\t\t\tupdatedScripts[name] = entry.defaultValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst revalidation = validateConditionalRules(\n\t\t\t\t\tupdatedScripts,\n\t\t\t\t\tconfig.rules,\n\t\t\t\t);\n\t\t\t\tconst remainingErrors = formatViolationErrors(revalidation.violations);\n\n\t\t\t\treturn {\n\t\t\t\t\tname: POLICY_NAME,\n\t\t\t\t\tfile,\n\t\t\t\t\tresolved: remainingErrors.length === 0,\n\t\t\t\t\terrorMessages:\n\t\t\t\t\t\tremainingErrors.length > 0\n\t\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\t\t`Fixed scripts: ${fixedScripts.join(\", \")}. Remaining errors:\\n${remainingErrors.join(\"\\n\")}`,\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t: [`Fixed scripts: ${fixedScripts.join(\", \")}`],\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// Fall through to return regular failure\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: hasAutoFixableErrors,\n\t\t\terrorMessages: errors,\n\t\t};\n\t},\n});\n"]}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Configuration for the ExactScripts policy.
3
+ *
4
+ * @alpha
5
+ */
6
+ export interface ExactScriptsConfig {
7
+ /**
8
+ * Scripts that must exist AND have exact content.
9
+ *
10
+ * @remarks
11
+ * Unlike RequiredScripts, scripts in `exact` are validated against
12
+ * the specified value. If a script exists but has different content, it fails validation.
13
+ * Both missing and mismatched scripts are auto-fixable.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * scripts: {
18
+ * clean: "rimraf dist esm",
19
+ * format: "biome format --write .",
20
+ * }
21
+ * ```
22
+ */
23
+ scripts: Record<string, string>;
24
+ }
25
+ /**
26
+ * A policy that validates scripts exist AND have exact content in package.json.
27
+ *
28
+ * @remarks
29
+ * Use this policy when you want to enforce exact script content, not just presence.
30
+ * This is useful for scripts that must be exactly the same across packages.
31
+ *
32
+ * For scripts where you only care about presence (not content), use RequiredScripts instead.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * import { policy } from "repopo";
37
+ * import { ExactScripts } from "repopo/policies";
38
+ *
39
+ * policy(ExactScripts, {
40
+ * scripts: {
41
+ * clean: "rimraf dist esm",
42
+ * format: "biome format --write .",
43
+ * lint: "biome lint .",
44
+ * },
45
+ * })
46
+ * ```
47
+ *
48
+ * @alpha
49
+ */
50
+ export declare const ExactScripts: import("../policy.js").PolicyShape<ExactScriptsConfig | undefined>;
51
+ //# sourceMappingURL=ExactScripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExactScripts.d.ts","sourceRoot":"","sources":["../../src/policies/ExactScripts.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IAClC;;;;;;;;;;;;;;;OAeG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAuED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,YAAY,oEAqDvB,CAAC"}
@@ -0,0 +1,107 @@
1
+ import jsonfile from "jsonfile";
2
+ import { definePackagePolicy } from "../policyDefiners/definePackagePolicy.js";
3
+ const POLICY_NAME = "ExactScripts";
4
+ function validateScripts(scripts, expectedScripts) {
5
+ const errors = [];
6
+ const missingScripts = [];
7
+ const mismatchedScripts = [];
8
+ for (const [scriptName, expectedValue] of Object.entries(expectedScripts)) {
9
+ if (Object.hasOwn(scripts, scriptName)) {
10
+ const actualValue = scripts[scriptName];
11
+ if (actualValue !== expectedValue) {
12
+ mismatchedScripts.push(scriptName);
13
+ errors.push(`Script "${scriptName}" must be "${expectedValue}", but found "${actualValue}"`);
14
+ }
15
+ }
16
+ else {
17
+ missingScripts.push(scriptName);
18
+ errors.push(`Missing required script: ${scriptName}`);
19
+ }
20
+ }
21
+ return { errors, missingScripts, mismatchedScripts };
22
+ }
23
+ async function fixScripts(json, file, scriptsToFix, expectedScripts, existingScripts) {
24
+ const updatedScripts = {};
25
+ // Copy existing scripts
26
+ for (const [key, value] of Object.entries(existingScripts)) {
27
+ if (value !== undefined) {
28
+ updatedScripts[key] = value;
29
+ }
30
+ }
31
+ // Add/update scripts
32
+ const fixedScripts = [];
33
+ for (const scriptName of scriptsToFix) {
34
+ const expectedValue = expectedScripts[scriptName];
35
+ if (expectedValue !== undefined) {
36
+ updatedScripts[scriptName] = expectedValue;
37
+ fixedScripts.push(scriptName);
38
+ }
39
+ }
40
+ await jsonfile.writeFile(file, { ...json, scripts: updatedScripts }, { spaces: 2 });
41
+ return fixedScripts;
42
+ }
43
+ /**
44
+ * A policy that validates scripts exist AND have exact content in package.json.
45
+ *
46
+ * @remarks
47
+ * Use this policy when you want to enforce exact script content, not just presence.
48
+ * This is useful for scripts that must be exactly the same across packages.
49
+ *
50
+ * For scripts where you only care about presence (not content), use RequiredScripts instead.
51
+ *
52
+ * @example
53
+ * ```typescript
54
+ * import { policy } from "repopo";
55
+ * import { ExactScripts } from "repopo/policies";
56
+ *
57
+ * policy(ExactScripts, {
58
+ * scripts: {
59
+ * clean: "rimraf dist esm",
60
+ * format: "biome format --write .",
61
+ * lint: "biome lint .",
62
+ * },
63
+ * })
64
+ * ```
65
+ *
66
+ * @alpha
67
+ */
68
+ export const ExactScripts = definePackagePolicy({
69
+ name: POLICY_NAME,
70
+ description: "Validates that scripts exist and have exact content in package.json.",
71
+ handler: async (json, { file, resolve, config }) => {
72
+ if (config === undefined || Object.keys(config.scripts).length === 0) {
73
+ return true;
74
+ }
75
+ const scripts = json.scripts ?? {};
76
+ const validation = validateScripts(scripts, config.scripts);
77
+ if (validation.errors.length === 0) {
78
+ return true;
79
+ }
80
+ const scriptsToFix = [
81
+ ...validation.missingScripts,
82
+ ...validation.mismatchedScripts,
83
+ ];
84
+ const hasAutoFixableErrors = scriptsToFix.length > 0;
85
+ if (resolve && hasAutoFixableErrors) {
86
+ try {
87
+ const fixedScripts = await fixScripts(json, file, scriptsToFix, config.scripts, scripts);
88
+ return {
89
+ name: POLICY_NAME,
90
+ file,
91
+ resolved: true,
92
+ errorMessages: [`Fixed scripts: ${fixedScripts.join(", ")}`],
93
+ };
94
+ }
95
+ catch {
96
+ // Fall through to return regular failure
97
+ }
98
+ }
99
+ return {
100
+ name: POLICY_NAME,
101
+ file,
102
+ autoFixable: hasAutoFixableErrors,
103
+ errorMessages: validation.errors,
104
+ };
105
+ },
106
+ });
107
+ //# sourceMappingURL=ExactScripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ExactScripts.js","sourceRoot":"","sources":["../../src/policies/ExactScripts.ts"],"names":[],"mappings":"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","sourcesContent":["import jsonfile from \"jsonfile\";\nimport type { PackageJson } from \"type-fest\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * Configuration for the ExactScripts policy.\n *\n * @alpha\n */\nexport interface ExactScriptsConfig {\n\t/**\n\t * Scripts that must exist AND have exact content.\n\t *\n\t * @remarks\n\t * Unlike RequiredScripts, scripts in `exact` are validated against\n\t * the specified value. If a script exists but has different content, it fails validation.\n\t * Both missing and mismatched scripts are auto-fixable.\n\t *\n\t * @example\n\t * ```typescript\n\t * scripts: {\n\t * clean: \"rimraf dist esm\",\n\t * format: \"biome format --write .\",\n\t * }\n\t * ```\n\t */\n\tscripts: Record<string, string>;\n}\n\nconst POLICY_NAME = \"ExactScripts\";\n\ninterface ValidationResult {\n\terrors: string[];\n\tmissingScripts: string[];\n\tmismatchedScripts: string[];\n}\n\nfunction validateScripts(\n\tscripts: Record<string, string | undefined>,\n\texpectedScripts: Record<string, string>,\n): ValidationResult {\n\tconst errors: string[] = [];\n\tconst missingScripts: string[] = [];\n\tconst mismatchedScripts: string[] = [];\n\n\tfor (const [scriptName, expectedValue] of Object.entries(expectedScripts)) {\n\t\tif (Object.hasOwn(scripts, scriptName)) {\n\t\t\tconst actualValue = scripts[scriptName];\n\t\t\tif (actualValue !== expectedValue) {\n\t\t\t\tmismatchedScripts.push(scriptName);\n\t\t\t\terrors.push(\n\t\t\t\t\t`Script \"${scriptName}\" must be \"${expectedValue}\", but found \"${actualValue}\"`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tmissingScripts.push(scriptName);\n\t\t\terrors.push(`Missing required script: ${scriptName}`);\n\t\t}\n\t}\n\n\treturn { errors, missingScripts, mismatchedScripts };\n}\n\nasync function fixScripts(\n\tjson: PackageJson,\n\tfile: string,\n\tscriptsToFix: string[],\n\texpectedScripts: Record<string, string>,\n\texistingScripts: Record<string, string | undefined>,\n): Promise<string[]> {\n\tconst updatedScripts: Record<string, string> = {};\n\n\t// Copy existing scripts\n\tfor (const [key, value] of Object.entries(existingScripts)) {\n\t\tif (value !== undefined) {\n\t\t\tupdatedScripts[key] = value;\n\t\t}\n\t}\n\n\t// Add/update scripts\n\tconst fixedScripts: string[] = [];\n\tfor (const scriptName of scriptsToFix) {\n\t\tconst expectedValue = expectedScripts[scriptName];\n\t\tif (expectedValue !== undefined) {\n\t\t\tupdatedScripts[scriptName] = expectedValue;\n\t\t\tfixedScripts.push(scriptName);\n\t\t}\n\t}\n\n\tawait jsonfile.writeFile(\n\t\tfile,\n\t\t{ ...json, scripts: updatedScripts },\n\t\t{ spaces: 2 },\n\t);\n\n\treturn fixedScripts;\n}\n\n/**\n * A policy that validates scripts exist AND have exact content in package.json.\n *\n * @remarks\n * Use this policy when you want to enforce exact script content, not just presence.\n * This is useful for scripts that must be exactly the same across packages.\n *\n * For scripts where you only care about presence (not content), use RequiredScripts instead.\n *\n * @example\n * ```typescript\n * import { policy } from \"repopo\";\n * import { ExactScripts } from \"repopo/policies\";\n *\n * policy(ExactScripts, {\n * scripts: {\n * clean: \"rimraf dist esm\",\n * format: \"biome format --write .\",\n * lint: \"biome lint .\",\n * },\n * })\n * ```\n *\n * @alpha\n */\nexport const ExactScripts = definePackagePolicy<\n\tPackageJson,\n\tExactScriptsConfig | undefined\n>({\n\tname: POLICY_NAME,\n\tdescription:\n\t\t\"Validates that scripts exist and have exact content in package.json.\",\n\thandler: async (json, { file, resolve, config }) => {\n\t\tif (config === undefined || Object.keys(config.scripts).length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst scripts = json.scripts ?? {};\n\t\tconst validation = validateScripts(scripts, config.scripts);\n\n\t\tif (validation.errors.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst scriptsToFix = [\n\t\t\t...validation.missingScripts,\n\t\t\t...validation.mismatchedScripts,\n\t\t];\n\t\tconst hasAutoFixableErrors = scriptsToFix.length > 0;\n\n\t\tif (resolve && hasAutoFixableErrors) {\n\t\t\ttry {\n\t\t\t\tconst fixedScripts = await fixScripts(\n\t\t\t\t\tjson,\n\t\t\t\t\tfile,\n\t\t\t\t\tscriptsToFix,\n\t\t\t\t\tconfig.scripts,\n\t\t\t\t\tscripts,\n\t\t\t\t);\n\n\t\t\t\treturn {\n\t\t\t\t\tname: POLICY_NAME,\n\t\t\t\t\tfile,\n\t\t\t\t\tresolved: true,\n\t\t\t\t\terrorMessages: [`Fixed scripts: ${fixedScripts.join(\", \")}`],\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// Fall through to return regular failure\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: hasAutoFixableErrors,\n\t\t\terrorMessages: validation.errors,\n\t\t};\n\t},\n});\n"]}
@@ -4,5 +4,5 @@ import { type FileHeaderPolicyConfig } from "../policyDefiners/defineFileHeaderP
4
4
  *
5
5
  * @alpha
6
6
  */
7
- export declare const HtmlFileHeaders: import("../policy.js").PolicyDefinition<FileHeaderPolicyConfig>;
7
+ export declare const HtmlFileHeaders: import("../policy.js").PolicyShape<FileHeaderPolicyConfig>;
8
8
  //# sourceMappingURL=HtmlFileHeaders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"HtmlFileHeaders.d.ts","sourceRoot":"","sources":["../../src/policies/HtmlFileHeaders.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,6CAA6C,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,eAAe,iEAkB1B,CAAC"}
1
+ {"version":3,"file":"HtmlFileHeaders.d.ts","sourceRoot":"","sources":["../../src/policies/HtmlFileHeaders.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,6CAA6C,CAAC;AAErD;;;;GAIG;AACH,eAAO,MAAM,eAAe,4DAkB1B,CAAC"}
@@ -4,5 +4,5 @@ import { type FileHeaderPolicyConfig } from "../policyDefiners/defineFileHeaderP
4
4
  *
5
5
  * @alpha
6
6
  */
7
- export declare const JsTsFileHeaders: import("../policy.js").PolicyDefinition<FileHeaderPolicyConfig>;
7
+ export declare const JsTsFileHeaders: import("../policy.js").PolicyShape<FileHeaderPolicyConfig>;
8
8
  //# sourceMappingURL=JsTsFileHeaders.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JsTsFileHeaders.d.ts","sourceRoot":"","sources":["../../src/policies/JsTsFileHeaders.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,6CAA6C,CAAC;AAkBrD;;;;GAIG;AACH,eAAO,MAAM,eAAe,iEAY1B,CAAC"}
1
+ {"version":3,"file":"JsTsFileHeaders.d.ts","sourceRoot":"","sources":["../../src/policies/JsTsFileHeaders.ts"],"names":[],"mappings":"AACA,OAAO,EAEN,KAAK,sBAAsB,EAC3B,MAAM,6CAA6C,CAAC;AAkBrD;;;;GAIG;AACH,eAAO,MAAM,eAAe,4DAY1B,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Configuration for the MutuallyExclusiveScripts policy.
3
+ *
4
+ * @alpha
5
+ */
6
+ export interface MutuallyExclusiveScriptsConfig {
7
+ /**
8
+ * List of mutually exclusive script groups. Each group is an array of script names
9
+ * where at most one script from the group can be present.
10
+ *
11
+ * Packages can have zero scripts from the group (all optional), but cannot have
12
+ * multiple scripts from the same group.
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // Allow "test:unit" OR "test:vitest" OR neither, but not both
17
+ * groups: [["test:unit", "test:vitest"]]
18
+ * ```
19
+ */
20
+ groups: string[][];
21
+ }
22
+ /**
23
+ * A policy that validates mutually exclusive script groups in package.json.
24
+ *
25
+ * @remarks
26
+ * Use this policy when you want to enforce that only one script from a group
27
+ * can exist in a package. This is useful for ensuring that packages don't have
28
+ * conflicting scripts (e.g., both "lint:eslint" and "lint:biome").
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * import { policy } from "repopo";
33
+ * import { MutuallyExclusiveScripts } from "repopo/policies";
34
+ *
35
+ * policy(MutuallyExclusiveScripts, {
36
+ * groups: [
37
+ * ["lint:eslint", "lint:biome"],
38
+ * ["test:jest", "test:vitest"],
39
+ * ],
40
+ * })
41
+ * ```
42
+ *
43
+ * @alpha
44
+ */
45
+ export declare const MutuallyExclusiveScripts: import("../policy.js").PolicyShape<MutuallyExclusiveScriptsConfig | undefined>;
46
+ //# sourceMappingURL=MutuallyExclusiveScripts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MutuallyExclusiveScripts.d.ts","sourceRoot":"","sources":["../../src/policies/MutuallyExclusiveScripts.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,MAAM,WAAW,8BAA8B;IAC9C;;;;;;;;;;;;OAYG;IACH,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC;CACnB;AAID;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,wBAAwB,gFAsCnC,CAAC"}
@@ -0,0 +1,52 @@
1
+ import { definePackagePolicy } from "../policyDefiners/definePackagePolicy.js";
2
+ const POLICY_NAME = "MutuallyExclusiveScripts";
3
+ /**
4
+ * A policy that validates mutually exclusive script groups in package.json.
5
+ *
6
+ * @remarks
7
+ * Use this policy when you want to enforce that only one script from a group
8
+ * can exist in a package. This is useful for ensuring that packages don't have
9
+ * conflicting scripts (e.g., both "lint:eslint" and "lint:biome").
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * import { policy } from "repopo";
14
+ * import { MutuallyExclusiveScripts } from "repopo/policies";
15
+ *
16
+ * policy(MutuallyExclusiveScripts, {
17
+ * groups: [
18
+ * ["lint:eslint", "lint:biome"],
19
+ * ["test:jest", "test:vitest"],
20
+ * ],
21
+ * })
22
+ * ```
23
+ *
24
+ * @alpha
25
+ */
26
+ export const MutuallyExclusiveScripts = definePackagePolicy({
27
+ name: POLICY_NAME,
28
+ description: "Validates that at most one script from each exclusive group exists in package.json.",
29
+ handler: async (json, { file, config }) => {
30
+ if (config === undefined || config.groups.length === 0) {
31
+ return true;
32
+ }
33
+ const scripts = json.scripts ?? {};
34
+ const errors = [];
35
+ for (const group of config.groups) {
36
+ const presentScripts = group.filter((scriptName) => Object.hasOwn(scripts, scriptName));
37
+ if (presentScripts.length > 1) {
38
+ errors.push(`Scripts are mutually exclusive, but found ${presentScripts.length}: ${presentScripts.join(", ")}`);
39
+ }
40
+ }
41
+ if (errors.length === 0) {
42
+ return true;
43
+ }
44
+ return {
45
+ name: POLICY_NAME,
46
+ file,
47
+ autoFixable: false,
48
+ errorMessages: errors,
49
+ };
50
+ },
51
+ });
52
+ //# sourceMappingURL=MutuallyExclusiveScripts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MutuallyExclusiveScripts.js","sourceRoot":"","sources":["../../src/policies/MutuallyExclusiveScripts.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0CAA0C,CAAC;AAwB/E,MAAM,WAAW,GAAG,0BAA0B,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,mBAAmB,CAGzD;IACD,IAAI,EAAE,WAAW;IACjB,WAAW,EACV,qFAAqF;IACtF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QACzC,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACxD,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;QACnC,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAClD,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,CAClC,CAAC;YAEF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CACV,6CAA6C,cAAc,CAAC,MAAM,KAAK,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAClG,CAAC;YACH,CAAC;QACF,CAAC;QAED,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,OAAO;YACN,IAAI,EAAE,WAAW;YACjB,IAAI;YACJ,WAAW,EAAE,KAAK;YAClB,aAAa,EAAE,MAAM;SACrB,CAAC;IACH,CAAC;CACD,CAAC,CAAC","sourcesContent":["import type { PackageJson } from \"type-fest\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * Configuration for the MutuallyExclusiveScripts policy.\n *\n * @alpha\n */\nexport interface MutuallyExclusiveScriptsConfig {\n\t/**\n\t * List of mutually exclusive script groups. Each group is an array of script names\n\t * where at most one script from the group can be present.\n\t *\n\t * Packages can have zero scripts from the group (all optional), but cannot have\n\t * multiple scripts from the same group.\n\t *\n\t * @example\n\t * ```typescript\n\t * // Allow \"test:unit\" OR \"test:vitest\" OR neither, but not both\n\t * groups: [[\"test:unit\", \"test:vitest\"]]\n\t * ```\n\t */\n\tgroups: string[][];\n}\n\nconst POLICY_NAME = \"MutuallyExclusiveScripts\";\n\n/**\n * A policy that validates mutually exclusive script groups in package.json.\n *\n * @remarks\n * Use this policy when you want to enforce that only one script from a group\n * can exist in a package. This is useful for ensuring that packages don't have\n * conflicting scripts (e.g., both \"lint:eslint\" and \"lint:biome\").\n *\n * @example\n * ```typescript\n * import { policy } from \"repopo\";\n * import { MutuallyExclusiveScripts } from \"repopo/policies\";\n *\n * policy(MutuallyExclusiveScripts, {\n * groups: [\n * [\"lint:eslint\", \"lint:biome\"],\n * [\"test:jest\", \"test:vitest\"],\n * ],\n * })\n * ```\n *\n * @alpha\n */\nexport const MutuallyExclusiveScripts = definePackagePolicy<\n\tPackageJson,\n\tMutuallyExclusiveScriptsConfig | undefined\n>({\n\tname: POLICY_NAME,\n\tdescription:\n\t\t\"Validates that at most one script from each exclusive group exists in package.json.\",\n\thandler: async (json, { file, config }) => {\n\t\tif (config === undefined || config.groups.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst scripts = json.scripts ?? {};\n\t\tconst errors: string[] = [];\n\n\t\tfor (const group of config.groups) {\n\t\t\tconst presentScripts = group.filter((scriptName) =>\n\t\t\t\tObject.hasOwn(scripts, scriptName),\n\t\t\t);\n\n\t\t\tif (presentScripts.length > 1) {\n\t\t\t\terrors.push(\n\t\t\t\t\t`Scripts are mutually exclusive, but found ${presentScripts.length}: ${presentScripts.join(\", \")}`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\tif (errors.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\treturn {\n\t\t\tname: POLICY_NAME,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages: errors,\n\t\t};\n\t},\n});\n"]}
@@ -33,5 +33,5 @@ export interface NoPrivateWorkspaceDependenciesSettings {
33
33
  * });
34
34
  * ```
35
35
  */
36
- export declare const NoPrivateWorkspaceDependencies: import("../policy.js").PolicyDefinition<NoPrivateWorkspaceDependenciesSettings | undefined>;
36
+ export declare const NoPrivateWorkspaceDependencies: import("../policy.js").PolicyShape<NoPrivateWorkspaceDependenciesSettings | undefined>;
37
37
  //# sourceMappingURL=NoPrivateWorkspaceDependencies.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NoPrivateWorkspaceDependencies.d.ts","sourceRoot":"","sources":["../../src/policies/NoPrivateWorkspaceDependencies.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,WAAW,sCAAsC;IACtD;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA6ED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,8BAA8B,6FAyEzC,CAAC"}
1
+ {"version":3,"file":"NoPrivateWorkspaceDependencies.d.ts","sourceRoot":"","sources":["../../src/policies/NoPrivateWorkspaceDependencies.ts"],"names":[],"mappings":"AAYA;;GAEG;AACH,MAAM,WAAW,sCAAsC;IACtD;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA6ED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,8BAA8B,wFAyEzC,CAAC"}
@@ -84,5 +84,5 @@ export interface PackageAllowedScopesConfig {
84
84
  *
85
85
  * @alpha
86
86
  */
87
- export declare const PackageAllowedScopes: import("../policy.js").PolicyDefinition<PackageAllowedScopesConfig | undefined>;
87
+ export declare const PackageAllowedScopes: import("../policy.js").PolicyShape<PackageAllowedScopesConfig | undefined>;
88
88
  //# sourceMappingURL=PackageAllowedScopes.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageAllowedScopes.d.ts","sourceRoot":"","sources":["../../src/policies/PackageAllowedScopes.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAiDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,oBAAoB,iFAuD/B,CAAC"}
1
+ {"version":3,"file":"PackageAllowedScopes.d.ts","sourceRoot":"","sources":["../../src/policies/PackageAllowedScopes.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;;;;;;;;;;;;;;OAeG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAiDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,eAAO,MAAM,oBAAoB,4EAuD/B,CAAC"}
@@ -96,5 +96,5 @@ export interface PackageEsmTypeConfig {
96
96
  *
97
97
  * @alpha
98
98
  */
99
- export declare const PackageEsmType: import("../policy.js").PolicyDefinition<PackageEsmTypeConfig | undefined>;
99
+ export declare const PackageEsmType: import("../policy.js").PolicyShape<PackageEsmTypeConfig | undefined>;
100
100
  //# sourceMappingURL=PackageEsmType.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageEsmType.d.ts","sourceRoot":"","sources":["../../src/policies/PackageEsmType.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAErC;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAC9C;AAyPD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,cAAc,2EAgEzB,CAAC"}
1
+ {"version":3,"file":"PackageEsmType.d.ts","sourceRoot":"","sources":["../../src/policies/PackageEsmType.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,oBAAoB;IACpC;;;;;;;;;;;OAWG;IACH,YAAY,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAC;IAErC;;;;;;;;;;OAUG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAE5B;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAE3B;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CAC9C;AAyPD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,cAAc,sEAgEzB,CAAC"}
@@ -93,5 +93,5 @@ export interface PackageFolderNameConfig {
93
93
  *
94
94
  * @alpha
95
95
  */
96
- export declare const PackageFolderName: import("../policy.js").PolicyDefinition<PackageFolderNameConfig | undefined>;
96
+ export declare const PackageFolderName: import("../policy.js").PolicyShape<PackageFolderNameConfig | undefined>;
97
97
  //# sourceMappingURL=PackageFolderName.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PackageFolderName.d.ts","sourceRoot":"","sources":["../../src/policies/PackageFolderName.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,uBAAuB;IACvC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAuCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,iBAAiB,8EAqD5B,CAAC"}
1
+ {"version":3,"file":"PackageFolderName.d.ts","sourceRoot":"","sources":["../../src/policies/PackageFolderName.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,uBAAuB;IACvC;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IAEvB;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAuCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,iBAAiB,yEAqD5B,CAAC"}