@webpieces/ai-hook-rules 0.3.138 → 0.3.140

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/ai-hook-rules",
3
- "version": "0.3.138",
3
+ "version": "0.3.140",
4
4
  "description": "Pluggable write-time validation framework for AI coding agents (@webpieces/ai-hook-rules). Claude Code PreToolUse + openclaw before_tool_call adapters share one rule engine.",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -32,7 +32,7 @@
32
32
  "directory": "packages/tooling/ai-hook-rules"
33
33
  },
34
34
  "dependencies": {
35
- "@webpieces/rules-config": "0.3.138"
35
+ "@webpieces/rules-config": "0.3.140"
36
36
  },
37
37
  "publishConfig": {
38
38
  "access": "public"
@@ -5,7 +5,7 @@ exports.defaultRulesDir = exports.defaultRules = void 0;
5
5
  exports.defaultRules = {
6
6
  'no-any-unknown': { mode: 'ON' },
7
7
  'max-file-lines': { mode: 'ON', limit: 900 },
8
- 'file-location': {
8
+ 'validate-ts-in-src': {
9
9
  mode: 'ON',
10
10
  allowedRootFiles: ['jest.setup.ts'],
11
11
  excludePaths: [
@@ -1 +1 @@
1
- {"version":3,"file":"default.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/configs/default.ts"],"names":[],"mappings":";;;AAAA,iFAAiF;AACpE,QAAA,YAAY,GAA4C;IACjE,gBAAgB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;IAChC,gBAAgB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE;IAC5C,eAAe,EAAE;QACb,IAAI,EAAE,IAAI;QACV,gBAAgB,EAAE,CAAC,eAAe,CAAC;QACnC,YAAY,EAAE;YACV,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;YACrC,cAAc,EAAE,KAAK,EAAE,SAAS;SACnC;KACJ;IACD,gBAAgB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IACrD,qBAAqB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;IACrC,yBAAyB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;IACzC,qBAAqB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;CACxC,CAAC;AAEW,QAAA,eAAe,GAAsB,EAAE,CAAC","sourcesContent":["// webpieces-disable no-any-unknown -- rule options are opaque at framework level\nexport const defaultRules: Record<string, Record<string, unknown>> = {\n 'no-any-unknown': { mode: 'ON' },\n 'max-file-lines': { mode: 'ON', limit: 900 },\n 'file-location': {\n mode: 'ON',\n allowedRootFiles: ['jest.setup.ts'],\n excludePaths: [\n 'node_modules', 'dist', '.nx', '.git',\n 'architecture', 'tmp', 'scripts',\n ],\n },\n 'no-destructure': { mode: 'ON', allowTopLevel: true },\n 'require-return-type': { mode: 'ON' },\n 'no-unmanaged-exceptions': { mode: 'ON' },\n 'catch-error-pattern': { mode: 'ON' },\n};\n\nexport const defaultRulesDir: readonly string[] = [];\n"]}
1
+ {"version":3,"file":"default.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/configs/default.ts"],"names":[],"mappings":";;;AAAA,iFAAiF;AACpE,QAAA,YAAY,GAA4C;IACjE,gBAAgB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;IAChC,gBAAgB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE;IAC5C,oBAAoB,EAAE;QAClB,IAAI,EAAE,IAAI;QACV,gBAAgB,EAAE,CAAC,eAAe,CAAC;QACnC,YAAY,EAAE;YACV,cAAc,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;YACrC,cAAc,EAAE,KAAK,EAAE,SAAS;SACnC;KACJ;IACD,gBAAgB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;IACrD,qBAAqB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;IACrC,yBAAyB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;IACzC,qBAAqB,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE;CACxC,CAAC;AAEW,QAAA,eAAe,GAAsB,EAAE,CAAC","sourcesContent":["// webpieces-disable no-any-unknown -- rule options are opaque at framework level\nexport const defaultRules: Record<string, Record<string, unknown>> = {\n 'no-any-unknown': { mode: 'ON' },\n 'max-file-lines': { mode: 'ON', limit: 900 },\n 'validate-ts-in-src': {\n mode: 'ON',\n allowedRootFiles: ['jest.setup.ts'],\n excludePaths: [\n 'node_modules', 'dist', '.nx', '.git',\n 'architecture', 'tmp', 'scripts',\n ],\n },\n 'no-destructure': { mode: 'ON', allowTopLevel: true },\n 'require-return-type': { mode: 'ON' },\n 'no-unmanaged-exceptions': { mode: 'ON' },\n 'catch-error-pattern': { mode: 'ON' },\n};\n\nexport const defaultRulesDir: readonly string[] = [];\n"]}
@@ -10,7 +10,7 @@ const index_1 = require("./rules/index");
10
10
  const no_any_unknown_1 = tslib_1.__importDefault(require("./rules/no-any-unknown"));
11
11
  const no_implicit_any_1 = tslib_1.__importDefault(require("./rules/no-implicit-any"));
12
12
  const max_file_lines_1 = tslib_1.__importDefault(require("./rules/max-file-lines"));
13
- const file_location_1 = tslib_1.__importDefault(require("./rules/file-location"));
13
+ const validate_ts_in_src_1 = tslib_1.__importDefault(require("./rules/validate-ts-in-src"));
14
14
  const no_destructure_1 = tslib_1.__importDefault(require("./rules/no-destructure"));
15
15
  const require_return_type_1 = tslib_1.__importDefault(require("./rules/require-return-type"));
16
16
  const no_unmanaged_exceptions_1 = tslib_1.__importDefault(require("./rules/no-unmanaged-exceptions"));
@@ -23,7 +23,7 @@ const BUILT_IN_RULE_MAP = {
23
23
  'no-any-unknown': no_any_unknown_1.default,
24
24
  'no-implicit-any': no_implicit_any_1.default,
25
25
  'max-file-lines': max_file_lines_1.default,
26
- 'file-location': file_location_1.default,
26
+ 'validate-ts-in-src': validate_ts_in_src_1.default,
27
27
  'no-destructure': no_destructure_1.default,
28
28
  'require-return-type': require_return_type_1.default,
29
29
  'no-unmanaged-exceptions': no_unmanaged_exceptions_1.default,
@@ -1 +1 @@
1
- {"version":3,"file":"load-rules.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/load-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport type { Rule, ResolvedConfig } from './types';\nimport { toError } from './to-error';\nimport { builtInRuleNames } from './rules/index';\nimport noAnyUnknown from './rules/no-any-unknown';\nimport noImplicitAny from './rules/no-implicit-any';\nimport maxFileLines from './rules/max-file-lines';\nimport fileLocation from './rules/file-location';\nimport noDestructure from './rules/no-destructure';\nimport requireReturnType from './rules/require-return-type';\nimport noUnmanagedExceptions from './rules/no-unmanaged-exceptions';\nimport catchErrorPattern from './rules/catch-error-pattern';\nimport noShellSubstitution from './rules/no-shell-substitution';\nimport noSymbolDiTokens from './rules/no-symbol-di-tokens';\n\nconst REQUIRED_FIELDS: readonly string[] = ['name', 'description', 'scope', 'files', 'check'];\nconst VALID_SCOPES = new Set(['edit', 'file', 'bash']);\n\nconst BUILT_IN_RULE_MAP: Record<string, Rule> = {\n 'no-any-unknown': noAnyUnknown as Rule,\n 'no-implicit-any': noImplicitAny as Rule,\n 'max-file-lines': maxFileLines as Rule,\n 'file-location': fileLocation as Rule,\n 'no-destructure': noDestructure as Rule,\n 'require-return-type': requireReturnType as Rule,\n 'no-unmanaged-exceptions': noUnmanagedExceptions as Rule,\n 'catch-error-pattern': catchErrorPattern as Rule,\n 'no-shell-substitution': noShellSubstitution as Rule,\n 'no-symbol-di-tokens': noSymbolDiTokens as Rule,\n};\n\nexport function loadRules(config: ResolvedConfig, workspaceRoot: string): readonly Rule[] {\n const builtIns = loadBuiltInRules();\n const custom = loadCustomRules(config.rulesDir, workspaceRoot);\n const all: Rule[] = [...builtIns, ...custom];\n return all.filter((rule: Rule) => validateRule(rule));\n}\n\nfunction loadBuiltInRules(): Rule[] {\n const modules: Rule[] = [];\n for (const name of builtInRuleNames) {\n const mod = BUILT_IN_RULE_MAP[name];\n if (mod) {\n modules.push(mod);\n } else {\n process.stderr.write(`[ai-hooks] unknown built-in rule: ${name}\\n`);\n }\n }\n return modules;\n}\n\nfunction loadCustomRules(rulesDirs: readonly string[], workspaceRoot: string): Rule[] {\n const modules: Rule[] = [];\n for (const dir of rulesDirs) {\n const absDir = path.isAbsolute(dir) ? dir : path.join(workspaceRoot, dir);\n if (!fs.existsSync(absDir)) {\n process.stderr.write(`[ai-hooks] rulesDir not found: ${absDir}\\n`);\n continue;\n }\n let entries: string[];\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n entries = fs.readdirSync(absDir).filter((e) => e.endsWith('.js'));\n } catch (err: unknown) {\n const error = toError(err);\n process.stderr.write(`[ai-hooks] cannot read rulesDir ${absDir}: ${error.message}\\n`);\n continue;\n }\n for (const entry of entries) {\n const full = path.join(absDir, entry);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const mod = require(full);\n modules.push(mod.default || mod);\n } catch (err: unknown) {\n const error = toError(err);\n process.stderr.write(`[ai-hooks] failed to load custom rule ${full}: ${error.message}\\n`);\n }\n }\n }\n return modules;\n}\n\n// webpieces-disable no-any-unknown -- validates untrusted require() output at system boundary\nfunction validateRule(rule: unknown): rule is Rule {\n if (!rule || typeof rule !== 'object') {\n process.stderr.write('[ai-hooks] rule is not an object, skipping\\n');\n return false;\n }\n // webpieces-disable no-any-unknown -- narrowing from unknown at system boundary\n const obj = rule as Record<string, unknown>;\n for (const field of REQUIRED_FIELDS) {\n if (obj[field] === undefined) {\n const name = typeof obj['name'] === 'string' ? obj['name'] : '<unnamed>';\n process.stderr.write(`[ai-hooks] rule \"${name}\" missing required field: ${field}\\n`);\n return false;\n }\n }\n if (!VALID_SCOPES.has(obj['scope'] as string)) {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" has invalid scope: ${String(obj['scope'])}\\n`);\n return false;\n }\n if (!Array.isArray(obj['files'])) {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" files must be an array\\n`);\n return false;\n }\n if (typeof obj['check'] !== 'function') {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" check must be a function\\n`);\n return false;\n }\n return true;\n}\n\nexport function globMatches(pattern: string, filePath: string): boolean {\n const regex = globToRegex(pattern);\n return regex.test(filePath);\n}\n\nfunction globToRegex(pattern: string): RegExp {\n let re = '';\n let i = 0;\n while (i < pattern.length) {\n const ch = pattern[i];\n if (ch === '*') {\n if (pattern[i + 1] === '*') {\n re += '.*';\n i += 2;\n if (pattern[i] === '/') i += 1;\n continue;\n }\n re += '[^/]*';\n i += 1;\n continue;\n }\n if (ch === '?') {\n re += '[^/]';\n i += 1;\n continue;\n }\n if ('.+^$(){}|[]\\\\'.includes(ch)) {\n re += '\\\\' + ch;\n i += 1;\n continue;\n }\n re += ch;\n i += 1;\n }\n return new RegExp('^' + re + '$');\n}\n"]}
1
+ {"version":3,"file":"load-rules.js","sourceRoot":"","sources":["../../../../../../packages/tooling/ai-hook-rules/src/core/load-rules.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport type { Rule, ResolvedConfig } from './types';\nimport { toError } from './to-error';\nimport { builtInRuleNames } from './rules/index';\nimport noAnyUnknown from './rules/no-any-unknown';\nimport noImplicitAny from './rules/no-implicit-any';\nimport maxFileLines from './rules/max-file-lines';\nimport validateTsInSrc from './rules/validate-ts-in-src';\nimport noDestructure from './rules/no-destructure';\nimport requireReturnType from './rules/require-return-type';\nimport noUnmanagedExceptions from './rules/no-unmanaged-exceptions';\nimport catchErrorPattern from './rules/catch-error-pattern';\nimport noShellSubstitution from './rules/no-shell-substitution';\nimport noSymbolDiTokens from './rules/no-symbol-di-tokens';\n\nconst REQUIRED_FIELDS: readonly string[] = ['name', 'description', 'scope', 'files', 'check'];\nconst VALID_SCOPES = new Set(['edit', 'file', 'bash']);\n\nconst BUILT_IN_RULE_MAP: Record<string, Rule> = {\n 'no-any-unknown': noAnyUnknown as Rule,\n 'no-implicit-any': noImplicitAny as Rule,\n 'max-file-lines': maxFileLines as Rule,\n 'validate-ts-in-src': validateTsInSrc as Rule,\n 'no-destructure': noDestructure as Rule,\n 'require-return-type': requireReturnType as Rule,\n 'no-unmanaged-exceptions': noUnmanagedExceptions as Rule,\n 'catch-error-pattern': catchErrorPattern as Rule,\n 'no-shell-substitution': noShellSubstitution as Rule,\n 'no-symbol-di-tokens': noSymbolDiTokens as Rule,\n};\n\nexport function loadRules(config: ResolvedConfig, workspaceRoot: string): readonly Rule[] {\n const builtIns = loadBuiltInRules();\n const custom = loadCustomRules(config.rulesDir, workspaceRoot);\n const all: Rule[] = [...builtIns, ...custom];\n return all.filter((rule: Rule) => validateRule(rule));\n}\n\nfunction loadBuiltInRules(): Rule[] {\n const modules: Rule[] = [];\n for (const name of builtInRuleNames) {\n const mod = BUILT_IN_RULE_MAP[name];\n if (mod) {\n modules.push(mod);\n } else {\n process.stderr.write(`[ai-hooks] unknown built-in rule: ${name}\\n`);\n }\n }\n return modules;\n}\n\nfunction loadCustomRules(rulesDirs: readonly string[], workspaceRoot: string): Rule[] {\n const modules: Rule[] = [];\n for (const dir of rulesDirs) {\n const absDir = path.isAbsolute(dir) ? dir : path.join(workspaceRoot, dir);\n if (!fs.existsSync(absDir)) {\n process.stderr.write(`[ai-hooks] rulesDir not found: ${absDir}\\n`);\n continue;\n }\n let entries: string[];\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n entries = fs.readdirSync(absDir).filter((e) => e.endsWith('.js'));\n } catch (err: unknown) {\n const error = toError(err);\n process.stderr.write(`[ai-hooks] cannot read rulesDir ${absDir}: ${error.message}\\n`);\n continue;\n }\n for (const entry of entries) {\n const full = path.join(absDir, entry);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions\n try {\n const mod = require(full);\n modules.push(mod.default || mod);\n } catch (err: unknown) {\n const error = toError(err);\n process.stderr.write(`[ai-hooks] failed to load custom rule ${full}: ${error.message}\\n`);\n }\n }\n }\n return modules;\n}\n\n// webpieces-disable no-any-unknown -- validates untrusted require() output at system boundary\nfunction validateRule(rule: unknown): rule is Rule {\n if (!rule || typeof rule !== 'object') {\n process.stderr.write('[ai-hooks] rule is not an object, skipping\\n');\n return false;\n }\n // webpieces-disable no-any-unknown -- narrowing from unknown at system boundary\n const obj = rule as Record<string, unknown>;\n for (const field of REQUIRED_FIELDS) {\n if (obj[field] === undefined) {\n const name = typeof obj['name'] === 'string' ? obj['name'] : '<unnamed>';\n process.stderr.write(`[ai-hooks] rule \"${name}\" missing required field: ${field}\\n`);\n return false;\n }\n }\n if (!VALID_SCOPES.has(obj['scope'] as string)) {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" has invalid scope: ${String(obj['scope'])}\\n`);\n return false;\n }\n if (!Array.isArray(obj['files'])) {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" files must be an array\\n`);\n return false;\n }\n if (typeof obj['check'] !== 'function') {\n process.stderr.write(`[ai-hooks] rule \"${obj['name']}\" check must be a function\\n`);\n return false;\n }\n return true;\n}\n\nexport function globMatches(pattern: string, filePath: string): boolean {\n const regex = globToRegex(pattern);\n return regex.test(filePath);\n}\n\nfunction globToRegex(pattern: string): RegExp {\n let re = '';\n let i = 0;\n while (i < pattern.length) {\n const ch = pattern[i];\n if (ch === '*') {\n if (pattern[i + 1] === '*') {\n re += '.*';\n i += 2;\n if (pattern[i] === '/') i += 1;\n continue;\n }\n re += '[^/]*';\n i += 1;\n continue;\n }\n if (ch === '?') {\n re += '[^/]';\n i += 1;\n continue;\n }\n if ('.+^$(){}|[]\\\\'.includes(ch)) {\n re += '\\\\' + ch;\n i += 1;\n continue;\n }\n re += ch;\n i += 1;\n }\n return new RegExp('^' + re + '$');\n}\n"]}
@@ -5,7 +5,7 @@ exports.builtInRuleNames = [
5
5
  'no-any-unknown',
6
6
  'no-implicit-any',
7
7
  'max-file-lines',
8
- 'file-location',
8
+ 'validate-ts-in-src',
9
9
  'no-destructure',
10
10
  'require-return-type',
11
11
  'no-unmanaged-exceptions',
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/index.ts"],"names":[],"mappings":";;;AAAa,QAAA,gBAAgB,GAAsB;IAC/C,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,eAAe;IACf,gBAAgB;IAChB,qBAAqB;IACrB,yBAAyB;IACzB,qBAAqB;IACrB,uBAAuB;IACvB,qBAAqB;CACxB,CAAC","sourcesContent":["export const builtInRuleNames: readonly string[] = [\n 'no-any-unknown',\n 'no-implicit-any',\n 'max-file-lines',\n 'file-location',\n 'no-destructure',\n 'require-return-type',\n 'no-unmanaged-exceptions',\n 'catch-error-pattern',\n 'no-shell-substitution',\n 'no-symbol-di-tokens',\n];\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/index.ts"],"names":[],"mappings":";;;AAAa,QAAA,gBAAgB,GAAsB;IAC/C,gBAAgB;IAChB,iBAAiB;IACjB,gBAAgB;IAChB,oBAAoB;IACpB,gBAAgB;IAChB,qBAAqB;IACrB,yBAAyB;IACzB,qBAAqB;IACrB,uBAAuB;IACvB,qBAAqB;CACxB,CAAC","sourcesContent":["export const builtInRuleNames: readonly string[] = [\n 'no-any-unknown',\n 'no-implicit-any',\n 'max-file-lines',\n 'validate-ts-in-src',\n 'no-destructure',\n 'require-return-type',\n 'no-unmanaged-exceptions',\n 'catch-error-pattern',\n 'no-shell-substitution',\n 'no-symbol-di-tokens',\n];\n"]}
@@ -0,0 +1,3 @@
1
+ import type { FileRule } from '../types';
2
+ declare const validateTsInSrcRule: FileRule;
3
+ export default validateTsInSrcRule;
@@ -20,8 +20,8 @@ function findProjectRoot(filePath, workspaceRoot) {
20
20
  }
21
21
  return null;
22
22
  }
23
- const fileLocationRule = {
24
- name: 'file-location',
23
+ const validateTsInSrcRule = {
24
+ name: 'validate-ts-in-src',
25
25
  description: 'Every .ts file must belong to a project\'s src/ directory.',
26
26
  scope: 'file',
27
27
  files: ['**/*.ts', '**/*.tsx'],
@@ -31,7 +31,7 @@ const fileLocationRule = {
31
31
  },
32
32
  fixHint: [
33
33
  'Move the file into an existing project\'s src/ directory, or create a new project with project.json that owns the directory.',
34
- 'Add a dir or glob (e.g. "**/codegen.ts") to file-location.excludePaths in webpieces.config.json',
34
+ 'Add a dir or glob (e.g. "**/codegen.ts") to validate-ts-in-src.excludePaths in webpieces.config.json',
35
35
  ],
36
36
  check(ctx) {
37
37
  if (ctx.tool !== 'Write')
@@ -46,7 +46,7 @@ const fileLocationRule = {
46
46
  if ((0, rules_config_1.isPathExcluded)(ctx.relativePath, excludePaths))
47
47
  return [];
48
48
  const relParts = ctx.relativePath.split(path.sep);
49
- if (relParts.length === 1 && allowedRootFiles.indexOf(relParts[0]) >= 0)
49
+ if (relParts.length === 1 && allowedRootFiles.indexOf(relParts[0] ?? '') >= 0)
50
50
  return [];
51
51
  const projectRoot = findProjectRoot(ctx.filePath, ctx.workspaceRoot);
52
52
  if (!projectRoot) {
@@ -60,5 +60,5 @@ const fileLocationRule = {
60
60
  return [];
61
61
  },
62
62
  };
63
- exports.default = fileLocationRule;
64
- //# sourceMappingURL=file-location.js.map
63
+ exports.default = validateTsInSrcRule;
64
+ //# sourceMappingURL=validate-ts-in-src.js.map
@@ -0,0 +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 } from '@webpieces/rules-config';\n\nimport type { FileRule, FileContext, Violation } from '../types';\nimport { Violation as V } from '../types';\n\nconst DEFAULT_EXCLUDE_PATHS = [\n 'node_modules', 'dist', '.nx', '.git',\n 'architecture', 'tmp', 'scripts',\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\nconst validateTsInSrcRule: FileRule = {\n name: 'validate-ts-in-src',\n description: 'Every .ts file must belong to a project\\'s src/ directory.',\n scope: 'file',\n files: ['**/*.ts', '**/*.tsx'],\n defaultOptions: {\n excludePaths: DEFAULT_EXCLUDE_PATHS,\n allowedRootFiles: DEFAULT_ALLOWED_ROOT_FILES,\n },\n fixHint: [\n 'Move the file into an existing project\\'s src/ directory, or create a new project with project.json that owns the directory.',\n 'Add a dir or glob (e.g. \"**/codegen.ts\") to validate-ts-in-src.excludePaths in webpieces.config.json',\n ],\n\n check(ctx: FileContext): readonly Violation[] {\n if (ctx.tool !== 'Write') return [];\n\n const excludePaths = Array.isArray(ctx.options['excludePaths'])\n ? ctx.options['excludePaths'] as string[]\n : DEFAULT_EXCLUDE_PATHS;\n const allowedRootFiles = Array.isArray(ctx.options['allowedRootFiles'])\n ? ctx.options['allowedRootFiles'] as string[]\n : DEFAULT_ALLOWED_ROOT_FILES;\n\n // Holistic exclusion (Layer 1 + Layer 2): bare dir names + globs.\n if (isPathExcluded(ctx.relativePath, excludePaths)) return [];\n\n const relParts = ctx.relativePath.split(path.sep);\n if (relParts.length === 1 && allowedRootFiles.indexOf(relParts[0] ?? '') >= 0) return [];\n\n const projectRoot = findProjectRoot(ctx.filePath, ctx.workspaceRoot);\n\n if (!projectRoot) {\n return [new V(\n 1,\n ctx.relativePath,\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.workspaceRoot, projectRoot);\n return [new V(\n 1,\n ctx.relativePath,\n `File is inside project \\`${projectName}\\` but outside its src/ directory. Move it into src/.`,\n )];\n }\n\n return [];\n },\n};\n\nexport default validateTsInSrcRule;\n"]}
@@ -1,3 +0,0 @@
1
- import type { FileRule } from '../types';
2
- declare const fileLocationRule: FileRule;
3
- export default fileLocationRule;
@@ -1 +0,0 @@
1
- {"version":3,"file":"file-location.js","sourceRoot":"","sources":["../../../../../../../packages/tooling/ai-hook-rules/src/core/rules/file-location.ts"],"names":[],"mappings":"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","sourcesContent":["import * as fs from 'fs';\nimport * as path from 'path';\n\nimport { isPathExcluded } from '@webpieces/rules-config';\n\nimport type { FileRule, FileContext, Violation } from '../types';\nimport { Violation as V } from '../types';\n\nconst DEFAULT_EXCLUDE_PATHS = [\n 'node_modules', 'dist', '.nx', '.git',\n 'architecture', 'tmp', 'scripts',\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\nconst fileLocationRule: FileRule = {\n name: 'file-location',\n description: 'Every .ts file must belong to a project\\'s src/ directory.',\n scope: 'file',\n files: ['**/*.ts', '**/*.tsx'],\n defaultOptions: {\n excludePaths: DEFAULT_EXCLUDE_PATHS,\n allowedRootFiles: DEFAULT_ALLOWED_ROOT_FILES,\n },\n fixHint: [\n 'Move the file into an existing project\\'s src/ directory, or create a new project with project.json that owns the directory.',\n 'Add a dir or glob (e.g. \"**/codegen.ts\") to file-location.excludePaths in webpieces.config.json',\n ],\n\n check(ctx: FileContext): readonly Violation[] {\n if (ctx.tool !== 'Write') return [];\n\n const excludePaths = Array.isArray(ctx.options['excludePaths'])\n ? ctx.options['excludePaths'] as string[]\n : DEFAULT_EXCLUDE_PATHS;\n const allowedRootFiles = Array.isArray(ctx.options['allowedRootFiles'])\n ? ctx.options['allowedRootFiles'] as string[]\n : DEFAULT_ALLOWED_ROOT_FILES;\n\n // Holistic exclusion (Layer 1 + Layer 2): bare dir names + globs.\n if (isPathExcluded(ctx.relativePath, excludePaths)) return [];\n\n const relParts = ctx.relativePath.split(path.sep);\n if (relParts.length === 1 && allowedRootFiles.indexOf(relParts[0]) >= 0) return [];\n\n const projectRoot = findProjectRoot(ctx.filePath, ctx.workspaceRoot);\n\n if (!projectRoot) {\n return [new V(\n 1,\n ctx.relativePath,\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.workspaceRoot, projectRoot);\n return [new V(\n 1,\n ctx.relativePath,\n `File is inside project \\`${projectName}\\` but outside its src/ directory. Move it into src/.`,\n )];\n }\n\n return [];\n },\n};\n\nexport default fileLocationRule;\n"]}