repopo 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/THIRD-PARTY-LICENSES.txt +4 -3
  3. package/esm/adapters/fluidFramework.js +8 -3
  4. package/esm/adapters/fluidFramework.js.map +1 -1
  5. package/esm/baseCommand.d.ts.map +1 -1
  6. package/esm/baseCommand.js +2 -1
  7. package/esm/baseCommand.js.map +1 -1
  8. package/esm/commands/check.d.ts.map +1 -1
  9. package/esm/commands/check.js +69 -44
  10. package/esm/commands/check.js.map +1 -1
  11. package/esm/commands/list.d.ts.map +1 -1
  12. package/esm/commands/list.js +3 -1
  13. package/esm/commands/list.js.map +1 -1
  14. package/esm/generators.d.ts +30 -2
  15. package/esm/generators.d.ts.map +1 -1
  16. package/esm/generators.js +31 -1
  17. package/esm/generators.js.map +1 -1
  18. package/esm/index.d.ts +13 -3
  19. package/esm/index.d.ts.map +1 -1
  20. package/esm/index.js +12 -2
  21. package/esm/index.js.map +1 -1
  22. package/esm/makePolicy.d.ts +31 -2
  23. package/esm/makePolicy.d.ts.map +1 -1
  24. package/esm/makePolicy.js +27 -13
  25. package/esm/makePolicy.js.map +1 -1
  26. package/esm/perf.d.ts +3 -2
  27. package/esm/perf.d.ts.map +1 -1
  28. package/esm/perf.js +2 -2
  29. package/esm/perf.js.map +1 -1
  30. package/esm/policies/HtmlFileHeaders.d.ts.map +1 -1
  31. package/esm/policies/HtmlFileHeaders.js +11 -7
  32. package/esm/policies/HtmlFileHeaders.js.map +1 -1
  33. package/esm/policies/JsTsFileHeaders.d.ts.map +1 -1
  34. package/esm/policies/JsTsFileHeaders.js +11 -7
  35. package/esm/policies/JsTsFileHeaders.js.map +1 -1
  36. package/esm/policies/LicenseFileExists.d.ts.map +1 -1
  37. package/esm/policies/LicenseFileExists.js +22 -18
  38. package/esm/policies/LicenseFileExists.js.map +1 -1
  39. package/esm/policies/NoJsFileExtensions.d.ts.map +1 -1
  40. package/esm/policies/NoJsFileExtensions.js +16 -12
  41. package/esm/policies/NoJsFileExtensions.js.map +1 -1
  42. package/esm/policies/NoLargeBinaryFiles.d.ts.map +1 -1
  43. package/esm/policies/NoLargeBinaryFiles.js +35 -31
  44. package/esm/policies/NoLargeBinaryFiles.js.map +1 -1
  45. package/esm/policies/NoPrivateWorkspaceDependencies.d.ts.map +1 -1
  46. package/esm/policies/NoPrivateWorkspaceDependencies.js +53 -45
  47. package/esm/policies/NoPrivateWorkspaceDependencies.js.map +1 -1
  48. package/esm/policies/PackageAllowedScopes.d.ts.map +1 -1
  49. package/esm/policies/PackageAllowedScopes.js +45 -40
  50. package/esm/policies/PackageAllowedScopes.js.map +1 -1
  51. package/esm/policies/PackageEsmType.d.ts.map +1 -1
  52. package/esm/policies/PackageEsmType.js +48 -44
  53. package/esm/policies/PackageEsmType.js.map +1 -1
  54. package/esm/policies/PackageFolderName.d.ts.map +1 -1
  55. package/esm/policies/PackageFolderName.js +38 -34
  56. package/esm/policies/PackageFolderName.js.map +1 -1
  57. package/esm/policies/PackageJsonProperties.d.ts.map +1 -1
  58. package/esm/policies/PackageJsonProperties.js +36 -31
  59. package/esm/policies/PackageJsonProperties.js.map +1 -1
  60. package/esm/policies/PackageJsonRepoDirectoryProperty.d.ts.map +1 -1
  61. package/esm/policies/PackageJsonRepoDirectoryProperty.js +41 -38
  62. package/esm/policies/PackageJsonRepoDirectoryProperty.js.map +1 -1
  63. package/esm/policies/PackageJsonSorted.d.ts.map +1 -1
  64. package/esm/policies/PackageJsonSorted.js +40 -36
  65. package/esm/policies/PackageJsonSorted.js.map +1 -1
  66. package/esm/policies/PackageLicense.d.ts.map +1 -1
  67. package/esm/policies/PackageLicense.js +58 -54
  68. package/esm/policies/PackageLicense.js.map +1 -1
  69. package/esm/policies/PackagePrivateField.d.ts.map +1 -1
  70. package/esm/policies/PackagePrivateField.js +58 -54
  71. package/esm/policies/PackagePrivateField.js.map +1 -1
  72. package/esm/policies/PackageReadme.d.ts.map +1 -1
  73. package/esm/policies/PackageReadme.js +30 -26
  74. package/esm/policies/PackageReadme.js.map +1 -1
  75. package/esm/policies/PackageScripts.d.ts.map +1 -1
  76. package/esm/policies/PackageScripts.js +39 -35
  77. package/esm/policies/PackageScripts.js.map +1 -1
  78. package/esm/policies/PackageTestScripts.d.ts.map +1 -1
  79. package/esm/policies/PackageTestScripts.js +46 -40
  80. package/esm/policies/PackageTestScripts.js.map +1 -1
  81. package/esm/policies/RequiredGitignorePatterns.d.ts.map +1 -1
  82. package/esm/policies/RequiredGitignorePatterns.js +20 -15
  83. package/esm/policies/RequiredGitignorePatterns.js.map +1 -1
  84. package/esm/policy.d.ts +32 -7
  85. package/esm/policy.d.ts.map +1 -1
  86. package/esm/policy.js +18 -9
  87. package/esm/policy.js.map +1 -1
  88. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts +43 -1
  89. package/esm/policyDefiners/defineFileHeaderPolicy.d.ts.map +1 -1
  90. package/esm/policyDefiners/defineFileHeaderPolicy.js +16 -4
  91. package/esm/policyDefiners/defineFileHeaderPolicy.js.map +1 -1
  92. package/esm/policyDefiners/definePackagePolicy.d.ts +43 -2
  93. package/esm/policyDefiners/definePackagePolicy.d.ts.map +1 -1
  94. package/esm/policyDefiners/definePackagePolicy.js +40 -5
  95. package/esm/policyDefiners/definePackagePolicy.js.map +1 -1
  96. package/esm/tsdoc-metadata.json +1 -1
  97. package/oclif.manifest.json +1 -1
  98. package/package.json +6 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,51 @@
1
1
  # repopo
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 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)_
8
+
9
+ BREAKING CHANGE: `PolicyDefinition.description` is now required (was optional). All policies must include a description that explains their purpose.
10
+
11
+ All built-in policies now include descriptions.
12
+
13
+ - 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)_
14
+
15
+ BREAKING CHANGES:
16
+ - `makePolicyDefinition()` now takes an object argument: `{ name, description, match, handler, defaultConfig?, resolver? }`
17
+ - `definePackagePolicy()` now takes an object argument: `{ name, description, handler }`
18
+ - `defineFileHeaderPolicy()` now takes an object argument: `{ name, description, config }`
19
+ - `Policy` class constructor now takes a `PolicyDefinition` object instead of positional arguments
20
+
21
+ This change makes it easier to add new optional properties in the future without breaking changes.
22
+
23
+ New exports:
24
+ - `makePolicyDefinition` function (previously internal)
25
+ - `PolicyDefinitionInput` type
26
+ - `DefinePackagePolicyArgs` interface
27
+ - `DefineFileHeaderPolicyArgs` interface
28
+
29
+ ### Patch Changes
30
+
31
+ - 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)_
32
+ - Replace manual async handling with Effection's structured concurrency primitives
33
+ - Policy handlers now support generator functions for better cancellation and resource management
34
+ - Improved internal architecture for concurrent policy execution
35
+ - Added comprehensive test coverage for async/generator patterns
36
+
37
+ <details><summary>Updated 1 dependency</summary>
38
+
39
+ <small>
40
+
41
+ [`c577266`](https://github.com/tylerbutler/tools-monorepo/commit/c577266129da545000aea343256b06129a243987)
42
+
43
+ </small>
44
+
45
+ - `@tylerbu/cli-api@0.10.1`
46
+
47
+ </details>
48
+
3
49
  ## 0.8.0
4
50
 
5
51
  ### Minor Changes
@@ -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.0
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 package may be included in this product:
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
- This package contains the following license:
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(policyName, fluidHandler.match, handler, undefined, // no config
65
- undefined, // no description
66
- resolver);
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,CAC1B,UAAU,EACV,YAAY,CAAC,KAAK,EAClB,OAAO,EACP,SAAS,EAAE,YAAY;IACvB,SAAS,EAAE,iBAAiB;IAC5B,QAAQ,CACR,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+CG;AACH,MAAM,UAAU,iBAAiB,CAChC,aAA6B,EAC7B,OAA6B;IAE7B,OAAO,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AAC/D,CAAC","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\tpolicyName,\n\t\tfluidHandler.match,\n\t\thandler,\n\t\tundefined, // no config\n\t\tundefined, // no description\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"]}
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"]}
@@ -1 +1 @@
1
- {"version":3,"file":"baseCommand.d.ts","sourceRoot":"","sources":["../src/baseCommand.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,iBAAiB,EACjB,KAAK,kBAAkB,EAEvB,KAAK,WAAW,EAChB,MAAM,kBAAkB,CAAC;AAE1B,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"}
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"}
@@ -1,4 +1,5 @@
1
- import { CommandWithConfig, createConsolaLogger, } from "@tylerbu/cli-api";
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";
@@ -1 +1 @@
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
+ {"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"]}
@@ -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;YAuBpB,kBAAkB;IAwBhC,OAAO,CAAC,eAAe;YAoBT,mBAAmB;YAyBnB,iBAAiB;IAyB/B,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,WAAW;CAOnB"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAmBA,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;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;IA6C7B,OAAO,CAAE,kBAAkB;IAwB3B,OAAO,CAAC,eAAe;IAoBvB,OAAO,CAAE,mBAAmB;IAyB5B,OAAO,CAAE,iBAAiB;IAsC1B,OAAO,CAAC,gBAAgB;IAgBxB,OAAO,CAAC,WAAW;CAOnB"}
@@ -2,7 +2,17 @@ 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
18
  import { isPolicyFixResult, } from "../policy.js";
@@ -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 readStdin();
62
- if (stdInput !== undefined) {
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
- async checkAllFiles(pathsToCheck, context) {
105
+ *checkAllFiles(pathsToCheck, context) {
94
106
  try {
95
107
  for (const pathToCheck of pathsToCheck) {
96
- await this.checkOrExcludeFile(pathToCheck, context);
108
+ yield* this.checkOrExcludeFile(pathToCheck, context);
97
109
  }
98
110
  }
99
111
  finally {
@@ -108,82 +120,83 @@ export class CheckPolicy extends BaseRepopoCommand {
108
120
  *
109
121
  * @param relPath - A git repo-relative path to a file.
110
122
  */
111
- async checkOrExcludeFile(relPath, context) {
123
+ *checkOrExcludeFile(relPath, context) {
112
124
  const { perfStats } = context;
113
125
  perfStats.count++;
114
126
  try {
115
- const wasProcessed = await this.routeToPolicies(relPath, context);
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
- async routeToPolicies(relPath, context) {
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 false; // File was excluded from all policies
138
+ return;
130
139
  }
131
140
  // Run all matching policies
132
141
  const matchingPolicies = policies.filter((policy) => policy.match.test(relPath));
133
- // for(const policy of matchingPolicies) {
134
- // bars.addFile(policy.name,
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
- async runPolicyOnFile(relPath, policy, context) {
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 false; // Policy didn't run on this file
151
+ return;
154
152
  }
155
153
  try {
156
154
  // Execute the policy handler
157
- const result = await this.executePolicyHandler(relPath, policy, perfStats, gitRoot);
155
+ const result = yield* this.executePolicyHandler(relPath, policy, perfStats, gitRoot);
158
156
  // Handle the result of the policy execution
159
- await this.handlePolicyResult(result, relPath, policy, perfStats, gitRoot);
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
- async executePolicyHandler(relPath, policy, perfStats, gitRoot) {
169
+ *executePolicyHandler(relPath, policy, perfStats, gitRoot) {
170
+ const resolve = this.flags.fix;
173
171
  try {
174
- const action = this.flags.fix ? "resolve" : "check";
175
- return await runWithPerf(policy.name, action, perfStats, () => policy.handler({
176
- file: relPath,
177
- root: gitRoot,
178
- resolve: this.flags.fix,
179
- config: policy.config,
180
- }));
172
+ const result = yield* runWithPerf(policy.name, "handle", perfStats, function* () {
173
+ const handlerResult = policy.handler({
174
+ file: relPath,
175
+ root: gitRoot,
176
+ resolve,
177
+ config: policy.config,
178
+ });
179
+ // Handle both Operation (generator) and Promise return types
180
+ if (handlerResult instanceof Promise) {
181
+ return yield* call(() => handlerResult);
182
+ }
183
+ // Check if it's an Effection Operation (generator)
184
+ if (isOperation(handlerResult)) {
185
+ return yield* handlerResult;
186
+ }
187
+ // This should never happen with proper handler typing
188
+ throw new Error(`Unexpected handler result type: ${typeof handlerResult}`);
189
+ });
190
+ if (result === undefined) {
191
+ throw new Error("Policy result was undefined.");
192
+ }
193
+ return result;
181
194
  }
182
195
  catch (error) {
183
196
  this.exit(`Error in policy handler '${policy.name}' for file '${relPath}': ${error}`);
184
197
  }
185
198
  }
186
- async handlePolicyResult(result, relPath, policy, perfStats, gitRoot) {
199
+ *handlePolicyResult(result, relPath, policy, perfStats, gitRoot) {
187
200
  if (result === true) {
188
201
  return;
189
202
  }
@@ -191,7 +204,7 @@ export class CheckPolicy extends BaseRepopoCommand {
191
204
  this.handleFixResult(result, policy);
192
205
  }
193
206
  else {
194
- await this.handleFailureResult(result, relPath, policy, perfStats, gitRoot);
207
+ yield* this.handleFailureResult(result, relPath, policy, perfStats, gitRoot);
195
208
  }
196
209
  }
197
210
  handleFixResult(result, policy) {
@@ -205,19 +218,31 @@ export class CheckPolicy extends BaseRepopoCommand {
205
218
  }
206
219
  this.logMessages(messages);
207
220
  }
208
- async handleFailureResult(result, relPath, policy, perfStats, gitRoot) {
221
+ *handleFailureResult(result, relPath, policy, perfStats, gitRoot) {
209
222
  const messages = new StringBuilder();
210
223
  if (this.flags.fix && policy.resolver) {
211
- await this.attemptResolution(relPath, policy, policy.resolver, perfStats, gitRoot, messages);
224
+ yield* this.attemptResolution(relPath, policy, policy.resolver, perfStats, gitRoot, messages);
212
225
  }
213
226
  else {
214
227
  this.logPolicyFailure(result, policy, messages);
215
228
  }
216
229
  this.logMessages(messages);
217
230
  }
218
- async attemptResolution(relPath, policy, resolver, perfStats, gitRoot, messages) {
231
+ *attemptResolution(relPath, policy, resolver, perfStats, gitRoot, messages) {
219
232
  messages.append(`${newline}Attempting to resolve: ${relPath}`);
220
- const resolveResult = await runWithPerf(policy.name, "resolve", perfStats, () => resolver({ file: relPath, root: gitRoot }));
233
+ const resolveResult = yield* runWithPerf(policy.name, "resolve", perfStats, function* () {
234
+ const result = resolver({ file: relPath, root: gitRoot });
235
+ // Handle both Operation (generator) and Promise return types
236
+ if (result instanceof Promise) {
237
+ return yield* call(() => result);
238
+ }
239
+ // Check if it's an Effection Operation (generator)
240
+ if (isOperation(result)) {
241
+ return yield* result;
242
+ }
243
+ // This should never happen with proper resolver typing
244
+ throw new Error(`Unexpected resolver result type: ${typeof result}`);
245
+ });
221
246
  if (!resolveResult.resolved) {
222
247
  process.exitCode = 1;
223
248
  }
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,IAAI,OAAO,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,OAAO,EAAE,QAAQ,EAA+B,WAAW,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,EACN,iBAAiB,GAMjB,MAAM,cAAc,CAAC;AAEtB,KAAK,UAAU,SAAS;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC9B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAC5B,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAE1B,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YAC1B,IAAI,IAAI,KAAK,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;YACpB,OAAO,CAAC,IAAI,CAAC,CAAC;QACf,CAAC,CAAC,CAAC;QAEH,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,CAAC,EAAE,CAAC,CAAC;QACb,CAAC;IACF,CAAC,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,WAKX,SAAQ,iBAAoB;IACtB,MAAM,CAAmB,OAAO,GACtC,6DAA6D,CAAC;IAExD,MAAM,CAAmB,KAAK,GAAG;QACvC,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC;YAClB,OAAO,EAAE,CAAC,SAAS,CAAC;YACpB,WAAW,EAAE,yBAAyB;YACtC,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,GAAG;SACT,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;YACpB,WAAW,EAAE,gCAAgC;YAC7C,QAAQ,EAAE,KAAK;SACf,CAAC;QACF,GAAG,iBAAiB,CAAC,KAAK;KACjB,CAAC;IAEK,KAAK,CAAC,GAAG;QACxB,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;QAC5C,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC;QAClC,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,IAAI,EAAE,CAAC;QACxC,IAAI,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,MAAM,mBAAmB,CAAC,CAAC;QACpD,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YAC1B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC;QAED,MAAM,gBAAgB,GAAa,EAAE,CAAC;QAEtC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACtB,MAAM,QAAQ,GAAG,MAAM,SAAS,EAAE,CAAC;YAEnC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC5B,gBAAgB,CAAC,IAAI,CACpB,GAAG,QAAQ;qBACT,OAAO;gBACP,kDAAkD;gBAClD,KAAK,EACL,GAAG,CACH;qBACA,KAAK,CAAC,IAAI,CAAC,CACb,CAAC;YACH,CAAC;QACF,CAAC;aAAM,CAAC;YACP,MAAM,QAAQ,GACb,CAAC,MAAM,IAAI,CAAC,GAAG,CAAC,GAAG,CAClB,UAAU;YACV,2CAA2C;YAC3C,KAAK;YACL,2DAA2D;YAC3D,oBAAoB;YACpB,qGAAqG;YACrG,aAAa,CACb,CAAC,IAAI,EAAE,CAAC;YAEV,gBAAgB,CAAC,IAAI,CACpB,GAAG,QAAQ;iBACT,OAAO;YACP,kDAAkD;YAClD,KAAK,EACL,GAAG,CACH;iBACA,KAAK,CAAC,IAAI,CAAC,CACb,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAyB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAE9D,MAAM,IAAI,CAAC,aAAa,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC;IACrD,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,aAAa,CAC1B,YAAsB,EACtB,OAA6B;QAE7B,IAAI,CAAC;YACJ,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;gBACxC,MAAM,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;YACrD,CAAC;QACF,CAAC;gBAAS,CAAC;YACV,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACvB,QAAQ,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAC1C,CAAC;QACF,CAAC;IACF,CAAC;IAED;;;;;OAKG;IACK,KAAK,CAAC,kBAAkB,CAC/B,OAAe,EACf,OAA6B;QAE7B,MAAM,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;QAC9B,SAAS,CAAC,KAAK,EAAE,CAAC;QAElB,IAAI,CAAC;YACJ,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YAClE,IAAI,YAAY,EAAE,CAAC;gBAClB,SAAS,CAAC,SAAS,EAAE,CAAC;YACvB,CAAC;QACF,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CACd,iBAAiB,OAAO,gBAAgB,KAAK,aAAc,KAAe,CAAC,KAAK,EAAE,CAClF,CAAC;QACH,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,eAAe,CAC5B,OAAe,EACf,OAA6B;QAE7B,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;QAE7C,mBAAmB;QACnB,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACzD,IAAI,CAAC,OAAO,CAAC,0BAA0B,OAAO,EAAE,CAAC,CAAC;YAClD,OAAO,KAAK,CAAC,CAAC,sCAAsC;QACrD,CAAC;QAED,4BAA4B;QAC5B,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CACnD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAC1B,CAAC;QAEF,0CAA0C;QAC1C,6BAA6B;QAC7B,IAAI;QAEJ,kEAAkE;QAClE,oDAAoD;QACpD,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,gBAAgB,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACrC,OAAO,MAAM,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QAC7D,CAAC,CAAC,CACF,CAAC;QAEF,gEAAgE;QAChE,0DAA0D;QAC1D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,eAAe,CAC5B,OAAe,EACf,MAAsB,EACtB,OAA6B;QAE7B,MAAM,EAAE,uBAAuB,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAEhE,+CAA+C;QAC/C,IAAI,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,uBAAuB,CAAC,EAAE,CAAC;YACrE,IAAI,CAAC,OAAO,CAAC,kBAAkB,MAAM,CAAC,IAAI,aAAa,OAAO,EAAE,CAAC,CAAC;YAClE,OAAO,KAAK,CAAC,CAAC,iCAAiC;QAChD,CAAC;QAED,IAAI,CAAC;YACJ,6BAA6B;YAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAC7C,OAAO,EACP,MAAM,EACN,SAAS,EACT,OAAO,CACP,CAAC;YAEF,4CAA4C;YAC5C,MAAM,IAAI,CAAC,kBAAkB,CAC5B,MAAM,EACN,OAAO,EACP,MAAM,EACN,SAAS,EACT,OAAO,CACP,CAAC;QACH,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACzB,sDAAsD;YACtD,IAAI,CAAC,IAAI,CACR,2BAA2B,MAAM,CAAC,IAAI,eAAe,OAAO,MAAM,KAAK,EAAE,CACzE,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC,CAAC,0CAA0C;IACxD,CAAC;IAEO,gBAAgB,CACvB,OAAe,EACf,MAAsB,EACtB,uBAA8C;QAE9C,OAAO,CACN,uBAAuB;aACrB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;YACjB,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAChD,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,oBAAoB,CACjC,OAAe,EACf,MAAsB,EACtB,SAAiC,EACjC,OAAe;QAEf,IAAI,CAAC;YACJ,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;YACpD,OAAO,MAAM,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,CAC7D,MAAM,CAAC,OAAO,CAAC;gBACd,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG;gBACvB,MAAM,EAAE,MAAM,CAAC,MAAM;aACrB,CAAC,CACF,CAAC;QACH,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CACR,4BAA4B,MAAM,CAAC,IAAI,eAAe,OAAO,MAAM,KAAK,EAAE,CAC1E,CAAC;QACH,CAAC;IACF,CAAC;IAEO,KAAK,CAAC,kBAAkB,CAC/B,MAA2B,EAC3B,OAAe,EACf,MAAsB,EACtB,SAAiC,EACjC,OAAe;QAEf,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO;QACR,CAAC;QAED,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACtC,CAAC;aAAM,CAAC;YACP,MAAM,IAAI,CAAC,mBAAmB,CAC7B,MAAM,EACN,OAAO,EACP,MAAM,EACN,SAAS,EACT,OAAO,CACP,CAAC;QACH,CAAC;IACF,CAAC;IAEO,eAAe,CACtB,MAAuB,EACvB,MAAsB;QAEtB,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAErC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrB,QAAQ,CAAC,MAAM,CACd,YAAY,MAAM,CAAC,IAAI,6BAA6B,MAAM,CAAC,IAAI,EAAE,CACjE,CAAC;QACH,CAAC;aAAM,CAAC;YACP,QAAQ,CAAC,MAAM,CACd,gBAAgB,MAAM,CAAC,IAAI,sBAAsB,MAAM,CAAC,IAAI,EAAE,CAC9D,CAAC;YACF,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAChC,MAAqB,EACrB,OAAe,EACf,MAAsB,EACtB,SAAiC,EACjC,OAAe;QAEf,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QAErC,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACvC,MAAM,IAAI,CAAC,iBAAiB,CAC3B,OAAO,EACP,MAAM,EACN,MAAM,CAAC,QAAQ,EACf,SAAS,EACT,OAAO,EACP,QAAQ,CACR,CAAC;QACH,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QACjD,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC5B,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAC9B,OAAe,EACf,MAAsB,EACtB,QAAkC,EAClC,SAAiC,EACjC,OAAe,EACf,QAAuB;QAEvB,QAAQ,CAAC,MAAM,CAAC,GAAG,OAAO,0BAA0B,OAAO,EAAE,CAAC,CAAC;QAC/D,MAAM,aAAa,GAAG,MAAM,WAAW,CACtC,MAAM,CAAC,IAAI,EACX,SAAS,EACT,SAAS,EACT,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAChD,CAAC;QAEF,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;YAC7B,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACtB,CAAC;QAED,IAAI,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7C,QAAQ,CAAC,MAAM,CAAC,OAAO,GAAG,aAAa,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACtE,CAAC;IACF,CAAC;IAEO,gBAAgB,CACvB,MAAqB,EACrB,MAAsB,EACtB,QAAuB;QAEvB,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5E,QAAQ,CAAC,MAAM,CACd,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,WAAW,KAAK,MAAM,CAAC,IAAI,EAAE,CAC3E,CAAC;QACF,IAAI,MAAM,CAAC,aAAa,EAAE,MAAM,GAAG,CAAC,EAAE,CAAC;YACtC,QAAQ,CAAC,MAAM,CACd,GAAG,OAAO,KAAK,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,OAAO,IAAI,CAAC,EAAE,CAC1D,CAAC;QACH,CAAC;QACD,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACtB,CAAC;IACO,WAAW,CAAC,QAAuB;QAC1C,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACP,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC;QACnC,CAAC;IACF,CAAC","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\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 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 handlerResult = policy.handler({\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// 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\tif (isPolicyFixResult(result)) {\n\t\t\tthis.handleFixResult(result, policy);\n\t\t} else {\n\t\t\tyield* 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 *handleFailureResult(\n\t\tresult: PolicyFailure,\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, 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,\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 +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;CAQ1C"}
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"}
@@ -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}\nresolver: ${h.resolver !== undefined}\n`);
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
  }
@@ -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;QAChE,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}\\nresolver: ${h.resolver !== undefined}\\n`);\n\t\t}\n\t\tthis.log(`${policies.length} TOTAL POLICY HANDLERS`);\n\t}\n}\n"]}
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"]}
@@ -12,10 +12,38 @@ export type PolicyCreatorFunction<C = undefined> = (args: PolicyDefinition<C>) =
12
12
  */
13
13
  export type PolicyCreatorConstructor<C = undefined> = new (args: PolicyDefinition<C>) => PolicyDefinition<C>;
14
14
  /**
15
- * A PolicyCreator is a function that can be used to generate a {@link PolicyDefinition}. The function can be a free function
16
- * or a constructor that creates a class implementing the {@link PolicyDefinition} interface.
15
+ * A PolicyCreator is a function that can be used to generate a {@link PolicyDefinition}. The function can be a free
16
+ * function or a constructor that creates a class implementing the {@link PolicyDefinition} interface.
17
17
  *
18
18
  * @alpha
19
19
  */
20
20
  export type PolicyCreator = PolicyCreatorConstructor | PolicyCreatorFunction;
21
+ /**
22
+ * Checks if a given function is a generator function.
23
+ *
24
+ * A generator function is a function that can be paused and resumed, and can yield
25
+ * multiple values over time. This utility function helps identify such functions
26
+ * by checking their constructor name.
27
+ *
28
+ * @param fn - The function to check
29
+ * @returns `true` if the function is a generator function, `false` otherwise
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * function* myGenerator() {
34
+ * yield 1;
35
+ * yield 2;
36
+ * }
37
+ *
38
+ * function regularFunction() {
39
+ * return 1;
40
+ * }
41
+ *
42
+ * console.log(isGeneratorFunction(myGenerator)); // true
43
+ * console.log(isGeneratorFunction(regularFunction)); // false
44
+ * ```
45
+ *
46
+ * @alpha
47
+ */
48
+ export declare function isGeneratorFunction(fn: Function): fn is GeneratorFunction;
21
49
  //# sourceMappingURL=generators.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../src/generators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,GAAG,SAAS,IAAI,CAClD,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,KACrB,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAEzB;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,CAAC,CAAC,GAAG,SAAS,IAAI,KACrD,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,KACrB,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,wBAAwB,GAAG,qBAAqB,CAAC"}
1
+ {"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../src/generators.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,GAAG,SAAS,IAAI,CAClD,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,KACrB,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAEzB;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,CAAC,CAAC,GAAG,SAAS,IAAI,KACrD,IAAI,EAAE,gBAAgB,CAAC,CAAC,CAAC,KACrB,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,wBAAwB,GAAG,qBAAqB,CAAC;AAE7E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,QAAQ,GAAG,EAAE,IAAI,iBAAiB,CAEzE"}
package/esm/generators.js CHANGED
@@ -1,2 +1,32 @@
1
- export {};
1
+ /**
2
+ * Checks if a given function is a generator function.
3
+ *
4
+ * A generator function is a function that can be paused and resumed, and can yield
5
+ * multiple values over time. This utility function helps identify such functions
6
+ * by checking their constructor name.
7
+ *
8
+ * @param fn - The function to check
9
+ * @returns `true` if the function is a generator function, `false` otherwise
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * function* myGenerator() {
14
+ * yield 1;
15
+ * yield 2;
16
+ * }
17
+ *
18
+ * function regularFunction() {
19
+ * return 1;
20
+ * }
21
+ *
22
+ * console.log(isGeneratorFunction(myGenerator)); // true
23
+ * console.log(isGeneratorFunction(regularFunction)); // false
24
+ * ```
25
+ *
26
+ * @alpha
27
+ */
28
+ // biome-ignore lint/complexity/noBannedTypes: broad type is OK here
29
+ export function isGeneratorFunction(fn) {
30
+ return fn.constructor.name === "GeneratorFunction";
31
+ }
2
32
  //# sourceMappingURL=generators.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"generators.js","sourceRoot":"","sources":["../src/generators.ts"],"names":[],"mappings":"","sourcesContent":["import type { PolicyDefinition } from \"./policy.js\";\n\n/**\n * The definition of a free function that returns a RepoPolicy.\n *\n * @alpha\n */\nexport type PolicyCreatorFunction<C = undefined> = (\n\targs: PolicyDefinition<C>,\n) => PolicyDefinition<C>;\n\n/**\n * The definition of a constructor function that returns a RepoPolicy.\n *\n * @alpha\n */\nexport type PolicyCreatorConstructor<C = undefined> = new (\n\targs: PolicyDefinition<C>,\n) => PolicyDefinition<C>;\n\n/**\n * A PolicyCreator is a function that can be used to generate a {@link PolicyDefinition}. The function can be a free function\n * or a constructor that creates a class implementing the {@link PolicyDefinition} interface.\n *\n * @alpha\n */\nexport type PolicyCreator = PolicyCreatorConstructor | PolicyCreatorFunction;\n"]}
1
+ {"version":3,"file":"generators.js","sourceRoot":"","sources":["../src/generators.ts"],"names":[],"mappings":"AA4BA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,oEAAoE;AACpE,MAAM,UAAU,mBAAmB,CAAC,EAAY;IAC/C,OAAO,EAAE,CAAC,WAAW,CAAC,IAAI,KAAK,mBAAmB,CAAC;AACpD,CAAC","sourcesContent":["import type { PolicyDefinition } from \"./policy.js\";\n\n/**\n * The definition of a free function that returns a RepoPolicy.\n *\n * @alpha\n */\nexport type PolicyCreatorFunction<C = undefined> = (\n\targs: PolicyDefinition<C>,\n) => PolicyDefinition<C>;\n\n/**\n * The definition of a constructor function that returns a RepoPolicy.\n *\n * @alpha\n */\nexport type PolicyCreatorConstructor<C = undefined> = new (\n\targs: PolicyDefinition<C>,\n) => PolicyDefinition<C>;\n\n/**\n * A PolicyCreator is a function that can be used to generate a {@link PolicyDefinition}. The function can be a free\n * function or a constructor that creates a class implementing the {@link PolicyDefinition} interface.\n *\n * @alpha\n */\nexport type PolicyCreator = PolicyCreatorConstructor | PolicyCreatorFunction;\n\n/**\n * Checks if a given function is a generator function.\n *\n * A generator function is a function that can be paused and resumed, and can yield\n * multiple values over time. This utility function helps identify such functions\n * by checking their constructor name.\n *\n * @param fn - The function to check\n * @returns `true` if the function is a generator function, `false` otherwise\n *\n * @example\n * ```typescript\n * function* myGenerator() {\n * yield 1;\n * yield 2;\n * }\n *\n * function regularFunction() {\n * return 1;\n * }\n *\n * console.log(isGeneratorFunction(myGenerator)); // true\n * console.log(isGeneratorFunction(regularFunction)); // false\n * ```\n *\n * @alpha\n */\n// biome-ignore lint/complexity/noBannedTypes: broad type is OK here\nexport function isGeneratorFunction(fn: Function): fn is GeneratorFunction {\n\treturn fn.constructor.name === \"GeneratorFunction\";\n}\n"]}