repopo 0.7.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +171 -6
- package/THIRD-PARTY-LICENSES.txt +149 -3
- package/esm/adapters/fluidFramework.d.ts +103 -0
- package/esm/adapters/fluidFramework.d.ts.map +1 -0
- package/esm/adapters/fluidFramework.js +119 -0
- package/esm/adapters/fluidFramework.js.map +1 -0
- package/esm/baseCommand.d.ts +1 -0
- package/esm/baseCommand.d.ts.map +1 -1
- package/esm/baseCommand.js +2 -1
- package/esm/baseCommand.js.map +1 -1
- package/esm/commands/check.d.ts.map +1 -1
- package/esm/commands/check.js +9 -8
- package/esm/commands/check.js.map +1 -1
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/index.js.map +1 -1
- package/esm/perf.d.ts +4 -1
- package/esm/perf.d.ts.map +1 -1
- package/esm/perf.js +3 -2
- package/esm/perf.js.map +1 -1
- package/esm/policies/LicenseFileExists.d.ts.map +1 -1
- package/esm/policies/LicenseFileExists.js +3 -1
- package/esm/policies/LicenseFileExists.js.map +1 -1
- package/esm/policies/NoJsFileExtensions.d.ts.map +1 -1
- package/esm/policies/NoJsFileExtensions.js +4 -1
- package/esm/policies/NoJsFileExtensions.js.map +1 -1
- package/esm/policies/NoLargeBinaryFiles.d.ts.map +1 -1
- package/esm/policies/NoLargeBinaryFiles.js +3 -1
- package/esm/policies/NoLargeBinaryFiles.js.map +1 -1
- package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +37 -0
- package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -0
- package/esm/policies/NoPrivateWorkspaceDependencies.js +137 -0
- package/esm/policies/NoPrivateWorkspaceDependencies.js.map +1 -0
- package/esm/policies/PackageAllowedScopes.d.ts +88 -0
- package/esm/policies/PackageAllowedScopes.d.ts.map +1 -0
- package/esm/policies/PackageAllowedScopes.js +113 -0
- package/esm/policies/PackageAllowedScopes.js.map +1 -0
- package/esm/policies/PackageEsmType.d.ts +100 -0
- package/esm/policies/PackageEsmType.d.ts.map +1 -0
- package/esm/policies/PackageEsmType.js +257 -0
- package/esm/policies/PackageEsmType.js.map +1 -0
- package/esm/policies/PackageFolderName.d.ts +97 -0
- package/esm/policies/PackageFolderName.d.ts.map +1 -0
- package/esm/policies/PackageFolderName.js +104 -0
- package/esm/policies/PackageFolderName.js.map +1 -0
- package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
- package/esm/policies/PackageJsonProperties.js +2 -1
- package/esm/policies/PackageJsonProperties.js.map +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.js +4 -3
- package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
- package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
- package/esm/policies/PackageJsonSorted.js +11 -3
- package/esm/policies/PackageJsonSorted.js.map +1 -1
- package/esm/policies/PackageLicense.d.ts +61 -0
- package/esm/policies/PackageLicense.d.ts.map +1 -0
- package/esm/policies/PackageLicense.js +131 -0
- package/esm/policies/PackageLicense.js.map +1 -0
- package/esm/policies/PackagePrivateField.d.ts +124 -0
- package/esm/policies/PackagePrivateField.d.ts.map +1 -0
- package/esm/policies/PackagePrivateField.js +155 -0
- package/esm/policies/PackagePrivateField.js.map +1 -0
- package/esm/policies/PackageReadme.d.ts +77 -0
- package/esm/policies/PackageReadme.d.ts.map +1 -0
- package/esm/policies/PackageReadme.js +209 -0
- package/esm/policies/PackageReadme.js.map +1 -0
- package/esm/policies/PackageScripts.d.ts +180 -2
- package/esm/policies/PackageScripts.d.ts.map +1 -1
- package/esm/policies/PackageScripts.js +349 -29
- package/esm/policies/PackageScripts.js.map +1 -1
- package/esm/policies/PackageTestScripts.d.ts +100 -0
- package/esm/policies/PackageTestScripts.d.ts.map +1 -0
- package/esm/policies/PackageTestScripts.js +149 -0
- package/esm/policies/PackageTestScripts.js.map +1 -0
- package/esm/policies/RequiredGitignorePatterns.d.ts.map +1 -1
- package/esm/policies/RequiredGitignorePatterns.js +10 -4
- package/esm/policies/RequiredGitignorePatterns.js.map +1 -1
- package/esm/policies.d.ts +9 -1
- package/esm/policies.d.ts.map +1 -1
- package/esm/policies.js +10 -1
- package/esm/policies.js.map +1 -1
- package/esm/policy.d.ts +5 -1
- package/esm/policy.d.ts.map +1 -1
- package/esm/policy.js.map +1 -1
- package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
- package/esm/policyDefiners/defineFileHeaderPolicy.js +2 -1
- package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
- package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
- package/esm/policyDefiners/definePackagePolicy.js +2 -1
- package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
- package/esm/tsdoc-metadata.json +1 -1
- package/esm/utils/indentation.d.ts +73 -0
- package/esm/utils/indentation.d.ts.map +1 -0
- package/esm/utils/indentation.js +97 -0
- package/esm/utils/indentation.js.map +1 -0
- package/esm/utils/packageName.d.ts +71 -0
- package/esm/utils/packageName.d.ts.map +1 -0
- package/esm/utils/packageName.js +79 -0
- package/esm/utils/packageName.js.map +1 -0
- package/oclif.manifest.json +1 -1
- package/package.json +30 -15
package/esm/baseCommand.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CommandWithConfig, } from "@tylerbu/cli-api";
|
|
1
|
+
import { CommandWithConfig, createConsolaLogger, } from "@tylerbu/cli-api";
|
|
2
2
|
import { findGitRootSync } from "@tylerbu/fundamentals/git";
|
|
3
3
|
import { simpleGit } from "simple-git";
|
|
4
4
|
import { DefaultPolicyConfig } from "./config.js";
|
|
@@ -10,6 +10,7 @@ import { DefaultPolicies } from "./policy.js";
|
|
|
10
10
|
*/
|
|
11
11
|
export class BaseRepopoCommand extends CommandWithConfig {
|
|
12
12
|
defaultConfig = DefaultPolicyConfig;
|
|
13
|
+
_logger = createConsolaLogger();
|
|
13
14
|
static flags = {
|
|
14
15
|
...CommandWithConfig.flags,
|
|
15
16
|
};
|
package/esm/baseCommand.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseCommand.js","sourceRoot":"","sources":["../src/baseCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,iBAAiB,
|
|
1
|
+
{"version":3,"file":"baseCommand.js","sourceRoot":"","sources":["../src/baseCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,iBAAiB,EAEjB,mBAAmB,GAEnB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAkB,SAAS,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,mBAAmB,EAAqB,MAAM,aAAa,CAAC;AAErE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;GAEG;AACH,MAAM,OAAgB,iBAMrB,SAAQ,iBAAkC;IAGvB,aAAa,GAAG,mBAAmB,CAAC;IACpC,OAAO,GAAG,mBAAmB,EAAE,CAAC;IAE5C,MAAM,CAAmB,KAAK,GAAG;QACvC,GAAG,iBAAiB,CAAC,KAAK;KACjB,CAAC;IAEH,IAAI,CAAwB;IACpC,IAAW,GAAG;QACb,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IAClB,CAAC;IAEe,KAAK,CAAC,IAAI;QACzB,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QAEnB,MAAM,YAAY,GACjB,IAAI,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAExE,MAAM,uBAAuB,GAA0B,IAAI,GAAG,EAAE,CAAC;QACjE,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,aAAa,EAAE,QAAQ,IAAI,EAAE,EAAE,CAAC;YACzD,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1E,uBAAuB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,OAAO,GAAG,eAAe,EAAE,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,SAAS,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,GAAG;YACf,cAAc,EAAE,YAAY;YAC5B,QAAQ,EACP,IAAI,CAAC,aAAa,EAAE,QAAQ;gBAC5B,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;YAC1C,uBAAuB;YACvB,OAAO;YACP,SAAS,EAAE,YAAY,EAAE;SACzB,CAAC;IACH,CAAC;IAEO,QAAQ,CAAmC;IAE5C,KAAK,CAAC,UAAU;QACtB,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC","sourcesContent":["import {\n\tCommandWithConfig,\n\ttype CommandWithContext,\n\tcreateConsolaLogger,\n\ttype RequiresGit,\n} from \"@tylerbu/cli-api\";\nimport { findGitRootSync } from \"@tylerbu/fundamentals/git\";\nimport { type SimpleGit, simpleGit } from \"simple-git\";\nimport { DefaultPolicyConfig, type RepopoConfig } from \"./config.js\";\nimport type { ExcludedPolicyFileMap, RepopoCommandContext } from \"./context.js\";\nimport { makePolicy } from \"./makePolicy.js\";\nimport { newPerfStats } from \"./perf.js\";\nimport { DefaultPolicies } from \"./policy.js\";\n\n/**\n * This class is the base for all repopo commands. It contains common flags and config loading.\n */\nexport abstract class BaseRepopoCommand<\n\t\tT extends typeof BaseRepopoCommand & {\n\t\t\targs: typeof CommandWithConfig.args;\n\t\t\tflags: typeof CommandWithConfig.flags;\n\t\t},\n\t>\n\textends CommandWithConfig<T, RepopoConfig>\n\timplements CommandWithContext<RepopoCommandContext>, RequiresGit\n{\n\tprotected override defaultConfig = DefaultPolicyConfig;\n\tprotected override _logger = createConsolaLogger();\n\n\tpublic static override readonly flags = {\n\t\t...CommandWithConfig.flags,\n\t} as const;\n\n\tprivate _git: SimpleGit | undefined;\n\tpublic get git(): SimpleGit {\n\t\tif (this._git === undefined) {\n\t\t\tthrow new Error(\"git property is undefined\");\n\t\t}\n\t\treturn this._git;\n\t}\n\n\tpublic override async init(): Promise<void> {\n\t\tawait super.init();\n\n\t\tconst excludeFiles: RegExp[] =\n\t\t\tthis.commandConfig?.excludeFiles?.map((e) => new RegExp(e, \"i\")) ?? [];\n\n\t\tconst excludePoliciesForFiles: ExcludedPolicyFileMap = new Map();\n\t\tfor (const policy of this.commandConfig?.policies ?? []) {\n\t\t\tconst regexes = policy.excludeFiles?.map((e) => new RegExp(e, \"i\")) ?? [];\n\t\t\texcludePoliciesForFiles.set(policy.name, regexes);\n\t\t}\n\n\t\tconst gitRoot = findGitRootSync();\n\t\tthis._git = simpleGit({ baseDir: gitRoot });\n\t\tthis._context = {\n\t\t\texcludeFromAll: excludeFiles,\n\t\t\tpolicies:\n\t\t\t\tthis.commandConfig?.policies ??\n\t\t\t\tDefaultPolicies.map((p) => makePolicy(p)),\n\t\t\texcludePoliciesForFiles,\n\t\t\tgitRoot,\n\t\t\tperfStats: newPerfStats(),\n\t\t};\n\t}\n\n\tprivate _context: RepopoCommandContext | undefined;\n\n\tpublic async getContext(): Promise<RepopoCommandContext> {\n\t\tif (this._context === undefined) {\n\t\t\tthrow new Error(\"Context not initialized.\");\n\t\t}\n\t\treturn this._context;\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAgCtD;;;;;;;;GAQG;AACH,qBAAa,WAAW,CACvB,CAAC,SAAS,OAAO,iBAAiB,GAAG;IACpC,IAAI,EAAE,OAAO,WAAW,CAAC,IAAI,CAAC;IAC9B,KAAK,EAAE,OAAO,WAAW,CAAC,KAAK,CAAC;CAChC,CACA,SAAQ,iBAAiB,CAAC,CAAC,CAAC;IAC7B,gBAAgC,OAAO,iEACwB;IAE/D,gBAAgC,KAAK;;;;MAY1B;IAEW,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAwD1C;;;;;OAKG;YACW,aAAa;IAe3B;;;;;OAKG;YACW,kBAAkB;YAmBlB,eAAe;YAsCf,eAAe;IAwC7B,OAAO,CAAC,gBAAgB;YAYV,oBAAoB;
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAgCtD;;;;;;;;GAQG;AACH,qBAAa,WAAW,CACvB,CAAC,SAAS,OAAO,iBAAiB,GAAG;IACpC,IAAI,EAAE,OAAO,WAAW,CAAC,IAAI,CAAC;IAC9B,KAAK,EAAE,OAAO,WAAW,CAAC,KAAK,CAAC;CAChC,CACA,SAAQ,iBAAiB,CAAC,CAAC,CAAC;IAC7B,gBAAgC,OAAO,iEACwB;IAE/D,gBAAgC,KAAK;;;;MAY1B;IAEW,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAwD1C;;;;;OAKG;YACW,aAAa;IAe3B;;;;;OAKG;YACW,kBAAkB;YAmBlB,eAAe;YAsCf,eAAe;IAwC7B,OAAO,CAAC,gBAAgB;YAYV,oBAAoB;YAuBpB,kBAAkB;IAwBhC,OAAO,CAAC,eAAe;YAoBT,mBAAmB;YAyBnB,iBAAiB;IAyB/B,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,WAAW;CAOnB"}
|
package/esm/commands/check.js
CHANGED
|
@@ -98,7 +98,7 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
98
98
|
}
|
|
99
99
|
finally {
|
|
100
100
|
if (!this.flags.quiet) {
|
|
101
|
-
logStats(context.perfStats, this);
|
|
101
|
+
logStats(context.perfStats, this.logger);
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
}
|
|
@@ -160,7 +160,7 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
160
160
|
}
|
|
161
161
|
catch (error) {
|
|
162
162
|
// Log and rethrow the error for higher-level handling
|
|
163
|
-
this.
|
|
163
|
+
this.exit(`Error executing policy '${policy.name}' for file '${relPath}': ${error}`);
|
|
164
164
|
}
|
|
165
165
|
return true; // Policy ran (successfully or with error)
|
|
166
166
|
}
|
|
@@ -171,7 +171,8 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
171
171
|
}
|
|
172
172
|
async executePolicyHandler(relPath, policy, perfStats, gitRoot) {
|
|
173
173
|
try {
|
|
174
|
-
|
|
174
|
+
const action = this.flags.fix ? "resolve" : "check";
|
|
175
|
+
return await runWithPerf(policy.name, action, perfStats, () => policy.handler({
|
|
175
176
|
file: relPath,
|
|
176
177
|
root: gitRoot,
|
|
177
178
|
resolve: this.flags.fix,
|
|
@@ -179,7 +180,7 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
179
180
|
}));
|
|
180
181
|
}
|
|
181
182
|
catch (error) {
|
|
182
|
-
this.
|
|
183
|
+
this.exit(`Error in policy handler '${policy.name}' for file '${relPath}': ${error}`);
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
186
|
async handlePolicyResult(result, relPath, policy, perfStats, gitRoot) {
|
|
@@ -220,15 +221,15 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
220
221
|
if (!resolveResult.resolved) {
|
|
221
222
|
process.exitCode = 1;
|
|
222
223
|
}
|
|
223
|
-
if (resolveResult.
|
|
224
|
-
messages.append(newline + resolveResult.
|
|
224
|
+
if (resolveResult.errorMessages?.length > 0) {
|
|
225
|
+
messages.append(newline + resolveResult.errorMessages.join(newline));
|
|
225
226
|
}
|
|
226
227
|
}
|
|
227
228
|
logPolicyFailure(result, policy, messages) {
|
|
228
229
|
const autoFixable = result.autoFixable ? chalk.green(" (autofixable)") : "";
|
|
229
230
|
messages.append(`'${chalk.bold(policy.name)}' policy failure${autoFixable}: ${result.file}`);
|
|
230
|
-
if (result.
|
|
231
|
-
messages.append(`${newline}\t${result.
|
|
231
|
+
if (result.errorMessages?.length > 0) {
|
|
232
|
+
messages.append(`${newline}\t${result.errorMessages.join(`${newline}\t`)}`);
|
|
232
233
|
}
|
|
233
234
|
process.exitCode = 1;
|
|
234
235
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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","sourcesContent":["import { EOL as newline } from \"node:os\";\nimport process from \"node:process\";\nimport { Flags } from \"@oclif/core\";\nimport { StringBuilder } from \"@rushstack/node-core-library\";\nimport chalk from \"picocolors\";\nimport { BaseRepopoCommand } from \"../baseCommand.js\";\nimport type { RepopoCommandContext } from \"../context.js\";\nimport { logStats, type PolicyHandlerPerfStats, runWithPerf } from \"../perf.js\";\nimport {\n\tisPolicyFixResult,\n\ttype PolicyFailure,\n\ttype PolicyFixResult,\n\ttype PolicyHandlerResult,\n\ttype PolicyInstance,\n\ttype PolicyStandaloneResolver,\n} from \"../policy.js\";\n\nasync function readStdin(): Promise<string> {\n\treturn new Promise((resolve) => {\n\t\tconst stdin = process.stdin;\n\t\tstdin.setEncoding(\"utf8\");\n\n\t\tlet data = \"\";\n\t\tstdin.on(\"data\", (chunk) => {\n\t\t\tdata += chunk;\n\t\t});\n\n\t\tstdin.on(\"end\", () => {\n\t\t\tresolve(data);\n\t\t});\n\n\t\tif (stdin.isTTY) {\n\t\t\tresolve(\"\");\n\t\t}\n\t});\n}\n\n/**\n * This tool enforces policies across the code base via a series of handler functions. The handler functions are\n * associated with a regular expression, and all files matching that expression are passed to the handler function.\n *\n * By default, the list of files to check comes from `git ls-files. You can also pipe in file names from stdin. For\n * example:\n *\n * `git ls-files -co --exclude-standard --full-name | repopo check --stdin --verbose`\n */\nexport class CheckPolicy<\n\tT extends typeof BaseRepopoCommand & {\n\t\targs: typeof CheckPolicy.args;\n\t\tflags: typeof CheckPolicy.flags;\n\t},\n> extends BaseRepopoCommand<T> {\n\tpublic static override readonly summary =\n\t\t\"Checks and applies policies to the files in the repository.\";\n\n\tpublic static override readonly flags = {\n\t\tfix: Flags.boolean({\n\t\t\taliases: [\"resolve\"],\n\t\t\tdescription: \"Fix errors if possible.\",\n\t\t\trequired: false,\n\t\t\tchar: \"f\",\n\t\t}),\n\t\tstdin: Flags.boolean({\n\t\t\tdescription: \"Read list of files from stdin.\",\n\t\t\trequired: false,\n\t\t}),\n\t\t...BaseRepopoCommand.flags,\n\t} as const;\n\n\tpublic override async run(): Promise<void> {\n\t\tif (this.flags.fix) {\n\t\t\tthis.info(\"Resolving errors if possible.\");\n\t\t}\n\n\t\tconst config = this.commandConfig;\n\t\tconst policies = config?.policies ?? [];\n\t\tthis.verbose(`${policies.length} policies loaded.`);\n\t\tfor (const h of policies) {\n\t\t\tthis.verbose(h.name);\n\t\t}\n\n\t\tconst filePathsToCheck: string[] = [];\n\n\t\tif (this.flags.stdin) {\n\t\t\tconst stdInput = await readStdin();\n\n\t\t\tif (stdInput !== undefined) {\n\t\t\t\tfilePathsToCheck.push(\n\t\t\t\t\t...stdInput\n\t\t\t\t\t\t.replace(\n\t\t\t\t\t\t\t// normalize slashes in case they're windows paths\n\t\t\t\t\t\t\t/\\\\/g,\n\t\t\t\t\t\t\t\"/\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.split(\"\\n\"),\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tconst gitFiles =\n\t\t\t\t(await this.git.raw(\n\t\t\t\t\t\"ls-files\",\n\t\t\t\t\t// include staged files and untracked files\n\t\t\t\t\t\"-co\",\n\t\t\t\t\t// exclude gitignored files and other standard ignore rules\n\t\t\t\t\t\"--exclude-standard\",\n\t\t\t\t\t// Outputs paths relative to the root of the repository, regardless of the current working directory.\n\t\t\t\t\t\"--full-name\",\n\t\t\t\t)) ?? \"\";\n\n\t\t\tfilePathsToCheck.push(\n\t\t\t\t...gitFiles\n\t\t\t\t\t.replace(\n\t\t\t\t\t\t// normalize slashes in case they're windows paths\n\t\t\t\t\t\t/\\\\/g,\n\t\t\t\t\t\t\"/\",\n\t\t\t\t\t)\n\t\t\t\t\t.split(\"\\n\"),\n\t\t\t);\n\t\t}\n\n\t\tconst context: RepopoCommandContext = await this.getContext();\n\n\t\tawait this.checkAllFiles(filePathsToCheck, context);\n\t}\n\n\t/**\n\t * Executes all policies against the provided paths.\n\t *\n\t * @param pathsToCheck - All paths that should be checked. Paths should be relative to the repository root.\n\t * @param context - The context.\n\t */\n\tprivate async checkAllFiles(\n\t\tpathsToCheck: string[],\n\t\tcontext: RepopoCommandContext,\n\t): Promise<void> {\n\t\ttry {\n\t\t\tfor (const pathToCheck of pathsToCheck) {\n\t\t\t\tawait this.checkOrExcludeFile(pathToCheck, context);\n\t\t\t}\n\t\t} finally {\n\t\t\tif (!this.flags.quiet) {\n\t\t\t\tlogStats(context.perfStats, this);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Given a string that represents a path to a file in the repo, determines if the file should be checked, and if so,\n\t * routes the file to the appropriate handlers.\n\t *\n\t * @param relPath - A git repo-relative path to a file.\n\t */\n\tprivate async checkOrExcludeFile(\n\t\trelPath: string,\n\t\tcontext: RepopoCommandContext,\n\t): Promise<void> {\n\t\tconst { perfStats } = context;\n\t\tperfStats.count++;\n\n\t\ttry {\n\t\t\tconst wasProcessed = await this.routeToPolicies(relPath, context);\n\t\t\tif (wasProcessed) {\n\t\t\t\tperfStats.processed++;\n\t\t\t}\n\t\t} catch (error: unknown) {\n\t\t\tthrow new Error(\n\t\t\t\t`Error routing ${relPath} to handler: ${error}\\nStack:\\n${(error as Error).stack}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async routeToPolicies(\n\t\trelPath: string,\n\t\tcontext: RepopoCommandContext,\n\t): Promise<boolean> {\n\t\tconst { policies, excludeFromAll } = context;\n\n\t\t// Check exclusions\n\t\tif (excludeFromAll.some((regex) => regex.test(relPath))) {\n\t\t\tthis.verbose(`Excluded all handlers: ${relPath}`);\n\t\t\treturn false; // File was excluded from all policies\n\t\t}\n\n\t\t// Run all matching policies\n\t\tconst matchingPolicies = policies.filter((policy) =>\n\t\t\tpolicy.match.test(relPath),\n\t\t);\n\n\t\t// for(const policy of matchingPolicies) {\n\t\t// \tbars.addFile(policy.name,\n\t\t// }\n\n\t\t// If no policies match this file, it's still considered processed\n\t\t// (we examined it and determined no policies apply)\n\t\tif (matchingPolicies.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst results = await Promise.all(\n\t\t\tmatchingPolicies.map(async (policy) => {\n\t\t\t\treturn await this.runPolicyOnFile(relPath, policy, context);\n\t\t\t}),\n\t\t);\n\n\t\t// File is considered processed if at least one policy ran on it\n\t\t// If all matching policies excluded it, count as excluded\n\t\treturn results.some((ran) => ran);\n\t}\n\n\tprivate async runPolicyOnFile(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tcontext: RepopoCommandContext,\n\t): Promise<boolean> {\n\t\tconst { excludePoliciesForFiles, perfStats, gitRoot } = context;\n\n\t\t// Check if the policy is excluded for the file\n\t\tif (this.isPolicyExcluded(relPath, policy, excludePoliciesForFiles)) {\n\t\t\tthis.verbose(`Excluded from '${policy.name}' policy: ${relPath}`);\n\t\t\treturn false; // Policy didn't run on this file\n\t\t}\n\n\t\ttry {\n\t\t\t// Execute the policy handler\n\t\t\tconst result = await this.executePolicyHandler(\n\t\t\t\trelPath,\n\t\t\t\tpolicy,\n\t\t\t\tperfStats,\n\t\t\t\tgitRoot,\n\t\t\t);\n\n\t\t\t// Handle the result of the policy execution\n\t\t\tawait this.handlePolicyResult(\n\t\t\t\tresult,\n\t\t\t\trelPath,\n\t\t\t\tpolicy,\n\t\t\t\tperfStats,\n\t\t\t\tgitRoot,\n\t\t\t);\n\t\t} catch (error: unknown) {\n\t\t\t// Log and rethrow the error for higher-level handling\n\t\t\tthis.error(\n\t\t\t\t`Error executing policy '${policy.name}' for file '${relPath}': ${error}`,\n\t\t\t);\n\t\t}\n\n\t\treturn true; // Policy ran (successfully or with error)\n\t}\n\n\tprivate isPolicyExcluded(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\texcludePoliciesForFiles: Map<string, RegExp[]>,\n\t): boolean {\n\t\treturn (\n\t\t\texcludePoliciesForFiles\n\t\t\t\t.get(policy.name)\n\t\t\t\t?.some((regex) => regex.test(relPath)) ?? false\n\t\t);\n\t}\n\n\tprivate async executePolicyHandler(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t): Promise<PolicyHandlerResult> {\n\t\ttry {\n\t\t\treturn await runWithPerf(policy.name, \"handle\", perfStats, () =>\n\t\t\t\tpolicy.handler({\n\t\t\t\t\tfile: relPath,\n\t\t\t\t\troot: gitRoot,\n\t\t\t\t\tresolve: this.flags.fix,\n\t\t\t\t\tconfig: policy.config,\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (error: unknown) {\n\t\t\tthis.error(\n\t\t\t\t`Error in policy handler '${policy.name}' for file '${relPath}': ${error}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async handlePolicyResult(\n\t\tresult: PolicyHandlerResult,\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t): Promise<void> {\n\t\tif (result === true) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (isPolicyFixResult(result)) {\n\t\t\tthis.handleFixResult(result, policy);\n\t\t} else {\n\t\t\tawait this.handleFailureResult(\n\t\t\t\tresult,\n\t\t\t\trelPath,\n\t\t\t\tpolicy,\n\t\t\t\tperfStats,\n\t\t\t\tgitRoot,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate handleFixResult(\n\t\tresult: PolicyFixResult,\n\t\tpolicy: PolicyInstance,\n\t): void {\n\t\tconst messages = new StringBuilder();\n\n\t\tif (result.resolved) {\n\t\t\tmessages.append(\n\t\t\t\t`Resolved ${policy.name} policy failure for file: ${result.file}`,\n\t\t\t);\n\t\t} else {\n\t\t\tmessages.append(\n\t\t\t\t`Error fixing ${policy.name} policy failure in ${result.file}`,\n\t\t\t);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\n\t\tthis.logMessages(messages);\n\t}\n\n\tprivate async handleFailureResult(\n\t\tresult: PolicyFailure,\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t): Promise<void> {\n\t\tconst messages = new StringBuilder();\n\n\t\tif (this.flags.fix && policy.resolver) {\n\t\t\tawait this.attemptResolution(\n\t\t\t\trelPath,\n\t\t\t\tpolicy,\n\t\t\t\tpolicy.resolver,\n\t\t\t\tperfStats,\n\t\t\t\tgitRoot,\n\t\t\t\tmessages,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.logPolicyFailure(result, policy, messages);\n\t\t}\n\n\t\tthis.logMessages(messages);\n\t}\n\n\tprivate async attemptResolution(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tresolver: PolicyStandaloneResolver,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t\tmessages: StringBuilder,\n\t): Promise<void> {\n\t\tmessages.append(`${newline}Attempting to resolve: ${relPath}`);\n\t\tconst resolveResult = await runWithPerf(\n\t\t\tpolicy.name,\n\t\t\t\"resolve\",\n\t\t\tperfStats,\n\t\t\t() => resolver({ file: relPath, root: gitRoot }),\n\t\t);\n\n\t\tif (!resolveResult.resolved) {\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\n\t\tif (resolveResult.errorMessage) {\n\t\t\tmessages.append(newline + resolveResult.errorMessage);\n\t\t}\n\t}\n\n\tprivate logPolicyFailure(\n\t\tresult: PolicyFailure,\n\t\tpolicy: PolicyInstance,\n\t\tmessages: StringBuilder,\n\t): void {\n\t\tconst autoFixable = result.autoFixable ? chalk.green(\" (autofixable)\") : \"\";\n\t\tmessages.append(\n\t\t\t`'${chalk.bold(policy.name)}' policy failure${autoFixable}: ${result.file}`,\n\t\t);\n\t\tif (result.errorMessage) {\n\t\t\tmessages.append(`${newline}\\t${result.errorMessage}`);\n\t\t}\n\t\tprocess.exitCode = 1;\n\t}\n\tprivate logMessages(messages: StringBuilder): void {\n\t\tif ((process.exitCode ?? 0) === 0) {\n\t\t\tthis.info(messages.toString());\n\t\t} else {\n\t\t\tthis.warning(messages.toString());\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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","sourcesContent":["import { EOL as newline } from \"node:os\";\nimport process from \"node:process\";\nimport { Flags } from \"@oclif/core\";\nimport { StringBuilder } from \"@rushstack/node-core-library\";\nimport chalk from \"picocolors\";\nimport { BaseRepopoCommand } from \"../baseCommand.js\";\nimport type { RepopoCommandContext } from \"../context.js\";\nimport { logStats, type PolicyHandlerPerfStats, runWithPerf } from \"../perf.js\";\nimport {\n\tisPolicyFixResult,\n\ttype PolicyFailure,\n\ttype PolicyFixResult,\n\ttype PolicyHandlerResult,\n\ttype PolicyInstance,\n\ttype PolicyStandaloneResolver,\n} from \"../policy.js\";\n\nasync function readStdin(): Promise<string> {\n\treturn new Promise((resolve) => {\n\t\tconst stdin = process.stdin;\n\t\tstdin.setEncoding(\"utf8\");\n\n\t\tlet data = \"\";\n\t\tstdin.on(\"data\", (chunk) => {\n\t\t\tdata += chunk;\n\t\t});\n\n\t\tstdin.on(\"end\", () => {\n\t\t\tresolve(data);\n\t\t});\n\n\t\tif (stdin.isTTY) {\n\t\t\tresolve(\"\");\n\t\t}\n\t});\n}\n\n/**\n * This tool enforces policies across the code base via a series of handler functions. The handler functions are\n * associated with a regular expression, and all files matching that expression are passed to the handler function.\n *\n * By default, the list of files to check comes from `git ls-files. You can also pipe in file names from stdin. For\n * example:\n *\n * `git ls-files -co --exclude-standard --full-name | repopo check --stdin --verbose`\n */\nexport class CheckPolicy<\n\tT extends typeof BaseRepopoCommand & {\n\t\targs: typeof CheckPolicy.args;\n\t\tflags: typeof CheckPolicy.flags;\n\t},\n> extends BaseRepopoCommand<T> {\n\tpublic static override readonly summary =\n\t\t\"Checks and applies policies to the files in the repository.\";\n\n\tpublic static override readonly flags = {\n\t\tfix: Flags.boolean({\n\t\t\taliases: [\"resolve\"],\n\t\t\tdescription: \"Fix errors if possible.\",\n\t\t\trequired: false,\n\t\t\tchar: \"f\",\n\t\t}),\n\t\tstdin: Flags.boolean({\n\t\t\tdescription: \"Read list of files from stdin.\",\n\t\t\trequired: false,\n\t\t}),\n\t\t...BaseRepopoCommand.flags,\n\t} as const;\n\n\tpublic override async run(): Promise<void> {\n\t\tif (this.flags.fix) {\n\t\t\tthis.info(\"Resolving errors if possible.\");\n\t\t}\n\n\t\tconst config = this.commandConfig;\n\t\tconst policies = config?.policies ?? [];\n\t\tthis.verbose(`${policies.length} policies loaded.`);\n\t\tfor (const h of policies) {\n\t\t\tthis.verbose(h.name);\n\t\t}\n\n\t\tconst filePathsToCheck: string[] = [];\n\n\t\tif (this.flags.stdin) {\n\t\t\tconst stdInput = await readStdin();\n\n\t\t\tif (stdInput !== undefined) {\n\t\t\t\tfilePathsToCheck.push(\n\t\t\t\t\t...stdInput\n\t\t\t\t\t\t.replace(\n\t\t\t\t\t\t\t// normalize slashes in case they're windows paths\n\t\t\t\t\t\t\t/\\\\/g,\n\t\t\t\t\t\t\t\"/\",\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.split(\"\\n\"),\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tconst gitFiles =\n\t\t\t\t(await this.git.raw(\n\t\t\t\t\t\"ls-files\",\n\t\t\t\t\t// include staged files and untracked files\n\t\t\t\t\t\"-co\",\n\t\t\t\t\t// exclude gitignored files and other standard ignore rules\n\t\t\t\t\t\"--exclude-standard\",\n\t\t\t\t\t// Outputs paths relative to the root of the repository, regardless of the current working directory.\n\t\t\t\t\t\"--full-name\",\n\t\t\t\t)) ?? \"\";\n\n\t\t\tfilePathsToCheck.push(\n\t\t\t\t...gitFiles\n\t\t\t\t\t.replace(\n\t\t\t\t\t\t// normalize slashes in case they're windows paths\n\t\t\t\t\t\t/\\\\/g,\n\t\t\t\t\t\t\"/\",\n\t\t\t\t\t)\n\t\t\t\t\t.split(\"\\n\"),\n\t\t\t);\n\t\t}\n\n\t\tconst context: RepopoCommandContext = await this.getContext();\n\n\t\tawait this.checkAllFiles(filePathsToCheck, context);\n\t}\n\n\t/**\n\t * Executes all policies against the provided paths.\n\t *\n\t * @param pathsToCheck - All paths that should be checked. Paths should be relative to the repository root.\n\t * @param context - The context.\n\t */\n\tprivate async checkAllFiles(\n\t\tpathsToCheck: string[],\n\t\tcontext: RepopoCommandContext,\n\t): Promise<void> {\n\t\ttry {\n\t\t\tfor (const pathToCheck of pathsToCheck) {\n\t\t\t\tawait this.checkOrExcludeFile(pathToCheck, context);\n\t\t\t}\n\t\t} finally {\n\t\t\tif (!this.flags.quiet) {\n\t\t\t\tlogStats(context.perfStats, this.logger);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Given a string that represents a path to a file in the repo, determines if the file should be checked, and if so,\n\t * routes the file to the appropriate handlers.\n\t *\n\t * @param relPath - A git repo-relative path to a file.\n\t */\n\tprivate async checkOrExcludeFile(\n\t\trelPath: string,\n\t\tcontext: RepopoCommandContext,\n\t): Promise<void> {\n\t\tconst { perfStats } = context;\n\t\tperfStats.count++;\n\n\t\ttry {\n\t\t\tconst wasProcessed = await this.routeToPolicies(relPath, context);\n\t\t\tif (wasProcessed) {\n\t\t\t\tperfStats.processed++;\n\t\t\t}\n\t\t} catch (error: unknown) {\n\t\t\tthrow new Error(\n\t\t\t\t`Error routing ${relPath} to handler: ${error}\\nStack:\\n${(error as Error).stack}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async routeToPolicies(\n\t\trelPath: string,\n\t\tcontext: RepopoCommandContext,\n\t): Promise<boolean> {\n\t\tconst { policies, excludeFromAll } = context;\n\n\t\t// Check exclusions\n\t\tif (excludeFromAll.some((regex) => regex.test(relPath))) {\n\t\t\tthis.verbose(`Excluded all handlers: ${relPath}`);\n\t\t\treturn false; // File was excluded from all policies\n\t\t}\n\n\t\t// Run all matching policies\n\t\tconst matchingPolicies = policies.filter((policy) =>\n\t\t\tpolicy.match.test(relPath),\n\t\t);\n\n\t\t// for(const policy of matchingPolicies) {\n\t\t// \tbars.addFile(policy.name,\n\t\t// }\n\n\t\t// If no policies match this file, it's still considered processed\n\t\t// (we examined it and determined no policies apply)\n\t\tif (matchingPolicies.length === 0) {\n\t\t\treturn true;\n\t\t}\n\n\t\tconst results = await Promise.all(\n\t\t\tmatchingPolicies.map(async (policy) => {\n\t\t\t\treturn await this.runPolicyOnFile(relPath, policy, context);\n\t\t\t}),\n\t\t);\n\n\t\t// File is considered processed if at least one policy ran on it\n\t\t// If all matching policies excluded it, count as excluded\n\t\treturn results.some((ran) => ran);\n\t}\n\n\tprivate async runPolicyOnFile(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tcontext: RepopoCommandContext,\n\t): Promise<boolean> {\n\t\tconst { excludePoliciesForFiles, perfStats, gitRoot } = context;\n\n\t\t// Check if the policy is excluded for the file\n\t\tif (this.isPolicyExcluded(relPath, policy, excludePoliciesForFiles)) {\n\t\t\tthis.verbose(`Excluded from '${policy.name}' policy: ${relPath}`);\n\t\t\treturn false; // Policy didn't run on this file\n\t\t}\n\n\t\ttry {\n\t\t\t// Execute the policy handler\n\t\t\tconst result = await this.executePolicyHandler(\n\t\t\t\trelPath,\n\t\t\t\tpolicy,\n\t\t\t\tperfStats,\n\t\t\t\tgitRoot,\n\t\t\t);\n\n\t\t\t// Handle the result of the policy execution\n\t\t\tawait this.handlePolicyResult(\n\t\t\t\tresult,\n\t\t\t\trelPath,\n\t\t\t\tpolicy,\n\t\t\t\tperfStats,\n\t\t\t\tgitRoot,\n\t\t\t);\n\t\t} catch (error: unknown) {\n\t\t\t// Log and rethrow the error for higher-level handling\n\t\t\tthis.exit(\n\t\t\t\t`Error executing policy '${policy.name}' for file '${relPath}': ${error}`,\n\t\t\t);\n\t\t}\n\n\t\treturn true; // Policy ran (successfully or with error)\n\t}\n\n\tprivate isPolicyExcluded(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\texcludePoliciesForFiles: Map<string, RegExp[]>,\n\t): boolean {\n\t\treturn (\n\t\t\texcludePoliciesForFiles\n\t\t\t\t.get(policy.name)\n\t\t\t\t?.some((regex) => regex.test(relPath)) ?? false\n\t\t);\n\t}\n\n\tprivate async executePolicyHandler(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t): Promise<PolicyHandlerResult> {\n\t\ttry {\n\t\t\tconst action = this.flags.fix ? \"resolve\" : \"check\";\n\t\t\treturn await runWithPerf(policy.name, action, perfStats, () =>\n\t\t\t\tpolicy.handler({\n\t\t\t\t\tfile: relPath,\n\t\t\t\t\troot: gitRoot,\n\t\t\t\t\tresolve: this.flags.fix,\n\t\t\t\t\tconfig: policy.config,\n\t\t\t\t}),\n\t\t\t);\n\t\t} catch (error: unknown) {\n\t\t\tthis.exit(\n\t\t\t\t`Error in policy handler '${policy.name}' for file '${relPath}': ${error}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate async handlePolicyResult(\n\t\tresult: PolicyHandlerResult,\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t): Promise<void> {\n\t\tif (result === true) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (isPolicyFixResult(result)) {\n\t\t\tthis.handleFixResult(result, policy);\n\t\t} else {\n\t\t\tawait this.handleFailureResult(\n\t\t\t\tresult,\n\t\t\t\trelPath,\n\t\t\t\tpolicy,\n\t\t\t\tperfStats,\n\t\t\t\tgitRoot,\n\t\t\t);\n\t\t}\n\t}\n\n\tprivate handleFixResult(\n\t\tresult: PolicyFixResult,\n\t\tpolicy: PolicyInstance,\n\t): void {\n\t\tconst messages = new StringBuilder();\n\n\t\tif (result.resolved) {\n\t\t\tmessages.append(\n\t\t\t\t`Resolved ${policy.name} policy failure for file: ${result.file}`,\n\t\t\t);\n\t\t} else {\n\t\t\tmessages.append(\n\t\t\t\t`Error fixing ${policy.name} policy failure in ${result.file}`,\n\t\t\t);\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\n\t\tthis.logMessages(messages);\n\t}\n\n\tprivate async handleFailureResult(\n\t\tresult: PolicyFailure,\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t): Promise<void> {\n\t\tconst messages = new StringBuilder();\n\n\t\tif (this.flags.fix && policy.resolver) {\n\t\t\tawait this.attemptResolution(\n\t\t\t\trelPath,\n\t\t\t\tpolicy,\n\t\t\t\tpolicy.resolver,\n\t\t\t\tperfStats,\n\t\t\t\tgitRoot,\n\t\t\t\tmessages,\n\t\t\t);\n\t\t} else {\n\t\t\tthis.logPolicyFailure(result, policy, messages);\n\t\t}\n\n\t\tthis.logMessages(messages);\n\t}\n\n\tprivate async attemptResolution(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tresolver: PolicyStandaloneResolver,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t\tmessages: StringBuilder,\n\t): Promise<void> {\n\t\tmessages.append(`${newline}Attempting to resolve: ${relPath}`);\n\t\tconst resolveResult = await runWithPerf(\n\t\t\tpolicy.name,\n\t\t\t\"resolve\",\n\t\t\tperfStats,\n\t\t\t() => resolver({ file: relPath, root: gitRoot }),\n\t\t);\n\n\t\tif (!resolveResult.resolved) {\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\n\t\tif (resolveResult.errorMessages?.length > 0) {\n\t\t\tmessages.append(newline + resolveResult.errorMessages.join(newline));\n\t\t}\n\t}\n\n\tprivate logPolicyFailure(\n\t\tresult: PolicyFailure,\n\t\tpolicy: PolicyInstance,\n\t\tmessages: StringBuilder,\n\t): void {\n\t\tconst autoFixable = result.autoFixable ? chalk.green(\" (autofixable)\") : \"\";\n\t\tmessages.append(\n\t\t\t`'${chalk.bold(policy.name)}' policy failure${autoFixable}: ${result.file}`,\n\t\t);\n\t\tif (result.errorMessages?.length > 0) {\n\t\t\tmessages.append(\n\t\t\t\t`${newline}\\t${result.errorMessages.join(`${newline}\\t`)}`,\n\t\t\t);\n\t\t}\n\t\tprocess.exitCode = 1;\n\t}\n\tprivate logMessages(messages: StringBuilder): void {\n\t\tif ((process.exitCode ?? 0) === 0) {\n\t\t\tthis.info(messages.toString());\n\t\t} else {\n\t\t\tthis.warning(messages.toString());\n\t\t}\n\t}\n}\n"]}
|
package/esm/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { run } from "@oclif/core";
|
|
2
|
+
export { type FluidAdapterOptions, type FluidHandler, fromFluidHandlers, } from "./adapters/fluidFramework.js";
|
|
2
3
|
export type { RepopoConfig, } from "./config.js";
|
|
3
4
|
export { makePolicy } from "./makePolicy.js";
|
|
4
5
|
export type { PolicyDefinition, PolicyFailure, PolicyFixResult, PolicyFunctionArguments, PolicyHandler, PolicyHandlerResult, PolicyInstance, PolicyInstanceSettings, PolicyName, PolicyStandaloneResolver, } from "./policy.js";
|
package/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,YAAY,EAEX,YAAY,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EACX,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,uBAAuB,EACvB,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,UAAU,EACV,wBAAwB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,sBAAsB,IAAI,wBAAwB,EAClD,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,GAC3B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACN,mBAAmB,IAAI,qBAAqB,EAC5C,KAAK,kBAAkB,GACvB,MAAM,yCAAyC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EACN,KAAK,mBAAmB,EACxB,KAAK,YAAY,EACjB,iBAAiB,GACjB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAEX,YAAY,GACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EACX,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,uBAAuB,EACvB,aAAa,EACb,mBAAmB,EACnB,cAAc,EACd,sBAAsB,EACtB,UAAU,EACV,wBAAwB,GACxB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,sBAAsB,IAAI,wBAAwB,EAClD,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,GAC3B,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACN,mBAAmB,IAAI,qBAAqB,EAC5C,KAAK,kBAAkB,GACvB,MAAM,yCAAyC,CAAC"}
|
package/esm/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { run } from "@oclif/core";
|
|
2
|
+
export { fromFluidHandlers, } from "./adapters/fluidFramework.js";
|
|
2
3
|
export { makePolicy } from "./makePolicy.js";
|
|
3
4
|
export { defineFileHeaderPolicy as generateFileHeaderPolicy, } from "./policyDefiners/defineFileHeaderPolicy.js";
|
|
4
5
|
export { definePackagePolicy as generatePackagePolicy, } from "./policyDefiners/definePackagePolicy.js";
|
package/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,EAGN,iBAAiB,GACjB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAa7C,OAAO,EACN,sBAAsB,IAAI,wBAAwB,GAGlD,MAAM,4CAA4C,CAAC;AACpD,OAAO,EACN,mBAAmB,IAAI,qBAAqB,GAE5C,MAAM,yCAAyC,CAAC","sourcesContent":["export { run } from \"@oclif/core\";\nexport {\n\ttype FluidAdapterOptions,\n\ttype FluidHandler,\n\tfromFluidHandlers,\n} from \"./adapters/fluidFramework.js\";\nexport type {\n\t// PolicyList,\n\tRepopoConfig,\n} from \"./config.js\";\nexport { makePolicy } from \"./makePolicy.js\";\nexport type {\n\tPolicyDefinition,\n\tPolicyFailure,\n\tPolicyFixResult,\n\tPolicyFunctionArguments,\n\tPolicyHandler,\n\tPolicyHandlerResult,\n\tPolicyInstance,\n\tPolicyInstanceSettings,\n\tPolicyName,\n\tPolicyStandaloneResolver,\n} from \"./policy.js\";\nexport {\n\tdefineFileHeaderPolicy as generateFileHeaderPolicy,\n\ttype FileHeaderGeneratorConfig,\n\ttype FileHeaderPolicyConfig,\n} from \"./policyDefiners/defineFileHeaderPolicy.js\";\nexport {\n\tdefinePackagePolicy as generatePackagePolicy,\n\ttype PackageJsonHandler,\n} from \"./policyDefiners/definePackagePolicy.js\";\n"]}
|
package/esm/perf.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import type { Logger } from "@tylerbu/cli-api";
|
|
2
2
|
import type { PolicyName } from "./policy.js";
|
|
3
|
-
export type PolicyAction = "
|
|
3
|
+
export type PolicyAction = "check" | "resolve";
|
|
4
|
+
/**
|
|
5
|
+
* Stores performance data for each handler. Used to collect and display performance stats.
|
|
6
|
+
*/
|
|
4
7
|
export interface PolicyHandlerPerfStats {
|
|
5
8
|
count: number;
|
|
6
9
|
processed: number;
|
package/esm/perf.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perf.d.ts","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,
|
|
1
|
+
{"version":3,"file":"perf.d.ts","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,SAAS,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC;CACjD;AAED,wBAAgB,YAAY,IAAI,sBAAsB,CAMrD;AAED,wBAAsB,WAAW,CAAC,CAAC,EAClC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,YAAY,EACpB,KAAK,EAAE,sBAAsB,EAC7B,GAAG,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAWZ;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,sBAAsB,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAWzE"}
|
package/esm/perf.js
CHANGED
|
@@ -16,11 +16,12 @@ export async function runWithPerf(name, action, stats, run) {
|
|
|
16
16
|
return result;
|
|
17
17
|
}
|
|
18
18
|
export function logStats(stats, log) {
|
|
19
|
-
log.log(`Statistics: ${stats.processed}
|
|
19
|
+
log.log(`Statistics: ${stats.processed} files processed, ` +
|
|
20
|
+
`${stats.count - stats.processed} excluded, ${stats.count} total`);
|
|
20
21
|
for (const [action, handlerPerf] of stats.data.entries()) {
|
|
21
22
|
log.log(`Performance for "${action}":`);
|
|
22
23
|
for (const [handler, dur] of handlerPerf.entries()) {
|
|
23
|
-
log.log(
|
|
24
|
+
log.log(` ${handler}: ${dur}ms`);
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
}
|
package/esm/perf.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"perf.js","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"perf.js","sourceRoot":"","sources":["../src/perf.ts"],"names":[],"mappings":"AAcA,MAAM,UAAU,YAAY;IAC3B,OAAO;QACN,KAAK,EAAE,CAAC;QACR,SAAS,EAAE,CAAC;QACZ,IAAI,EAAE,IAAI,GAAG,EAAyC;KACtD,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,IAAY,EACZ,MAAoB,EACpB,KAA6B,EAC7B,GAAqB;IAErB,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,GAAG,EAAkB,CAAC;IACtE,IAAI,GAAG,GAAG,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEnC,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,MAAM,GAAG,EAAE,CAAC;IAC3B,GAAG,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;IAE1B,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACzB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC;AACf,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,KAA6B,EAAE,GAAW;IAClE,GAAG,CAAC,GAAG,CACN,eAAe,KAAK,CAAC,SAAS,oBAAoB;QACjD,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,SAAS,cAAc,KAAK,CAAC,KAAK,QAAQ,CAClE,CAAC;IACF,KAAK,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;QAC1D,GAAG,CAAC,GAAG,CAAC,oBAAoB,MAAM,IAAI,CAAC,CAAC;QACxC,KAAK,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,OAAO,OAAO,KAAK,GAAG,IAAI,CAAC,CAAC;QACrC,CAAC;IACF,CAAC;AACF,CAAC","sourcesContent":["import type { Logger } from \"@tylerbu/cli-api\";\nimport type { PolicyName } from \"./policy.js\";\n\nexport type PolicyAction = \"check\" | \"resolve\";\n\n/**\n * Stores performance data for each handler. Used to collect and display performance stats.\n */\nexport interface PolicyHandlerPerfStats {\n\tcount: number;\n\tprocessed: number;\n\tdata: Map<PolicyAction, Map<PolicyName, number>>;\n}\n\nexport function newPerfStats(): PolicyHandlerPerfStats {\n\treturn {\n\t\tcount: 0,\n\t\tprocessed: 0,\n\t\tdata: new Map<PolicyAction, Map<PolicyName, number>>(),\n\t};\n}\n\nexport async function runWithPerf<T>(\n\tname: string,\n\taction: PolicyAction,\n\tstats: PolicyHandlerPerfStats,\n\trun: () => Promise<T>,\n): Promise<T> {\n\tconst actionMap = stats.data.get(action) ?? new Map<string, number>();\n\tlet dur = actionMap.get(name) ?? 0;\n\n\tconst start = Date.now();\n\tconst result = await run();\n\tdur += Date.now() - start;\n\n\tactionMap.set(name, dur);\n\tstats.data.set(action, actionMap);\n\treturn result;\n}\n\nexport function logStats(stats: PolicyHandlerPerfStats, log: Logger): void {\n\tlog.log(\n\t\t`Statistics: ${stats.processed} files processed, ` +\n\t\t\t`${stats.count - stats.processed} excluded, ${stats.count} total`,\n\t);\n\tfor (const [action, handlerPerf] of stats.data.entries()) {\n\t\tlog.log(`Performance for \"${action}\":`);\n\t\tfor (const [handler, dur] of handlerPerf.entries()) {\n\t\t\tlog.log(` ${handler}: ${dur}ms`);\n\t\t}\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LicenseFileExists.d.ts","sourceRoot":"","sources":["../../src/policies/LicenseFileExists.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,cAAc,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACzC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAgBD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,gBAAgB,CAAC,yBAAyB,
|
|
1
|
+
{"version":3,"file":"LicenseFileExists.d.ts","sourceRoot":"","sources":["../../src/policies/LicenseFileExists.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,cAAc,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACzC;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAgBD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,EAAE,gBAAgB,CAAC,yBAAyB,CA4BxE,CAAC"}
|
|
@@ -33,7 +33,9 @@ export const LicenseFileExists = makePolicyDefinition("LicenseFileExists",
|
|
|
33
33
|
name: LicenseFileExists.name,
|
|
34
34
|
file: ".", // Report against repository root
|
|
35
35
|
autoFixable: false,
|
|
36
|
-
|
|
36
|
+
errorMessages: [
|
|
37
|
+
`No LICENSE file found in repository root. Expected one of: ${acceptedNames.join(", ")}`,
|
|
38
|
+
],
|
|
37
39
|
};
|
|
38
40
|
return result;
|
|
39
41
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LicenseFileExists.js","sourceRoot":"","sources":["../../src/policies/LicenseFileExists.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAexD;;GAEG;AACH,MAAM,qBAAqB,GAAG;IAC7B,SAAS;IACT,aAAa;IACb,YAAY;IACZ,aAAa;IACb,SAAS;IACT,aAAa;IACb,YAAY;IACZ,aAAa;CACb,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAC7B,oBAAoB,CACnB,mBAAmB;AACnB,4DAA4D;AAC5D,iBAAiB,EACjB,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;IAC1B,MAAM,aAAa,GAAG,MAAM,EAAE,aAAa,IAAI,qBAAqB,CAAC;IAErE,+DAA+D;IAC/D,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAClD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CACjC,CAAC;IAEF,IAAI,cAAc,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAAkB;QAC7B,IAAI,EAAE,iBAAiB,CAAC,IAAI;QAC5B,IAAI,EAAE,GAAG,EAAE,iCAAiC;QAC5C,WAAW,EAAE,KAAK;QAClB,
|
|
1
|
+
{"version":3,"file":"LicenseFileExists.js","sourceRoot":"","sources":["../../src/policies/LicenseFileExists.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAexD;;GAEG;AACH,MAAM,qBAAqB,GAAG;IAC7B,SAAS;IACT,aAAa;IACb,YAAY;IACZ,aAAa;IACb,SAAS;IACT,aAAa;IACb,YAAY;IACZ,aAAa;CACb,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAC7B,oBAAoB,CACnB,mBAAmB;AACnB,4DAA4D;AAC5D,iBAAiB,EACjB,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;IAC1B,MAAM,aAAa,GAAG,MAAM,EAAE,aAAa,IAAI,qBAAqB,CAAC;IAErE,+DAA+D;IAC/D,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAClD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CACjC,CAAC;IAEF,IAAI,cAAc,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAAkB;QAC7B,IAAI,EAAE,iBAAiB,CAAC,IAAI;QAC5B,IAAI,EAAE,GAAG,EAAE,iCAAiC;QAC5C,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE;YACd,8DAA8D,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;SACxF;KACD,CAAC;IAEF,OAAO,MAAM,CAAC;AACf,CAAC,CACD,CAAC","sourcesContent":["import { existsSync } from \"node:fs\";\nimport path from \"pathe\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition, PolicyFailure } from \"../policy.js\";\n\n/**\n * Policy settings for the LicenseFileExists repo policy.\n *\n * @alpha\n */\nexport interface LicenseFileExistsSettings {\n\t/**\n\t * Array of acceptable license file names. Defaults to common variations.\n\t */\n\tacceptedNames?: string[];\n}\n\n/**\n * Default license file names to check for.\n */\nconst DEFAULT_LICENSE_NAMES = [\n\t\"LICENSE\",\n\t\"LICENSE.txt\",\n\t\"LICENSE.md\",\n\t\"LICENSE.rst\",\n\t\"LICENCE\",\n\t\"LICENCE.txt\",\n\t\"LICENCE.md\",\n\t\"LICENCE.rst\",\n];\n\n/**\n * A repo policy that checks that a LICENSE file exists in the repository root.\n * This is essential for open source projects to clarify usage rights and obligations.\n *\n * @alpha\n */\nexport const LicenseFileExists: PolicyDefinition<LicenseFileExistsSettings> =\n\tmakePolicyDefinition(\n\t\t\"LicenseFileExists\",\n\t\t// Only trigger on package.json to check once per repository\n\t\t/^package\\.json$/,\n\t\tasync ({ root, config }) => {\n\t\t\tconst acceptedNames = config?.acceptedNames ?? DEFAULT_LICENSE_NAMES;\n\n\t\t\t// Check if any of the accepted license files exist in the root\n\t\t\tconst hasLicenseFile = acceptedNames.some((name) =>\n\t\t\t\texistsSync(path.join(root, name)),\n\t\t\t);\n\n\t\t\tif (hasLicenseFile) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\tconst result: PolicyFailure = {\n\t\t\t\tname: LicenseFileExists.name,\n\t\t\t\tfile: \".\", // Report against repository root\n\t\t\t\tautoFixable: false,\n\t\t\t\terrorMessages: [\n\t\t\t\t\t`No LICENSE file found in repository root. Expected one of: ${acceptedNames.join(\", \")}`,\n\t\t\t\t],\n\t\t\t};\n\n\t\t\treturn result;\n\t\t},\n\t);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NoJsFileExtensions.d.ts","sourceRoot":"","sources":["../../src/policies/NoJsFileExtensions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,cAAc,CAAC;AAEpE;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"NoJsFileExtensions.d.ts","sourceRoot":"","sources":["../../src/policies/NoJsFileExtensions.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,cAAc,CAAC;AAEpE;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAgBhC,CAAC"}
|
|
@@ -14,7 +14,10 @@ export const NoJsFileExtensions = makePolicyDefinition("NoJsFileExtensions", /(^
|
|
|
14
14
|
name: NoJsFileExtensions.name,
|
|
15
15
|
file,
|
|
16
16
|
autoFixable: false,
|
|
17
|
-
|
|
17
|
+
errorMessages: [
|
|
18
|
+
"JavaScript files should have a .cjs or .mjs file extension based on the module format of the file.",
|
|
19
|
+
],
|
|
20
|
+
manualFix: "Rename the file to have a .cjs or .mjs file extension.",
|
|
18
21
|
};
|
|
19
22
|
return result;
|
|
20
23
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NoJsFileExtensions.js","sourceRoot":"","sources":["../../src/policies/NoJsFileExtensions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAqB,oBAAoB,CACvE,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;IAClB,qCAAqC;IACrC,MAAM,MAAM,GAAkB;QAC7B,IAAI,EAAE,kBAAkB,CAAC,IAAI;QAC7B,IAAI;QACJ,WAAW,EAAE,KAAK;QAClB,
|
|
1
|
+
{"version":3,"file":"NoJsFileExtensions.js","sourceRoot":"","sources":["../../src/policies/NoJsFileExtensions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAGxD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAqB,oBAAoB,CACvE,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;IAClB,qCAAqC;IACrC,MAAM,MAAM,GAAkB;QAC7B,IAAI,EAAE,kBAAkB,CAAC,IAAI;QAC7B,IAAI;QACJ,WAAW,EAAE,KAAK;QAClB,aAAa,EAAE;YACd,oGAAoG;SACpG;QACD,SAAS,EAAE,wDAAwD;KACnE,CAAC;IACF,OAAO,MAAM,CAAC;AACf,CAAC,CACD,CAAC","sourcesContent":["import { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition, PolicyFailure } from \"../policy.js\";\n\n/**\n * A repo policy that checks for JavaScript source files that just use the .js file extension. Such files may be\n * interpreted by node as either CommonJS or ESM based on the `type` field in the nearest package.json file. This\n * can create unexpected behavior for JS files; changing the package.json nearest to one will change how the JS\n * is processed by node. Using explicit file extensions reduces ambiguity and ensures a CJS file isn't suddenly treated\n * like an ESM file.\n *\n * @alpha\n */\nexport const NoJsFileExtensions: PolicyDefinition = makePolicyDefinition(\n\t\"NoJsFileExtensions\",\n\t/(^|\\/)[^/]+\\.js$/i,\n\tasync ({ file }) => {\n\t\t// Any match is considered a failure.\n\t\tconst result: PolicyFailure = {\n\t\t\tname: NoJsFileExtensions.name,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages: [\n\t\t\t\t\"JavaScript files should have a .cjs or .mjs file extension based on the module format of the file.\",\n\t\t\t],\n\t\t\tmanualFix: \"Rename the file to have a .cjs or .mjs file extension.\",\n\t\t};\n\t\treturn result;\n\t},\n);\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NoLargeBinaryFiles.d.ts","sourceRoot":"","sources":["../../src/policies/NoLargeBinaryFiles.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,cAAc,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE7B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AA2FD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,CAAC,0BAA0B,
|
|
1
|
+
{"version":3,"file":"NoLargeBinaryFiles.d.ts","sourceRoot":"","sources":["../../src/policies/NoLargeBinaryFiles.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAiB,MAAM,cAAc,CAAC;AAEpE;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IAC1C;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAE7B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AA2FD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,EAAE,gBAAgB,CAAC,0BAA0B,CA4C1E,CAAC"}
|
|
@@ -104,7 +104,9 @@ export const NoLargeBinaryFiles = makePolicyDefinition("NoLargeBinaryFiles",
|
|
|
104
104
|
name: NoLargeBinaryFiles.name,
|
|
105
105
|
file,
|
|
106
106
|
autoFixable: false,
|
|
107
|
-
|
|
107
|
+
errorMessages: [
|
|
108
|
+
`File is too large: ${formatBytes(stats.size)} (max: ${formatBytes(maxSizeBytes)}). Consider using Git LFS or removing the file.`,
|
|
109
|
+
],
|
|
108
110
|
};
|
|
109
111
|
return result;
|
|
110
112
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NoLargeBinaryFiles.js","sourceRoot":"","sources":["../../src/policies/NoLargeBinaryFiles.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"NoLargeBinaryFiles.js","sourceRoot":"","sources":["../../src/policies/NoLargeBinaryFiles.ts"],"names":[],"mappings":"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","sourcesContent":["import { statSync } from \"node:fs\";\nimport path from \"pathe\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type { PolicyDefinition, PolicyFailure } from \"../policy.js\";\n\n/**\n * Policy settings for the NoLargeBinaryFiles repo policy.\n *\n * @alpha\n */\nexport interface NoLargeBinaryFilesSettings {\n\t/**\n\t * Maximum file size in bytes. Defaults to 10MB.\n\t */\n\tmaxSizeBytes?: number;\n\n\t/**\n\t * File extensions to exclude from size checking.\n\t * Useful for known large files that should be allowed.\n\t */\n\texcludeExtensions?: string[];\n\n\t/**\n\t * File patterns to exclude from size checking.\n\t * Uses glob-style patterns.\n\t */\n\texcludePatterns?: string[];\n}\n\n/**\n * Default maximum file size (10MB in bytes).\n */\nconst DEFAULT_MAX_SIZE = 10 * 1024 * 1024;\n\n/**\n * Default file extensions that are typically safe to exclude from size limits.\n */\nconst DEFAULT_EXCLUDE_EXTENSIONS = [\n\t\".md\",\n\t\".txt\",\n\t\".json\",\n\t\".js\",\n\t\".ts\",\n\t\".jsx\",\n\t\".tsx\",\n\t\".css\",\n\t\".scss\",\n\t\".sass\",\n\t\".less\",\n\t\".html\",\n\t\".xml\",\n\t\".yml\",\n\t\".yaml\",\n\t\".toml\",\n\t\".ini\",\n\t\".conf\",\n\t\".config\",\n];\n\n/**\n * Convert a glob pattern to a regex pattern by escaping special characters\n * and converting * to .* for wildcard matching.\n */\nfunction globToRegex(pattern: string): RegExp {\n\t// Escape all regex special characters except *\n\tconst escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\t// Convert * to .* for wildcard matching\n\tconst regexPattern = escaped.replace(/\\*/g, \".*\");\n\treturn new RegExp(`^${regexPattern}$`);\n}\n\n/**\n * Check if a file matches any of the exclude patterns.\n */\nfunction isExcluded(\n\tfilePath: string,\n\texcludePatterns: string[],\n\texcludeExtensions: string[],\n): boolean {\n\tconst ext = path.extname(filePath).toLowerCase();\n\n\t// Check extensions\n\tif (excludeExtensions.includes(ext)) {\n\t\treturn true;\n\t}\n\n\t// Check patterns (simple glob-like matching)\n\tfor (const pattern of excludePatterns) {\n\t\tif (pattern.includes(\"*\")) {\n\t\t\tconst regex = globToRegex(pattern);\n\t\t\tif (regex.test(filePath)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else if (filePath.includes(pattern)) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n}\n\n/**\n * Format bytes in a human-readable format.\n */\nfunction formatBytes(bytes: number): string {\n\tif (bytes === 0) {\n\t\treturn \"0 B\";\n\t}\n\tconst k = 1024;\n\tconst sizes = [\"B\", \"KB\", \"MB\", \"GB\", \"TB\"];\n\tconst i = Math.min(\n\t\tMath.floor(Math.log(bytes) / Math.log(k)),\n\t\tsizes.length - 1,\n\t);\n\tconst formatted = (bytes / k ** i).toFixed(1);\n\treturn `${formatted} ${sizes[i]}`;\n}\n\n/**\n * A repo policy that prevents large binary files from being committed to the repository.\n * Large files can bloat the repository and slow down clones. Consider using Git LFS for large assets.\n *\n * @alpha\n */\nexport const NoLargeBinaryFiles: PolicyDefinition<NoLargeBinaryFilesSettings> =\n\tmakePolicyDefinition(\n\t\t\"NoLargeBinaryFiles\",\n\t\t// Match all files\n\t\t/.*/,\n\t\tasync ({ file, root, config }) => {\n\t\t\tconst maxSizeBytes = config?.maxSizeBytes ?? DEFAULT_MAX_SIZE;\n\t\t\tconst excludeExtensions =\n\t\t\t\tconfig?.excludeExtensions ?? DEFAULT_EXCLUDE_EXTENSIONS;\n\t\t\tconst excludePatterns = config?.excludePatterns ?? [];\n\n\t\t\t// Skip excluded files\n\t\t\tif (isExcluded(file, excludePatterns, excludeExtensions)) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst filePath = path.resolve(root, file);\n\t\t\t\tconst stats = statSync(filePath);\n\n\t\t\t\t// Skip directories\n\t\t\t\tif (stats.isDirectory()) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tif (stats.size > maxSizeBytes) {\n\t\t\t\t\tconst result: PolicyFailure = {\n\t\t\t\t\t\tname: NoLargeBinaryFiles.name,\n\t\t\t\t\t\tfile,\n\t\t\t\t\t\tautoFixable: false,\n\t\t\t\t\t\terrorMessages: [\n\t\t\t\t\t\t\t`File is too large: ${formatBytes(stats.size)} (max: ${formatBytes(maxSizeBytes)}). Consider using Git LFS or removing the file.`,\n\t\t\t\t\t\t],\n\t\t\t\t\t};\n\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\treturn true;\n\t\t\t} catch (_error: unknown) {\n\t\t\t\t// File doesn't exist or can't be accessed, skip it\n\t\t\t\treturn true;\n\t\t\t}\n\t\t},\n\t);\n"]}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for the NoPrivateWorkspaceDependencies policy.
|
|
3
|
+
*/
|
|
4
|
+
export interface NoPrivateWorkspaceDependenciesSettings {
|
|
5
|
+
/**
|
|
6
|
+
* Whether to check devDependencies in addition to dependencies.
|
|
7
|
+
* @default false
|
|
8
|
+
*/
|
|
9
|
+
checkDevDependencies?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Policy that prevents publishable packages from depending on private workspace packages.
|
|
13
|
+
*
|
|
14
|
+
* A package is considered "publishable" if it does not have `"private": true` in its package.json.
|
|
15
|
+
* Such packages cannot have `workspace:` dependencies on packages that are marked as private,
|
|
16
|
+
* because those dependencies won't be resolvable when the package is published to npm.
|
|
17
|
+
*
|
|
18
|
+
* This policy uses the workspace configuration (pnpm-workspace.yaml or package.json workspaces field)
|
|
19
|
+
* to locate workspace packages, rather than hardcoding directory conventions.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // In repopo.config.ts
|
|
24
|
+
* import { NoPrivateWorkspaceDependencies } from "repopo/policies";
|
|
25
|
+
*
|
|
26
|
+
* makePolicy(NoPrivateWorkspaceDependencies, {
|
|
27
|
+
* checkDevDependencies: false, // Only check production dependencies (default)
|
|
28
|
+
* });
|
|
29
|
+
*
|
|
30
|
+
* // Or check both dependencies and devDependencies
|
|
31
|
+
* makePolicy(NoPrivateWorkspaceDependencies, {
|
|
32
|
+
* checkDevDependencies: true,
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare const NoPrivateWorkspaceDependencies: import("../policy.js").PolicyDefinition<NoPrivateWorkspaceDependenciesSettings | undefined>;
|
|
37
|
+
//# sourceMappingURL=NoPrivateWorkspaceDependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoPrivateWorkspaceDependencies.d.ts","sourceRoot":"","sources":["../../src/policies/NoPrivateWorkspaceDependencies.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,sCAAsC;IACtD;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC/B;AA6ED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,8BAA8B,6FAmEzC,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { getWorkspaceGlobs } from "resolve-workspace-root";
|
|
3
|
+
import { globSync } from "tinyglobby";
|
|
4
|
+
import { definePackagePolicy } from "../policyDefiners/definePackagePolicy.js";
|
|
5
|
+
/**
|
|
6
|
+
* Cache for workspace package lookups to avoid repeated filesystem operations.
|
|
7
|
+
*/
|
|
8
|
+
const workspacePackageCache = new Map();
|
|
9
|
+
/**
|
|
10
|
+
* Builds a map of package name to package.json for all packages in the workspace.
|
|
11
|
+
* Uses the workspace configuration (pnpm-workspace.yaml or package.json workspaces) to find packages.
|
|
12
|
+
*/
|
|
13
|
+
function buildWorkspacePackageMap(root) {
|
|
14
|
+
// Check cache first
|
|
15
|
+
const cached = workspacePackageCache.get(root);
|
|
16
|
+
if (cached !== undefined) {
|
|
17
|
+
return cached;
|
|
18
|
+
}
|
|
19
|
+
const packageMap = new Map();
|
|
20
|
+
// Get workspace globs from pnpm-workspace.yaml or package.json
|
|
21
|
+
const workspaceGlobs = getWorkspaceGlobs(root);
|
|
22
|
+
if (workspaceGlobs === null) {
|
|
23
|
+
// Not a workspace - return empty map
|
|
24
|
+
workspacePackageCache.set(root, packageMap);
|
|
25
|
+
return packageMap;
|
|
26
|
+
}
|
|
27
|
+
// Find all package.json files matching the workspace globs
|
|
28
|
+
const packageGlobs = workspaceGlobs.map((g) => `${g}/package.json`);
|
|
29
|
+
const packageJsonPaths = globSync(packageGlobs, {
|
|
30
|
+
cwd: root,
|
|
31
|
+
ignore: ["**/node_modules/**"],
|
|
32
|
+
onlyFiles: true,
|
|
33
|
+
absolute: true,
|
|
34
|
+
});
|
|
35
|
+
// Load each package.json and map by name
|
|
36
|
+
for (const pkgPath of packageJsonPaths) {
|
|
37
|
+
try {
|
|
38
|
+
const content = readFileSync(pkgPath, "utf-8");
|
|
39
|
+
const pkg = JSON.parse(content);
|
|
40
|
+
if (pkg.name) {
|
|
41
|
+
packageMap.set(pkg.name, pkg);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// Ignore parse errors
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
workspacePackageCache.set(root, packageMap);
|
|
49
|
+
return packageMap;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Looks up a workspace package by name using the workspace configuration.
|
|
53
|
+
*/
|
|
54
|
+
function findWorkspacePackage(depName, root) {
|
|
55
|
+
const packageMap = buildWorkspacePackageMap(root);
|
|
56
|
+
return packageMap.get(depName);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Checks if a dependency version uses the workspace protocol.
|
|
60
|
+
*/
|
|
61
|
+
function isWorkspaceDependency(version) {
|
|
62
|
+
return version?.startsWith("workspace:") ?? false;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Policy that prevents publishable packages from depending on private workspace packages.
|
|
66
|
+
*
|
|
67
|
+
* A package is considered "publishable" if it does not have `"private": true` in its package.json.
|
|
68
|
+
* Such packages cannot have `workspace:` dependencies on packages that are marked as private,
|
|
69
|
+
* because those dependencies won't be resolvable when the package is published to npm.
|
|
70
|
+
*
|
|
71
|
+
* This policy uses the workspace configuration (pnpm-workspace.yaml or package.json workspaces field)
|
|
72
|
+
* to locate workspace packages, rather than hardcoding directory conventions.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* // In repopo.config.ts
|
|
77
|
+
* import { NoPrivateWorkspaceDependencies } from "repopo/policies";
|
|
78
|
+
*
|
|
79
|
+
* makePolicy(NoPrivateWorkspaceDependencies, {
|
|
80
|
+
* checkDevDependencies: false, // Only check production dependencies (default)
|
|
81
|
+
* });
|
|
82
|
+
*
|
|
83
|
+
* // Or check both dependencies and devDependencies
|
|
84
|
+
* makePolicy(NoPrivateWorkspaceDependencies, {
|
|
85
|
+
* checkDevDependencies: true,
|
|
86
|
+
* });
|
|
87
|
+
* ```
|
|
88
|
+
*/
|
|
89
|
+
export const NoPrivateWorkspaceDependencies = definePackagePolicy("NoPrivateWorkspaceDependencies", async (json, { file, root, config }) => {
|
|
90
|
+
// Private packages can depend on anything - they won't be published
|
|
91
|
+
if (json.private === true) {
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
94
|
+
const checkDevDeps = config?.checkDevDependencies ?? false;
|
|
95
|
+
// Collect dependencies to check
|
|
96
|
+
const depsToCheck = {
|
|
97
|
+
...(json.dependencies ?? {}),
|
|
98
|
+
};
|
|
99
|
+
if (checkDevDeps) {
|
|
100
|
+
Object.assign(depsToCheck, json.devDependencies ?? {});
|
|
101
|
+
}
|
|
102
|
+
const privateWorkspaceDeps = [];
|
|
103
|
+
const unresolvableDeps = [];
|
|
104
|
+
for (const [depName, version] of Object.entries(depsToCheck)) {
|
|
105
|
+
if (!isWorkspaceDependency(version)) {
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const depPackageJson = findWorkspacePackage(depName, root);
|
|
109
|
+
if (depPackageJson === undefined) {
|
|
110
|
+
// Could not find the package - might be a configuration issue
|
|
111
|
+
// We'll warn but not fail, as this could be a valid setup we don't understand
|
|
112
|
+
unresolvableDeps.push(depName);
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
if (depPackageJson.private === true) {
|
|
116
|
+
privateWorkspaceDeps.push(depName);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
const errorMessages = [];
|
|
120
|
+
if (privateWorkspaceDeps.length > 0) {
|
|
121
|
+
errorMessages.push(`Publishable package has workspace dependencies on private packages that won't be available on npm:\n\t${privateWorkspaceDeps.join("\n\t")}`);
|
|
122
|
+
}
|
|
123
|
+
if (unresolvableDeps.length > 0) {
|
|
124
|
+
errorMessages.push(`Could not resolve workspace dependencies (verify they exist):\n\t${unresolvableDeps.join("\n\t")}`);
|
|
125
|
+
}
|
|
126
|
+
if (errorMessages.length > 0) {
|
|
127
|
+
const failResult = {
|
|
128
|
+
name: NoPrivateWorkspaceDependencies.name,
|
|
129
|
+
file,
|
|
130
|
+
autoFixable: false,
|
|
131
|
+
errorMessages,
|
|
132
|
+
};
|
|
133
|
+
return failResult;
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
});
|
|
137
|
+
//# sourceMappingURL=NoPrivateWorkspaceDependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoPrivateWorkspaceDependencies.js","sourceRoot":"","sources":["../../src/policies/NoPrivateWorkspaceDependencies.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { getWorkspaceGlobs } from \"resolve-workspace-root\";\nimport { globSync } from \"tinyglobby\";\nimport type { PackageJson } from \"type-fest\";\nimport type { PolicyFailure } from \"../policy.js\";\nimport { definePackagePolicy } from \"../policyDefiners/definePackagePolicy.js\";\n\n/**\n * Configuration for the NoPrivateWorkspaceDependencies policy.\n */\nexport interface NoPrivateWorkspaceDependenciesSettings {\n\t/**\n\t * Whether to check devDependencies in addition to dependencies.\n\t * @default false\n\t */\n\tcheckDevDependencies?: boolean;\n}\n\n/**\n * Cache for workspace package lookups to avoid repeated filesystem operations.\n */\nconst workspacePackageCache = new Map<\n\tstring,\n\tMap<string, PackageJson | undefined>\n>();\n\n/**\n * Builds a map of package name to package.json for all packages in the workspace.\n * Uses the workspace configuration (pnpm-workspace.yaml or package.json workspaces) to find packages.\n */\nfunction buildWorkspacePackageMap(\n\troot: string,\n): Map<string, PackageJson | undefined> {\n\t// Check cache first\n\tconst cached = workspacePackageCache.get(root);\n\tif (cached !== undefined) {\n\t\treturn cached;\n\t}\n\n\tconst packageMap = new Map<string, PackageJson | undefined>();\n\n\t// Get workspace globs from pnpm-workspace.yaml or package.json\n\tconst workspaceGlobs = getWorkspaceGlobs(root);\n\tif (workspaceGlobs === null) {\n\t\t// Not a workspace - return empty map\n\t\tworkspacePackageCache.set(root, packageMap);\n\t\treturn packageMap;\n\t}\n\n\t// Find all package.json files matching the workspace globs\n\tconst packageGlobs = workspaceGlobs.map((g) => `${g}/package.json`);\n\tconst packageJsonPaths = globSync(packageGlobs, {\n\t\tcwd: root,\n\t\tignore: [\"**/node_modules/**\"],\n\t\tonlyFiles: true,\n\t\tabsolute: true,\n\t});\n\n\t// Load each package.json and map by name\n\tfor (const pkgPath of packageJsonPaths) {\n\t\ttry {\n\t\t\tconst content = readFileSync(pkgPath, \"utf-8\");\n\t\t\tconst pkg = JSON.parse(content) as PackageJson;\n\t\t\tif (pkg.name) {\n\t\t\t\tpackageMap.set(pkg.name, pkg);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Ignore parse errors\n\t\t}\n\t}\n\n\tworkspacePackageCache.set(root, packageMap);\n\treturn packageMap;\n}\n\n/**\n * Looks up a workspace package by name using the workspace configuration.\n */\nfunction findWorkspacePackage(\n\tdepName: string,\n\troot: string,\n): PackageJson | undefined {\n\tconst packageMap = buildWorkspacePackageMap(root);\n\treturn packageMap.get(depName);\n}\n\n/**\n * Checks if a dependency version uses the workspace protocol.\n */\nfunction isWorkspaceDependency(version: string | undefined): boolean {\n\treturn version?.startsWith(\"workspace:\") ?? false;\n}\n\n/**\n * Policy that prevents publishable packages from depending on private workspace packages.\n *\n * A package is considered \"publishable\" if it does not have `\"private\": true` in its package.json.\n * Such packages cannot have `workspace:` dependencies on packages that are marked as private,\n * because those dependencies won't be resolvable when the package is published to npm.\n *\n * This policy uses the workspace configuration (pnpm-workspace.yaml or package.json workspaces field)\n * to locate workspace packages, rather than hardcoding directory conventions.\n *\n * @example\n * ```typescript\n * // In repopo.config.ts\n * import { NoPrivateWorkspaceDependencies } from \"repopo/policies\";\n *\n * makePolicy(NoPrivateWorkspaceDependencies, {\n * checkDevDependencies: false, // Only check production dependencies (default)\n * });\n *\n * // Or check both dependencies and devDependencies\n * makePolicy(NoPrivateWorkspaceDependencies, {\n * checkDevDependencies: true,\n * });\n * ```\n */\nexport const NoPrivateWorkspaceDependencies = definePackagePolicy<\n\tPackageJson,\n\tNoPrivateWorkspaceDependenciesSettings | undefined\n>(\"NoPrivateWorkspaceDependencies\", async (json, { file, root, config }) => {\n\t// Private packages can depend on anything - they won't be published\n\tif (json.private === true) {\n\t\treturn true;\n\t}\n\n\tconst checkDevDeps = config?.checkDevDependencies ?? false;\n\n\t// Collect dependencies to check\n\tconst depsToCheck: Record<string, string | undefined> = {\n\t\t...(json.dependencies ?? {}),\n\t};\n\n\tif (checkDevDeps) {\n\t\tObject.assign(depsToCheck, json.devDependencies ?? {});\n\t}\n\n\tconst privateWorkspaceDeps: string[] = [];\n\tconst unresolvableDeps: string[] = [];\n\n\tfor (const [depName, version] of Object.entries(depsToCheck)) {\n\t\tif (!isWorkspaceDependency(version)) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst depPackageJson = findWorkspacePackage(depName, root);\n\n\t\tif (depPackageJson === undefined) {\n\t\t\t// Could not find the package - might be a configuration issue\n\t\t\t// We'll warn but not fail, as this could be a valid setup we don't understand\n\t\t\tunresolvableDeps.push(depName);\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (depPackageJson.private === true) {\n\t\t\tprivateWorkspaceDeps.push(depName);\n\t\t}\n\t}\n\n\tconst errorMessages: string[] = [];\n\n\tif (privateWorkspaceDeps.length > 0) {\n\t\terrorMessages.push(\n\t\t\t`Publishable package has workspace dependencies on private packages that won't be available on npm:\\n\\t${privateWorkspaceDeps.join(\"\\n\\t\")}`,\n\t\t);\n\t}\n\n\tif (unresolvableDeps.length > 0) {\n\t\terrorMessages.push(\n\t\t\t`Could not resolve workspace dependencies (verify they exist):\\n\\t${unresolvableDeps.join(\"\\n\\t\")}`,\n\t\t);\n\t}\n\n\tif (errorMessages.length > 0) {\n\t\tconst failResult: PolicyFailure = {\n\t\t\tname: NoPrivateWorkspaceDependencies.name,\n\t\t\tfile,\n\t\t\tautoFixable: false,\n\t\t\terrorMessages,\n\t\t};\n\t\treturn failResult;\n\t}\n\n\treturn true;\n});\n"]}
|