@webpieces/code-rules 0.3.351 → 0.3.352

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 (67) hide show
  1. package/package.json +7 -2
  2. package/src/cli.d.ts +1 -1
  3. package/src/cli.js +27 -5
  4. package/src/cli.js.map +1 -1
  5. package/src/code-rules-app.d.ts +13 -0
  6. package/src/code-rules-app.js +31 -0
  7. package/src/code-rules-app.js.map +1 -0
  8. package/src/code-rules-config-table.d.ts +10 -0
  9. package/src/code-rules-config-table.js +31 -0
  10. package/src/code-rules-config-table.js.map +1 -0
  11. package/src/code-rules-context.d.ts +19 -0
  12. package/src/code-rules-context.js +28 -0
  13. package/src/code-rules-context.js.map +1 -0
  14. package/src/code-rules-engine.d.ts +67 -0
  15. package/src/code-rules-engine.js +156 -0
  16. package/src/code-rules-engine.js.map +1 -0
  17. package/src/code-validator.d.ts +10 -0
  18. package/src/code-validator.js +15 -1
  19. package/src/code-validator.js.map +1 -1
  20. package/src/rule-reporter.d.ts +15 -10
  21. package/src/rule-reporter.js +59 -47
  22. package/src/rule-reporter.js.map +1 -1
  23. package/src/validate-catch-error-pattern.js +9 -2
  24. package/src/validate-catch-error-pattern.js.map +1 -1
  25. package/src/validate-code.d.ts +8 -5
  26. package/src/validate-code.js +22 -70
  27. package/src/validate-code.js.map +1 -1
  28. package/src/validate-dtos.js +9 -2
  29. package/src/validate-dtos.js.map +1 -1
  30. package/src/validate-framework-tag.js +11 -2
  31. package/src/validate-framework-tag.js.map +1 -1
  32. package/src/validate-inject-annotation-not-needed-for-concrete-class.js +9 -2
  33. package/src/validate-inject-annotation-not-needed-for-concrete-class.js.map +1 -1
  34. package/src/validate-match-rules.d.ts +17 -11
  35. package/src/validate-match-rules.js +116 -120
  36. package/src/validate-match-rules.js.map +1 -1
  37. package/src/validate-modified-files.js +9 -2
  38. package/src/validate-modified-files.js.map +1 -1
  39. package/src/validate-modified-methods.js +9 -2
  40. package/src/validate-modified-methods.js.map +1 -1
  41. package/src/validate-no-any-unknown.js +9 -2
  42. package/src/validate-no-any-unknown.js.map +1 -1
  43. package/src/validate-no-destructure.js +9 -2
  44. package/src/validate-no-destructure.js.map +1 -1
  45. package/src/validate-no-direct-api-resolver.js +9 -2
  46. package/src/validate-no-direct-api-resolver.js.map +1 -1
  47. package/src/validate-no-function-outside-class.js +9 -2
  48. package/src/validate-no-function-outside-class.js.map +1 -1
  49. package/src/validate-no-implicit-any.js +9 -2
  50. package/src/validate-no-implicit-any.js.map +1 -1
  51. package/src/validate-no-inline-types.js +9 -2
  52. package/src/validate-no-inline-types.js.map +1 -1
  53. package/src/validate-no-process-exit-outside-main.js +9 -2
  54. package/src/validate-no-process-exit-outside-main.js.map +1 -1
  55. package/src/validate-no-symbol-di-tokens.js +9 -2
  56. package/src/validate-no-symbol-di-tokens.js.map +1 -1
  57. package/src/validate-no-unmanaged-exceptions.js +9 -2
  58. package/src/validate-no-unmanaged-exceptions.js.map +1 -1
  59. package/src/validate-prisma-converters.js +9 -2
  60. package/src/validate-prisma-converters.js.map +1 -1
  61. package/src/validate-return-types.js +9 -2
  62. package/src/validate-return-types.js.map +1 -1
  63. package/src/validate-role-tag.js +11 -2
  64. package/src/validate-role-tag.js.map +1 -1
  65. package/src/wp-ci.d.ts +1 -1
  66. package/src/wp-ci.js +20 -3
  67. package/src/wp-ci.js.map +1 -1
@@ -1,57 +1,69 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runValidators = runValidators;
3
+ exports.RuleReporter = void 0;
4
+ const tslib_1 = require("tslib");
4
5
  const rules_config_1 = require("@webpieces/rules-config");
5
- // Human/CI console block for a validator that threw a RuleFailError. code-rules is developer-facing,
6
- // so it prints humanMessage (falls back to aiMessage inside RuleFailError when not set).
7
- function reportRuleFail(err) {
8
- console.error('');
9
- console.error(`❌ [${err.ruleName}] ${err.humanMessage}`);
10
- if (err.line !== undefined) {
11
- console.error(` L${String(err.line)}: ${err.snippet ?? ''}`);
12
- }
13
- for (const hint of err.fixHints) {
14
- console.error(` Fix: ${hint}`);
15
- }
16
- console.error('');
17
- }
18
- // A validator that threw a plain Error is a BUG in the validator — surface it (don't swallow) and
19
- // keep going so it doesn't hide the other validators' results.
20
- function reportCrash(name, error) {
21
- console.error('');
22
- console.error(`❌ Validator '${name}' crashed: ${error.message}`);
23
- console.error(' (a bug in the validator — the other validators still ran)');
24
- console.error('');
25
- }
6
+ const core_context_1 = require("@webpieces/core-context");
7
+ const inversify_1 = require("inversify");
26
8
  /**
27
- * Run every active validator with per-validator isolation: a validator that throws — a `RuleFailError`
28
- * (an expected failure) OR a plain `Error` (a bug) — is caught, reported, and marks the run failed,
29
- * but the remaining validators STILL run. One validator can no longer abort the whole CI run (the
30
- * previous raw loop had no per-validator try/catch, so a single bug aborted everything).
31
- *
32
- * Back-compatible: validators that still `console.error(...)` + `return { success: false }` keep
33
- * working; their `false` result flips the aggregate exactly as before.
9
+ * Runs the active validators with per-validator isolation and prints failures for humans/CI.
34
10
  */
35
- async function runValidators(active, workspaceRoot) {
36
- let anyFailed = false;
37
- for (const validator of active) {
38
- // webpieces-disable no-unmanaged-exceptions -- per-validator isolation chokepoint: one validator must never abort the rest
39
- try {
40
- const result = await validator.run(workspaceRoot);
41
- if (!result.success)
42
- anyFailed = true;
43
- }
44
- catch (err) {
45
- const error = (0, rules_config_1.toError)(err);
46
- if (error instanceof rules_config_1.RuleFailError) {
47
- reportRuleFail(error);
11
+ let RuleReporter = class RuleReporter {
12
+ /**
13
+ * Run every {@link RuleRun} with per-run isolation: a run that throws — a `RuleFailError` (an
14
+ * expected failure) OR a plain `Error` (a bug) is caught, reported, and marks the whole run
15
+ * failed, but the remaining runs STILL execute. One validator can no longer abort the CI run.
16
+ *
17
+ * Back-compatible: runs that still `console.error(...)` + `return { success: false }` keep
18
+ * working; their `false` result flips the aggregate exactly as before.
19
+ */
20
+ async runValidators(runs) {
21
+ let anyFailed = false;
22
+ for (const item of runs) {
23
+ // webpieces-disable no-unmanaged-exceptions -- per-run isolation chokepoint: one validator must never abort the rest
24
+ try {
25
+ const result = await item.run();
26
+ if (!result.success)
27
+ anyFailed = true;
48
28
  }
49
- else {
50
- reportCrash(validator.name, error);
29
+ catch (err) {
30
+ const error = (0, rules_config_1.toError)(err);
31
+ if (error instanceof rules_config_1.RuleFailError) {
32
+ this.reportRuleFail(error);
33
+ }
34
+ else {
35
+ this.reportCrash(item.name, error);
36
+ }
37
+ anyFailed = true;
51
38
  }
52
- anyFailed = true;
53
39
  }
40
+ return { success: !anyFailed };
41
+ }
42
+ // Human/CI console block for a validator that threw a RuleFailError. code-rules is developer-
43
+ // facing, so it prints humanMessage (falls back to aiMessage inside RuleFailError when not set).
44
+ reportRuleFail(err) {
45
+ console.error('');
46
+ console.error(`❌ [${err.ruleName}] ${err.humanMessage}`);
47
+ if (err.line !== undefined) {
48
+ console.error(` L${String(err.line)}: ${err.snippet ?? ''}`);
49
+ }
50
+ for (const hint of err.fixHints) {
51
+ console.error(` Fix: ${hint}`);
52
+ }
53
+ console.error('');
54
+ }
55
+ // A validator that threw a plain Error is a BUG in the validator — surface it (don't swallow) and
56
+ // keep going so it doesn't hide the other validators' results.
57
+ reportCrash(name, error) {
58
+ console.error('');
59
+ console.error(`❌ Validator '${name}' crashed: ${error.message}`);
60
+ console.error(' (a bug in the validator — the other validators still ran)');
61
+ console.error('');
54
62
  }
55
- return { success: !anyFailed };
56
- }
63
+ };
64
+ exports.RuleReporter = RuleReporter;
65
+ exports.RuleReporter = RuleReporter = tslib_1.__decorate([
66
+ (0, core_context_1.provideSingleton)(),
67
+ (0, inversify_1.injectable)()
68
+ ], RuleReporter);
57
69
  //# sourceMappingURL=rule-reporter.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rule-reporter.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/rule-reporter.ts"],"names":[],"mappings":";;AAoCA,sCAqBC;AAzDD,0DAAiF;AAIjF,qGAAqG;AACrG,yFAAyF;AACzF,SAAS,cAAc,CAAC,GAAkB;IACtC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;IACzD,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QACzB,OAAO,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QAC9B,OAAO,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACtB,CAAC;AAED,kGAAkG;AAClG,+DAA+D;AAC/D,SAAS,WAAW,CAAC,IAAY,EAAE,KAAY;IAC3C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAClB,OAAO,CAAC,KAAK,CAAC,gBAAgB,IAAI,cAAc,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,OAAO,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC;IAC9E,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACtB,CAAC;AAED;;;;;;;;GAQG;AACI,KAAK,UAAU,aAAa,CAC/B,MAAgD,EAChD,aAAqB;IAErB,IAAI,SAAS,GAAG,KAAK,CAAC;IACtB,KAAK,MAAM,SAAS,IAAI,MAAM,EAAE,CAAC;QAC7B,2HAA2H;QAC3H,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,OAAO;gBAAE,SAAS,GAAG,IAAI,CAAC;QAC1C,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,KAAK,GAAG,IAAA,sBAAO,EAAC,GAAG,CAAC,CAAC;YAC3B,IAAI,KAAK,YAAY,4BAAa,EAAE,CAAC;gBACjC,cAAc,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACJ,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACvC,CAAC;YACD,SAAS,GAAG,IAAI,CAAC;QACrB,CAAC;IACL,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,CAAC;AACnC,CAAC","sourcesContent":["import { RuleFailError, toError, BaseRuleConfig } from '@webpieces/rules-config';\n\nimport { CodeValidator, ExecutorResult } from './code-validator';\n\n// Human/CI console block for a validator that threw a RuleFailError. code-rules is developer-facing,\n// so it prints humanMessage (falls back to aiMessage inside RuleFailError when not set).\nfunction reportRuleFail(err: RuleFailError): void {\n console.error('');\n console.error(`❌ [${err.ruleName}] ${err.humanMessage}`);\n if (err.line !== undefined) {\n console.error(` L${String(err.line)}: ${err.snippet ?? ''}`);\n }\n for (const hint of err.fixHints) {\n console.error(` Fix: ${hint}`);\n }\n console.error('');\n}\n\n// A validator that threw a plain Error is a BUG in the validator surface it (don't swallow) and\n// keep going so it doesn't hide the other validators' results.\nfunction reportCrash(name: string, error: Error): void {\n console.error('');\n console.error(`❌ Validator '${name}' crashed: ${error.message}`);\n console.error(' (a bug in the validator — the other validators still ran)');\n console.error('');\n}\n\n/**\n * Run every active validator with per-validator isolation: a validator that throws — a `RuleFailError`\n * (an expected failure) OR a plain `Error` (a bug) — is caught, reported, and marks the run failed,\n * but the remaining validators STILL run. One validator can no longer abort the whole CI run (the\n * previous raw loop had no per-validator try/catch, so a single bug aborted everything).\n *\n * Back-compatible: validators that still `console.error(...)` + `return { success: false }` keep\n * working; their `false` result flips the aggregate exactly as before.\n */\nexport async function runValidators(\n active: readonly CodeValidator<BaseRuleConfig>[],\n workspaceRoot: string,\n): Promise<ExecutorResult> {\n let anyFailed = false;\n for (const validator of active) {\n // webpieces-disable no-unmanaged-exceptions -- per-validator isolation chokepoint: one validator must never abort the rest\n try {\n const result = await validator.run(workspaceRoot);\n if (!result.success) anyFailed = true;\n } catch (err: unknown) {\n const error = toError(err);\n if (error instanceof RuleFailError) {\n reportRuleFail(error);\n } else {\n reportCrash(validator.name, error);\n }\n anyFailed = true;\n }\n }\n return { success: !anyFailed };\n}\n"]}
1
+ {"version":3,"file":"rule-reporter.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/rule-reporter.ts"],"names":[],"mappings":";;;;AAAA,0DAAiE;AACjE,0DAA2D;AAC3D,yCAAuC;AAIvC;;GAEG;AAGI,IAAM,YAAY,GAAlB,MAAM,YAAY;IACrB;;;;;;;OAOG;IACH,KAAK,CAAC,aAAa,CAAC,IAAwB;QACxC,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;YACtB,qHAAqH;YACrH,IAAI,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;gBAChC,IAAI,CAAC,MAAM,CAAC,OAAO;oBAAE,SAAS,GAAG,IAAI,CAAC;YAC1C,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACpB,MAAM,KAAK,GAAG,IAAA,sBAAO,EAAC,GAAG,CAAC,CAAC;gBAC3B,IAAI,KAAK,YAAY,4BAAa,EAAE,CAAC;oBACjC,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;gBAC/B,CAAC;qBAAM,CAAC;oBACJ,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBACvC,CAAC;gBACD,SAAS,GAAG,IAAI,CAAC;YACrB,CAAC;QACL,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,CAAC,SAAS,EAAE,CAAC;IACnC,CAAC;IAED,8FAA8F;IAC9F,iGAAiG;IACzF,cAAc,CAAC,GAAkB;QACrC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,QAAQ,KAAK,GAAG,CAAC,YAAY,EAAE,CAAC,CAAC;QACzD,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC9B,OAAO,CAAC,KAAK,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QACrC,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtB,CAAC;IAED,kGAAkG;IAClG,+DAA+D;IACvD,WAAW,CAAC,IAAY,EAAE,KAAY;QAC1C,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,gBAAgB,IAAI,cAAc,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACjE,OAAO,CAAC,KAAK,CAAC,8DAA8D,CAAC,CAAC;QAC9E,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACtB,CAAC;CACJ,CAAA;AAnDY,oCAAY;uBAAZ,YAAY;IAFxB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;GACA,YAAY,CAmDxB","sourcesContent":["import { RuleFailError, toError } from '@webpieces/rules-config';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\n\nimport { RuleRun, ExecutorResult } from './code-validator';\n\n/**\n * Runs the active validators with per-validator isolation and prints failures for humans/CI.\n */\n@provideSingleton()\n@injectable()\nexport class RuleReporter {\n /**\n * Run every {@link RuleRun} with per-run isolation: a run that throws — a `RuleFailError` (an\n * expected failure) OR a plain `Error` (a bug) — is caught, reported, and marks the whole run\n * failed, but the remaining runs STILL execute. One validator can no longer abort the CI run.\n *\n * Back-compatible: runs that still `console.error(...)` + `return { success: false }` keep\n * working; their `false` result flips the aggregate exactly as before.\n */\n async runValidators(runs: readonly RuleRun[]): Promise<ExecutorResult> {\n let anyFailed = false;\n for (const item of runs) {\n // webpieces-disable no-unmanaged-exceptions -- per-run isolation chokepoint: one validator must never abort the rest\n try {\n const result = await item.run();\n if (!result.success) anyFailed = true;\n } catch (err: unknown) {\n const error = toError(err);\n if (error instanceof RuleFailError) {\n this.reportRuleFail(error);\n } else {\n this.reportCrash(item.name, error);\n }\n anyFailed = true;\n }\n }\n return { success: !anyFailed };\n }\n\n // Human/CI console block for a validator that threw a RuleFailError. code-rules is developer-\n // facing, so it prints humanMessage (falls back to aiMessage inside RuleFailError when not set).\n private reportRuleFail(err: RuleFailError): void {\n console.error('');\n console.error(`❌ [${err.ruleName}] ${err.humanMessage}`);\n if (err.line !== undefined) {\n console.error(` L${String(err.line)}: ${err.snippet ?? ''}`);\n }\n for (const hint of err.fixHints) {\n console.error(` Fix: ${hint}`);\n }\n console.error('');\n }\n\n // A validator that threw a plain Error is a BUG in the validator — surface it (don't swallow) and\n // keep going so it doesn't hide the other validators' results.\n private reportCrash(name: string, error: Error): void {\n console.error('');\n console.error(`❌ Validator '${name}' crashed: ${error.message}`);\n console.error(' (a bug in the validator — the other validators still ran)');\n console.error('');\n }\n}\n"]}
@@ -44,6 +44,8 @@ const path = tslib_1.__importStar(require("path"));
44
44
  const ts = tslib_1.__importStar(require("typescript"));
45
45
  const rules_config_1 = require("@webpieces/rules-config");
46
46
  const code_validator_1 = require("./code-validator");
47
+ const core_context_1 = require("@webpieces/core-context");
48
+ const inversify_1 = require("inversify");
47
49
  const resolve_mode_1 = require("./resolve-mode");
48
50
  /**
49
51
  * Check if a line contains a disable comment for catch-error-pattern.
@@ -372,13 +374,18 @@ async function runValidatorImpl(options, workspaceRoot) {
372
374
  reportViolations(violations, mode, disableAllowed);
373
375
  return { success: false };
374
376
  }
375
- class CatchErrorPatternValidator extends code_validator_1.CodeValidator {
377
+ let CatchErrorPatternValidator = class CatchErrorPatternValidator extends code_validator_1.CodeValidator {
376
378
  constructor(config) {
377
379
  super(config, 'catch-error-pattern');
378
380
  }
379
381
  async run(workspaceRoot) {
380
382
  return runValidatorImpl(this.config, workspaceRoot);
381
383
  }
382
- }
384
+ };
383
385
  exports.CatchErrorPatternValidator = CatchErrorPatternValidator;
386
+ exports.CatchErrorPatternValidator = CatchErrorPatternValidator = tslib_1.__decorate([
387
+ (0, core_context_1.provideSingleton)(),
388
+ (0, inversify_1.injectable)(),
389
+ tslib_1.__metadata("design:paramtypes", [rules_config_1.CatchErrorPatternConfig])
390
+ ], CatchErrorPatternValidator);
384
391
  //# sourceMappingURL=validate-catch-error-pattern.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate-catch-error-pattern.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-catch-error-pattern.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate Catch Error Pattern Executor\n *\n * Validates that catch blocks follow the standardized error handling pattern.\n * Uses TypeScript AST for detection and LINE-BASED git diff filtering.\n *\n * ============================================================================\n * REQUIRED PATTERN\n * ============================================================================\n *\n * Standard: catch (err: unknown) { const error = toError(err); ... }\n * Ignored: catch (err: unknown) { //const error = toError(err); ... }\n * Nested: catch (err2: unknown) { const error2 = toError(err2); ... }\n *\n * ============================================================================\n * VIOLATIONS (BAD) - These patterns are flagged:\n * ============================================================================\n *\n * - catch (e) { ... } — wrong parameter name\n * - catch (err) { ... } — missing : unknown type annotation\n * - catch (err: unknown) { ... } — missing toError() as first statement\n * - catch (err: unknown) { const x = toError(err); } — wrong variable name\n *\n * ============================================================================\n * MODES (LINE-BASED)\n * ============================================================================\n * - OFF: Skip validation entirely\n * - NEW_AND_MODIFIED_CODE: Flag catch violations on changed lines (lines in diff hunks)\n * - NEW_AND_MODIFIED_FILES: Flag ALL catch violations in files that were modified\n *\n * ============================================================================\n * ESCAPE HATCH\n * ============================================================================\n * Add comment above the violation:\n * // webpieces-disable catch-error-pattern -- [your justification]\n * } catch (err: unknown) {\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { hasDisable, RULE_NAMES, CatchErrorPatternConfig, ModifiedCodeMode, detectBase, getChangedFiles, getFileDiff, getChangedLineNumbers } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { shouldSkipRule } from './resolve-mode';\n\ninterface CatchViolation {\n file: string;\n line: number;\n message: string;\n context: string;\n}\n\ninterface CatchViolationInfo {\n line: number;\n message: string;\n context: string;\n hasDisableComment: boolean;\n}\n\n/**\n * Check if a line contains a disable comment for catch-error-pattern.\n * Recognizes both webpieces-disable and eslint-disable-next-line @webpieces/ formats.\n */\nfunction hasDisableComment(lines: string[], lineNumber: number): boolean {\n const startCheck = Math.max(0, lineNumber - 5);\n for (let i = lineNumber - 2; i >= startCheck; i--) {\n const line = lines[i]?.trim() ?? '';\n if (line.startsWith('function ') || line.startsWith('class ') || line.endsWith('}')) {\n break;\n }\n if (hasDisable(line, RULE_NAMES.CATCH_ERROR_PATTERN)) {\n return true;\n }\n if (line.includes('@webpieces/catch-error-pattern')) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if the catch block contains a disable comment for catch-error-pattern.\n */\nfunction hasBlockLevelDisable(sourceText: string, blockStart: number, blockEnd: number): boolean {\n const blockText = sourceText.substring(blockStart, blockEnd);\n return hasDisable(blockText, RULE_NAMES.CATCH_ERROR_PATTERN) ||\n blockText.includes('@webpieces/catch-error-pattern');\n}\n\n/**\n * Check if the catch block body text contains the commented-out ignore pattern.\n */\nfunction hasIgnoreComment(\n sourceText: string,\n blockStart: number,\n blockEnd: number,\n expectedVarName: string,\n actualParamName: string,\n): boolean {\n const blockText = sourceText.substring(blockStart, blockEnd);\n const ignorePattern = new RegExp(\n `//\\\\s*const\\\\s+${expectedVarName}\\\\s*=\\\\s*toError\\\\(${actualParamName}\\\\)`,\n );\n return ignorePattern.test(blockText);\n}\n\n/**\n * Validate a single CatchClause node.\n */\n// webpieces-disable max-lines-new-methods -- AST validation with multiple check paths for param name, type, and toError\nfunction validateCatchClause(\n node: ts.CatchClause,\n sourceFile: ts.SourceFile,\n fileLines: string[],\n depth: number,\n disableAllowed: boolean,\n): CatchViolationInfo[] {\n const violations: CatchViolationInfo[] = [];\n const suffix = depth === 1 ? '' : String(depth);\n const expectedParam = 'err' + suffix;\n const expectedVar = 'error' + suffix;\n\n const catchLine = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;\n const catchContext = fileLines[catchLine - 1]?.trim() ?? '';\n const blockStart = node.block.getStart(sourceFile);\n const blockEnd = node.block.getEnd();\n const disabled = hasDisableComment(fileLines, catchLine) ||\n hasBlockLevelDisable(sourceFile.text, blockStart, blockEnd);\n\n const varDecl = node.variableDeclaration;\n if (!varDecl) {\n violations.push({\n line: catchLine, context: catchContext,\n message: `Catch clause must declare a parameter: catch (${expectedParam}: unknown)`,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n });\n return violations;\n }\n\n const actualParam = ts.isIdentifier(varDecl.name) ? varDecl.name.text : expectedParam;\n\n // Check parameter name\n if (ts.isIdentifier(varDecl.name) && varDecl.name.text !== expectedParam) {\n violations.push({\n line: catchLine, context: catchContext,\n message: `Catch parameter must be named \"${expectedParam}\" (or \"err2\", \"err3\" for nested), got \"${varDecl.name.text}\"`,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n });\n }\n\n // Check type annotation is : unknown\n if (!varDecl.type || varDecl.type.kind !== ts.SyntaxKind.UnknownKeyword) {\n violations.push({\n line: catchLine, context: catchContext,\n message: `Catch parameter must be typed as \"unknown\": catch (${actualParam}: unknown)`,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n });\n }\n\n // Check for commented-out ignore pattern\n if (hasIgnoreComment(sourceFile.text, blockStart, blockEnd, expectedVar, actualParam)) {\n return violations;\n }\n\n // Check first statement is const error = toError(err)\n if (node.block.statements.length === 0) {\n violations.push({\n line: catchLine, context: catchContext,\n message: `Catch block must call toError(${actualParam}) as first statement: const ${expectedVar} = toError(${actualParam});`,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n });\n return violations;\n }\n\n const firstStmt = node.block.statements[0];\n const toErrorViolation = validateToErrorStatement(firstStmt, sourceFile, fileLines, expectedParam, expectedVar, actualParam, disabled, disableAllowed);\n if (toErrorViolation) {\n violations.push(toErrorViolation);\n }\n\n return violations;\n}\n\nfunction resolveDisable(disabled: boolean, disableAllowed: boolean): boolean {\n if (!disableAllowed && disabled) {\n return false;\n }\n return disabled;\n}\n\n/**\n * Validate that the first statement is `const error = toError(err);`\n */\n// webpieces-disable max-lines-new-methods -- Deep AST check for variable declaration with toError call expression\nfunction validateToErrorStatement(\n stmt: ts.Statement,\n sourceFile: ts.SourceFile,\n fileLines: string[],\n expectedParam: string,\n expectedVar: string,\n actualParam: string,\n disabled: boolean,\n disableAllowed: boolean,\n): CatchViolationInfo | null {\n const stmtLine = sourceFile.getLineAndCharacterOfPosition(stmt.getStart(sourceFile)).line + 1;\n const stmtContext = fileLines[stmtLine - 1]?.trim() ?? '';\n\n if (!ts.isVariableStatement(stmt)) {\n return {\n line: stmtLine,\n message: `First statement in catch must be: const ${expectedVar} = toError(${actualParam});`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n const declarations = stmt.declarationList.declarations;\n if (declarations.length === 0) {\n return {\n line: stmtLine,\n message: `First statement in catch must be: const ${expectedVar} = toError(${actualParam});`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n const decl = declarations[0];\n\n // Check variable name\n if (ts.isIdentifier(decl.name) && decl.name.text !== expectedVar) {\n return {\n line: stmtLine,\n message: `Error variable must be named \"${expectedVar}\", got \"${decl.name.text}\"`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n // Check initializer is toError(actualParam)\n const init = decl.initializer;\n if (!init || !ts.isCallExpression(init)) {\n return {\n line: stmtLine,\n message: `First statement in catch must be: const ${expectedVar} = toError(${actualParam});`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n if (!ts.isIdentifier(init.expression) || init.expression.text !== 'toError') {\n return {\n line: stmtLine,\n message: `First statement in catch must call toError(), not \"${init.expression.getText(sourceFile)}\"`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n // Check argument\n const args = init.arguments;\n if (args.length !== 1 || !ts.isIdentifier(args[0]) || args[0].text !== actualParam) {\n return {\n line: stmtLine,\n message: `toError() must be called with \"${actualParam}\"`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n return null;\n}\n\n/**\n * Find all catch pattern violations in a file using AST.\n */\nfunction findCatchViolationsInFile(\n filePath: string,\n workspaceRoot: string,\n disableAllowed: boolean,\n): CatchViolationInfo[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const violations: CatchViolationInfo[] = [];\n let catchDepth = 0;\n\n function visit(node: ts.Node): void {\n if (ts.isCatchClause(node)) {\n catchDepth++;\n const clauseViolations = validateCatchClause(node, sourceFile, fileLines, catchDepth, disableAllowed);\n violations.push(...clauseViolations);\n ts.forEachChild(node, visit);\n catchDepth--;\n return;\n }\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return violations;\n}\n\n/**\n * NEW_AND_MODIFIED_CODE mode: Flag violations on changed lines.\n */\nfunction findViolationsForModifiedCode(\n workspaceRoot: string,\n changedFiles: string[],\n base: string,\n head: string | undefined,\n disableAllowed: boolean,\n): CatchViolation[] {\n const violations: CatchViolation[] = [];\n\n for (const file of changedFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n\n if (changedLines.size === 0) continue;\n\n const allViolations = findCatchViolationsInFile(file, workspaceRoot, disableAllowed);\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n if (!changedLines.has(v.line)) continue;\n\n violations.push({ file, line: v.line, message: v.message, context: v.context });\n }\n }\n\n return violations;\n}\n\n/**\n * NEW_AND_MODIFIED_FILES mode: Flag ALL violations in modified files.\n */\nfunction findViolationsForModifiedFiles(\n workspaceRoot: string,\n changedFiles: string[],\n disableAllowed: boolean,\n): CatchViolation[] {\n const violations: CatchViolation[] = [];\n\n for (const file of changedFiles) {\n const allViolations = findCatchViolationsInFile(file, workspaceRoot, disableAllowed);\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n violations.push({ file, line: v.line, message: v.message, context: v.context });\n }\n }\n\n return violations;\n}\n\n/**\n * Report violations to console.\n */\n// webpieces-disable max-lines-new-methods -- Console output with pattern examples and escape hatch\nfunction reportViolations(violations: CatchViolation[], mode: ModifiedCodeMode, disableAllowed: boolean): void {\n console.error('');\n console.error('\\u274c Catch blocks must follow the standardized error handling pattern!');\n console.error('');\n console.error('\\ud83d\\udcda Required pattern:');\n console.error('');\n console.error(' catch (err: unknown) {');\n console.error(' const error = toError(err);');\n console.error(' // ... use error ...');\n console.error(' }');\n console.error('');\n console.error(' Or to explicitly ignore:');\n console.error(' catch (err: unknown) {');\n console.error(' //const error = toError(err);');\n console.error(' }');\n console.error('');\n console.error(' For nested catches: err2/error2, err3/error3, etc.');\n console.error('');\n\n for (const v of violations) {\n console.error(` \\u274c ${v.file}:${v.line}`);\n console.error(` ${v.message}`);\n console.error(` ${v.context}`);\n }\n console.error('');\n\n if (disableAllowed) {\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable catch-error-pattern -- [your reason]');\n } else {\n console.error(' Escape hatch: DISABLED (disableAllowed: false)');\n console.error(' Disable comments are ignored. Fix the catch block directly.');\n }\n console.error('');\n console.error(` Current mode: ${mode}`);\n console.error('');\n}\n\n/**\n * Resolve mode considering ignoreModifiedUntilEpoch override.\n */\nfunction resolveMode(normalMode: ModifiedCodeMode, epoch: number | undefined, branchPattern: string | undefined): ModifiedCodeMode {\n if (normalMode === 'OFF') {\n return normalMode;\n }\n const skip = shouldSkipRule(epoch, branchPattern);\n if (skip.skip) {\n console.log(`\\n\\u23ed\\ufe0f Skipping catch-error-pattern validation (${skip.reason})`);\n console.log('');\n return 'OFF';\n }\n return normalMode;\n}\n\nasync function runValidatorImpl(\n options: CatchErrorPatternConfig,\n workspaceRoot: string\n): Promise<ExecutorResult> {\n const mode: ModifiedCodeMode = resolveMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch, options.ignoreRuleWhileOnBranch);\n const disableAllowed = options.disableAllowed ?? true;\n\n if (mode === 'OFF') {\n console.log('\\n\\u23ed\\ufe0f Skipping catch-error-pattern validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n console.log('\\n\\ud83d\\udccf Validating Catch Error Pattern\\n');\n console.log(` Mode: ${mode}`);\n\n let base = process.env['NX_BASE'];\n const head = process.env['NX_HEAD'];\n\n if (!base) {\n base = detectBase(workspaceRoot) ?? undefined;\n\n if (!base) {\n console.log('\\n\\u23ed\\ufe0f Skipping catch-error-pattern validation (could not detect base branch)');\n console.log('');\n return { success: true };\n }\n }\n\n console.log(` Base: ${base}`);\n console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);\n console.log('');\n\n const changedFiles = getChangedFiles(workspaceRoot, base, head);\n\n if (changedFiles.length === 0) {\n console.log('\\u2705 No TypeScript files changed');\n return { success: true };\n }\n\n console.log(`\\ud83d\\udcc2 Checking ${changedFiles.length} changed file(s)...`);\n\n let violations: CatchViolation[] = [];\n\n if (mode === 'NEW_AND_MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed);\n } else if (mode === 'NEW_AND_MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed);\n }\n\n if (violations.length === 0) {\n console.log('\\u2705 No catch error pattern violations found');\n return { success: true };\n }\n\n reportViolations(violations, mode, disableAllowed);\n\n return { success: false };\n}\n\nexport class CatchErrorPatternValidator extends CodeValidator<CatchErrorPatternConfig> {\n constructor(config: CatchErrorPatternConfig) {\n super(config, 'catch-error-pattern');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
1
+ {"version":3,"file":"validate-catch-error-pattern.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-catch-error-pattern.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Validate Catch Error Pattern Executor\n *\n * Validates that catch blocks follow the standardized error handling pattern.\n * Uses TypeScript AST for detection and LINE-BASED git diff filtering.\n *\n * ============================================================================\n * REQUIRED PATTERN\n * ============================================================================\n *\n * Standard: catch (err: unknown) { const error = toError(err); ... }\n * Ignored: catch (err: unknown) { //const error = toError(err); ... }\n * Nested: catch (err2: unknown) { const error2 = toError(err2); ... }\n *\n * ============================================================================\n * VIOLATIONS (BAD) - These patterns are flagged:\n * ============================================================================\n *\n * - catch (e) { ... } — wrong parameter name\n * - catch (err) { ... } — missing : unknown type annotation\n * - catch (err: unknown) { ... } — missing toError() as first statement\n * - catch (err: unknown) { const x = toError(err); } — wrong variable name\n *\n * ============================================================================\n * MODES (LINE-BASED)\n * ============================================================================\n * - OFF: Skip validation entirely\n * - NEW_AND_MODIFIED_CODE: Flag catch violations on changed lines (lines in diff hunks)\n * - NEW_AND_MODIFIED_FILES: Flag ALL catch violations in files that were modified\n *\n * ============================================================================\n * ESCAPE HATCH\n * ============================================================================\n * Add comment above the violation:\n * // webpieces-disable catch-error-pattern -- [your justification]\n * } catch (err: unknown) {\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport * as ts from 'typescript';\nimport { hasDisable, RULE_NAMES, CatchErrorPatternConfig, ModifiedCodeMode, detectBase, getChangedFiles, getFileDiff, getChangedLineNumbers } from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { injectable } from 'inversify';\nimport { shouldSkipRule } from './resolve-mode';\n\ninterface CatchViolation {\n file: string;\n line: number;\n message: string;\n context: string;\n}\n\ninterface CatchViolationInfo {\n line: number;\n message: string;\n context: string;\n hasDisableComment: boolean;\n}\n\n/**\n * Check if a line contains a disable comment for catch-error-pattern.\n * Recognizes both webpieces-disable and eslint-disable-next-line @webpieces/ formats.\n */\nfunction hasDisableComment(lines: string[], lineNumber: number): boolean {\n const startCheck = Math.max(0, lineNumber - 5);\n for (let i = lineNumber - 2; i >= startCheck; i--) {\n const line = lines[i]?.trim() ?? '';\n if (line.startsWith('function ') || line.startsWith('class ') || line.endsWith('}')) {\n break;\n }\n if (hasDisable(line, RULE_NAMES.CATCH_ERROR_PATTERN)) {\n return true;\n }\n if (line.includes('@webpieces/catch-error-pattern')) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Check if the catch block contains a disable comment for catch-error-pattern.\n */\nfunction hasBlockLevelDisable(sourceText: string, blockStart: number, blockEnd: number): boolean {\n const blockText = sourceText.substring(blockStart, blockEnd);\n return hasDisable(blockText, RULE_NAMES.CATCH_ERROR_PATTERN) ||\n blockText.includes('@webpieces/catch-error-pattern');\n}\n\n/**\n * Check if the catch block body text contains the commented-out ignore pattern.\n */\nfunction hasIgnoreComment(\n sourceText: string,\n blockStart: number,\n blockEnd: number,\n expectedVarName: string,\n actualParamName: string,\n): boolean {\n const blockText = sourceText.substring(blockStart, blockEnd);\n const ignorePattern = new RegExp(\n `//\\\\s*const\\\\s+${expectedVarName}\\\\s*=\\\\s*toError\\\\(${actualParamName}\\\\)`,\n );\n return ignorePattern.test(blockText);\n}\n\n/**\n * Validate a single CatchClause node.\n */\n// webpieces-disable max-lines-new-methods -- AST validation with multiple check paths for param name, type, and toError\nfunction validateCatchClause(\n node: ts.CatchClause,\n sourceFile: ts.SourceFile,\n fileLines: string[],\n depth: number,\n disableAllowed: boolean,\n): CatchViolationInfo[] {\n const violations: CatchViolationInfo[] = [];\n const suffix = depth === 1 ? '' : String(depth);\n const expectedParam = 'err' + suffix;\n const expectedVar = 'error' + suffix;\n\n const catchLine = sourceFile.getLineAndCharacterOfPosition(node.getStart(sourceFile)).line + 1;\n const catchContext = fileLines[catchLine - 1]?.trim() ?? '';\n const blockStart = node.block.getStart(sourceFile);\n const blockEnd = node.block.getEnd();\n const disabled = hasDisableComment(fileLines, catchLine) ||\n hasBlockLevelDisable(sourceFile.text, blockStart, blockEnd);\n\n const varDecl = node.variableDeclaration;\n if (!varDecl) {\n violations.push({\n line: catchLine, context: catchContext,\n message: `Catch clause must declare a parameter: catch (${expectedParam}: unknown)`,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n });\n return violations;\n }\n\n const actualParam = ts.isIdentifier(varDecl.name) ? varDecl.name.text : expectedParam;\n\n // Check parameter name\n if (ts.isIdentifier(varDecl.name) && varDecl.name.text !== expectedParam) {\n violations.push({\n line: catchLine, context: catchContext,\n message: `Catch parameter must be named \"${expectedParam}\" (or \"err2\", \"err3\" for nested), got \"${varDecl.name.text}\"`,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n });\n }\n\n // Check type annotation is : unknown\n if (!varDecl.type || varDecl.type.kind !== ts.SyntaxKind.UnknownKeyword) {\n violations.push({\n line: catchLine, context: catchContext,\n message: `Catch parameter must be typed as \"unknown\": catch (${actualParam}: unknown)`,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n });\n }\n\n // Check for commented-out ignore pattern\n if (hasIgnoreComment(sourceFile.text, blockStart, blockEnd, expectedVar, actualParam)) {\n return violations;\n }\n\n // Check first statement is const error = toError(err)\n if (node.block.statements.length === 0) {\n violations.push({\n line: catchLine, context: catchContext,\n message: `Catch block must call toError(${actualParam}) as first statement: const ${expectedVar} = toError(${actualParam});`,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n });\n return violations;\n }\n\n const firstStmt = node.block.statements[0];\n const toErrorViolation = validateToErrorStatement(firstStmt, sourceFile, fileLines, expectedParam, expectedVar, actualParam, disabled, disableAllowed);\n if (toErrorViolation) {\n violations.push(toErrorViolation);\n }\n\n return violations;\n}\n\nfunction resolveDisable(disabled: boolean, disableAllowed: boolean): boolean {\n if (!disableAllowed && disabled) {\n return false;\n }\n return disabled;\n}\n\n/**\n * Validate that the first statement is `const error = toError(err);`\n */\n// webpieces-disable max-lines-new-methods -- Deep AST check for variable declaration with toError call expression\nfunction validateToErrorStatement(\n stmt: ts.Statement,\n sourceFile: ts.SourceFile,\n fileLines: string[],\n expectedParam: string,\n expectedVar: string,\n actualParam: string,\n disabled: boolean,\n disableAllowed: boolean,\n): CatchViolationInfo | null {\n const stmtLine = sourceFile.getLineAndCharacterOfPosition(stmt.getStart(sourceFile)).line + 1;\n const stmtContext = fileLines[stmtLine - 1]?.trim() ?? '';\n\n if (!ts.isVariableStatement(stmt)) {\n return {\n line: stmtLine,\n message: `First statement in catch must be: const ${expectedVar} = toError(${actualParam});`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n const declarations = stmt.declarationList.declarations;\n if (declarations.length === 0) {\n return {\n line: stmtLine,\n message: `First statement in catch must be: const ${expectedVar} = toError(${actualParam});`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n const decl = declarations[0];\n\n // Check variable name\n if (ts.isIdentifier(decl.name) && decl.name.text !== expectedVar) {\n return {\n line: stmtLine,\n message: `Error variable must be named \"${expectedVar}\", got \"${decl.name.text}\"`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n // Check initializer is toError(actualParam)\n const init = decl.initializer;\n if (!init || !ts.isCallExpression(init)) {\n return {\n line: stmtLine,\n message: `First statement in catch must be: const ${expectedVar} = toError(${actualParam});`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n if (!ts.isIdentifier(init.expression) || init.expression.text !== 'toError') {\n return {\n line: stmtLine,\n message: `First statement in catch must call toError(), not \"${init.expression.getText(sourceFile)}\"`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n // Check argument\n const args = init.arguments;\n if (args.length !== 1 || !ts.isIdentifier(args[0]) || args[0].text !== actualParam) {\n return {\n line: stmtLine,\n message: `toError() must be called with \"${actualParam}\"`,\n context: stmtContext,\n hasDisableComment: resolveDisable(disabled, disableAllowed),\n };\n }\n\n return null;\n}\n\n/**\n * Find all catch pattern violations in a file using AST.\n */\nfunction findCatchViolationsInFile(\n filePath: string,\n workspaceRoot: string,\n disableAllowed: boolean,\n): CatchViolationInfo[] {\n const fullPath = path.join(workspaceRoot, filePath);\n if (!fs.existsSync(fullPath)) return [];\n\n const content = fs.readFileSync(fullPath, 'utf-8');\n const fileLines = content.split('\\n');\n const sourceFile = ts.createSourceFile(filePath, content, ts.ScriptTarget.Latest, true);\n\n const violations: CatchViolationInfo[] = [];\n let catchDepth = 0;\n\n function visit(node: ts.Node): void {\n if (ts.isCatchClause(node)) {\n catchDepth++;\n const clauseViolations = validateCatchClause(node, sourceFile, fileLines, catchDepth, disableAllowed);\n violations.push(...clauseViolations);\n ts.forEachChild(node, visit);\n catchDepth--;\n return;\n }\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return violations;\n}\n\n/**\n * NEW_AND_MODIFIED_CODE mode: Flag violations on changed lines.\n */\nfunction findViolationsForModifiedCode(\n workspaceRoot: string,\n changedFiles: string[],\n base: string,\n head: string | undefined,\n disableAllowed: boolean,\n): CatchViolation[] {\n const violations: CatchViolation[] = [];\n\n for (const file of changedFiles) {\n const diff = getFileDiff(workspaceRoot, file, base, head);\n const changedLines = getChangedLineNumbers(diff);\n\n if (changedLines.size === 0) continue;\n\n const allViolations = findCatchViolationsInFile(file, workspaceRoot, disableAllowed);\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n if (!changedLines.has(v.line)) continue;\n\n violations.push({ file, line: v.line, message: v.message, context: v.context });\n }\n }\n\n return violations;\n}\n\n/**\n * NEW_AND_MODIFIED_FILES mode: Flag ALL violations in modified files.\n */\nfunction findViolationsForModifiedFiles(\n workspaceRoot: string,\n changedFiles: string[],\n disableAllowed: boolean,\n): CatchViolation[] {\n const violations: CatchViolation[] = [];\n\n for (const file of changedFiles) {\n const allViolations = findCatchViolationsInFile(file, workspaceRoot, disableAllowed);\n\n for (const v of allViolations) {\n if (disableAllowed && v.hasDisableComment) continue;\n violations.push({ file, line: v.line, message: v.message, context: v.context });\n }\n }\n\n return violations;\n}\n\n/**\n * Report violations to console.\n */\n// webpieces-disable max-lines-new-methods -- Console output with pattern examples and escape hatch\nfunction reportViolations(violations: CatchViolation[], mode: ModifiedCodeMode, disableAllowed: boolean): void {\n console.error('');\n console.error('\\u274c Catch blocks must follow the standardized error handling pattern!');\n console.error('');\n console.error('\\ud83d\\udcda Required pattern:');\n console.error('');\n console.error(' catch (err: unknown) {');\n console.error(' const error = toError(err);');\n console.error(' // ... use error ...');\n console.error(' }');\n console.error('');\n console.error(' Or to explicitly ignore:');\n console.error(' catch (err: unknown) {');\n console.error(' //const error = toError(err);');\n console.error(' }');\n console.error('');\n console.error(' For nested catches: err2/error2, err3/error3, etc.');\n console.error('');\n\n for (const v of violations) {\n console.error(` \\u274c ${v.file}:${v.line}`);\n console.error(` ${v.message}`);\n console.error(` ${v.context}`);\n }\n console.error('');\n\n if (disableAllowed) {\n console.error(' Escape hatch (use sparingly):');\n console.error(' // webpieces-disable catch-error-pattern -- [your reason]');\n } else {\n console.error(' Escape hatch: DISABLED (disableAllowed: false)');\n console.error(' Disable comments are ignored. Fix the catch block directly.');\n }\n console.error('');\n console.error(` Current mode: ${mode}`);\n console.error('');\n}\n\n/**\n * Resolve mode considering ignoreModifiedUntilEpoch override.\n */\nfunction resolveMode(normalMode: ModifiedCodeMode, epoch: number | undefined, branchPattern: string | undefined): ModifiedCodeMode {\n if (normalMode === 'OFF') {\n return normalMode;\n }\n const skip = shouldSkipRule(epoch, branchPattern);\n if (skip.skip) {\n console.log(`\\n\\u23ed\\ufe0f Skipping catch-error-pattern validation (${skip.reason})`);\n console.log('');\n return 'OFF';\n }\n return normalMode;\n}\n\nasync function runValidatorImpl(\n options: CatchErrorPatternConfig,\n workspaceRoot: string\n): Promise<ExecutorResult> {\n const mode: ModifiedCodeMode = resolveMode(options.mode ?? 'OFF', options.ignoreModifiedUntilEpoch, options.ignoreRuleWhileOnBranch);\n const disableAllowed = options.disableAllowed ?? true;\n\n if (mode === 'OFF') {\n console.log('\\n\\u23ed\\ufe0f Skipping catch-error-pattern validation (mode: OFF)');\n console.log('');\n return { success: true };\n }\n\n console.log('\\n\\ud83d\\udccf Validating Catch Error Pattern\\n');\n console.log(` Mode: ${mode}`);\n\n let base = process.env['NX_BASE'];\n const head = process.env['NX_HEAD'];\n\n if (!base) {\n base = detectBase(workspaceRoot) ?? undefined;\n\n if (!base) {\n console.log('\\n\\u23ed\\ufe0f Skipping catch-error-pattern validation (could not detect base branch)');\n console.log('');\n return { success: true };\n }\n }\n\n console.log(` Base: ${base}`);\n console.log(` Head: ${head ?? 'working tree (includes uncommitted changes)'}`);\n console.log('');\n\n const changedFiles = getChangedFiles(workspaceRoot, base, head);\n\n if (changedFiles.length === 0) {\n console.log('\\u2705 No TypeScript files changed');\n return { success: true };\n }\n\n console.log(`\\ud83d\\udcc2 Checking ${changedFiles.length} changed file(s)...`);\n\n let violations: CatchViolation[] = [];\n\n if (mode === 'NEW_AND_MODIFIED_CODE') {\n violations = findViolationsForModifiedCode(workspaceRoot, changedFiles, base, head, disableAllowed);\n } else if (mode === 'NEW_AND_MODIFIED_FILES') {\n violations = findViolationsForModifiedFiles(workspaceRoot, changedFiles, disableAllowed);\n }\n\n if (violations.length === 0) {\n console.log('\\u2705 No catch error pattern violations found');\n return { success: true };\n }\n\n reportViolations(violations, mode, disableAllowed);\n\n return { success: false };\n}\n\n@provideSingleton()\n@injectable()\nexport class CatchErrorPatternValidator extends CodeValidator<CatchErrorPatternConfig> {\n constructor(config: CatchErrorPatternConfig) {\n super(config, 'catch-error-pattern');\n }\n\n async run(workspaceRoot: string): Promise<ExecutorResult> {\n return runValidatorImpl(this.config, workspaceRoot);\n }\n}\n"]}
@@ -1,11 +1,14 @@
1
+ import 'reflect-metadata';
1
2
  import { ExecutorResult } from './code-validator';
2
3
  export { ExecutorResult } from './code-validator';
3
4
  /**
4
- * Run all configured code validators against the workspace.
5
+ * Run all configured code validators against the workspace root (the nx `validate-code` executor's
6
+ * entry, via `@webpieces/code-rules`'s `validateCode` export).
5
7
  *
6
- * Owns config loading: callers just pass the workspace root. Config comes from
7
- * webpieces.config.json (loaded via @webpieces/rules-config so ai-hooks and this
8
- * executor agree on every rule's enabled/mode/options). A validator runs only when
9
- * `shouldRun()` is true (i.e. its mode is not OFF and no branch/epoch escape hatch matches).
8
+ * Composition root: binds the workspace root + each rule's typed config into an inversify container,
9
+ * then RESOLVES {@link CodeRulesApp} so inversify constructs the ENTIRE validator DAG — nothing in the
10
+ * DAG is `new`-ed (every validator, the reporter, and the match-rules checker are injected). Config
11
+ * comes from webpieces.config.json (loaded via @webpieces/rules-config so ai-hooks and this executor
12
+ * agree on every rule's mode/options).
10
13
  */
11
14
  export default function runValidator(workspaceRoot: string): Promise<ExecutorResult>;
@@ -1,65 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.default = runValidator;
4
+ require("reflect-metadata");
5
+ const inversify_1 = require("inversify");
6
+ const binding_decorators_1 = require("@inversifyjs/binding-decorators");
4
7
  const rules_config_1 = require("@webpieces/rules-config");
5
- const rule_reporter_1 = require("./rule-reporter");
6
- const validate_modified_methods_1 = require("./validate-modified-methods");
7
- const validate_modified_files_1 = require("./validate-modified-files");
8
- const validate_return_types_1 = require("./validate-return-types");
9
- const validate_no_inline_types_1 = require("./validate-no-inline-types");
10
- const validate_no_any_unknown_1 = require("./validate-no-any-unknown");
11
- const validate_no_implicit_any_1 = require("./validate-no-implicit-any");
12
- const validate_dtos_1 = require("./validate-dtos");
13
- const validate_prisma_converters_1 = require("./validate-prisma-converters");
14
- const validate_no_destructure_1 = require("./validate-no-destructure");
15
- const validate_catch_error_pattern_1 = require("./validate-catch-error-pattern");
16
- const validate_no_unmanaged_exceptions_1 = require("./validate-no-unmanaged-exceptions");
17
- const validate_no_direct_api_resolver_1 = require("./validate-no-direct-api-resolver");
18
- const validate_no_symbol_di_tokens_1 = require("./validate-no-symbol-di-tokens");
19
- const validate_no_process_exit_outside_main_1 = require("./validate-no-process-exit-outside-main");
20
- const validate_no_function_outside_class_1 = require("./validate-no-function-outside-class");
21
- const validate_inject_annotation_not_needed_for_concrete_class_1 = require("./validate-inject-annotation-not-needed-for-concrete-class");
22
- const validate_framework_tag_1 = require("./validate-framework-tag");
23
- const validate_role_tag_1 = require("./validate-role-tag");
24
- const validate_match_rules_1 = require("./validate-match-rules");
8
+ const code_rules_app_1 = require("./code-rules-app");
9
+ const code_rules_context_1 = require("./code-rules-context");
10
+ const code_rules_config_table_1 = require("./code-rules-config-table");
25
11
  /**
26
- * Build every code validator from the typed WebpiecesRulesConfig. Each validator is
27
- * constructed with its own `*Config` (the genuinely-consumed config class), so the
28
- * config types are exercised at compile time. Missing rule keys fall back to an empty
29
- * config instance — `loadAndValidate` already validates that configured rules
30
- * carry an explicit `mode`, so in practice every key is present.
31
- */
32
- function buildValidators(config, matchRules) {
33
- return [
34
- new validate_modified_methods_1.MaxMethodLinesValidator(config['max-method-lines'] ?? new rules_config_1.MaxMethodLinesConfig()),
35
- new validate_modified_files_1.MaxFileLinesValidator(config['max-file-lines'] ?? new rules_config_1.MaxFileLinesConfig()),
36
- new validate_return_types_1.RequireReturnTypeValidator(config['require-return-type'] ?? new rules_config_1.RequireReturnTypeConfig()),
37
- new validate_no_inline_types_1.NoInlineTypeLiteralsValidator(config['no-inline-type-literals'] ?? new rules_config_1.NoInlineTypeLiteralsConfig()),
38
- new validate_no_any_unknown_1.NoAnyUnknownValidator(config['no-any-unknown'] ?? new rules_config_1.NoAnyUnknownConfig()),
39
- new validate_no_implicit_any_1.NoImplicitAnyValidator(config['no-implicit-any'] ?? new rules_config_1.NoImplicitAnyConfig()),
40
- new validate_dtos_1.PrismaValidateDtosValidator(config['prisma-validate-dtos'] ?? new rules_config_1.PrismaValidateDtosConfig()),
41
- new validate_prisma_converters_1.PrismaConverterValidator(config['prisma-converter'] ?? new rules_config_1.PrismaConverterConfig()),
42
- new validate_no_destructure_1.NoDestructureValidator(config['no-destructure'] ?? new rules_config_1.NoDestructureConfig()),
43
- new validate_catch_error_pattern_1.CatchErrorPatternValidator(config['catch-error-pattern'] ?? new rules_config_1.CatchErrorPatternConfig()),
44
- new validate_no_unmanaged_exceptions_1.NoUnmanagedExceptionsValidator(config['no-unmanaged-exceptions'] ?? new rules_config_1.NoUnmanagedExceptionsConfig()),
45
- new validate_no_direct_api_resolver_1.NoDirectApiResolverValidator(config['angular-no-direct-api-in-resolver'] ?? new rules_config_1.AngularNoDirectApiInResolverConfig()),
46
- new validate_no_symbol_di_tokens_1.NoSymbolDiTokensValidator(config['no-symbol-di-tokens'] ?? new rules_config_1.NoSymbolDiTokensConfig()),
47
- new validate_no_process_exit_outside_main_1.NoProcessExitOutsideMainValidator(config['no-process-exit-outside-main'] ?? new rules_config_1.NoProcessExitOutsideMainConfig()),
48
- new validate_no_function_outside_class_1.NoFunctionOutsideClassValidator(config['no-function-outside-class'] ?? new rules_config_1.NoFunctionOutsideClassConfig()),
49
- new validate_inject_annotation_not_needed_for_concrete_class_1.InjectAnnotationNotNeededForConcreteClassValidator(config['inject-annotation-not-needed-for-concrete-class'] ?? new rules_config_1.InjectAnnotationNotNeededForConcreteClassConfig()),
50
- new validate_framework_tag_1.FrameworkTagValidator(config['framework-tag'] ?? new rules_config_1.FrameworkTagConfig()),
51
- new validate_role_tag_1.RoleTagValidator(config['role-tag'] ?? new rules_config_1.RoleTagConfig()),
52
- // One validator per client-authored match-rules entry (each with its own name/mode/epoch).
53
- ...matchRules.map((mr) => new validate_match_rules_1.MatchRulesValidator(mr)),
54
- ];
55
- }
56
- /**
57
- * Run all configured code validators against the workspace.
12
+ * Run all configured code validators against the workspace root (the nx `validate-code` executor's
13
+ * entry, via `@webpieces/code-rules`'s `validateCode` export).
58
14
  *
59
- * Owns config loading: callers just pass the workspace root. Config comes from
60
- * webpieces.config.json (loaded via @webpieces/rules-config so ai-hooks and this
61
- * executor agree on every rule's enabled/mode/options). A validator runs only when
62
- * `shouldRun()` is true (i.e. its mode is not OFF and no branch/epoch escape hatch matches).
15
+ * Composition root: binds the workspace root + each rule's typed config into an inversify container,
16
+ * then RESOLVES {@link CodeRulesApp} so inversify constructs the ENTIRE validator DAG — nothing in the
17
+ * DAG is `new`-ed (every validator, the reporter, and the match-rules checker are injected). Config
18
+ * comes from webpieces.config.json (loaded via @webpieces/rules-config so ai-hooks and this executor
19
+ * agree on every rule's mode/options).
63
20
  */
64
21
  async function runValidator(workspaceRoot) {
65
22
  const loaded = (0, rules_config_1.loadAndValidate)(workspaceRoot);
@@ -68,20 +25,15 @@ async function runValidator(workspaceRoot) {
68
25
  return { success: false };
69
26
  }
70
27
  console.log(`\n📄 Loaded config: ${loaded.configPath}`);
71
- const validators = buildValidators(loaded.rulesConfig, loaded.matchRules);
72
- const active = validators.filter((v) => v.shouldRun());
73
- if (active.length === 0) {
74
- console.log('\n⏭️ Skipping all code validations (all modes: OFF)\n');
75
- return { success: true };
28
+ const container = new inversify_1.Container();
29
+ container.bind(code_rules_context_1.WorkspaceRoot).toConstantValue(new code_rules_context_1.WorkspaceRoot(workspaceRoot));
30
+ container.bind(code_rules_context_1.MatchRulesHolder).toConstantValue(new code_rules_context_1.MatchRulesHolder(loaded.matchRules));
31
+ for (const binding of code_rules_config_table_1.CONFIG_BINDINGS) {
32
+ const ConfigClass = binding[0];
33
+ const configured = loaded.rulesConfig[binding[1]];
34
+ container.bind(ConfigClass).toConstantValue(configured ?? new ConfigClass());
76
35
  }
77
- console.log('\n📏 Running Code Validations\n');
78
- console.log(` Active rules: ${active.map((v) => v.name).join(', ')}`);
79
- console.log('');
80
- // Per-validator isolation lives in runValidators: a bug in one validator no longer aborts the
81
- // rest, and a thrown RuleFailError is reported like any other failure.
82
- const result = await (0, rule_reporter_1.runValidators)(active, workspaceRoot);
83
- const allSuccess = result.success;
84
- console.log(allSuccess ? '\n✅ All code validations passed\n' : '\n❌ Some code validations failed\n');
85
- return { success: allSuccess };
36
+ await container.load((0, binding_decorators_1.buildProviderModule)());
37
+ return container.get(code_rules_app_1.CodeRulesApp).run();
86
38
  }
87
39
  //# sourceMappingURL=validate-code.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate-code.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-code.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n loadAndValidate,\n WebpiecesRulesConfig,\n BaseRuleConfig,\n MaxMethodLinesConfig,\n MaxFileLinesConfig,\n RequireReturnTypeConfig,\n NoInlineTypeLiteralsConfig,\n NoAnyUnknownConfig,\n NoImplicitAnyConfig,\n PrismaValidateDtosConfig,\n PrismaConverterConfig,\n NoDestructureConfig,\n CatchErrorPatternConfig,\n NoUnmanagedExceptionsConfig,\n AngularNoDirectApiInResolverConfig,\n NoSymbolDiTokensConfig,\n NoProcessExitOutsideMainConfig,\n NoFunctionOutsideClassConfig,\n InjectAnnotationNotNeededForConcreteClassConfig,\n FrameworkTagConfig,\n RoleTagConfig,\n} from '@webpieces/rules-config';\nimport { CodeValidator, ExecutorResult } from './code-validator';\nimport { runValidators } from './rule-reporter';\nimport { MaxMethodLinesValidator } from './validate-modified-methods';\nimport { MaxFileLinesValidator } from './validate-modified-files';\nimport { RequireReturnTypeValidator } from './validate-return-types';\nimport { NoInlineTypeLiteralsValidator } from './validate-no-inline-types';\nimport { NoAnyUnknownValidator } from './validate-no-any-unknown';\nimport { NoImplicitAnyValidator } from './validate-no-implicit-any';\nimport { PrismaValidateDtosValidator } from './validate-dtos';\nimport { PrismaConverterValidator } from './validate-prisma-converters';\nimport { NoDestructureValidator } from './validate-no-destructure';\nimport { CatchErrorPatternValidator } from './validate-catch-error-pattern';\nimport { NoUnmanagedExceptionsValidator } from './validate-no-unmanaged-exceptions';\nimport { NoDirectApiResolverValidator } from './validate-no-direct-api-resolver';\nimport { NoSymbolDiTokensValidator } from './validate-no-symbol-di-tokens';\nimport { NoProcessExitOutsideMainValidator } from './validate-no-process-exit-outside-main';\nimport { NoFunctionOutsideClassValidator } from './validate-no-function-outside-class';\nimport { InjectAnnotationNotNeededForConcreteClassValidator } from './validate-inject-annotation-not-needed-for-concrete-class';\nimport { FrameworkTagValidator } from './validate-framework-tag';\nimport { RoleTagValidator } from './validate-role-tag';\nimport { MatchRulesValidator } from './validate-match-rules';\nimport { MatchRuleConfig } from '@webpieces/rules-config';\n\nexport { ExecutorResult } from './code-validator';\n\n/**\n * Build every code validator from the typed WebpiecesRulesConfig. Each validator is\n * constructed with its own `*Config` (the genuinely-consumed config class), so the\n * config types are exercised at compile time. Missing rule keys fall back to an empty\n * config instance — `loadAndValidate` already validates that configured rules\n * carry an explicit `mode`, so in practice every key is present.\n */\nfunction buildValidators(\n config: WebpiecesRulesConfig,\n matchRules: readonly MatchRuleConfig[],\n): CodeValidator<BaseRuleConfig>[] {\n return [\n new MaxMethodLinesValidator(config['max-method-lines'] ?? new MaxMethodLinesConfig()),\n new MaxFileLinesValidator(config['max-file-lines'] ?? new MaxFileLinesConfig()),\n new RequireReturnTypeValidator(config['require-return-type'] ?? new RequireReturnTypeConfig()),\n new NoInlineTypeLiteralsValidator(config['no-inline-type-literals'] ?? new NoInlineTypeLiteralsConfig()),\n new NoAnyUnknownValidator(config['no-any-unknown'] ?? new NoAnyUnknownConfig()),\n new NoImplicitAnyValidator(config['no-implicit-any'] ?? new NoImplicitAnyConfig()),\n new PrismaValidateDtosValidator(config['prisma-validate-dtos'] ?? new PrismaValidateDtosConfig()),\n new PrismaConverterValidator(config['prisma-converter'] ?? new PrismaConverterConfig()),\n new NoDestructureValidator(config['no-destructure'] ?? new NoDestructureConfig()),\n new CatchErrorPatternValidator(config['catch-error-pattern'] ?? new CatchErrorPatternConfig()),\n new NoUnmanagedExceptionsValidator(config['no-unmanaged-exceptions'] ?? new NoUnmanagedExceptionsConfig()),\n new NoDirectApiResolverValidator(config['angular-no-direct-api-in-resolver'] ?? new AngularNoDirectApiInResolverConfig()),\n new NoSymbolDiTokensValidator(config['no-symbol-di-tokens'] ?? new NoSymbolDiTokensConfig()),\n new NoProcessExitOutsideMainValidator(config['no-process-exit-outside-main'] ?? new NoProcessExitOutsideMainConfig()),\n new NoFunctionOutsideClassValidator(config['no-function-outside-class'] ?? new NoFunctionOutsideClassConfig()),\n new InjectAnnotationNotNeededForConcreteClassValidator(config['inject-annotation-not-needed-for-concrete-class'] ?? new InjectAnnotationNotNeededForConcreteClassConfig()),\n new FrameworkTagValidator(config['framework-tag'] ?? new FrameworkTagConfig()),\n new RoleTagValidator(config['role-tag'] ?? new RoleTagConfig()),\n // One validator per client-authored match-rules entry (each with its own name/mode/epoch).\n ...matchRules.map((mr: MatchRuleConfig) => new MatchRulesValidator(mr)),\n ];\n}\n\n/**\n * Run all configured code validators against the workspace.\n *\n * Owns config loading: callers just pass the workspace root. Config comes from\n * webpieces.config.json (loaded via @webpieces/rules-config so ai-hooks and this\n * executor agree on every rule's enabled/mode/options). A validator runs only when\n * `shouldRun()` is true (i.e. its mode is not OFF and no branch/epoch escape hatch matches).\n */\nexport default async function runValidator(workspaceRoot: string): Promise<ExecutorResult> {\n const loaded = loadAndValidate(workspaceRoot);\n if (loaded.configPath === null) {\n console.error('\\n❌ No webpieces.config.json found at workspace root (or any ancestor).\\n');\n return { success: false };\n }\n\n console.log(`\\n📄 Loaded config: ${loaded.configPath}`);\n\n const validators = buildValidators(loaded.rulesConfig, loaded.matchRules);\n const active = validators.filter((v: CodeValidator<BaseRuleConfig>) => v.shouldRun());\n\n if (active.length === 0) {\n console.log('\\n⏭️ Skipping all code validations (all modes: OFF)\\n');\n return { success: true };\n }\n\n console.log('\\n📏 Running Code Validations\\n');\n console.log(` Active rules: ${active.map((v: CodeValidator<BaseRuleConfig>) => v.name).join(', ')}`);\n console.log('');\n\n // Per-validator isolation lives in runValidators: a bug in one validator no longer aborts the\n // rest, and a thrown RuleFailError is reported like any other failure.\n const result = await runValidators(active, workspaceRoot);\n const allSuccess = result.success;\n\n console.log(allSuccess ? '\\n✅ All code validations passed\\n' : '\\n❌ Some code validations failed\\n');\n return { success: allSuccess };\n}\n"]}
1
+ {"version":3,"file":"validate-code.js","sourceRoot":"","sources":["../../../../../packages/tooling/code-rules/src/validate-code.ts"],"names":[],"mappings":";;AAsBA,+BAmBC;AAzCD,4BAA0B;AAC1B,yCAAsC;AACtC,wEAAsE;AACtE,0DAA0E;AAG1E,qDAAgD;AAChD,6DAAuE;AACvE,uEAA4D;AAI5D;;;;;;;;;GASG;AACY,KAAK,UAAU,YAAY,CAAC,aAAqB;IAC5D,MAAM,MAAM,GAAG,IAAA,8BAAe,EAAC,aAAa,CAAC,CAAC;IAC9C,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI,EAAE,CAAC;QAC7B,OAAO,CAAC,KAAK,CAAC,2EAA2E,CAAC,CAAC;QAC3F,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC9B,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,uBAAuB,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;IAExD,MAAM,SAAS,GAAG,IAAI,qBAAS,EAAE,CAAC;IAClC,SAAS,CAAC,IAAI,CAAC,kCAAa,CAAC,CAAC,eAAe,CAAC,IAAI,kCAAa,CAAC,aAAa,CAAC,CAAC,CAAC;IAChF,SAAS,CAAC,IAAI,CAAC,qCAAgB,CAAC,CAAC,eAAe,CAAC,IAAI,qCAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1F,KAAK,MAAM,OAAO,IAAI,yCAAe,EAAE,CAAC;QACpC,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAA+B,CAAC;QAChF,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,eAAe,CAAC,UAAU,IAAI,IAAI,WAAW,EAAE,CAAC,CAAC;IACjF,CAAC;IACD,MAAM,SAAS,CAAC,IAAI,CAAC,IAAA,wCAAmB,GAAE,CAAC,CAAC;IAE5C,OAAO,SAAS,CAAC,GAAG,CAAC,6BAAY,CAAC,CAAC,GAAG,EAAE,CAAC;AAC7C,CAAC","sourcesContent":["import 'reflect-metadata';\nimport { Container } from 'inversify';\nimport { buildProviderModule } from '@inversifyjs/binding-decorators';\nimport { loadAndValidate, BaseRuleConfig } from '@webpieces/rules-config';\n\nimport { ExecutorResult } from './code-validator';\nimport { CodeRulesApp } from './code-rules-app';\nimport { WorkspaceRoot, MatchRulesHolder } from './code-rules-context';\nimport { CONFIG_BINDINGS } from './code-rules-config-table';\n\nexport { ExecutorResult } from './code-validator';\n\n/**\n * Run all configured code validators against the workspace root (the nx `validate-code` executor's\n * entry, via `@webpieces/code-rules`'s `validateCode` export).\n *\n * Composition root: binds the workspace root + each rule's typed config into an inversify container,\n * then RESOLVES {@link CodeRulesApp} so inversify constructs the ENTIRE validator DAG nothing in the\n * DAG is `new`-ed (every validator, the reporter, and the match-rules checker are injected). Config\n * comes from webpieces.config.json (loaded via @webpieces/rules-config so ai-hooks and this executor\n * agree on every rule's mode/options).\n */\nexport default async function runValidator(workspaceRoot: string): Promise<ExecutorResult> {\n const loaded = loadAndValidate(workspaceRoot);\n if (loaded.configPath === null) {\n console.error('\\n❌ No webpieces.config.json found at workspace root (or any ancestor).\\n');\n return { success: false };\n }\n console.log(`\\n📄 Loaded config: ${loaded.configPath}`);\n\n const container = new Container();\n container.bind(WorkspaceRoot).toConstantValue(new WorkspaceRoot(workspaceRoot));\n container.bind(MatchRulesHolder).toConstantValue(new MatchRulesHolder(loaded.matchRules));\n for (const binding of CONFIG_BINDINGS) {\n const ConfigClass = binding[0];\n const configured = loaded.rulesConfig[binding[1]] as BaseRuleConfig | undefined;\n container.bind(ConfigClass).toConstantValue(configured ?? new ConfigClass());\n }\n await container.load(buildProviderModule());\n\n return container.get(CodeRulesApp).run();\n}\n"]}
@@ -36,6 +36,8 @@ const path = tslib_1.__importStar(require("path"));
36
36
  const ts = tslib_1.__importStar(require("typescript"));
37
37
  const rules_config_1 = require("@webpieces/rules-config");
38
38
  const code_validator_1 = require("./code-validator");
39
+ const core_context_1 = require("@webpieces/core-context");
40
+ const inversify_1 = require("inversify");
39
41
  const resolve_mode_1 = require("./resolve-mode");
40
42
  /**
41
43
  * Convert a snake_case string to camelCase.
@@ -433,13 +435,18 @@ async function runValidatorImpl(options, workspaceRoot) {
433
435
  const changedFiles = (0, rules_config_1.getChangedFiles)(workspaceRoot, base, head, { tsOnly: false });
434
436
  return validateDtoFiles(workspaceRoot, prismaSchemaPath, changedFiles, dtoSourcePaths, mode, base, head);
435
437
  }
436
- class PrismaValidateDtosValidator extends code_validator_1.CodeValidator {
438
+ let PrismaValidateDtosValidator = class PrismaValidateDtosValidator extends code_validator_1.CodeValidator {
437
439
  constructor(config) {
438
440
  super(config, 'prisma-validate-dtos');
439
441
  }
440
442
  async run(workspaceRoot) {
441
443
  return runValidatorImpl(this.config, workspaceRoot);
442
444
  }
443
- }
445
+ };
444
446
  exports.PrismaValidateDtosValidator = PrismaValidateDtosValidator;
447
+ exports.PrismaValidateDtosValidator = PrismaValidateDtosValidator = tslib_1.__decorate([
448
+ (0, core_context_1.provideSingleton)(),
449
+ (0, inversify_1.injectable)(),
450
+ tslib_1.__metadata("design:paramtypes", [rules_config_1.PrismaValidateDtosConfig])
451
+ ], PrismaValidateDtosValidator);
445
452
  //# sourceMappingURL=validate-dtos.js.map