@webpieces/ai-hook-rules 0.4.847 → 0.4.849

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 (39) hide show
  1. package/package.json +8 -7
  2. package/src/adapters/hook-app-fixtures.d.ts +2 -2
  3. package/src/adapters/hook-app-fixtures.js +60 -18
  4. package/src/adapters/hook-app-fixtures.js.map +1 -1
  5. package/src/core/load-rules.d.ts +2 -5
  6. package/src/core/load-rules.js +2 -148
  7. package/src/core/load-rules.js.map +1 -1
  8. package/src/core/rules/index.d.ts +13 -2
  9. package/src/core/rules/index.js +27 -17
  10. package/src/core/rules/index.js.map +1 -1
  11. package/src/core/rules/max-file-lines.d.ts +1 -1
  12. package/src/core/rules/max-file-lines.js +11 -4
  13. package/src/core/rules/max-file-lines.js.map +1 -1
  14. package/src/core/rules/no-custom-css.d.ts +1 -1
  15. package/src/core/rules/no-custom-css.js +2 -2
  16. package/src/core/rules/no-custom-css.js.map +1 -1
  17. package/src/core/rules/no-destructure.d.ts +1 -1
  18. package/src/core/rules/no-destructure.js +5 -3
  19. package/src/core/rules/no-destructure.js.map +1 -1
  20. package/src/core/rules/no-js-files.d.ts +1 -1
  21. package/src/core/rules/no-js-files.js +4 -2
  22. package/src/core/rules/no-js-files.js.map +1 -1
  23. package/src/core/rules/validate-ts-in-src.d.ts +1 -1
  24. package/src/core/rules/validate-ts-in-src.js +18 -8
  25. package/src/core/rules/validate-ts-in-src.js.map +1 -1
  26. package/src/core/runner.d.ts +3 -3
  27. package/src/core/runner.js +16 -12
  28. package/src/core/runner.js.map +1 -1
  29. package/src/rule-help.d.ts +3 -0
  30. package/src/rule-help.js +11 -0
  31. package/src/rule-help.js.map +1 -0
  32. package/src/rule-pack.js +2 -21
  33. package/src/rule-pack.js.map +1 -1
  34. package/src/rule-runtime.d.ts +7 -0
  35. package/src/rule-runtime.js +27 -0
  36. package/src/rule-runtime.js.map +1 -0
  37. package/src/source-policy-registry.d.ts +10 -0
  38. package/src/source-policy-registry.js +40 -0
  39. package/src/source-policy-registry.js.map +1 -0
@@ -8,26 +8,33 @@ const hook_runtime_3 = require("@webpieces/hook-runtime");
8
8
  const DEFAULT_LIMIT = 900;
9
9
  const INSTRUCT_FILE = 'webpieces.filesize.md';
10
10
  class MaxFileLinesRule extends hook_runtime_2.FileRuleBase {
11
- constructor(config) { super(config, 'max-file-lines', 'max-file-lines'); }
11
+ constructor(config) {
12
+ super(config, 'max-file-lines', 'max-file-lines');
13
+ }
12
14
  description = 'Cap file length at a configured line limit.';
13
15
  files = ['**/*.ts', '**/*.tsx'];
14
16
  defaultOptions = { limit: DEFAULT_LIMIT, allowedPaths: [] };
15
17
  get fixHint() {
16
18
  return new hook_runtime_3.FixHint('File exceeds the max-file-lines limit.', 'Pick one:', [
17
19
  new rules_config_1.Option('Refactor to reduce the file size — READ the instruct-ai doc at the absolute path on the violation line above.', true),
18
- new rules_config_1.Option('If this file is MACHINE-GENERATED and its size is not yours to control, add its tree to max-file-lines.allowedPaths in webpieces.config.json (the generated trees in GENERATED_CODE_PATHS are already exempt with no config at all). Never do this for hand-written code.'),
20
+ new rules_config_1.Option('If this file is MACHINE-GENERATED and its size is not yours to control, add its tree to max-file-lines.allowedPaths in {configFile} (the generated trees in GENERATED_CODE_PATHS are already exempt with no config at all). Never do this for hand-written code.'),
19
21
  ], new hook_runtime_3.DisableEscape(this.config.disableAllowed ?? true, '// eslint-disable-next-line @webpieces/max-file-lines (also suppresses the eslint rule)'));
20
22
  }
21
23
  check(ctx) {
22
24
  const limit = this.config.limit ?? DEFAULT_LIMIT;
23
25
  // Machine-generated trees are exempt unconditionally; allowedPaths ADDS to that floor.
24
- if ((0, rules_config_1.isPathExcluded)(ctx.relativePath, [...rules_config_1.GENERATED_CODE_PATHS, ...(this.config.allowedPaths ?? [])]))
26
+ if ((0, rules_config_1.isPathExcluded)(ctx.relativePath, [
27
+ ...rules_config_1.GENERATED_CODE_PATHS,
28
+ ...(this.config.allowedPaths ?? []),
29
+ ]))
25
30
  return [];
26
31
  if (ctx.projectedFileLines <= limit)
27
32
  return [];
28
33
  (0, rules_config_1.writeTemplateIfMissing)(ctx.workspaceRoot, INSTRUCT_FILE);
29
34
  const docPath = new rules_config_1.RepoRootFinder().instructAiDocPath(ctx.workspaceRoot, INSTRUCT_FILE);
30
- return [new hook_runtime_1.Violation(1, `(projected ${String(ctx.projectedFileLines)} lines)`, `File will be ${String(ctx.projectedFileLines)} lines, exceeding the ${String(limit)}-line limit. READ ${docPath} for detailed refactoring instructions.`)];
35
+ return [
36
+ new hook_runtime_1.Violation(1, `(projected ${String(ctx.projectedFileLines)} lines)`, `File will be ${String(ctx.projectedFileLines)} lines, exceeding the ${String(limit)}-line limit. READ ${docPath} for detailed refactoring instructions.`),
37
+ ];
31
38
  }
32
39
  }
33
40
  exports.MaxFileLinesRule = MaxFileLinesRule;
@@ -1 +1 @@
1
- {"version":3,"file":"max-file-lines.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/max-file-lines.ts"],"names":[],"mappings":";;;AACA,0DAA+H;AAG/H,0DAAyD;AACzD,0DAAuD;AACvD,0DAAiE;AAEjE,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAE9C,MAAa,gBAAiB,SAAQ,2BAAsC;IACxE,YAAY,MAAgC,IAAI,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAE3F,WAAW,GAAG,6CAA6C,CAAC;IACnD,KAAK,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAChC,cAAc,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC9E,IAAI,OAAO;QACP,OAAO,IAAI,sBAAO,CACd,wCAAwC,EACxC,WAAW,EACX;YACI,IAAI,qBAAM,CAAC,+GAA+G,EAAE,IAAI,CAAC;YACjI,IAAI,qBAAM,CAAC,2QAA2Q,CAAC;SAC1R,EACD,IAAI,4BAAa,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,IAAI,EAAE,0FAA0F,CAAC,CACpJ,CAAC;IACN,CAAC;IAED,KAAK,CAAC,GAAgB;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,aAAa,CAAC;QACjD,uFAAuF;QACvF,IAAI,IAAA,6BAAc,EAAC,GAAG,CAAC,YAAY,EAAE,CAAC,GAAG,mCAAoB,EAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC,CAAC;YAAE,OAAO,EAAE,CAAC;QAChH,IAAI,GAAG,CAAC,kBAAkB,IAAI,KAAK;YAAE,OAAO,EAAE,CAAC;QAC/C,IAAA,qCAAsB,EAAC,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,IAAI,6BAAc,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACzF,OAAO,CAAC,IAAI,wBAAC,CACT,CAAC,EACD,cAAc,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,SAAS,EACrD,gBAAgB,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,yBAAyB,MAAM,CAAC,KAAK,CAAC,qBAAqB,OAAO,yCAAyC,CAC5J,CAAC,CAAC;IACP,CAAC;CACJ;AA/BD,4CA+BC","sourcesContent":["import { SourceContributionConfig } from \"../source-contribution-config\";\nimport { writeTemplateIfMissing, RepoRootFinder, isPathExcluded, GENERATED_CODE_PATHS, Option } from \"@webpieces/rules-config\";\n\nimport type { FileContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { FileRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint, DisableEscape } from '@webpieces/hook-runtime';\n\nconst DEFAULT_LIMIT = 900;\nconst INSTRUCT_FILE = 'webpieces.filesize.md';\n\nexport class MaxFileLinesRule extends FileRuleBase<SourceContributionConfig> {\n constructor(config: SourceContributionConfig) { super(config, 'max-file-lines', 'max-file-lines'); }\n\n readonly description = 'Cap file length at a configured line limit.';\n override readonly files = ['**/*.ts', '**/*.tsx'];\n override readonly defaultOptions = { limit: DEFAULT_LIMIT, allowedPaths: [] };\n get fixHint(): FixHint {\n return new FixHint(\n 'File exceeds the max-file-lines limit.',\n 'Pick one:',\n [\n new Option('Refactor to reduce the file size — READ the instruct-ai doc at the absolute path on the violation line above.', true),\n new Option('If this file is MACHINE-GENERATED and its size is not yours to control, add its tree to max-file-lines.allowedPaths in webpieces.config.json (the generated trees in GENERATED_CODE_PATHS are already exempt with no config at all). Never do this for hand-written code.'),\n ],\n new DisableEscape(this.config.disableAllowed ?? true, '// eslint-disable-next-line @webpieces/max-file-lines (also suppresses the eslint rule)'),\n );\n }\n\n check(ctx: FileContext): readonly Violation[] {\n const limit = this.config.limit ?? DEFAULT_LIMIT;\n // Machine-generated trees are exempt unconditionally; allowedPaths ADDS to that floor.\n if (isPathExcluded(ctx.relativePath, [...GENERATED_CODE_PATHS, ...(this.config.allowedPaths ?? [])])) return [];\n if (ctx.projectedFileLines <= limit) return [];\n writeTemplateIfMissing(ctx.workspaceRoot, INSTRUCT_FILE);\n const docPath = new RepoRootFinder().instructAiDocPath(ctx.workspaceRoot, INSTRUCT_FILE);\n return [new V(\n 1,\n `(projected ${String(ctx.projectedFileLines)} lines)`,\n `File will be ${String(ctx.projectedFileLines)} lines, exceeding the ${String(limit)}-line limit. READ ${docPath} for detailed refactoring instructions.`,\n )];\n }\n}\n"]}
1
+ {"version":3,"file":"max-file-lines.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/max-file-lines.ts"],"names":[],"mappings":";;;AACA,0DAMiC;AAGjC,0DAAyD;AACzD,0DAAuD;AACvD,0DAAiE;AAEjE,MAAM,aAAa,GAAG,GAAG,CAAC;AAC1B,MAAM,aAAa,GAAG,uBAAuB,CAAC;AAE9C,MAAa,gBAAiB,SAAQ,2BAAsC;IACxE,YAAY,MAAgC;QACxC,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;IACtD,CAAC;IAEQ,WAAW,GAAG,6CAA6C,CAAC;IACnD,KAAK,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAChC,cAAc,GAAG,EAAE,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC9E,IAAI,OAAO;QACP,OAAO,IAAI,sBAAO,CACd,wCAAwC,EACxC,WAAW,EACX;YACI,IAAI,qBAAM,CACN,+GAA+G,EAC/G,IAAI,CACP;YACD,IAAI,qBAAM,CACN,kQAAkQ,CACrQ;SACJ,EACD,IAAI,4BAAa,CACb,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,IAAI,EAClC,0FAA0F,CAC7F,CACJ,CAAC;IACN,CAAC;IAED,KAAK,CAAC,GAAgB;QAClB,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,aAAa,CAAC;QACjD,uFAAuF;QACvF,IACI,IAAA,6BAAc,EAAC,GAAG,CAAC,YAAY,EAAE;YAC7B,GAAG,mCAAoB;YACvB,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;SACtC,CAAC;YAEF,OAAO,EAAE,CAAC;QACd,IAAI,GAAG,CAAC,kBAAkB,IAAI,KAAK;YAAE,OAAO,EAAE,CAAC;QAC/C,IAAA,qCAAsB,EAAC,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,IAAI,6BAAc,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;QACzF,OAAO;YACH,IAAI,wBAAC,CACD,CAAC,EACD,cAAc,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,SAAS,EACrD,gBAAgB,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,yBAAyB,MAAM,CAAC,KAAK,CAAC,qBAAqB,OAAO,yCAAyC,CAC5J;SACJ,CAAC;IACN,CAAC;CACJ;AAjDD,4CAiDC","sourcesContent":["import { SourceContributionConfig } from '../source-contribution-config';\nimport {\n writeTemplateIfMissing,\n RepoRootFinder,\n isPathExcluded,\n GENERATED_CODE_PATHS,\n Option,\n} from '@webpieces/rules-config';\n\nimport type { FileContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { FileRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint, DisableEscape } from '@webpieces/hook-runtime';\n\nconst DEFAULT_LIMIT = 900;\nconst INSTRUCT_FILE = 'webpieces.filesize.md';\n\nexport class MaxFileLinesRule extends FileRuleBase<SourceContributionConfig> {\n constructor(config: SourceContributionConfig) {\n super(config, 'max-file-lines', 'max-file-lines');\n }\n\n readonly description = 'Cap file length at a configured line limit.';\n override readonly files = ['**/*.ts', '**/*.tsx'];\n override readonly defaultOptions = { limit: DEFAULT_LIMIT, allowedPaths: [] };\n get fixHint(): FixHint {\n return new FixHint(\n 'File exceeds the max-file-lines limit.',\n 'Pick one:',\n [\n new Option(\n 'Refactor to reduce the file size — READ the instruct-ai doc at the absolute path on the violation line above.',\n true,\n ),\n new Option(\n 'If this file is MACHINE-GENERATED and its size is not yours to control, add its tree to max-file-lines.allowedPaths in {configFile} (the generated trees in GENERATED_CODE_PATHS are already exempt with no config at all). Never do this for hand-written code.',\n ),\n ],\n new DisableEscape(\n this.config.disableAllowed ?? true,\n '// eslint-disable-next-line @webpieces/max-file-lines (also suppresses the eslint rule)',\n ),\n );\n }\n\n check(ctx: FileContext): readonly Violation[] {\n const limit = this.config.limit ?? DEFAULT_LIMIT;\n // Machine-generated trees are exempt unconditionally; allowedPaths ADDS to that floor.\n if (\n isPathExcluded(ctx.relativePath, [\n ...GENERATED_CODE_PATHS,\n ...(this.config.allowedPaths ?? []),\n ])\n )\n return [];\n if (ctx.projectedFileLines <= limit) return [];\n writeTemplateIfMissing(ctx.workspaceRoot, INSTRUCT_FILE);\n const docPath = new RepoRootFinder().instructAiDocPath(ctx.workspaceRoot, INSTRUCT_FILE);\n return [\n new V(\n 1,\n `(projected ${String(ctx.projectedFileLines)} lines)`,\n `File will be ${String(ctx.projectedFileLines)} lines, exceeding the ${String(limit)}-line limit. READ ${docPath} for detailed refactoring instructions.`,\n ),\n ];\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { SourceContributionConfig } from "../source-contribution-config";
1
+ import { SourceContributionConfig } from '../source-contribution-config';
2
2
  import type { EditContext, Violation } from '@webpieces/hook-runtime';
3
3
  import { EditRuleBase } from '@webpieces/hook-runtime';
4
4
  import { FixHint } from '@webpieces/hook-runtime';
@@ -29,7 +29,7 @@ class NoCustomCssRule extends hook_runtime_2.EditRuleBase {
29
29
  new rules_config_1.Option('Delete the CSS and use Tailwind utility classes (flex, grid, gap-4, text-red-600).', true),
30
30
  new rules_config_1.Option('Need a specific value? Use an arbitrary-value class: w-[240px], bg-[#fffde7], grid-cols-[2fr_2fr_48px].'),
31
31
  new rules_config_1.Option('Dynamic on/off? Prefer [class.x]="cond" over a style binding.'),
32
- new rules_config_1.Option('Whole tree not yours to restyle (a vendored kit, a generated artifact)? Add a glob to no-custom-css.allowGlobs in webpieces.config.json — it exempts the path in the editor and in CI alike.'),
32
+ new rules_config_1.Option('Whole tree not yours to restyle (a vendored kit, a generated artifact)? Add a glob to no-custom-css.allowGlobs in {configFile} — it exempts the path in the editor and in CI alike.'),
33
33
  ], new hook_runtime_3.DisableEscape(this.config.disableAllowed ?? true, '// webpieces-disable no-custom-css -- <reason>'));
34
34
  }
35
35
  check(ctx) {
@@ -43,7 +43,7 @@ class NoCustomCssRule extends hook_runtime_2.EditRuleBase {
43
43
  if (!detail)
44
44
  continue;
45
45
  const lineNum = i + 1;
46
- if (disableAllowed && ctx.isLineDisabled(lineNum, "no-custom-css"))
46
+ if (disableAllowed && ctx.isLineDisabled(lineNum, 'no-custom-css'))
47
47
  continue;
48
48
  violations.push(new hook_runtime_1.Violation(lineNum, `${detail}: ${ctx.lines[i]?.trim() ?? ''}`));
49
49
  }
@@ -1 +1 @@
1
- {"version":3,"file":"no-custom-css.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/no-custom-css.ts"],"names":[],"mappings":"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","sourcesContent":["import { SourceContributionConfig } from \"../source-contribution-config\";\nimport { NoCustomCssScope, Option } from \"@webpieces/rules-config\";\n\nimport type { EditContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { EditRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint, DisableEscape } from '@webpieces/hook-runtime';\n\n// Edit-time (regex/line) counterpart to the CI code-rule validate-no-custom-css. The hook has no TS\n// AST, so the `.ts` side matches the @Component style props by shape; the `.html` side matches inline\n// style attributes/bindings. Both are diff-precise via the hook's per-line edit context.\nconst RE_STYLE_URLS = /(^|\\s)styleUrls?\\s*:/; // styleUrls: / styleUrl:\nconst RE_STYLES_ARRAY = /(^|\\s)styles\\s*:\\s*\\[/; // styles: [ ... ] (component inline CSS)\nconst RE_INLINE_STYLE = /(^|\\s)style\\s*=\\s*[\"']/; // static style=\"…\"\nconst RE_NG_STYLE = /\\[?ngStyle\\]?\\s*=/; // [ngStyle]=\"…\"\nconst RE_STYLE_BINDING = /\\[style(?:\\.[\\w.-]+)?\\]/; // [style] / [style.width]\n\nexport class NoCustomCssRule extends EditRuleBase<SourceContributionConfig> {\n // The SAME exemption the CI validator narrows its changed-file set with. Shared, because a second copy\n // of this predicate is how `allowGlobs` came to be honoured here and ignored there.\n private readonly pathScope: NoCustomCssScope;\n\n constructor(config: SourceContributionConfig) {\n super(config, 'no-custom-css', 'no-custom-css');\n this.pathScope = new NoCustomCssScope(config);\n }\n\n readonly description =\n 'Ban hand-written CSS in Angular (styles/styleUrls in @Component, inline style=, [style.x], [ngStyle]) — style with Tailwind utility classes.';\n override readonly files = ['**/*.ts', '**/*.tsx', '**/*.html'];\n override readonly defaultOptions = { allowGlobs: [] };\n\n get fixHint(): FixHint {\n return new FixHint(\n 'Custom CSS bypasses Tailwind-first styling.',\n 'Pick one:',\n [\n new Option('Delete the CSS and use Tailwind utility classes (flex, grid, gap-4, text-red-600).', true),\n new Option('Need a specific value? Use an arbitrary-value class: w-[240px], bg-[#fffde7], grid-cols-[2fr_2fr_48px].'),\n new Option('Dynamic on/off? Prefer [class.x]=\"cond\" over a style binding.'),\n new Option('Whole tree not yours to restyle (a vendored kit, a generated artifact)? Add a glob to no-custom-css.allowGlobs in webpieces.config.json — it exempts the path in the editor and in CI alike.'),\n ],\n new DisableEscape(this.config.disableAllowed ?? true, '// webpieces-disable no-custom-css -- <reason>'),\n );\n }\n\n check(ctx: EditContext): readonly Violation[] {\n if (this.pathScope.isExempt(ctx.relativePath)) return [];\n\n const isHtml = ctx.relativePath.endsWith('.html');\n const disableAllowed = this.config.disableAllowed ?? true;\n const violations: V[] = [];\n for (let i = 0; i < ctx.strippedLines.length; i += 1) {\n const detail = this.detailForLine(ctx.strippedLines[i] ?? '', isHtml);\n if (!detail) continue;\n const lineNum = i + 1;\n if (disableAllowed && ctx.isLineDisabled(lineNum, \"no-custom-css\")) continue;\n violations.push(new V(lineNum, `${detail}: ${ctx.lines[i]?.trim() ?? ''}`));\n }\n return violations;\n }\n\n /** The banned-pattern label for a line, or '' when clean. Branches on the file being a template. */\n private detailForLine(line: string, isHtml: boolean): string {\n if (isHtml) {\n if (RE_NG_STYLE.test(line)) return 'inline `[ngStyle]`';\n if (RE_STYLE_BINDING.test(line)) return 'inline `[style.x]` binding';\n if (RE_INLINE_STYLE.test(line)) return 'inline `style=` attribute';\n return '';\n }\n if (RE_STYLE_URLS.test(line)) return '`styleUrls`/`styleUrl` in @Component';\n if (RE_STYLES_ARRAY.test(line)) return '`styles` block in @Component';\n return '';\n }\n}\n"]}
1
+ {"version":3,"file":"no-custom-css.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/no-custom-css.ts"],"names":[],"mappings":"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","sourcesContent":["import { SourceContributionConfig } from '../source-contribution-config';\nimport { NoCustomCssScope, Option } from '@webpieces/rules-config';\n\nimport type { EditContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { EditRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint, DisableEscape } from '@webpieces/hook-runtime';\n\n// Edit-time (regex/line) counterpart to the CI code-rule validate-no-custom-css. The hook has no TS\n// AST, so the `.ts` side matches the @Component style props by shape; the `.html` side matches inline\n// style attributes/bindings. Both are diff-precise via the hook's per-line edit context.\nconst RE_STYLE_URLS = /(^|\\s)styleUrls?\\s*:/; // styleUrls: / styleUrl:\nconst RE_STYLES_ARRAY = /(^|\\s)styles\\s*:\\s*\\[/; // styles: [ ... ] (component inline CSS)\nconst RE_INLINE_STYLE = /(^|\\s)style\\s*=\\s*[\"']/; // static style=\"…\"\nconst RE_NG_STYLE = /\\[?ngStyle\\]?\\s*=/; // [ngStyle]=\"…\"\nconst RE_STYLE_BINDING = /\\[style(?:\\.[\\w.-]+)?\\]/; // [style] / [style.width]\n\nexport class NoCustomCssRule extends EditRuleBase<SourceContributionConfig> {\n // The SAME exemption the CI validator narrows its changed-file set with. Shared, because a second copy\n // of this predicate is how `allowGlobs` came to be honoured here and ignored there.\n private readonly pathScope: NoCustomCssScope;\n\n constructor(config: SourceContributionConfig) {\n super(config, 'no-custom-css', 'no-custom-css');\n this.pathScope = new NoCustomCssScope(config);\n }\n\n readonly description =\n 'Ban hand-written CSS in Angular (styles/styleUrls in @Component, inline style=, [style.x], [ngStyle]) — style with Tailwind utility classes.';\n override readonly files = ['**/*.ts', '**/*.tsx', '**/*.html'];\n override readonly defaultOptions = { allowGlobs: [] };\n\n get fixHint(): FixHint {\n return new FixHint(\n 'Custom CSS bypasses Tailwind-first styling.',\n 'Pick one:',\n [\n new Option(\n 'Delete the CSS and use Tailwind utility classes (flex, grid, gap-4, text-red-600).',\n true,\n ),\n new Option(\n 'Need a specific value? Use an arbitrary-value class: w-[240px], bg-[#fffde7], grid-cols-[2fr_2fr_48px].',\n ),\n new Option('Dynamic on/off? Prefer [class.x]=\"cond\" over a style binding.'),\n new Option(\n 'Whole tree not yours to restyle (a vendored kit, a generated artifact)? Add a glob to no-custom-css.allowGlobs in {configFile} — it exempts the path in the editor and in CI alike.',\n ),\n ],\n new DisableEscape(\n this.config.disableAllowed ?? true,\n '// webpieces-disable no-custom-css -- <reason>',\n ),\n );\n }\n\n check(ctx: EditContext): readonly Violation[] {\n if (this.pathScope.isExempt(ctx.relativePath)) return [];\n\n const isHtml = ctx.relativePath.endsWith('.html');\n const disableAllowed = this.config.disableAllowed ?? true;\n const violations: V[] = [];\n for (let i = 0; i < ctx.strippedLines.length; i += 1) {\n const detail = this.detailForLine(ctx.strippedLines[i] ?? '', isHtml);\n if (!detail) continue;\n const lineNum = i + 1;\n if (disableAllowed && ctx.isLineDisabled(lineNum, 'no-custom-css')) continue;\n violations.push(new V(lineNum, `${detail}: ${ctx.lines[i]?.trim() ?? ''}`));\n }\n return violations;\n }\n\n /** The banned-pattern label for a line, or '' when clean. Branches on the file being a template. */\n private detailForLine(line: string, isHtml: boolean): string {\n if (isHtml) {\n if (RE_NG_STYLE.test(line)) return 'inline `[ngStyle]`';\n if (RE_STYLE_BINDING.test(line)) return 'inline `[style.x]` binding';\n if (RE_INLINE_STYLE.test(line)) return 'inline `style=` attribute';\n return '';\n }\n if (RE_STYLE_URLS.test(line)) return '`styleUrls`/`styleUrl` in @Component';\n if (RE_STYLES_ARRAY.test(line)) return '`styles` block in @Component';\n return '';\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { SourceContributionConfig } from "../source-contribution-config";
1
+ import { SourceContributionConfig } from '../source-contribution-config';
2
2
  import type { EditContext, Violation } from '@webpieces/hook-runtime';
3
3
  import { EditRuleBase } from '@webpieces/hook-runtime';
4
4
  import { FixHint } from '@webpieces/hook-runtime';
@@ -7,14 +7,16 @@ const hook_runtime_2 = require("@webpieces/hook-runtime");
7
7
  const hook_runtime_3 = require("@webpieces/hook-runtime");
8
8
  const VARIABLE_DESTRUCTURE = /\b(?:const|let|var)\s*\{/;
9
9
  class NoDestructureRule extends hook_runtime_2.EditRuleBase {
10
- constructor(config) { super(config, 'no-destructure', 'no-destructure'); }
10
+ constructor(config) {
11
+ super(config, 'no-destructure', 'no-destructure');
12
+ }
11
13
  description = 'Disallow destructuring patterns. Assign the whole result and pass it around or access properties explicitly.';
12
14
  files = ['**/*.ts', '**/*.tsx'];
13
15
  defaultOptions = { allowTopLevel: true, allowedPaths: [] };
14
16
  get fixHint() {
15
17
  return new hook_runtime_3.FixHint('Destructuring pattern on a call result.', 'Pick one:', [
16
18
  new rules_config_1.Option('Assign the whole result instead: const obj = methodCall(); then pass obj around or use obj.x.', true),
17
- new rules_config_1.Option('If this whole tree is destructuring by construction (a React/React Native component or hook tree), add a glob to no-destructure.allowedPaths in webpieces.config.json'),
19
+ new rules_config_1.Option('If this whole tree is destructuring by construction (a React/React Native component or hook tree), add a glob to no-destructure.allowedPaths in {configFile}'),
18
20
  ], new hook_runtime_3.DisableEscape(this.config.disableAllowed ?? true, '// webpieces-disable no-destructure -- <reason>'));
19
21
  }
20
22
  check(ctx) {
@@ -28,7 +30,7 @@ class NoDestructureRule extends hook_runtime_2.EditRuleBase {
28
30
  if (!VARIABLE_DESTRUCTURE.test(stripped))
29
31
  continue;
30
32
  const lineNum = i + 1;
31
- if (disableAllowed && ctx.isLineDisabled(lineNum, "no-destructure"))
33
+ if (disableAllowed && ctx.isLineDisabled(lineNum, 'no-destructure'))
32
34
  continue;
33
35
  violations.push(new hook_runtime_1.Violation(lineNum, ctx.lines[i].trim()));
34
36
  }
@@ -1 +1 @@
1
- {"version":3,"file":"no-destructure.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/no-destructure.ts"],"names":[],"mappings":";;;AACA,0DAAiE;AAGjE,0DAAyD;AACzD,0DAAuD;AACvD,0DAAiE;AAEjE,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAExD,MAAa,iBAAkB,SAAQ,2BAAsC;IACzE,YAAY,MAAgC,IAAI,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC;IAE3F,WAAW,GAAG,8GAA8G,CAAC;IACpH,KAAK,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAChC,cAAc,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC7E,IAAI,OAAO;QACP,OAAO,IAAI,sBAAO,CACd,yCAAyC,EACzC,WAAW,EACX;YACI,IAAI,qBAAM,CAAC,+FAA+F,EAAE,IAAI,CAAC;YACjH,IAAI,qBAAM,CAAC,uKAAuK,CAAC;SACtL,EACD,IAAI,4BAAa,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,IAAI,EAAE,iDAAiD,CAAC,CAC3G,CAAC;IACN,CAAC;IAED,KAAK,CAAC,GAAgB;QAClB,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;QACpD,IAAI,IAAA,6BAAc,EAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC;YAAE,OAAO,EAAE,CAAC;QAE9D,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,IAAI,CAAC;QAC1D,MAAM,UAAU,GAAQ,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACtC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAAE,SAAS;YACnD,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;YACtB,IAAI,cAAc,IAAI,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE,gBAAgB,CAAC;gBAAE,SAAS;YAC9E,UAAU,CAAC,IAAI,CAAC,IAAI,wBAAC,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;CACJ;AAjCD,8CAiCC","sourcesContent":["import { SourceContributionConfig } from \"../source-contribution-config\";\nimport { isPathExcluded, Option } from \"@webpieces/rules-config\";\n\nimport type { EditContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { EditRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint, DisableEscape } from '@webpieces/hook-runtime';\n\nconst VARIABLE_DESTRUCTURE = /\\b(?:const|let|var)\\s*\\{/;\n\nexport class NoDestructureRule extends EditRuleBase<SourceContributionConfig> {\n constructor(config: SourceContributionConfig) { super(config, 'no-destructure', 'no-destructure'); }\n\n readonly description = 'Disallow destructuring patterns. Assign the whole result and pass it around or access properties explicitly.';\n override readonly files = ['**/*.ts', '**/*.tsx'];\n override readonly defaultOptions = { allowTopLevel: true, allowedPaths: [] };\n get fixHint(): FixHint {\n return new FixHint(\n 'Destructuring pattern on a call result.',\n 'Pick one:',\n [\n new Option('Assign the whole result instead: const obj = methodCall(); then pass obj around or use obj.x.', true),\n new Option('If this whole tree is destructuring by construction (a React/React Native component or hook tree), add a glob to no-destructure.allowedPaths in webpieces.config.json'),\n ],\n new DisableEscape(this.config.disableAllowed ?? true, '// webpieces-disable no-destructure -- <reason>'),\n );\n }\n\n check(ctx: EditContext): readonly Violation[] {\n const allowedPaths = this.config.allowedPaths ?? [];\n if (isPathExcluded(ctx.relativePath, allowedPaths)) return [];\n\n const disableAllowed = this.config.disableAllowed ?? true;\n const violations: V[] = [];\n for (let i = 0; i < ctx.strippedLines.length; i += 1) {\n const stripped = ctx.strippedLines[i];\n if (!VARIABLE_DESTRUCTURE.test(stripped)) continue;\n const lineNum = i + 1;\n if (disableAllowed && ctx.isLineDisabled(lineNum, \"no-destructure\")) continue;\n violations.push(new V(lineNum, ctx.lines[i].trim()));\n }\n return violations;\n }\n}\n"]}
1
+ {"version":3,"file":"no-destructure.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/no-destructure.ts"],"names":[],"mappings":";;;AACA,0DAAiE;AAGjE,0DAAyD;AACzD,0DAAuD;AACvD,0DAAiE;AAEjE,MAAM,oBAAoB,GAAG,0BAA0B,CAAC;AAExD,MAAa,iBAAkB,SAAQ,2BAAsC;IACzE,YAAY,MAAgC;QACxC,KAAK,CAAC,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC;IACtD,CAAC;IAEQ,WAAW,GAChB,8GAA8G,CAAC;IACjG,KAAK,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAChC,cAAc,GAAG,EAAE,aAAa,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC7E,IAAI,OAAO;QACP,OAAO,IAAI,sBAAO,CACd,yCAAyC,EACzC,WAAW,EACX;YACI,IAAI,qBAAM,CACN,+FAA+F,EAC/F,IAAI,CACP;YACD,IAAI,qBAAM,CACN,8JAA8J,CACjK;SACJ,EACD,IAAI,4BAAa,CACb,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,IAAI,EAClC,iDAAiD,CACpD,CACJ,CAAC;IACN,CAAC;IAED,KAAK,CAAC,GAAgB;QAClB,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;QACpD,IAAI,IAAA,6BAAc,EAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC;YAAE,OAAO,EAAE,CAAC;QAE9D,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,IAAI,CAAC;QAC1D,MAAM,UAAU,GAAQ,EAAE,CAAC;QAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACnD,MAAM,QAAQ,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACtC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,QAAQ,CAAC;gBAAE,SAAS;YACnD,MAAM,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;YACtB,IAAI,cAAc,IAAI,GAAG,CAAC,cAAc,CAAC,OAAO,EAAE,gBAAgB,CAAC;gBAAE,SAAS;YAC9E,UAAU,CAAC,IAAI,CAAC,IAAI,wBAAC,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACzD,CAAC;QACD,OAAO,UAAU,CAAC;IACtB,CAAC;CACJ;AA5CD,8CA4CC","sourcesContent":["import { SourceContributionConfig } from '../source-contribution-config';\nimport { isPathExcluded, Option } from '@webpieces/rules-config';\n\nimport type { EditContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { EditRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint, DisableEscape } from '@webpieces/hook-runtime';\n\nconst VARIABLE_DESTRUCTURE = /\\b(?:const|let|var)\\s*\\{/;\n\nexport class NoDestructureRule extends EditRuleBase<SourceContributionConfig> {\n constructor(config: SourceContributionConfig) {\n super(config, 'no-destructure', 'no-destructure');\n }\n\n readonly description =\n 'Disallow destructuring patterns. Assign the whole result and pass it around or access properties explicitly.';\n override readonly files = ['**/*.ts', '**/*.tsx'];\n override readonly defaultOptions = { allowTopLevel: true, allowedPaths: [] };\n get fixHint(): FixHint {\n return new FixHint(\n 'Destructuring pattern on a call result.',\n 'Pick one:',\n [\n new Option(\n 'Assign the whole result instead: const obj = methodCall(); then pass obj around or use obj.x.',\n true,\n ),\n new Option(\n 'If this whole tree is destructuring by construction (a React/React Native component or hook tree), add a glob to no-destructure.allowedPaths in {configFile}',\n ),\n ],\n new DisableEscape(\n this.config.disableAllowed ?? true,\n '// webpieces-disable no-destructure -- <reason>',\n ),\n );\n }\n\n check(ctx: EditContext): readonly Violation[] {\n const allowedPaths = this.config.allowedPaths ?? [];\n if (isPathExcluded(ctx.relativePath, allowedPaths)) return [];\n\n const disableAllowed = this.config.disableAllowed ?? true;\n const violations: V[] = [];\n for (let i = 0; i < ctx.strippedLines.length; i += 1) {\n const stripped = ctx.strippedLines[i];\n if (!VARIABLE_DESTRUCTURE.test(stripped)) continue;\n const lineNum = i + 1;\n if (disableAllowed && ctx.isLineDisabled(lineNum, 'no-destructure')) continue;\n violations.push(new V(lineNum, ctx.lines[i].trim()));\n }\n return violations;\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { NoJsFilesConfig } from "../../configs/rule-configs";
1
+ import { NoJsFilesConfig } from '../../configs/rule-configs';
2
2
  import type { FileContext, Violation } from '@webpieces/hook-runtime';
3
3
  import { FileRuleBase } from '@webpieces/hook-runtime';
4
4
  import { FixHint } from '@webpieces/hook-runtime';
@@ -6,13 +6,15 @@ const hook_runtime_1 = require("@webpieces/hook-runtime");
6
6
  const hook_runtime_2 = require("@webpieces/hook-runtime");
7
7
  const hook_runtime_3 = require("@webpieces/hook-runtime");
8
8
  class NoJsFilesRule extends hook_runtime_2.FileRuleBase {
9
- constructor(config) { super(config, 'no-js-files', 'no-js-files'); }
9
+ constructor(config) {
10
+ super(config, 'no-js-files', 'no-js-files');
11
+ }
10
12
  description = 'Disallow writing new .js/.jsx files. Use .ts/.tsx instead.';
11
13
  files = ['**/*.js', '**/*.jsx'];
12
14
  defaultOptions = { allowedPaths: [] };
13
15
  fixHint = new hook_runtime_3.FixHint('Writing .js/.jsx files is not allowed. Use .ts/.tsx instead.', 'Pick one:', [
14
16
  new rules_config_1.Option('Write a .ts or .tsx file instead of .js/.jsx.', true),
15
- new rules_config_1.Option('If this path must be .js (generated/legacy), add it to no-js-files.allowedPaths in webpieces.config.json'),
17
+ new rules_config_1.Option('If this path must be .js (generated/legacy), add it to no-js-files.allowedPaths in {configFile}'),
16
18
  ]);
17
19
  check(ctx) {
18
20
  if (ctx.tool !== 'Write')
@@ -1 +1 @@
1
- {"version":3,"file":"no-js-files.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/no-js-files.ts"],"names":[],"mappings":";;;AAAA,0DAAiE;AAIjE,0DAAyD;AACzD,0DAAuD;AACvD,0DAAkD;AAElD,MAAa,aAAc,SAAQ,2BAA6B;IAC5D,YAAY,MAAuB,IAAI,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC;IAE5E,WAAW,GAAG,4DAA4D,CAAC;IAClE,KAAK,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAChC,cAAc,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC/C,OAAO,GAAG,IAAI,sBAAO,CAC1B,8DAA8D,EAC9D,WAAW,EACX;QACI,IAAI,qBAAM,CAAC,+CAA+C,EAAE,IAAI,CAAC;QACjE,IAAI,qBAAM,CAAC,0GAA0G,CAAC;KACzH,CACJ,CAAC;IAEF,KAAK,CAAC,GAAgB;QAClB,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,EAAE,CAAC;QAEpC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;QAEpD,IAAI,IAAA,6BAAc,EAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC;YAAE,OAAO,EAAE,CAAC;QAE9D,OAAO,CAAC,IAAI,wBAAC,CAAC,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;IACxC,CAAC;CACJ;AAxBD,sCAwBC","sourcesContent":["import { isPathExcluded, Option } from \"@webpieces/rules-config\";\nimport { NoJsFilesConfig } from \"../../configs/rule-configs\";\n\nimport type { FileContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { FileRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint } from '@webpieces/hook-runtime';\n\nexport class NoJsFilesRule extends FileRuleBase<NoJsFilesConfig> {\n constructor(config: NoJsFilesConfig) { super(config, 'no-js-files', 'no-js-files'); }\n\n readonly description = 'Disallow writing new .js/.jsx files. Use .ts/.tsx instead.';\n override readonly files = ['**/*.js', '**/*.jsx'];\n override readonly defaultOptions = { allowedPaths: [] };\n readonly fixHint = new FixHint(\n 'Writing .js/.jsx files is not allowed. Use .ts/.tsx instead.',\n 'Pick one:',\n [\n new Option('Write a .ts or .tsx file instead of .js/.jsx.', true),\n new Option('If this path must be .js (generated/legacy), add it to no-js-files.allowedPaths in webpieces.config.json'),\n ],\n );\n\n check(ctx: FileContext): readonly Violation[] {\n if (ctx.tool !== 'Write') return [];\n\n const allowedPaths = this.config.allowedPaths ?? [];\n\n if (isPathExcluded(ctx.relativePath, allowedPaths)) return [];\n\n return [new V(1, ctx.relativePath)];\n }\n}\n"]}
1
+ {"version":3,"file":"no-js-files.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/no-js-files.ts"],"names":[],"mappings":";;;AAAA,0DAAiE;AAIjE,0DAAyD;AACzD,0DAAuD;AACvD,0DAAkD;AAElD,MAAa,aAAc,SAAQ,2BAA6B;IAC5D,YAAY,MAAuB;QAC/B,KAAK,CAAC,MAAM,EAAE,aAAa,EAAE,aAAa,CAAC,CAAC;IAChD,CAAC;IAEQ,WAAW,GAAG,4DAA4D,CAAC;IAClE,KAAK,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAChC,cAAc,GAAG,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC;IAC/C,OAAO,GAAG,IAAI,sBAAO,CAC1B,8DAA8D,EAC9D,WAAW,EACX;QACI,IAAI,qBAAM,CAAC,+CAA+C,EAAE,IAAI,CAAC;QACjE,IAAI,qBAAM,CACN,iGAAiG,CACpG;KACJ,CACJ,CAAC;IAEF,KAAK,CAAC,GAAgB;QAClB,IAAI,GAAG,CAAC,IAAI,KAAK,OAAO;YAAE,OAAO,EAAE,CAAC;QAEpC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,EAAE,CAAC;QAEpD,IAAI,IAAA,6BAAc,EAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC;YAAE,OAAO,EAAE,CAAC;QAE9D,OAAO,CAAC,IAAI,wBAAC,CAAC,CAAC,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC;IACxC,CAAC;CACJ;AA5BD,sCA4BC","sourcesContent":["import { isPathExcluded, Option } from '@webpieces/rules-config';\nimport { NoJsFilesConfig } from '../../configs/rule-configs';\n\nimport type { FileContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { FileRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint } from '@webpieces/hook-runtime';\n\nexport class NoJsFilesRule extends FileRuleBase<NoJsFilesConfig> {\n constructor(config: NoJsFilesConfig) {\n super(config, 'no-js-files', 'no-js-files');\n }\n\n readonly description = 'Disallow writing new .js/.jsx files. Use .ts/.tsx instead.';\n override readonly files = ['**/*.js', '**/*.jsx'];\n override readonly defaultOptions = { allowedPaths: [] };\n readonly fixHint = new FixHint(\n 'Writing .js/.jsx files is not allowed. Use .ts/.tsx instead.',\n 'Pick one:',\n [\n new Option('Write a .ts or .tsx file instead of .js/.jsx.', true),\n new Option(\n 'If this path must be .js (generated/legacy), add it to no-js-files.allowedPaths in {configFile}',\n ),\n ],\n );\n\n check(ctx: FileContext): readonly Violation[] {\n if (ctx.tool !== 'Write') return [];\n\n const allowedPaths = this.config.allowedPaths ?? [];\n\n if (isPathExcluded(ctx.relativePath, allowedPaths)) return [];\n\n return [new V(1, ctx.relativePath)];\n }\n}\n"]}
@@ -1,4 +1,4 @@
1
- import { ValidateTsInSrcConfig } from "../../configs/rule-configs";
1
+ import { ValidateTsInSrcConfig } from '../../configs/rule-configs';
2
2
  import type { FileContext, Violation } from '@webpieces/hook-runtime';
3
3
  import { FileRuleBase } from '@webpieces/hook-runtime';
4
4
  import { FixHint } from '@webpieces/hook-runtime';
@@ -9,8 +9,12 @@ const hook_runtime_1 = require("@webpieces/hook-runtime");
9
9
  const hook_runtime_2 = require("@webpieces/hook-runtime");
10
10
  const hook_runtime_3 = require("@webpieces/hook-runtime");
11
11
  const DEFAULT_EXCLUDE_PATHS = [
12
- 'node_modules', 'dist', '.nx', '.git',
13
- '**/*.d.ts', '**/jest.config.ts',
12
+ 'node_modules',
13
+ 'dist',
14
+ '.nx',
15
+ '.git',
16
+ '**/*.d.ts',
17
+ '**/jest.config.ts',
14
18
  ];
15
19
  const DEFAULT_ALLOWED_ROOT_FILES = ['jest.setup.ts'];
16
20
  function findProjectRoot(filePath, workspaceRoot) {
@@ -23,16 +27,18 @@ function findProjectRoot(filePath, workspaceRoot) {
23
27
  return null;
24
28
  }
25
29
  class ValidateTsInSrcRule extends hook_runtime_2.FileRuleBase {
26
- constructor(config) { super(config, 'validate-ts-in-src', 'validate-ts-in-src'); }
27
- description = 'Every .ts file must belong to a project\'s src/ directory.';
30
+ constructor(config) {
31
+ super(config, 'validate-ts-in-src', 'validate-ts-in-src');
32
+ }
33
+ description = "Every .ts file must belong to a project's src/ directory.";
28
34
  files = ['**/*.ts', '**/*.tsx'];
29
35
  defaultOptions = {
30
36
  excludePaths: DEFAULT_EXCLUDE_PATHS,
31
37
  allowedRootFiles: DEFAULT_ALLOWED_ROOT_FILES,
32
38
  };
33
39
  fixHint = new hook_runtime_3.FixHint('TypeScript file is outside a project src/ directory.', 'Fix by one of:', [
34
- new rules_config_1.Option('Move the file into an existing project\'s src/ directory, or create a new project with project.json that owns the directory.', true),
35
- new rules_config_1.Option('Add a dir or glob (e.g. "**/codegen.ts") to validate-ts-in-src.excludePaths in webpieces.config.json'),
40
+ new rules_config_1.Option("Move the file into an existing project's src/ directory, or create a new project with project.json that owns the directory.", true),
41
+ new rules_config_1.Option('Add a dir or glob (e.g. "**/codegen.ts") to validate-ts-in-src.excludePaths in {configFile}'),
36
42
  ]);
37
43
  check(ctx) {
38
44
  if (ctx.tool !== 'Write')
@@ -47,12 +53,16 @@ class ValidateTsInSrcRule extends hook_runtime_2.FileRuleBase {
47
53
  return [];
48
54
  const projectRoot = findProjectRoot(ctx.filePath, ctx.targetRoot);
49
55
  if (!projectRoot) {
50
- return [new hook_runtime_1.Violation(1, ctx.targetRelativePath, 'File is not inside any Nx project. Move it into a project\'s src/ directory.')];
56
+ return [
57
+ new hook_runtime_1.Violation(1, ctx.targetRelativePath, "File is not inside any Nx project. Move it into a project's src/ directory."),
58
+ ];
51
59
  }
52
60
  const relToProject = path.relative(projectRoot, ctx.filePath);
53
61
  if (!relToProject.startsWith('src' + path.sep) && relToProject !== 'src') {
54
62
  const projectName = path.relative(ctx.targetRoot, projectRoot);
55
- return [new hook_runtime_1.Violation(1, ctx.targetRelativePath, `File is inside project \`${projectName}\` but outside its src/ directory. Move it into src/.`)];
63
+ return [
64
+ new hook_runtime_1.Violation(1, ctx.targetRelativePath, `File is inside project \`${projectName}\` but outside its src/ directory. Move it into src/.`),
65
+ ];
56
66
  }
57
67
  return [];
58
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validate-ts-in-src.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/validate-ts-in-src.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport { isPathExcluded, Option } from \"@webpieces/rules-config\";\nimport { ValidateTsInSrcConfig } from \"../../configs/rule-configs\";\n\nimport type { FileContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { FileRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint } from '@webpieces/hook-runtime';\n\nconst DEFAULT_EXCLUDE_PATHS = [\n 'node_modules', 'dist', '.nx', '.git',\n '**/*.d.ts', '**/jest.config.ts',\n];\nconst DEFAULT_ALLOWED_ROOT_FILES = ['jest.setup.ts'];\n\nfunction findProjectRoot(filePath: string, workspaceRoot: string): string | null {\n let dir = path.dirname(filePath);\n while (dir !== workspaceRoot && dir.startsWith(workspaceRoot)) {\n if (fs.existsSync(path.join(dir, 'project.json'))) return dir;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport class ValidateTsInSrcRule extends FileRuleBase<ValidateTsInSrcConfig> {\n constructor(config: ValidateTsInSrcConfig) { super(config, 'validate-ts-in-src', 'validate-ts-in-src'); }\n\n readonly description = 'Every .ts file must belong to a project\\'s src/ directory.';\n override readonly files = ['**/*.ts', '**/*.tsx'];\n override readonly defaultOptions = {\n excludePaths: DEFAULT_EXCLUDE_PATHS,\n allowedRootFiles: DEFAULT_ALLOWED_ROOT_FILES,\n };\n readonly fixHint = new FixHint(\n 'TypeScript file is outside a project src/ directory.',\n 'Fix by one of:',\n [\n new Option('Move the file into an existing project\\'s src/ directory, or create a new project with project.json that owns the directory.', true),\n new Option('Add a dir or glob (e.g. \"**/codegen.ts\") to validate-ts-in-src.excludePaths in webpieces.config.json'),\n ],\n );\n\n check(ctx: FileContext): readonly Violation[] {\n if (ctx.tool !== 'Write') return [];\n\n const excludePaths = this.config.excludePaths ?? DEFAULT_EXCLUDE_PATHS;\n const allowedRootFiles = this.config.allowedRootFiles ?? DEFAULT_ALLOWED_ROOT_FILES;\n\n // Holistic exclusion (Layer 1 + Layer 2): bare dir names + globs.\n if (isPathExcluded(ctx.targetRelativePath, excludePaths)) return [];\n\n const relParts = ctx.targetRelativePath.split(path.sep);\n if (relParts.length === 1 && allowedRootFiles.indexOf(relParts[0] ?? '') >= 0) return [];\n\n const projectRoot = findProjectRoot(ctx.filePath, ctx.targetRoot);\n\n if (!projectRoot) {\n return [new V(\n 1,\n ctx.targetRelativePath,\n 'File is not inside any Nx project. Move it into a project\\'s src/ directory.',\n )];\n }\n\n const relToProject = path.relative(projectRoot, ctx.filePath);\n if (!relToProject.startsWith('src' + path.sep) && relToProject !== 'src') {\n const projectName = path.relative(ctx.targetRoot, projectRoot);\n return [new V(\n 1,\n ctx.targetRelativePath,\n `File is inside project \\`${projectName}\\` but outside its src/ directory. Move it into src/.`,\n )];\n }\n\n return [];\n }\n}\n"]}
1
+ {"version":3,"file":"validate-ts-in-src.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/validate-ts-in-src.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport { isPathExcluded, Option } from '@webpieces/rules-config';\nimport { ValidateTsInSrcConfig } from '../../configs/rule-configs';\n\nimport type { FileContext, Violation } from '@webpieces/hook-runtime';\nimport { Violation as V } from '@webpieces/hook-runtime';\nimport { FileRuleBase } from '@webpieces/hook-runtime';\nimport { FixHint } from '@webpieces/hook-runtime';\n\nconst DEFAULT_EXCLUDE_PATHS = [\n 'node_modules',\n 'dist',\n '.nx',\n '.git',\n '**/*.d.ts',\n '**/jest.config.ts',\n];\nconst DEFAULT_ALLOWED_ROOT_FILES = ['jest.setup.ts'];\n\nfunction findProjectRoot(filePath: string, workspaceRoot: string): string | null {\n let dir = path.dirname(filePath);\n while (dir !== workspaceRoot && dir.startsWith(workspaceRoot)) {\n if (fs.existsSync(path.join(dir, 'project.json'))) return dir;\n dir = path.dirname(dir);\n }\n return null;\n}\n\nexport class ValidateTsInSrcRule extends FileRuleBase<ValidateTsInSrcConfig> {\n constructor(config: ValidateTsInSrcConfig) {\n super(config, 'validate-ts-in-src', 'validate-ts-in-src');\n }\n\n readonly description = \"Every .ts file must belong to a project's src/ directory.\";\n override readonly files = ['**/*.ts', '**/*.tsx'];\n override readonly defaultOptions = {\n excludePaths: DEFAULT_EXCLUDE_PATHS,\n allowedRootFiles: DEFAULT_ALLOWED_ROOT_FILES,\n };\n readonly fixHint = new FixHint(\n 'TypeScript file is outside a project src/ directory.',\n 'Fix by one of:',\n [\n new Option(\n \"Move the file into an existing project's src/ directory, or create a new project with project.json that owns the directory.\",\n true,\n ),\n new Option(\n 'Add a dir or glob (e.g. \"**/codegen.ts\") to validate-ts-in-src.excludePaths in {configFile}',\n ),\n ],\n );\n\n check(ctx: FileContext): readonly Violation[] {\n if (ctx.tool !== 'Write') return [];\n\n const excludePaths = this.config.excludePaths ?? DEFAULT_EXCLUDE_PATHS;\n const allowedRootFiles = this.config.allowedRootFiles ?? DEFAULT_ALLOWED_ROOT_FILES;\n\n // Holistic exclusion (Layer 1 + Layer 2): bare dir names + globs.\n if (isPathExcluded(ctx.targetRelativePath, excludePaths)) return [];\n\n const relParts = ctx.targetRelativePath.split(path.sep);\n if (relParts.length === 1 && allowedRootFiles.indexOf(relParts[0] ?? '') >= 0) return [];\n\n const projectRoot = findProjectRoot(ctx.filePath, ctx.targetRoot);\n\n if (!projectRoot) {\n return [\n new V(\n 1,\n ctx.targetRelativePath,\n \"File is not inside any Nx project. Move it into a project's src/ directory.\",\n ),\n ];\n }\n\n const relToProject = path.relative(projectRoot, ctx.filePath);\n if (!relToProject.startsWith('src' + path.sep) && relToProject !== 'src') {\n const projectName = path.relative(ctx.targetRoot, projectRoot);\n return [\n new V(\n 1,\n ctx.targetRelativePath,\n `File is inside project \\`${projectName}\\` but outside its src/ directory. Move it into src/.`,\n ),\n ];\n }\n\n return [];\n }\n}\n"]}
@@ -1,9 +1,9 @@
1
1
  import { LoadedConfig } from '@webpieces/rules-config';
2
2
  import { Rule, HookRuleSet, ToolKind, NormalizedToolInput, HookMode, BlockedResult } from '@webpieces/hook-runtime';
3
3
  export declare class SourceHookRuleSet extends HookRuleSet {
4
- readonly builtInRules: readonly Rule[];
5
- readonly extensionRules: readonly Rule[];
6
- constructor(builtInRules: readonly Rule[], extensionRules: readonly Rule[], configuredRules: readonly Rule[]);
4
+ readonly contributedRules: readonly Rule[];
5
+ readonly matchRules: readonly Rule[];
6
+ constructor(contributedRules: readonly Rule[], matchRules: readonly Rule[]);
7
7
  }
8
8
  export declare class SourceHookRules {
9
9
  load(loaded: LoadedConfig): SourceHookRuleSet;
@@ -2,26 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SourceHookRules = exports.SourceHookRuleSet = void 0;
4
4
  exports.run = run;
5
- const tslib_1 = require("tslib");
6
- const path = tslib_1.__importStar(require("path"));
5
+ const rule_runtime_1 = require("../rule-runtime");
7
6
  const rules_config_1 = require("@webpieces/rules-config");
8
7
  const hook_runtime_1 = require("@webpieces/hook-runtime");
9
8
  const load_rules_1 = require("./load-rules");
10
9
  class SourceHookRuleSet extends hook_runtime_1.HookRuleSet {
11
- builtInRules;
12
- extensionRules;
13
- constructor(builtInRules, extensionRules, configuredRules) {
14
- super([...builtInRules, ...extensionRules], configuredRules);
15
- this.builtInRules = builtInRules;
16
- this.extensionRules = extensionRules;
10
+ contributedRules;
11
+ matchRules;
12
+ constructor(contributedRules, matchRules) {
13
+ super([...contributedRules, ...matchRules]);
14
+ this.contributedRules = contributedRules;
15
+ this.matchRules = matchRules;
17
16
  }
18
17
  }
19
18
  exports.SourceHookRuleSet = SourceHookRuleSet;
20
19
  class SourceHookRules {
21
20
  load(loaded) {
22
- const builtIns = (0, load_rules_1.loadBuiltInRules)(loaded.rulesConfig);
23
- const custom = (0, load_rules_1.loadCustomRules)(loaded.rulesConfig, path.dirname(loaded.configPath ?? ''));
24
- return new SourceHookRuleSet(builtIns, [...custom, ...(0, load_rules_1.loadMatchRules)(loaded.matchRules)], [...builtIns, ...custom]);
21
+ const builtIns = new hook_runtime_1.HookPolicyContributions(new Map([['@webpieces/ai-hook-rules/rule-runtime', new rule_runtime_1.SourceRuleRuntime()]])).load(loaded, 'source-hook');
22
+ return new SourceHookRuleSet(builtIns, (0, load_rules_1.loadMatchRules)(loaded.matchRules));
25
23
  }
26
24
  }
27
25
  exports.SourceHookRules = SourceHookRules;
@@ -29,9 +27,15 @@ exports.SourceHookRules = SourceHookRules;
29
27
  function run(toolKind, input, cwd, mode = 'rules') {
30
28
  if (mode === 'guards')
31
29
  return null;
30
+ if (toolKind !== 'Delete' &&
31
+ (new rules_config_1.ConfigRepairAccess().isRepairFile(new rules_config_1.RepoRootFinder().resolveRepoRoot(cwd), input.filePath) ||
32
+ (0, hook_runtime_1.isRootManifest)(input.filePath) ||
33
+ new rules_config_1.HomeConfigService().isHomeConfigPath(input.filePath)))
34
+ return null;
32
35
  const loaded = (0, rules_config_1.loadAndValidate)(cwd);
33
36
  if (loaded.configPath === null)
34
- return new hook_runtime_1.BlockedResult(rules_config_1.CONFIG_MISSING_REPORT + (0, rules_config_1.guardMatrixPointer)((0, rules_config_1.writeGuardMatrixDoc)(new rules_config_1.RepoRootFinder().resolveRepoRoot(cwd))), rules_config_1.L0_FAULT_CONFIG_MISSING);
37
+ return new hook_runtime_1.BlockedResult(rules_config_1.CONFIG_MISSING_REPORT +
38
+ (0, rules_config_1.guardMatrixPointer)((0, rules_config_1.writeGuardMatrixDoc)(new rules_config_1.RepoRootFinder().resolveRepoRoot(cwd))), rules_config_1.L0_FAULT_CONFIG_MISSING);
35
39
  return new hook_runtime_1.HookFileEvaluation().evaluate(toolKind, input, loaded, new SourceHookRules().load(loaded));
36
40
  }
37
41
  //# sourceMappingURL=runner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/runner.ts"],"names":[],"mappings":";;;AAoBA,kBAKC;;AAzBD,mDAA6B;AAC7B,0DAAiL;AACjL,0DAAwI;AACxI,6CAAiF;AAEjF,MAAa,iBAAkB,SAAQ,0BAAW;IACzB;IAAwC;IAA7D,YAAqB,YAA6B,EAAW,cAA+B,EAAE,eAAgC;QAC1H,KAAK,CAAC,CAAC,GAAG,YAAY,EAAE,GAAG,cAAc,CAAC,EAAE,eAAe,CAAC,CAAC;QAD5C,iBAAY,GAAZ,YAAY,CAAiB;QAAW,mBAAc,GAAd,cAAc,CAAiB;IAE5F,CAAC;CACJ;AAJD,8CAIC;AAED,MAAa,eAAe;IACxB,IAAI,CAAC,MAAoB;QACrB,MAAM,QAAQ,GAAG,IAAA,6BAAgB,EAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,IAAA,4BAAe,EAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC;QAC1F,OAAO,IAAI,iBAAiB,CAAC,QAAQ,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,IAAA,2BAAc,EAAC,MAAM,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC;IACxH,CAAC;CACJ;AAND,0CAMC;AAED,kGAAkG;AAClG,SAAgB,GAAG,CAAC,QAAkB,EAAE,KAA0B,EAAE,GAAW,EAAE,OAAiB,OAAO;IACrG,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnC,MAAM,MAAM,GAAG,IAAA,8BAAe,EAAC,GAAG,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI;QAAE,OAAO,IAAI,4BAAa,CAAC,oCAAqB,GAAG,IAAA,iCAAkB,EAAC,IAAA,kCAAmB,EAAC,IAAI,6BAAc,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,sCAAuB,CAAC,CAAC;IAC9L,OAAO,IAAI,iCAAkB,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,eAAe,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC1G,CAAC","sourcesContent":["import * as path from 'path';\nimport { loadAndValidate, LoadedConfig, CONFIG_MISSING_REPORT, L0_FAULT_CONFIG_MISSING, RepoRootFinder, writeGuardMatrixDoc, guardMatrixPointer } from '@webpieces/rules-config';\nimport { Rule, HookRuleSet, HookFileEvaluation, ToolKind, NormalizedToolInput, HookMode, BlockedResult } from '@webpieces/hook-runtime';\nimport { loadBuiltInRules, loadCustomRules, loadMatchRules } from './load-rules';\n\nexport class SourceHookRuleSet extends HookRuleSet {\n constructor(readonly builtInRules: readonly Rule[], readonly extensionRules: readonly Rule[], configuredRules: readonly Rule[]) {\n super([...builtInRules, ...extensionRules], configuredRules);\n }\n}\n\nexport class SourceHookRules {\n load(loaded: LoadedConfig): SourceHookRuleSet {\n const builtIns = loadBuiltInRules(loaded.rulesConfig);\n const custom = loadCustomRules(loaded.rulesConfig, path.dirname(loaded.configPath ?? ''));\n return new SourceHookRuleSet(builtIns, [...custom, ...loadMatchRules(loaded.matchRules)], [...builtIns, ...custom]);\n }\n}\n\n// webpieces-disable no-function-outside-class -- preserves the existing source runner entry point\nexport function run(toolKind: ToolKind, input: NormalizedToolInput, cwd: string, mode: HookMode = 'rules'): BlockedResult | null {\n if (mode === 'guards') return null;\n const loaded = loadAndValidate(cwd);\n if (loaded.configPath === null) return new BlockedResult(CONFIG_MISSING_REPORT + guardMatrixPointer(writeGuardMatrixDoc(new RepoRootFinder().resolveRepoRoot(cwd))), L0_FAULT_CONFIG_MISSING);\n return new HookFileEvaluation().evaluate(toolKind, input, loaded, new SourceHookRules().load(loaded));\n}\n"]}
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/runner.ts"],"names":[],"mappings":";;;AA4CA,kBA8BC;AA1ED,kDAAoD;AACpD,0DAUiC;AACjC,0DAUiC;AACjC,6CAA8C;AAE9C,MAAa,iBAAkB,SAAQ,0BAAW;IAEjC;IACA;IAFb,YACa,gBAAiC,EACjC,UAA2B;QAEpC,KAAK,CAAC,CAAC,GAAG,gBAAgB,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC;QAHnC,qBAAgB,GAAhB,gBAAgB,CAAiB;QACjC,eAAU,GAAV,UAAU,CAAiB;IAGxC,CAAC;CACJ;AAPD,8CAOC;AAED,MAAa,eAAe;IACxB,IAAI,CAAC,MAAoB;QACrB,MAAM,QAAQ,GAAG,IAAI,sCAAuB,CACxC,IAAI,GAAG,CAAC,CAAC,CAAC,uCAAuC,EAAE,IAAI,gCAAiB,EAAE,CAAC,CAAC,CAAC,CAChF,CAAC,IAAI,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;QAC9B,OAAO,IAAI,iBAAiB,CAAC,QAAQ,EAAE,IAAA,2BAAc,EAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IAC9E,CAAC;CACJ;AAPD,0CAOC;AAED,kGAAkG;AAClG,SAAgB,GAAG,CACf,QAAkB,EAClB,KAA0B,EAC1B,GAAW,EACX,OAAiB,OAAO;IAExB,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnC,IACI,QAAQ,KAAK,QAAQ;QACrB,CAAC,IAAI,iCAAkB,EAAE,CAAC,YAAY,CAClC,IAAI,6BAAc,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,EACzC,KAAK,CAAC,QAAQ,CACjB;YACG,IAAA,6BAAc,EAAC,KAAK,CAAC,QAAQ,CAAC;YAC9B,IAAI,gCAAiB,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAE7D,OAAO,IAAI,CAAC;IAChB,MAAM,MAAM,GAAG,IAAA,8BAAe,EAAC,GAAG,CAAC,CAAC;IACpC,IAAI,MAAM,CAAC,UAAU,KAAK,IAAI;QAC1B,OAAO,IAAI,4BAAa,CACpB,oCAAqB;YACjB,IAAA,iCAAkB,EAAC,IAAA,kCAAmB,EAAC,IAAI,6BAAc,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EACtF,sCAAuB,CAC1B,CAAC;IACN,OAAO,IAAI,iCAAkB,EAAE,CAAC,QAAQ,CACpC,QAAQ,EACR,KAAK,EACL,MAAM,EACN,IAAI,eAAe,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CACrC,CAAC;AACN,CAAC","sourcesContent":["import { SourceRuleRuntime } from '../rule-runtime';\nimport {\n loadAndValidate,\n LoadedConfig,\n ConfigRepairAccess,\n HomeConfigService,\n CONFIG_MISSING_REPORT,\n L0_FAULT_CONFIG_MISSING,\n RepoRootFinder,\n writeGuardMatrixDoc,\n guardMatrixPointer,\n} from '@webpieces/rules-config';\nimport {\n Rule,\n isRootManifest,\n HookPolicyContributions,\n HookRuleSet,\n HookFileEvaluation,\n ToolKind,\n NormalizedToolInput,\n HookMode,\n BlockedResult,\n} from '@webpieces/hook-runtime';\nimport { loadMatchRules } from './load-rules';\n\nexport class SourceHookRuleSet extends HookRuleSet {\n constructor(\n readonly contributedRules: readonly Rule[],\n readonly matchRules: readonly Rule[],\n ) {\n super([...contributedRules, ...matchRules]);\n }\n}\n\nexport class SourceHookRules {\n load(loaded: LoadedConfig): SourceHookRuleSet {\n const builtIns = new HookPolicyContributions(\n new Map([['@webpieces/ai-hook-rules/rule-runtime', new SourceRuleRuntime()]]),\n ).load(loaded, 'source-hook');\n return new SourceHookRuleSet(builtIns, loadMatchRules(loaded.matchRules));\n }\n}\n\n// webpieces-disable no-function-outside-class -- preserves the existing source runner entry point\nexport function run(\n toolKind: ToolKind,\n input: NormalizedToolInput,\n cwd: string,\n mode: HookMode = 'rules',\n): BlockedResult | null {\n if (mode === 'guards') return null;\n if (\n toolKind !== 'Delete' &&\n (new ConfigRepairAccess().isRepairFile(\n new RepoRootFinder().resolveRepoRoot(cwd),\n input.filePath,\n ) ||\n isRootManifest(input.filePath) ||\n new HomeConfigService().isHomeConfigPath(input.filePath))\n )\n return null;\n const loaded = loadAndValidate(cwd);\n if (loaded.configPath === null)\n return new BlockedResult(\n CONFIG_MISSING_REPORT +\n guardMatrixPointer(writeGuardMatrixDoc(new RepoRootFinder().resolveRepoRoot(cwd))),\n L0_FAULT_CONFIG_MISSING,\n );\n return new HookFileEvaluation().evaluate(\n toolKind,\n input,\n loaded,\n new SourceHookRules().load(loaded),\n );\n}\n"]}
@@ -0,0 +1,3 @@
1
+ import { RuleHelp } from '@webpieces/rules-sdk';
2
+ /** Owner-authored guidance consumed by the registry catalog. */
3
+ export declare const ruleHelp: Readonly<Record<string, RuleHelp>>;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ruleHelp = void 0;
4
+ const rules_sdk_1 = require("@webpieces/rules-sdk");
5
+ /** Owner-authored guidance consumed by the registry catalog. */
6
+ exports.ruleHelp = {
7
+ 'throw-cause-required': new rules_sdk_1.RuleHelp('Preserve the original error as cause when throwing a replacement error.', 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.'),
8
+ 'no-js-files': new rules_sdk_1.RuleHelp('Keep governed source in TypeScript rather than JavaScript.', 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.'),
9
+ 'validate-ts-in-src': new rules_sdk_1.RuleHelp('Keep TypeScript implementation files inside their project source directory.', 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.'),
10
+ };
11
+ //# sourceMappingURL=rule-help.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-help.js","sourceRoot":"","sources":["../../../../../packages/tooling/ai-hook-rules/src/rule-help.ts"],"names":[],"mappings":";;;AAAA,oDAAgD;AAEhD,gEAAgE;AACnD,QAAA,QAAQ,GAAuC;IACxD,sBAAsB,EAAE,IAAI,oBAAQ,CAChC,yEAAyE,EACzE,sIAAsI,CACzI;IACD,aAAa,EAAE,IAAI,oBAAQ,CACvB,4DAA4D,EAC5D,sIAAsI,CACzI;IACD,oBAAoB,EAAE,IAAI,oBAAQ,CAC9B,6EAA6E,EAC7E,sIAAsI,CACzI;CACJ,CAAC","sourcesContent":["import { RuleHelp } from '@webpieces/rules-sdk';\n\n/** Owner-authored guidance consumed by the registry catalog. */\nexport const ruleHelp: Readonly<Record<string, RuleHelp>> = {\n 'throw-cause-required': new RuleHelp(\n 'Preserve the original error as cause when throwing a replacement error.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'no-js-files': new RuleHelp(\n 'Keep governed source in TypeScript rather than JavaScript.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n 'validate-ts-in-src': new RuleHelp(\n 'Keep TypeScript implementation files inside their project source directory.',\n 'Apply this policy in source, or review its explicit settings in {configFile}. An intentional opt-out requires complete OFF settings.',\n ),\n};\n"]}
package/src/rule-pack.js CHANGED
@@ -1,27 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.rulePackManifest = void 0;
4
- const rule_settings_1 = require("./rule-settings");
5
4
  const rules_sdk_1 = require("@webpieces/rules-sdk");
6
- const rule_configs_1 = require("./configs/rule-configs");
5
+ const source_policy_registry_1 = require("./source-policy-registry");
7
6
  const package_json_1 = require("../package.json");
8
- /** Source policies own their schema; other contributions consume their canonical owner's settings. */
9
- const ownedRules = [
10
- new rules_sdk_1.OwnedRuleDefinition('throw-cause-required', rule_configs_1.ThrowCauseRequiredConfig.SCHEMA, rules_sdk_1.RULE_SCHEMA_API_VERSION, rule_settings_1.optionalTuning['throw-cause-required'], rule_settings_1.recommendedSeeds['throw-cause-required'], 'rules'),
11
- new rules_sdk_1.OwnedRuleDefinition('no-js-files', rule_configs_1.NoJsFilesConfig.SCHEMA, rules_sdk_1.RULE_SCHEMA_API_VERSION, rule_settings_1.optionalTuning['no-js-files'], rule_settings_1.recommendedSeeds['no-js-files'], 'rules'),
12
- new rules_sdk_1.OwnedRuleDefinition('validate-ts-in-src', rule_configs_1.ValidateTsInSrcConfig.SCHEMA, rules_sdk_1.RULE_SCHEMA_API_VERSION, rule_settings_1.optionalTuning['validate-ts-in-src'], rule_settings_1.recommendedSeeds['validate-ts-in-src'], 'rules'),
13
- ];
14
- exports.rulePackManifest = new rules_sdk_1.RulePackManifest('@webpieces/ai-hook-rules', package_json_1.version, rules_sdk_1.RULE_PACK_API_VERSION, ownedRules, [
15
- ...ownedRules.map(rule => new rules_sdk_1.RuleContribution(rule.id, '@webpieces/ai-hook-rules', 'source-hook')),
16
- new rules_sdk_1.RuleContribution('no-any-unknown', '@webpieces/code-rules', 'source-hook'),
17
- new rules_sdk_1.RuleContribution('no-implicit-any', '@webpieces/code-rules', 'source-hook'),
18
- new rules_sdk_1.RuleContribution('max-file-lines', '@webpieces/code-rules', 'source-hook'),
19
- new rules_sdk_1.RuleContribution('no-destructure', '@webpieces/code-rules', 'source-hook'),
20
- new rules_sdk_1.RuleContribution('require-return-type', '@webpieces/code-rules', 'source-hook'),
21
- new rules_sdk_1.RuleContribution('no-unmanaged-exceptions', '@webpieces/code-rules', 'source-hook'),
22
- new rules_sdk_1.RuleContribution('catch-error-pattern', '@webpieces/code-rules', 'source-hook'),
23
- new rules_sdk_1.RuleContribution('no-symbol-di-tokens', '@webpieces/code-rules', 'source-hook'),
24
- new rules_sdk_1.RuleContribution('no-custom-css', '@webpieces/code-rules', 'source-hook'),
25
- new rules_sdk_1.RuleContribution('no-process-exit-outside-main', '@webpieces/code-rules', 'source-hook'),
26
- ], [], []);
7
+ exports.rulePackManifest = new rules_sdk_1.RulePackManifest('@webpieces/ai-hook-rules', package_json_1.version, rules_sdk_1.RULE_PACK_API_VERSION, source_policy_registry_1.ownedRules, source_policy_registry_1.SOURCE_POLICIES.map((policy) => new rules_sdk_1.RuleContribution(policy.id, policy.ownerPack, 'source-hook', '@webpieces/ai-hook-rules/rule-runtime')), [], []);
27
8
  //# sourceMappingURL=rule-pack.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rule-pack.js","sourceRoot":"","sources":["../../../../../packages/tooling/ai-hook-rules/src/rule-pack.ts"],"names":[],"mappings":";;;AAAA,mDAAmE;AACnE,oDAA+I;AAC/I,yDAA0G;AAC1G,kDAA0C;AAE1C,sGAAsG;AACtG,MAAM,UAAU,GAAG;IACf,IAAI,+BAAmB,CAAC,sBAAsB,EAAE,uCAAwB,CAAC,MAAM,EAAE,mCAAuB,EAAE,8BAAc,CAAC,sBAAsB,CAAC,EAAE,gCAAgB,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACpM,IAAI,+BAAmB,CAAC,aAAa,EAAE,8BAAe,CAAC,MAAM,EAAE,mCAAuB,EAAE,8BAAc,CAAC,aAAa,CAAC,EAAE,gCAAgB,CAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAChK,IAAI,+BAAmB,CAAC,oBAAoB,EAAE,oCAAqB,CAAC,MAAM,EAAE,mCAAuB,EAAE,8BAAc,CAAC,oBAAoB,CAAC,EAAE,gCAAgB,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAC9L,CAAC;AAEW,QAAA,gBAAgB,GAAG,IAAI,4BAAgB,CAChD,0BAA0B,EAC1B,sBAAO,EACP,iCAAqB,EACrB,UAAU,EACV;IACI,GAAG,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,4BAAgB,CAAC,IAAI,CAAC,EAAE,EAAE,0BAA0B,EAAE,aAAa,CAAC,CAAC;IACnG,IAAI,4BAAgB,CAAC,gBAAgB,EAAE,uBAAuB,EAAE,aAAa,CAAC;IAC9E,IAAI,4BAAgB,CAAC,iBAAiB,EAAE,uBAAuB,EAAE,aAAa,CAAC;IAC/E,IAAI,4BAAgB,CAAC,gBAAgB,EAAE,uBAAuB,EAAE,aAAa,CAAC;IAC9E,IAAI,4BAAgB,CAAC,gBAAgB,EAAE,uBAAuB,EAAE,aAAa,CAAC;IAC9E,IAAI,4BAAgB,CAAC,qBAAqB,EAAE,uBAAuB,EAAE,aAAa,CAAC;IACnF,IAAI,4BAAgB,CAAC,yBAAyB,EAAE,uBAAuB,EAAE,aAAa,CAAC;IACvF,IAAI,4BAAgB,CAAC,qBAAqB,EAAE,uBAAuB,EAAE,aAAa,CAAC;IACnF,IAAI,4BAAgB,CAAC,qBAAqB,EAAE,uBAAuB,EAAE,aAAa,CAAC;IACnF,IAAI,4BAAgB,CAAC,eAAe,EAAE,uBAAuB,EAAE,aAAa,CAAC;IAC7E,IAAI,4BAAgB,CAAC,8BAA8B,EAAE,uBAAuB,EAAE,aAAa,CAAC;CAC/F,EACD,EAAE,EACF,EAAE,CACL,CAAC","sourcesContent":["import { optionalTuning, recommendedSeeds } from './rule-settings';\nimport { OwnedRuleDefinition, RuleContribution, RulePackManifest, RULE_PACK_API_VERSION, RULE_SCHEMA_API_VERSION } from '@webpieces/rules-sdk';\nimport { ThrowCauseRequiredConfig, NoJsFilesConfig, ValidateTsInSrcConfig } from './configs/rule-configs';\nimport { version } from '../package.json';\n\n/** Source policies own their schema; other contributions consume their canonical owner's settings. */\nconst ownedRules = [\n new OwnedRuleDefinition('throw-cause-required', ThrowCauseRequiredConfig.SCHEMA, RULE_SCHEMA_API_VERSION, optionalTuning['throw-cause-required'], recommendedSeeds['throw-cause-required'], 'rules'),\n new OwnedRuleDefinition('no-js-files', NoJsFilesConfig.SCHEMA, RULE_SCHEMA_API_VERSION, optionalTuning['no-js-files'], recommendedSeeds['no-js-files'], 'rules'),\n new OwnedRuleDefinition('validate-ts-in-src', ValidateTsInSrcConfig.SCHEMA, RULE_SCHEMA_API_VERSION, optionalTuning['validate-ts-in-src'], recommendedSeeds['validate-ts-in-src'], 'rules'),\n];\n\nexport const rulePackManifest = new RulePackManifest(\n '@webpieces/ai-hook-rules',\n version,\n RULE_PACK_API_VERSION,\n ownedRules,\n [\n ...ownedRules.map(rule => new RuleContribution(rule.id, '@webpieces/ai-hook-rules', 'source-hook')),\n new RuleContribution('no-any-unknown', '@webpieces/code-rules', 'source-hook'),\n new RuleContribution('no-implicit-any', '@webpieces/code-rules', 'source-hook'),\n new RuleContribution('max-file-lines', '@webpieces/code-rules', 'source-hook'),\n new RuleContribution('no-destructure', '@webpieces/code-rules', 'source-hook'),\n new RuleContribution('require-return-type', '@webpieces/code-rules', 'source-hook'),\n new RuleContribution('no-unmanaged-exceptions', '@webpieces/code-rules', 'source-hook'),\n new RuleContribution('catch-error-pattern', '@webpieces/code-rules', 'source-hook'),\n new RuleContribution('no-symbol-di-tokens', '@webpieces/code-rules', 'source-hook'),\n new RuleContribution('no-custom-css', '@webpieces/code-rules', 'source-hook'),\n new RuleContribution('no-process-exit-outside-main', '@webpieces/code-rules', 'source-hook'),\n ],\n [],\n [],\n);\n"]}
1
+ {"version":3,"file":"rule-pack.js","sourceRoot":"","sources":["../../../../../packages/tooling/ai-hook-rules/src/rule-pack.ts"],"names":[],"mappings":";;;AAAA,oDAAiG;AACjG,qEAAqF;AACrF,kDAA0C;AAE7B,QAAA,gBAAgB,GAAG,IAAI,4BAAgB,CAChD,0BAA0B,EAC1B,sBAAO,EACP,iCAAqB,EACrB,mCAAU,EACV,wCAAe,CAAC,GAAG,CACf,CAAC,MAAoB,EAAE,EAAE,CACrB,IAAI,4BAAgB,CAChB,MAAM,CAAC,EAAE,EACT,MAAM,CAAC,SAAS,EAChB,aAAa,EACb,uCAAuC,CAC1C,CACR,EACD,EAAE,EACF,EAAE,CACL,CAAC","sourcesContent":["import { RuleContribution, RulePackManifest, RULE_PACK_API_VERSION } from '@webpieces/rules-sdk';\nimport { ownedRules, SOURCE_POLICIES, SourcePolicy } from './source-policy-registry';\nimport { version } from '../package.json';\n\nexport const rulePackManifest = new RulePackManifest(\n '@webpieces/ai-hook-rules',\n version,\n RULE_PACK_API_VERSION,\n ownedRules,\n SOURCE_POLICIES.map(\n (policy: SourcePolicy) =>\n new RuleContribution(\n policy.id,\n policy.ownerPack,\n 'source-hook',\n '@webpieces/ai-hook-rules/rule-runtime',\n ),\n ),\n [],\n [],\n);\n"]}
@@ -0,0 +1,7 @@
1
+ import { PolicyRuntimeRequest } from '@webpieces/rules-sdk';
2
+ import { Rule } from '@webpieces/hook-runtime';
3
+ /** Runtime imports are isolated from the public metadata module. */
4
+ export declare class SourceRuleRuntime {
5
+ create(request: PolicyRuntimeRequest): readonly Rule[];
6
+ }
7
+ export declare const sourceRuleRuntime: SourceRuleRuntime;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sourceRuleRuntime = exports.SourceRuleRuntime = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const tooling_common_1 = require("@webpieces/tooling-common");
6
+ const source_policy_registry_1 = require("./source-policy-registry");
7
+ const implementations = tslib_1.__importStar(require("./core/rules"));
8
+ /** Runtime imports are isolated from the public metadata module. */
9
+ class SourceRuleRuntime {
10
+ create(request) {
11
+ return request.ruleIds.map((id) => {
12
+ const policy = source_policy_registry_1.SOURCE_POLICIES.find((entry) => entry.id === id);
13
+ if (!policy)
14
+ throw new tooling_common_1.InformAiError(`Source runtime has no implementation of ${id}. Repair its contribution.`);
15
+ const config = request.configs[id];
16
+ if (!config)
17
+ throw new tooling_common_1.InformAiError(`Missing explicit config for ${id}. Repair its declared owner file.`);
18
+ const ctor = implementations[policy.implementationExport];
19
+ if (!ctor)
20
+ throw new tooling_common_1.InformAiError(`Missing source implementation ${policy.implementationExport}. Repair its runtime export.`);
21
+ return new ctor(config);
22
+ });
23
+ }
24
+ }
25
+ exports.SourceRuleRuntime = SourceRuleRuntime;
26
+ exports.sourceRuleRuntime = new SourceRuleRuntime();
27
+ //# sourceMappingURL=rule-runtime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-runtime.js","sourceRoot":"","sources":["../../../../../packages/tooling/ai-hook-rules/src/rule-runtime.ts"],"names":[],"mappings":";;;;AAEA,8DAA0D;AAC1D,qEAAyE;AACzE,sEAAgD;AAIhD,oEAAoE;AACpE,MAAa,iBAAiB;IAC1B,MAAM,CAAC,OAA6B;QAChC,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAU,EAAE,EAAE;YACtC,MAAM,MAAM,GAAG,wCAAe,CAAC,IAAI,CAAC,CAAC,KAAmB,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9E,IAAI,CAAC,MAAM;gBACP,MAAM,IAAI,8BAAa,CACnB,2CAA2C,EAAE,4BAA4B,CAC5E,CAAC;YACN,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACnC,IAAI,CAAC,MAAM;gBACP,MAAM,IAAI,8BAAa,CACnB,+BAA+B,EAAE,mCAAmC,CACvE,CAAC;YACN,MAAM,IAAI,GAAI,eAAkD,CAC5D,MAAM,CAAC,oBAAoB,CAC9B,CAAC;YACF,IAAI,CAAC,IAAI;gBACL,MAAM,IAAI,8BAAa,CACnB,iCAAiC,MAAM,CAAC,oBAAoB,8BAA8B,CAC7F,CAAC;YACN,OAAO,IAAI,IAAI,CAAC,MAAwB,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACP,CAAC;CACJ;AAvBD,8CAuBC;AAEY,QAAA,iBAAiB,GAAG,IAAI,iBAAiB,EAAE,CAAC","sourcesContent":["import { BaseRuleConfig, PolicyRuntimeRequest } from '@webpieces/rules-sdk';\nimport { Rule } from '@webpieces/hook-runtime';\nimport { InformAiError } from '@webpieces/tooling-common';\nimport { SOURCE_POLICIES, SourcePolicy } from './source-policy-registry';\nimport * as implementations from './core/rules';\n\ntype SourceRuleCtor = new (config: BaseRuleConfig) => Rule;\n\n/** Runtime imports are isolated from the public metadata module. */\nexport class SourceRuleRuntime {\n create(request: PolicyRuntimeRequest): readonly Rule[] {\n return request.ruleIds.map((id: string) => {\n const policy = SOURCE_POLICIES.find((entry: SourcePolicy) => entry.id === id);\n if (!policy)\n throw new InformAiError(\n `Source runtime has no implementation of ${id}. Repair its contribution.`,\n );\n const config = request.configs[id];\n if (!config)\n throw new InformAiError(\n `Missing explicit config for ${id}. Repair its declared owner file.`,\n );\n const ctor = (implementations as Record<string, SourceRuleCtor>)[\n policy.implementationExport\n ];\n if (!ctor)\n throw new InformAiError(\n `Missing source implementation ${policy.implementationExport}. Repair its runtime export.`,\n );\n return new ctor(config as BaseRuleConfig);\n });\n }\n}\n\nexport const sourceRuleRuntime = new SourceRuleRuntime();\n"]}
@@ -0,0 +1,10 @@
1
+ import { OwnedRuleDefinition } from '@webpieces/rules-sdk';
2
+ export declare const ownedRules: OwnedRuleDefinition[];
3
+ export declare class SourcePolicy {
4
+ readonly id: string;
5
+ readonly ownerPack: string;
6
+ readonly implementationExport: string;
7
+ constructor(id: string, ownerPack: string, implementationExport: string);
8
+ }
9
+ /** Source implementations and their canonical owners are declared exactly once. */
10
+ export declare const SOURCE_POLICIES: readonly SourcePolicy[];