repopo 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/THIRD-PARTY-LICENSES.txt +4 -3
- package/esm/adapters/fluidFramework.js +8 -3
- package/esm/adapters/fluidFramework.js.map +1 -1
- 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 +1 -0
- package/esm/commands/check.d.ts.map +1 -1
- package/esm/commands/check.js +114 -52
- package/esm/commands/check.js.map +1 -1
- package/esm/commands/list.d.ts.map +1 -1
- package/esm/commands/list.js +3 -1
- package/esm/commands/list.js.map +1 -1
- package/esm/config.d.ts +19 -4
- package/esm/config.d.ts.map +1 -1
- package/esm/config.js +2 -3
- package/esm/config.js.map +1 -1
- package/esm/generators.d.ts +30 -2
- package/esm/generators.d.ts.map +1 -1
- package/esm/generators.js +31 -1
- package/esm/generators.js.map +1 -1
- package/esm/index.d.ts +14 -4
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +17 -2
- package/esm/index.js.map +1 -1
- package/esm/makePolicy.d.ts +74 -3
- package/esm/makePolicy.d.ts.map +1 -1
- package/esm/makePolicy.js +87 -13
- package/esm/makePolicy.js.map +1 -1
- package/esm/perf.d.ts +3 -2
- package/esm/perf.d.ts.map +1 -1
- package/esm/perf.js +2 -2
- package/esm/perf.js.map +1 -1
- package/esm/policies/ConditionalScripts.d.ts +94 -0
- package/esm/policies/ConditionalScripts.d.ts.map +1 -0
- package/esm/policies/ConditionalScripts.js +144 -0
- package/esm/policies/ConditionalScripts.js.map +1 -0
- package/esm/policies/ExactScripts.d.ts +51 -0
- package/esm/policies/ExactScripts.d.ts.map +1 -0
- package/esm/policies/ExactScripts.js +107 -0
- package/esm/policies/ExactScripts.js.map +1 -0
- package/esm/policies/HtmlFileHeaders.d.ts +1 -1
- package/esm/policies/HtmlFileHeaders.d.ts.map +1 -1
- package/esm/policies/HtmlFileHeaders.js +11 -7
- package/esm/policies/HtmlFileHeaders.js.map +1 -1
- package/esm/policies/JsTsFileHeaders.d.ts +1 -1
- package/esm/policies/JsTsFileHeaders.d.ts.map +1 -1
- package/esm/policies/JsTsFileHeaders.js +11 -7
- package/esm/policies/JsTsFileHeaders.js.map +1 -1
- package/esm/policies/LicenseFileExists.d.ts.map +1 -1
- package/esm/policies/LicenseFileExists.js +22 -18
- package/esm/policies/LicenseFileExists.js.map +1 -1
- package/esm/policies/MutuallyExclusiveScripts.d.ts +46 -0
- package/esm/policies/MutuallyExclusiveScripts.d.ts.map +1 -0
- package/esm/policies/MutuallyExclusiveScripts.js +52 -0
- package/esm/policies/MutuallyExclusiveScripts.js.map +1 -0
- package/esm/policies/NoJsFileExtensions.d.ts.map +1 -1
- package/esm/policies/NoJsFileExtensions.js +16 -12
- package/esm/policies/NoJsFileExtensions.js.map +1 -1
- package/esm/policies/NoLargeBinaryFiles.d.ts.map +1 -1
- package/esm/policies/NoLargeBinaryFiles.js +35 -31
- package/esm/policies/NoLargeBinaryFiles.js.map +1 -1
- package/esm/policies/NoPrivateWorkspaceDependencies.d.ts +1 -1
- package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
- package/esm/policies/NoPrivateWorkspaceDependencies.js +53 -45
- package/esm/policies/NoPrivateWorkspaceDependencies.js.map +1 -1
- package/esm/policies/PackageAllowedScopes.d.ts +1 -1
- package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
- package/esm/policies/PackageAllowedScopes.js +45 -40
- package/esm/policies/PackageAllowedScopes.js.map +1 -1
- package/esm/policies/PackageEsmType.d.ts +1 -1
- package/esm/policies/PackageEsmType.d.ts.map +1 -1
- package/esm/policies/PackageEsmType.js +48 -44
- package/esm/policies/PackageEsmType.js.map +1 -1
- package/esm/policies/PackageFolderName.d.ts +1 -1
- package/esm/policies/PackageFolderName.d.ts.map +1 -1
- package/esm/policies/PackageFolderName.js +38 -34
- package/esm/policies/PackageFolderName.js.map +1 -1
- package/esm/policies/PackageJsonProperties.d.ts +1 -1
- package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
- package/esm/policies/PackageJsonProperties.js +36 -31
- package/esm/policies/PackageJsonProperties.js.map +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
- package/esm/policies/PackageJsonRepoDirectoryProperty.js +41 -38
- package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
- package/esm/policies/PackageJsonSorted.d.ts +1 -1
- package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
- package/esm/policies/PackageJsonSorted.js +40 -36
- package/esm/policies/PackageJsonSorted.js.map +1 -1
- package/esm/policies/PackageLicense.d.ts +1 -1
- package/esm/policies/PackageLicense.d.ts.map +1 -1
- package/esm/policies/PackageLicense.js +58 -54
- package/esm/policies/PackageLicense.js.map +1 -1
- package/esm/policies/PackagePrivateField.d.ts +1 -1
- package/esm/policies/PackagePrivateField.d.ts.map +1 -1
- package/esm/policies/PackagePrivateField.js +58 -54
- package/esm/policies/PackagePrivateField.js.map +1 -1
- package/esm/policies/PackageReadme.d.ts +1 -1
- package/esm/policies/PackageReadme.d.ts.map +1 -1
- package/esm/policies/PackageReadme.js +30 -26
- package/esm/policies/PackageReadme.js.map +1 -1
- package/esm/policies/PackageScripts.d.ts +1 -1
- package/esm/policies/PackageScripts.d.ts.map +1 -1
- package/esm/policies/PackageScripts.js +39 -35
- package/esm/policies/PackageScripts.js.map +1 -1
- package/esm/policies/PackageTestScripts.d.ts +1 -1
- package/esm/policies/PackageTestScripts.d.ts.map +1 -1
- package/esm/policies/PackageTestScripts.js +46 -40
- package/esm/policies/PackageTestScripts.js.map +1 -1
- package/esm/policies/RequiredGitignorePatterns.d.ts.map +1 -1
- package/esm/policies/RequiredGitignorePatterns.js +20 -15
- package/esm/policies/RequiredGitignorePatterns.js.map +1 -1
- package/esm/policies/RequiredScripts.d.ts +71 -0
- package/esm/policies/RequiredScripts.d.ts.map +1 -0
- package/esm/policies/RequiredScripts.js +120 -0
- package/esm/policies/RequiredScripts.js.map +1 -0
- package/esm/policies/ScriptContains.d.ts +64 -0
- package/esm/policies/ScriptContains.d.ts.map +1 -0
- package/esm/policies/ScriptContains.js +62 -0
- package/esm/policies/ScriptContains.js.map +1 -0
- package/esm/policies.d.ts +6 -1
- package/esm/policies.d.ts.map +1 -1
- package/esm/policies.js +18 -0
- package/esm/policies.js.map +1 -1
- package/esm/policy.d.ts +193 -74
- package/esm/policy.d.ts.map +1 -1
- package/esm/policy.js +110 -19
- package/esm/policy.js.map +1 -1
- package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +49 -2
- package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
- package/esm/policyDefiners/defineFileHeaderPolicy.js +21 -4
- package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
- package/esm/policyDefiners/definePackagePolicy.d.ts +57 -3
- package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
- package/esm/policyDefiners/definePackagePolicy.js +50 -5
- package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
- package/esm/tsdoc-metadata.json +1 -1
- package/oclif.manifest.json +1 -1
- package/package.json +6 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,72 @@
|
|
|
1
1
|
# repopo
|
|
2
2
|
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- Add new `policy()` function as simplified API for defining repository policies, replacing the more complex `makePolicy`/`makePolicyDefinition` workflow. _[`#617`](https://github.com/tylerbutler/tools-monorepo/pull/617) [`becd406`](https://github.com/tylerbutler/tools-monorepo/commit/becd4064e1434b2384cda991f2d0702d91ed5ed9) [@tylerbutler](https://github.com/tylerbutler)_
|
|
8
|
+
|
|
9
|
+
New features:
|
|
10
|
+
- `policy()` function with multiple overload signatures for defining policies concisely
|
|
11
|
+
- `PolicyShape` interface for object-literal policy definitions
|
|
12
|
+
- `ConfiguredPolicy` and `PolicyError` types for the new API surface
|
|
13
|
+
- Five new script-focused policies: `RequiredScripts`, `ExactScripts`, `MutuallyExclusiveScripts`, `ConditionalScripts`, and `ScriptContains`
|
|
14
|
+
- `isPolicyError` type guard and `convertLegacyResult`/`convertToPolicyFailure` conversion utilities
|
|
15
|
+
|
|
16
|
+
Deprecations (old APIs still work but are marked `@deprecated`):
|
|
17
|
+
- `makePolicy` → use `policy()` instead
|
|
18
|
+
- `makePolicyDefinition` → use `PolicyShape` object literals instead
|
|
19
|
+
- `PolicyFailure` → use `PolicyError` instead
|
|
20
|
+
- `PolicyInstance` → use `ConfiguredPolicy` instead
|
|
21
|
+
- `PolicyStandaloneResolver` → use `PolicyResolver` instead
|
|
22
|
+
- `isPolicyFailure` → use `isPolicyError` instead
|
|
23
|
+
|
|
24
|
+
## 0.9.0
|
|
25
|
+
|
|
26
|
+
### Minor Changes
|
|
27
|
+
|
|
28
|
+
- Make `description` required on PolicyDefinition _[`#594`](https://github.com/tylerbutler/tools-monorepo/pull/594) [`c3d1b65`](https://github.com/tylerbutler/tools-monorepo/commit/c3d1b65299f58b9fa605ebd18e7fb4346ae7745f) [@tylerbutler](https://github.com/tylerbutler)_
|
|
29
|
+
|
|
30
|
+
BREAKING CHANGE: `PolicyDefinition.description` is now required (was optional). All policies must include a description that explains their purpose.
|
|
31
|
+
|
|
32
|
+
All built-in policies now include descriptions.
|
|
33
|
+
|
|
34
|
+
- Use object parameters for policy factory functions and Policy class _[`#594`](https://github.com/tylerbutler/tools-monorepo/pull/594) [`c3d1b65`](https://github.com/tylerbutler/tools-monorepo/commit/c3d1b65299f58b9fa605ebd18e7fb4346ae7745f) [@tylerbutler](https://github.com/tylerbutler)_
|
|
35
|
+
|
|
36
|
+
BREAKING CHANGES:
|
|
37
|
+
- `makePolicyDefinition()` now takes an object argument: `{ name, description, match, handler, defaultConfig?, resolver? }`
|
|
38
|
+
- `definePackagePolicy()` now takes an object argument: `{ name, description, handler }`
|
|
39
|
+
- `defineFileHeaderPolicy()` now takes an object argument: `{ name, description, config }`
|
|
40
|
+
- `Policy` class constructor now takes a `PolicyDefinition` object instead of positional arguments
|
|
41
|
+
|
|
42
|
+
This change makes it easier to add new optional properties in the future without breaking changes.
|
|
43
|
+
|
|
44
|
+
New exports:
|
|
45
|
+
- `makePolicyDefinition` function (previously internal)
|
|
46
|
+
- `PolicyDefinitionInput` type
|
|
47
|
+
- `DefinePackagePolicyArgs` interface
|
|
48
|
+
- `DefineFileHeaderPolicyArgs` interface
|
|
49
|
+
|
|
50
|
+
### Patch Changes
|
|
51
|
+
|
|
52
|
+
- Refactor to use Effection 4 for structured concurrency _[`#379`](https://github.com/tylerbutler/tools-monorepo/pull/379) [`1582ad1`](https://github.com/tylerbutler/tools-monorepo/commit/1582ad1abc79b211492dba2e5172e995c9c47fe0) [@tylerbutler](https://github.com/tylerbutler)_
|
|
53
|
+
- Replace manual async handling with Effection's structured concurrency primitives
|
|
54
|
+
- Policy handlers now support generator functions for better cancellation and resource management
|
|
55
|
+
- Improved internal architecture for concurrent policy execution
|
|
56
|
+
- Added comprehensive test coverage for async/generator patterns
|
|
57
|
+
|
|
58
|
+
<details><summary>Updated 1 dependency</summary>
|
|
59
|
+
|
|
60
|
+
<small>
|
|
61
|
+
|
|
62
|
+
[`c577266`](https://github.com/tylerbutler/tools-monorepo/commit/c577266129da545000aea343256b06129a243987)
|
|
63
|
+
|
|
64
|
+
</small>
|
|
65
|
+
|
|
66
|
+
- `@tylerbu/cli-api@0.10.1`
|
|
67
|
+
|
|
68
|
+
</details>
|
|
69
|
+
|
|
3
70
|
## 0.8.0
|
|
4
71
|
|
|
5
72
|
### Minor Changes
|
package/THIRD-PARTY-LICENSES.txt
CHANGED
|
@@ -27,7 +27,7 @@ OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHE
|
|
|
27
27
|
|
|
28
28
|
The following npm package may be included in this product:
|
|
29
29
|
|
|
30
|
-
- @rushstack/node-core-library@5.19.
|
|
30
|
+
- @rushstack/node-core-library@5.19.1
|
|
31
31
|
|
|
32
32
|
This package contains the following license:
|
|
33
33
|
|
|
@@ -142,11 +142,12 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
142
142
|
|
|
143
143
|
-----------
|
|
144
144
|
|
|
145
|
-
The following npm
|
|
145
|
+
The following npm packages may be included in this product:
|
|
146
146
|
|
|
147
|
+
- effection@4.0.0
|
|
147
148
|
- simple-git@3.30.0
|
|
148
149
|
|
|
149
|
-
|
|
150
|
+
These packages each contain the following license:
|
|
150
151
|
|
|
151
152
|
MIT
|
|
152
153
|
|
|
@@ -61,9 +61,14 @@ function fromFluidHandler(fluidHandler, options) {
|
|
|
61
61
|
};
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
-
return makePolicyDefinition(
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
return makePolicyDefinition({
|
|
65
|
+
name: policyName,
|
|
66
|
+
description: `FluidFramework policy: ${fluidHandler.name}`,
|
|
67
|
+
match: fluidHandler.match,
|
|
68
|
+
handler,
|
|
69
|
+
defaultConfig: undefined, // no config
|
|
70
|
+
resolver,
|
|
71
|
+
});
|
|
67
72
|
}
|
|
68
73
|
/**
|
|
69
74
|
* Converts FluidFramework handlers to repopo PolicyDefinitions.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fluidFramework.js","sourceRoot":"","sources":["../../src/adapters/fluidFramework.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,OAAO,CAAC;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAgExD;;;;;;;;;;GAUG;AACH,SAAS,gBAAgB,CACxB,YAA0B,EAC1B,OAA6B;IAE7B,MAAM,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;IAC1C,MAAM,UAAU,GAAG,GAAG,UAAU,GAAG,YAAY,CAAC,IAAI,EAAE,CAAC;IAEvD,MAAM,OAAO,GAAkB,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,EAAE;QAChE,uCAAuC;QACvC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAE3C,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAEpE,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAChC,OAAO,IAAI,CAAC;QACb,CAAC;QAED,wDAAwD;QACxD,MAAM,WAAW,GAAG,YAAY,CAAC,QAAQ,KAAK,SAAS,CAAC;QAExD,6DAA6D;QAC7D,IAAI,OAAO,IAAI,YAAY,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACpD,MAAM,aAAa,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YAEtE,OAAO;gBACN,IAAI,EAAE,UAAU;gBAChB,IAAI;gBACJ,aAAa,EAAE,CAAC,aAAa,CAAC,OAAO,IAAI,YAAY,CAAC;gBACtD,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,aAAa,CAAC,QAAQ;aACN,CAAC;QAC7B,CAAC;QAED,OAAO;YACN,IAAI,EAAE,UAAU;YAChB,IAAI;YACJ,aAAa,EAAE,CAAC,YAAY,CAAC;YAC7B,WAAW;SACX,CAAC;IACH,CAAC,CAAC;IAEF,sDAAsD;IACtD,IAAI,QAA8C,CAAC;IACnD,IAAI,YAAY,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACzC,QAAQ,GAAG,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;YACnC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YAE3C,0CAA0C;YAC1C,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YAEpE,+EAA+E;YAC/E,MAAM,aAAa,GAAG,MAAM,YAAY,CAAC,QAAS,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YAEvE,OAAO;gBACN,IAAI,EAAE,UAAU;gBAChB,IAAI;gBACJ,aAAa,EAAE;oBACd,aAAa,CAAC,OAAO,IAAI,YAAY,IAAI,eAAe;iBACxD;gBACD,WAAW,EAAE,IAAI;gBACjB,QAAQ,EAAE,aAAa,CAAC,QAAQ;aAChC,CAAC;QACH,CAAC,CAAC;IACH,CAAC;IAED,OAAO,oBAAoB,
|
|
1
|
+
{"version":3,"file":"fluidFramework.js","sourceRoot":"","sources":["../../src/adapters/fluidFramework.ts"],"names":[],"mappings":"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","sourcesContent":["import path from \"pathe\";\nimport { makePolicyDefinition } from \"../makePolicy.js\";\nimport type {\n\tPolicyDefinition,\n\tPolicyFixResult,\n\tPolicyHandler,\n\tPolicyStandaloneResolver,\n} from \"../policy.js\";\n\n/**\n * A FluidFramework build-tools policy handler interface.\n *\n * This interface matches the `Handler` interface from `@fluidframework/build-tools`.\n *\n * @alpha\n */\nexport interface FluidHandler {\n\t/**\n\t * The name of the handler, used for filtering and display.\n\t */\n\tname: string;\n\n\t/**\n\t * A regex pattern that determines which files this handler applies to.\n\t */\n\tmatch: RegExp;\n\n\t/**\n\t * The handler function that checks a file against the policy.\n\t *\n\t * @param file - Absolute path to the file.\n\t * @param root - Path to the repo root.\n\t * @returns `undefined` if the check passes, otherwise an error message string.\n\t */\n\thandler: (file: string, root: string) => Promise<string | undefined>;\n\n\t/**\n\t * Optional resolver function that attempts to fix policy violations.\n\t *\n\t * @param file - Absolute path to the file.\n\t * @param root - Path to the repo root.\n\t * @returns An object indicating whether the fix was successful.\n\t */\n\tresolver?: (\n\t\tfile: string,\n\t\troot: string,\n\t) =>\n\t\t| Promise<{ resolved: boolean; message?: string }>\n\t\t| { resolved: boolean; message?: string };\n}\n\n/**\n * Options for converting FluidFramework handlers to repopo policies.\n *\n * @alpha\n */\nexport interface FluidAdapterOptions {\n\t/**\n\t * Optional prefix to add to policy names. Useful for namespacing Fluid policies.\n\t *\n\t * @example \"Fluid:\" would result in \"Fluid:my-handler-name\"\n\t */\n\tnamePrefix?: string;\n}\n\n/**\n * Converts a FluidFramework handler to a repopo PolicyDefinition.\n *\n * This is an internal function used by {@link fromFluidHandlers}.\n *\n * @param fluidHandler - A FluidFramework Handler object to convert.\n * @param options - Optional configuration for the conversion.\n * @returns A repopo PolicyDefinition that wraps the Fluid handler.\n *\n * @internal\n */\nfunction fromFluidHandler(\n\tfluidHandler: FluidHandler,\n\toptions?: FluidAdapterOptions,\n): PolicyDefinition {\n\tconst { namePrefix = \"\" } = options ?? {};\n\tconst policyName = `${namePrefix}${fluidHandler.name}`;\n\n\tconst handler: PolicyHandler = async ({ file, root, resolve }) => {\n\t\t// Fluid handlers expect absolute paths\n\t\tconst absolutePath = path.join(root, file);\n\n\t\tconst errorMessage = await fluidHandler.handler(absolutePath, root);\n\n\t\tif (errorMessage === undefined) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check if resolver exists to determine if auto-fixable\n\t\tconst autoFixable = fluidHandler.resolver !== undefined;\n\n\t\t// If resolve is requested and we have a resolver, try to fix\n\t\tif (resolve && fluidHandler.resolver !== undefined) {\n\t\t\tconst resolveResult = await fluidHandler.resolver(absolutePath, root);\n\n\t\t\treturn {\n\t\t\t\tname: policyName,\n\t\t\t\tfile,\n\t\t\t\terrorMessages: [resolveResult.message ?? errorMessage],\n\t\t\t\tautoFixable: true,\n\t\t\t\tresolved: resolveResult.resolved,\n\t\t\t} satisfies PolicyFixResult;\n\t\t}\n\n\t\treturn {\n\t\t\tname: policyName,\n\t\t\tfile,\n\t\t\terrorMessages: [errorMessage],\n\t\t\tautoFixable,\n\t\t};\n\t};\n\n\t// Create standalone resolver if Fluid handler has one\n\tlet resolver: PolicyStandaloneResolver | undefined;\n\tif (fluidHandler.resolver !== undefined) {\n\t\tresolver = async ({ file, root }) => {\n\t\t\tconst absolutePath = path.join(root, file);\n\n\t\t\t// First get the error message for context\n\t\t\tconst errorMessage = await fluidHandler.handler(absolutePath, root);\n\n\t\t\t// biome-ignore lint/style/noNonNullAssertion: we checked this is defined above\n\t\t\tconst resolveResult = await fluidHandler.resolver!(absolutePath, root);\n\n\t\t\treturn {\n\t\t\t\tname: policyName,\n\t\t\t\tfile,\n\t\t\t\terrorMessages: [\n\t\t\t\t\tresolveResult.message ?? errorMessage ?? \"Unknown error\",\n\t\t\t\t],\n\t\t\t\tautoFixable: true,\n\t\t\t\tresolved: resolveResult.resolved,\n\t\t\t};\n\t\t};\n\t}\n\n\treturn makePolicyDefinition({\n\t\tname: policyName,\n\t\tdescription: `FluidFramework policy: ${fluidHandler.name}`,\n\t\tmatch: fluidHandler.match,\n\t\thandler,\n\t\tdefaultConfig: undefined, // no config\n\t\tresolver,\n\t});\n}\n\n/**\n * Converts FluidFramework handlers to repopo PolicyDefinitions.\n *\n * This adapter bridges the gap between FluidFramework's build-tools policy system\n * and repopo's policy system, allowing you to reuse existing Fluid policies in repopo.\n *\n * @remarks\n *\n * Key differences handled by this adapter:\n *\n * - **Handler signature**: Fluid uses `(file, root) => string | undefined`,\n * repopo uses `(args) => PolicyHandlerResult`\n *\n * - **File paths**: Fluid passes absolute paths, repopo passes repo-relative paths.\n * The adapter converts between the two.\n *\n * - **Return types**: Fluid returns `string | undefined` (error message or success),\n * repopo returns `true | PolicyFailure | PolicyFixResult`\n *\n * For a single handler, wrap it in an array: `fromFluidHandlers([handler])`.\n *\n * @example\n * ```typescript\n * import { fromFluidHandlers, makePolicy } from \"repopo\";\n * import { copyrightFileHeaderHandlers, fluidCaseHandler } from \"@fluidframework/build-tools\";\n *\n * // Convert multiple handlers with a namespace prefix\n * const FluidCopyrightPolicies = fromFluidHandlers(copyrightFileHeaderHandlers, {\n * namePrefix: \"Fluid:\",\n * });\n *\n * // For a single handler, wrap it in an array\n * const [FluidCasePolicy] = fromFluidHandlers([fluidCaseHandler]);\n *\n * const config: RepopoConfig = {\n * policies: [\n * ...FluidCopyrightPolicies.map(p => makePolicy(p)),\n * makePolicy(FluidCasePolicy),\n * ],\n * };\n * ```\n *\n * @param fluidHandlers - An array of FluidFramework Handler objects to convert.\n * @param options - Optional configuration applied to all conversions.\n * @returns An array of repopo PolicyDefinitions.\n *\n * @alpha\n */\nexport function fromFluidHandlers(\n\tfluidHandlers: FluidHandler[],\n\toptions?: FluidAdapterOptions,\n): PolicyDefinition[] {\n\treturn fluidHandlers.map((h) => fromFluidHandler(h, options));\n}\n"]}
|
package/esm/baseCommand.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"baseCommand.d.ts","sourceRoot":"","sources":["../src/baseCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,iBAAiB,EACjB,KAAK,kBAAkB,
|
|
1
|
+
{"version":3,"file":"baseCommand.d.ts","sourceRoot":"","sources":["../src/baseCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,WAAW,EAChB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,KAAK,SAAS,EAAa,MAAM,YAAY,CAAC;AACvD,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,KAAK,EAAyB,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAKhF;;GAEG;AACH,8BAAsB,iBAAiB,CACrC,CAAC,SAAS,OAAO,iBAAiB,GAAG;IACpC,IAAI,EAAE,OAAO,iBAAiB,CAAC,IAAI,CAAC;IACpC,KAAK,EAAE,OAAO,iBAAiB,CAAC,KAAK,CAAC;CACtC,CAEF,SAAQ,iBAAiB,CAAC,CAAC,EAAE,YAAY,CACzC,YAAW,kBAAkB,CAAC,oBAAoB,CAAC,EAAE,WAAW;IAEhE,UAAmB,aAAa,eAAuB;IACvD,UAAmB,OAAO,oCAAyB;IAEnD,gBAAgC,KAAK;;MAE1B;IAEX,OAAO,CAAC,IAAI,CAAwB;IACpC,IAAW,GAAG,IAAI,SAAS,CAK1B;IAEqB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB3C,OAAO,CAAC,QAAQ,CAAmC;IAEtC,UAAU,IAAI,OAAO,CAAC,oBAAoB,CAAC;CAMxD"}
|
package/esm/baseCommand.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { CommandWithConfig,
|
|
1
|
+
import { CommandWithConfig, } from "@tylerbu/cli-api";
|
|
2
|
+
import { createConsolaLogger } from "@tylerbu/cli-api/loggers/consola";
|
|
2
3
|
import { findGitRootSync } from "@tylerbu/fundamentals/git";
|
|
3
4
|
import { simpleGit } from "simple-git";
|
|
4
5
|
import { DefaultPolicyConfig } from "./config.js";
|
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,GAGjB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,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\ttype RequiresGit,\n} from \"@tylerbu/cli-api\";\nimport { createConsolaLogger } from \"@tylerbu/cli-api/loggers/consola\";\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"]}
|
package/esm/commands/check.d.ts
CHANGED
|
@@ -39,6 +39,7 @@ export declare class CheckPolicy<T extends typeof BaseRepopoCommand & {
|
|
|
39
39
|
private executePolicyHandler;
|
|
40
40
|
private handlePolicyResult;
|
|
41
41
|
private handleFixResult;
|
|
42
|
+
private handlePolicyErrorFixResult;
|
|
42
43
|
private handleFailureResult;
|
|
43
44
|
private attemptResolution;
|
|
44
45
|
private logPolicyFailure;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAkCtD;;;;;;;;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;IA0D1C;;;;;OAKG;IACH,OAAO,CAAE,aAAa;IAetB;;;;;OAKG;IACH,OAAO,CAAE,kBAAkB;IAgB3B,OAAO,CAAE,eAAe;IAwBxB,OAAO,CAAE,eAAe;IAsCxB,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAE,oBAAoB;IAsD7B,OAAO,CAAE,kBAAkB;IAiC3B,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAC,0BAA0B;IAsBlC,OAAO,CAAE,mBAAmB;IAyB5B,OAAO,CAAE,iBAAiB;IAsC1B,OAAO,CAAC,gBAAgB;IA4BxB,OAAO,CAAC,WAAW;CAOnB"}
|
package/esm/commands/check.js
CHANGED
|
@@ -2,10 +2,20 @@ import { EOL as newline } from "node:os";
|
|
|
2
2
|
import process from "node:process";
|
|
3
3
|
import { Flags } from "@oclif/core";
|
|
4
4
|
import { StringBuilder } from "@rushstack/node-core-library";
|
|
5
|
+
import { all, call, run } from "effection";
|
|
5
6
|
import chalk from "picocolors";
|
|
7
|
+
/**
|
|
8
|
+
* Type guard to check if a value is an Effection Operation (generator).
|
|
9
|
+
*/
|
|
10
|
+
function isOperation(value) {
|
|
11
|
+
return (typeof value === "object" &&
|
|
12
|
+
value !== null &&
|
|
13
|
+
"next" in value &&
|
|
14
|
+
typeof value.next === "function");
|
|
15
|
+
}
|
|
6
16
|
import { BaseRepopoCommand } from "../baseCommand.js";
|
|
7
17
|
import { logStats, runWithPerf } from "../perf.js";
|
|
8
|
-
import { isPolicyFixResult, } from "../policy.js";
|
|
18
|
+
import { isPolicyError, isPolicyFixResult, } from "../policy.js";
|
|
9
19
|
async function readStdin() {
|
|
10
20
|
return new Promise((resolve) => {
|
|
11
21
|
const stdin = process.stdin;
|
|
@@ -58,8 +68,10 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
58
68
|
}
|
|
59
69
|
const filePathsToCheck = [];
|
|
60
70
|
if (this.flags.stdin) {
|
|
61
|
-
const stdInput = await
|
|
62
|
-
|
|
71
|
+
const stdInput = await run(function* () {
|
|
72
|
+
return yield* call(() => readStdin());
|
|
73
|
+
});
|
|
74
|
+
if (stdInput !== undefined && stdInput !== null) {
|
|
63
75
|
filePathsToCheck.push(...stdInput
|
|
64
76
|
.replace(
|
|
65
77
|
// normalize slashes in case they're windows paths
|
|
@@ -82,7 +94,7 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
82
94
|
.split("\n"));
|
|
83
95
|
}
|
|
84
96
|
const context = await this.getContext();
|
|
85
|
-
await this.checkAllFiles(filePathsToCheck, context);
|
|
97
|
+
await run(() => this.checkAllFiles(filePathsToCheck, context));
|
|
86
98
|
}
|
|
87
99
|
/**
|
|
88
100
|
* Executes all policies against the provided paths.
|
|
@@ -90,10 +102,10 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
90
102
|
* @param pathsToCheck - All paths that should be checked. Paths should be relative to the repository root.
|
|
91
103
|
* @param context - The context.
|
|
92
104
|
*/
|
|
93
|
-
|
|
105
|
+
*checkAllFiles(pathsToCheck, context) {
|
|
94
106
|
try {
|
|
95
107
|
for (const pathToCheck of pathsToCheck) {
|
|
96
|
-
|
|
108
|
+
yield* this.checkOrExcludeFile(pathToCheck, context);
|
|
97
109
|
}
|
|
98
110
|
}
|
|
99
111
|
finally {
|
|
@@ -108,91 +120,105 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
108
120
|
*
|
|
109
121
|
* @param relPath - A git repo-relative path to a file.
|
|
110
122
|
*/
|
|
111
|
-
|
|
123
|
+
*checkOrExcludeFile(relPath, context) {
|
|
112
124
|
const { perfStats } = context;
|
|
113
125
|
perfStats.count++;
|
|
114
126
|
try {
|
|
115
|
-
|
|
116
|
-
if (wasProcessed) {
|
|
117
|
-
perfStats.processed++;
|
|
118
|
-
}
|
|
127
|
+
yield* this.routeToPolicies(relPath, context);
|
|
119
128
|
}
|
|
120
129
|
catch (error) {
|
|
121
130
|
throw new Error(`Error routing ${relPath} to handler: ${error}\nStack:\n${error.stack}`);
|
|
122
131
|
}
|
|
123
132
|
}
|
|
124
|
-
|
|
133
|
+
*routeToPolicies(relPath, context) {
|
|
125
134
|
const { policies, excludeFromAll } = context;
|
|
126
135
|
// Check exclusions
|
|
127
136
|
if (excludeFromAll.some((regex) => regex.test(relPath))) {
|
|
128
137
|
this.verbose(`Excluded all handlers: ${relPath}`);
|
|
129
|
-
return
|
|
138
|
+
return;
|
|
130
139
|
}
|
|
131
140
|
// Run all matching policies
|
|
132
141
|
const matchingPolicies = policies.filter((policy) => policy.match.test(relPath));
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
// }
|
|
136
|
-
// If no policies match this file, it's still considered processed
|
|
137
|
-
// (we examined it and determined no policies apply)
|
|
138
|
-
if (matchingPolicies.length === 0) {
|
|
139
|
-
return true;
|
|
140
|
-
}
|
|
141
|
-
const results = await Promise.all(matchingPolicies.map(async (policy) => {
|
|
142
|
-
return await this.runPolicyOnFile(relPath, policy, context);
|
|
142
|
+
yield* all(matchingPolicies.map((policy) => {
|
|
143
|
+
return this.runPolicyOnFile(relPath, policy, context);
|
|
143
144
|
}));
|
|
144
|
-
// File is considered processed if at least one policy ran on it
|
|
145
|
-
// If all matching policies excluded it, count as excluded
|
|
146
|
-
return results.some((ran) => ran);
|
|
147
145
|
}
|
|
148
|
-
|
|
146
|
+
*runPolicyOnFile(relPath, policy, context) {
|
|
149
147
|
const { excludePoliciesForFiles, perfStats, gitRoot } = context;
|
|
150
148
|
// Check if the policy is excluded for the file
|
|
151
149
|
if (this.isPolicyExcluded(relPath, policy, excludePoliciesForFiles)) {
|
|
152
150
|
this.verbose(`Excluded from '${policy.name}' policy: ${relPath}`);
|
|
153
|
-
return
|
|
151
|
+
return;
|
|
154
152
|
}
|
|
155
153
|
try {
|
|
156
154
|
// Execute the policy handler
|
|
157
|
-
const result =
|
|
155
|
+
const result = yield* this.executePolicyHandler(relPath, policy, perfStats, gitRoot);
|
|
158
156
|
// Handle the result of the policy execution
|
|
159
|
-
|
|
157
|
+
yield* this.handlePolicyResult(result, relPath, policy, perfStats, gitRoot);
|
|
160
158
|
}
|
|
161
159
|
catch (error) {
|
|
162
160
|
// Log and rethrow the error for higher-level handling
|
|
163
161
|
this.exit(`Error executing policy '${policy.name}' for file '${relPath}': ${error}`);
|
|
164
162
|
}
|
|
165
|
-
return true; // Policy ran (successfully or with error)
|
|
166
163
|
}
|
|
167
164
|
isPolicyExcluded(relPath, policy, excludePoliciesForFiles) {
|
|
168
165
|
return (excludePoliciesForFiles
|
|
169
166
|
.get(policy.name)
|
|
170
167
|
?.some((regex) => regex.test(relPath)) ?? false);
|
|
171
168
|
}
|
|
172
|
-
|
|
169
|
+
*executePolicyHandler(relPath, policy, perfStats, gitRoot) {
|
|
170
|
+
const resolve = this.flags.fix;
|
|
173
171
|
try {
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
172
|
+
const result = yield* runWithPerf(policy.name, "handle", perfStats, function* () {
|
|
173
|
+
const args = {
|
|
174
|
+
file: relPath,
|
|
175
|
+
root: gitRoot,
|
|
176
|
+
resolve,
|
|
177
|
+
config: policy.config,
|
|
178
|
+
};
|
|
179
|
+
// Use normalized _internalHandler if available (from policy() function)
|
|
180
|
+
// This avoids per-invocation type checking
|
|
181
|
+
if (policy._internalHandler) {
|
|
182
|
+
return yield* policy._internalHandler(args);
|
|
183
|
+
}
|
|
184
|
+
// Fallback for policies not created with policy() function
|
|
185
|
+
const handlerResult = policy.handler(args);
|
|
186
|
+
// Handle both Operation (generator) and Promise return types
|
|
187
|
+
if (handlerResult instanceof Promise) {
|
|
188
|
+
return yield* call(() => handlerResult);
|
|
189
|
+
}
|
|
190
|
+
// Check if it's an Effection Operation (generator)
|
|
191
|
+
if (isOperation(handlerResult)) {
|
|
192
|
+
return yield* handlerResult;
|
|
193
|
+
}
|
|
194
|
+
// This should never happen with proper handler typing
|
|
195
|
+
throw new Error(`Unexpected handler result type: ${typeof handlerResult}`);
|
|
196
|
+
});
|
|
197
|
+
if (result === undefined) {
|
|
198
|
+
throw new Error("Policy result was undefined.");
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
181
201
|
}
|
|
182
202
|
catch (error) {
|
|
183
203
|
this.exit(`Error in policy handler '${policy.name}' for file '${relPath}': ${error}`);
|
|
184
204
|
}
|
|
185
205
|
}
|
|
186
|
-
|
|
206
|
+
*handlePolicyResult(result, relPath, policy, perfStats, gitRoot) {
|
|
187
207
|
if (result === true) {
|
|
188
208
|
return;
|
|
189
209
|
}
|
|
210
|
+
// Handle fix results (both legacy and new formats)
|
|
190
211
|
if (isPolicyFixResult(result)) {
|
|
191
212
|
this.handleFixResult(result, policy);
|
|
213
|
+
return;
|
|
192
214
|
}
|
|
193
|
-
|
|
194
|
-
|
|
215
|
+
// Handle new PolicyError with fixed property (fix was attempted)
|
|
216
|
+
if (isPolicyError(result) && result.fixed !== undefined) {
|
|
217
|
+
this.handlePolicyErrorFixResult(result, relPath, policy);
|
|
218
|
+
return;
|
|
195
219
|
}
|
|
220
|
+
// Handle failure results (PolicyFailure or PolicyError without fix)
|
|
221
|
+
yield* this.handleFailureResult(result, relPath, policy, perfStats, gitRoot);
|
|
196
222
|
}
|
|
197
223
|
handleFixResult(result, policy) {
|
|
198
224
|
const messages = new StringBuilder();
|
|
@@ -205,19 +231,45 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
205
231
|
}
|
|
206
232
|
this.logMessages(messages);
|
|
207
233
|
}
|
|
208
|
-
|
|
234
|
+
handlePolicyErrorFixResult(result, file, policy) {
|
|
235
|
+
const messages = new StringBuilder();
|
|
236
|
+
if (result.fixed) {
|
|
237
|
+
messages.append(`Resolved ${policy.name} policy failure for file: ${file}`);
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
messages.append(`Error fixing ${policy.name} policy failure in ${file}`);
|
|
241
|
+
if (result.error) {
|
|
242
|
+
messages.append(`${newline}\t${result.error}`);
|
|
243
|
+
}
|
|
244
|
+
process.exitCode = 1;
|
|
245
|
+
}
|
|
246
|
+
this.logMessages(messages);
|
|
247
|
+
}
|
|
248
|
+
*handleFailureResult(result, relPath, policy, perfStats, gitRoot) {
|
|
209
249
|
const messages = new StringBuilder();
|
|
210
250
|
if (this.flags.fix && policy.resolver) {
|
|
211
|
-
|
|
251
|
+
yield* this.attemptResolution(relPath, policy, policy.resolver, perfStats, gitRoot, messages);
|
|
212
252
|
}
|
|
213
253
|
else {
|
|
214
|
-
this.logPolicyFailure(result, policy, messages);
|
|
254
|
+
this.logPolicyFailure(result, relPath, policy, messages);
|
|
215
255
|
}
|
|
216
256
|
this.logMessages(messages);
|
|
217
257
|
}
|
|
218
|
-
|
|
258
|
+
*attemptResolution(relPath, policy, resolver, perfStats, gitRoot, messages) {
|
|
219
259
|
messages.append(`${newline}Attempting to resolve: ${relPath}`);
|
|
220
|
-
const resolveResult =
|
|
260
|
+
const resolveResult = yield* runWithPerf(policy.name, "resolve", perfStats, function* () {
|
|
261
|
+
const result = resolver({ file: relPath, root: gitRoot });
|
|
262
|
+
// Handle both Operation (generator) and Promise return types
|
|
263
|
+
if (result instanceof Promise) {
|
|
264
|
+
return yield* call(() => result);
|
|
265
|
+
}
|
|
266
|
+
// Check if it's an Effection Operation (generator)
|
|
267
|
+
if (isOperation(result)) {
|
|
268
|
+
return yield* result;
|
|
269
|
+
}
|
|
270
|
+
// This should never happen with proper resolver typing
|
|
271
|
+
throw new Error(`Unexpected resolver result type: ${typeof result}`);
|
|
272
|
+
});
|
|
221
273
|
if (!resolveResult.resolved) {
|
|
222
274
|
process.exitCode = 1;
|
|
223
275
|
}
|
|
@@ -225,11 +277,21 @@ export class CheckPolicy extends BaseRepopoCommand {
|
|
|
225
277
|
messages.append(newline + resolveResult.errorMessages.join(newline));
|
|
226
278
|
}
|
|
227
279
|
}
|
|
228
|
-
logPolicyFailure(result, policy, messages) {
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
messages.append(
|
|
280
|
+
logPolicyFailure(result, file, policy, messages) {
|
|
281
|
+
// Handle both legacy PolicyFailure and new PolicyError formats
|
|
282
|
+
if (isPolicyError(result)) {
|
|
283
|
+
const autoFixable = result.fixable ? chalk.green(" (autofixable)") : "";
|
|
284
|
+
messages.append(`'${chalk.bold(policy.name)}' policy failure${autoFixable}: ${file}`);
|
|
285
|
+
messages.append(`${newline}\t${result.error}`);
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
const autoFixable = result.autoFixable
|
|
289
|
+
? chalk.green(" (autofixable)")
|
|
290
|
+
: "";
|
|
291
|
+
messages.append(`'${chalk.bold(policy.name)}' policy failure${autoFixable}: ${result.file}`);
|
|
292
|
+
if (result.errorMessages?.length > 0) {
|
|
293
|
+
messages.append(`${newline}\t${result.errorMessages.join(`${newline}\t`)}`);
|
|
294
|
+
}
|
|
233
295
|
}
|
|
234
296
|
process.exitCode = 1;
|
|
235
297
|
}
|
|
@@ -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.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"]}
|
|
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 { all, call, type Operation, run } from \"effection\";\nimport chalk from \"picocolors\";\n\n/**\n * Type guard to check if a value is an Effection Operation (generator).\n */\nfunction isOperation<T>(value: unknown): value is Operation<T> {\n\treturn (\n\t\ttypeof value === \"object\" &&\n\t\tvalue !== null &&\n\t\t\"next\" in value &&\n\t\ttypeof (value as { next: unknown }).next === \"function\"\n\t);\n}\n\nimport { BaseRepopoCommand } from \"../baseCommand.js\";\nimport type { RepopoCommandContext } from \"../context.js\";\nimport { logStats, type PolicyHandlerPerfStats, runWithPerf } from \"../perf.js\";\nimport {\n\tisPolicyError,\n\tisPolicyFixResult,\n\ttype PolicyError,\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 run(function* () {\n\t\t\t\treturn yield* call(() => readStdin());\n\t\t\t});\n\n\t\t\tif (stdInput !== undefined && stdInput !== null) {\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 run(() => 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 *checkAllFiles(\n\t\tpathsToCheck: string[],\n\t\tcontext: RepopoCommandContext,\n\t): Operation<void> {\n\t\ttry {\n\t\t\tfor (const pathToCheck of pathsToCheck) {\n\t\t\t\tyield* 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 *checkOrExcludeFile(\n\t\trelPath: string,\n\t\tcontext: RepopoCommandContext,\n\t): Operation<void> {\n\t\tconst { perfStats } = context;\n\t\tperfStats.count++;\n\n\t\ttry {\n\t\t\tyield* this.routeToPolicies(relPath, context);\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 *routeToPolicies(\n\t\trelPath: string,\n\t\tcontext: RepopoCommandContext,\n\t): Operation<void> {\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;\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\tyield* all(\n\t\t\tmatchingPolicies.map((policy) => {\n\t\t\t\treturn this.runPolicyOnFile(relPath, policy, context);\n\t\t\t}),\n\t\t);\n\t}\n\n\tprivate *runPolicyOnFile(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tcontext: RepopoCommandContext,\n\t): Operation<void> {\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;\n\t\t}\n\n\t\ttry {\n\t\t\t// Execute the policy handler\n\t\t\tconst result = yield* 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\tyield* 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\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 *executePolicyHandler(\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t): Operation<PolicyHandlerResult> {\n\t\tconst resolve = this.flags.fix;\n\t\ttry {\n\t\t\tconst result = yield* runWithPerf(\n\t\t\t\tpolicy.name,\n\t\t\t\t\"handle\",\n\t\t\t\tperfStats,\n\t\t\t\tfunction* () {\n\t\t\t\t\tconst args = {\n\t\t\t\t\t\tfile: relPath,\n\t\t\t\t\t\troot: gitRoot,\n\t\t\t\t\t\tresolve,\n\t\t\t\t\t\tconfig: policy.config,\n\t\t\t\t\t};\n\n\t\t\t\t\t// Use normalized _internalHandler if available (from policy() function)\n\t\t\t\t\t// This avoids per-invocation type checking\n\t\t\t\t\tif (policy._internalHandler) {\n\t\t\t\t\t\treturn yield* policy._internalHandler(args);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fallback for policies not created with policy() function\n\t\t\t\t\tconst handlerResult = policy.handler(args);\n\n\t\t\t\t\t// Handle both Operation (generator) and Promise return types\n\t\t\t\t\tif (handlerResult instanceof Promise) {\n\t\t\t\t\t\treturn yield* call(() => handlerResult);\n\t\t\t\t\t}\n\t\t\t\t\t// Check if it's an Effection Operation (generator)\n\t\t\t\t\tif (isOperation<PolicyHandlerResult>(handlerResult)) {\n\t\t\t\t\t\treturn yield* handlerResult;\n\t\t\t\t\t}\n\t\t\t\t\t// This should never happen with proper handler typing\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Unexpected handler result type: ${typeof handlerResult}`,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t);\n\t\t\tif (result === undefined) {\n\t\t\t\tthrow new Error(\"Policy result was undefined.\");\n\t\t\t}\n\t\t\treturn result;\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 *handlePolicyResult(\n\t\tresult: PolicyHandlerResult,\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t): Operation<void> {\n\t\tif (result === true) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle fix results (both legacy and new formats)\n\t\tif (isPolicyFixResult(result)) {\n\t\t\tthis.handleFixResult(result, policy);\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle new PolicyError with fixed property (fix was attempted)\n\t\tif (isPolicyError(result) && result.fixed !== undefined) {\n\t\t\tthis.handlePolicyErrorFixResult(result, relPath, policy);\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle failure results (PolicyFailure or PolicyError without fix)\n\t\tyield* this.handleFailureResult(\n\t\t\tresult,\n\t\t\trelPath,\n\t\t\tpolicy,\n\t\t\tperfStats,\n\t\t\tgitRoot,\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 handlePolicyErrorFixResult(\n\t\tresult: PolicyError,\n\t\tfile: string,\n\t\tpolicy: PolicyInstance,\n\t): void {\n\t\tconst messages = new StringBuilder();\n\n\t\tif (result.fixed) {\n\t\t\tmessages.append(\n\t\t\t\t`Resolved ${policy.name} policy failure for file: ${file}`,\n\t\t\t);\n\t\t} else {\n\t\t\tmessages.append(`Error fixing ${policy.name} policy failure in ${file}`);\n\t\t\tif (result.error) {\n\t\t\t\tmessages.append(`${newline}\\t${result.error}`);\n\t\t\t}\n\t\t\tprocess.exitCode = 1;\n\t\t}\n\n\t\tthis.logMessages(messages);\n\t}\n\n\tprivate *handleFailureResult(\n\t\tresult: PolicyFailure | PolicyError,\n\t\trelPath: string,\n\t\tpolicy: PolicyInstance,\n\t\tperfStats: PolicyHandlerPerfStats,\n\t\tgitRoot: string,\n\t): Operation<void> {\n\t\tconst messages = new StringBuilder();\n\n\t\tif (this.flags.fix && policy.resolver) {\n\t\t\tyield* 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, relPath, policy, messages);\n\t\t}\n\n\t\tthis.logMessages(messages);\n\t}\n\n\tprivate *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): Operation<void> {\n\t\tmessages.append(`${newline}Attempting to resolve: ${relPath}`);\n\t\tconst resolveResult = yield* runWithPerf(\n\t\t\tpolicy.name,\n\t\t\t\"resolve\",\n\t\t\tperfStats,\n\t\t\tfunction* () {\n\t\t\t\tconst result = resolver({ file: relPath, root: gitRoot });\n\n\t\t\t\t// Handle both Operation (generator) and Promise return types\n\t\t\t\tif (result instanceof Promise) {\n\t\t\t\t\treturn yield* call(() => result);\n\t\t\t\t}\n\t\t\t\t// Check if it's an Effection Operation (generator)\n\t\t\t\tif (isOperation<PolicyFixResult>(result)) {\n\t\t\t\t\treturn yield* result;\n\t\t\t\t}\n\t\t\t\t// This should never happen with proper resolver typing\n\t\t\t\tthrow new Error(`Unexpected resolver result type: ${typeof result}`);\n\t\t\t},\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 | PolicyError,\n\t\tfile: string,\n\t\tpolicy: PolicyInstance,\n\t\tmessages: StringBuilder,\n\t): void {\n\t\t// Handle both legacy PolicyFailure and new PolicyError formats\n\t\tif (isPolicyError(result)) {\n\t\t\tconst autoFixable = result.fixable ? chalk.green(\" (autofixable)\") : \"\";\n\t\t\tmessages.append(\n\t\t\t\t`'${chalk.bold(policy.name)}' policy failure${autoFixable}: ${file}`,\n\t\t\t);\n\t\t\tmessages.append(`${newline}\\t${result.error}`);\n\t\t} else {\n\t\t\tconst autoFixable = result.autoFixable\n\t\t\t\t? chalk.green(\" (autofixable)\")\n\t\t\t\t: \"\";\n\t\t\tmessages.append(\n\t\t\t\t`'${chalk.bold(policy.name)}' policy failure${autoFixable}: ${result.file}`,\n\t\t\t);\n\t\t\tif (result.errorMessages?.length > 0) {\n\t\t\t\tmessages.append(\n\t\t\t\t\t`${newline}\\t${result.errorMessages.join(`${newline}\\t`)}`,\n\t\t\t\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"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD;;GAEG;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,2CACE;IAEnB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"list.d.ts","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAGtD;;GAEG;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,2CACE;IAEnB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;CAU1C"}
|
package/esm/commands/list.js
CHANGED
|
@@ -9,7 +9,9 @@ export class ListCommand extends BaseRepopoCommand {
|
|
|
9
9
|
const policies = this.commandConfig?.policies ?? DefaultPolicies;
|
|
10
10
|
// list the handlers then exit
|
|
11
11
|
for (const h of policies) {
|
|
12
|
-
this.log(`${h.name}
|
|
12
|
+
this.log(`${h.name}`);
|
|
13
|
+
this.log(` ${h.description}`);
|
|
14
|
+
this.log(` resolver: ${h.resolver !== undefined}\n`);
|
|
13
15
|
}
|
|
14
16
|
this.log(`${policies.length} TOTAL POLICY HANDLERS`);
|
|
15
17
|
}
|
package/esm/commands/list.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C;;GAEG;AACH,MAAM,OAAO,WAKX,SAAQ,iBAAoB;IACtB,MAAM,CAAmB,OAAO,GACtC,uCAAuC,CAAC;IAEzB,KAAK,CAAC,GAAG;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,IAAI,eAAe,CAAC;QACjE,8BAA8B;QAC9B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,eAAe,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"list.js","sourceRoot":"","sources":["../../src/commands/list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C;;GAEG;AACH,MAAM,OAAO,WAKX,SAAQ,iBAAoB;IACtB,MAAM,CAAmB,OAAO,GACtC,uCAAuC,CAAC;IAEzB,KAAK,CAAC,GAAG;QACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,EAAE,QAAQ,IAAI,eAAe,CAAC;QACjE,8BAA8B;QAC9B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC1B,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YACtB,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,KAAK,SAAS,IAAI,CAAC,CAAC;QACvD,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,wBAAwB,CAAC,CAAC;IACtD,CAAC","sourcesContent":["import { BaseRepopoCommand } from \"../baseCommand.js\";\nimport { DefaultPolicies } from \"../policy.js\";\n\n/**\n * This command lists all the policies configured to run.\n */\nexport class ListCommand<\n\tT extends typeof BaseRepopoCommand & {\n\t\targs: typeof ListCommand.args;\n\t\tflags: typeof ListCommand.flags;\n\t},\n> extends BaseRepopoCommand<T> {\n\tpublic static override readonly summary =\n\t\t\"Lists the policies configured to run.\";\n\n\tpublic override async run(): Promise<void> {\n\t\tconst policies = this.commandConfig?.policies ?? DefaultPolicies;\n\t\t// list the handlers then exit\n\t\tfor (const h of policies) {\n\t\t\tthis.log(`${h.name}`);\n\t\t\tthis.log(` ${h.description}`);\n\t\t\tthis.log(` resolver: ${h.resolver !== undefined}\\n`);\n\t\t}\n\t\tthis.log(`${policies.length} TOTAL POLICY HANDLERS`);\n\t}\n}\n"]}
|