@archest/vitest 1.0.0 → 1.0.2

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 (95) hide show
  1. package/dist/index.d.ts +3 -0
  2. package/dist/index.js +1 -17
  3. package/dist/index.js.map +1 -1
  4. package/dist/index.mjs +118 -551
  5. package/dist/index.mjs.map +1 -1
  6. package/dist/matchers/index.d.ts +21 -0
  7. package/dist/matchers/models.d.ts +201 -0
  8. package/node_modules/@archest/core/dist/classes/classCheckExtendClass.d.ts +3 -0
  9. package/node_modules/@archest/core/dist/classes/classCheckHaveMaxCyclomaticComplexity.d.ts +3 -0
  10. package/node_modules/@archest/core/dist/classes/classCheckHaveModifier.d.ts +3 -0
  11. package/node_modules/@archest/core/dist/classes/classCheckHaveNameMatchingFileName.d.ts +3 -0
  12. package/node_modules/@archest/core/dist/classes/classCheckImplementInterface.d.ts +3 -0
  13. package/node_modules/@archest/core/dist/classes/classCheckMatchNamePattern.d.ts +3 -0
  14. package/node_modules/@archest/core/dist/classes/classCheckResideInFolder.d.ts +3 -0
  15. package/node_modules/@archest/core/dist/classes/locateClasses.d.ts +5 -0
  16. package/node_modules/@archest/core/dist/classes/types.d.ts +25 -0
  17. package/node_modules/@archest/core/dist/dto.d.ts +78 -0
  18. package/node_modules/@archest/core/dist/files/checkDependOnExternalModule.d.ts +3 -0
  19. package/node_modules/@archest/core/dist/files/checkDependOnFilesInFolder.d.ts +3 -0
  20. package/node_modules/@archest/core/dist/files/fileCheckBeFreeOfCycles.d.ts +3 -0
  21. package/node_modules/@archest/core/dist/files/fileCheckHaveMaxCyclomaticComplexity.d.ts +3 -0
  22. package/node_modules/@archest/core/dist/files/fileCheckHaveMaxExportedFunctions.d.ts +3 -0
  23. package/node_modules/@archest/core/dist/files/fileCheckHaveMinMaintainabilityIndex.d.ts +3 -0
  24. package/node_modules/@archest/core/dist/files/fileCheckMatchNamePattern.d.ts +3 -0
  25. package/node_modules/@archest/core/dist/files/getFileDependencies.d.ts +2 -0
  26. package/node_modules/@archest/core/dist/files/locateFiles.d.ts +4 -0
  27. package/node_modules/@archest/core/dist/files/types.d.ts +17 -0
  28. package/node_modules/@archest/core/dist/functions/functionCheckHaveExplicitReturnType.d.ts +3 -0
  29. package/node_modules/@archest/core/dist/functions/functionCheckHaveMaxCyclomaticComplexity.d.ts +3 -0
  30. package/node_modules/@archest/core/dist/functions/functionCheckHaveMinMaintainabilityIndex.d.ts +3 -0
  31. package/node_modules/@archest/core/dist/functions/functionCheckHaveModifier.d.ts +3 -0
  32. package/node_modules/@archest/core/dist/functions/functionCheckHaveNameMatchingFileName.d.ts +3 -0
  33. package/node_modules/@archest/core/dist/functions/functionCheckMatchNamePattern.d.ts +3 -0
  34. package/node_modules/@archest/core/dist/functions/locateFunctions.d.ts +5 -0
  35. package/node_modules/@archest/core/dist/functions/types.d.ts +19 -0
  36. package/node_modules/@archest/core/dist/index.d.ts +43 -0
  37. package/node_modules/@archest/core/dist/index.js +14 -0
  38. package/node_modules/@archest/core/dist/index.js.map +1 -0
  39. package/node_modules/@archest/core/dist/index.mjs +615 -0
  40. package/node_modules/@archest/core/dist/index.mjs.map +1 -0
  41. package/node_modules/@archest/core/dist/layers/checkLayeredArchitecture.d.ts +3 -0
  42. package/node_modules/@archest/core/dist/layers/createLayeredArchitecture.d.ts +3 -0
  43. package/node_modules/@archest/core/dist/layers/getLayerDependencies.d.ts +2 -0
  44. package/node_modules/@archest/core/dist/layers/layer.d.ts +2 -0
  45. package/node_modules/@archest/core/dist/layers/layerShouldNotBeAccessedByAnyLayer.d.ts +2 -0
  46. package/node_modules/@archest/core/dist/layers/layerShouldOnlyBeAccessedBy.d.ts +2 -0
  47. package/node_modules/@archest/core/dist/layers/types.d.ts +8 -0
  48. package/node_modules/@archest/core/dist/metrics/calculateCyclomaticComplexity.d.ts +2 -0
  49. package/node_modules/@archest/core/dist/metrics/calculateMaintainabilityIndex.d.ts +2 -0
  50. package/node_modules/@archest/core/dist/project/parseProject.d.ts +55 -0
  51. package/node_modules/@archest/core/dist/properties/locateProperties.d.ts +5 -0
  52. package/node_modules/@archest/core/dist/properties/propertyCheckBeReadonly.d.ts +3 -0
  53. package/node_modules/@archest/core/dist/properties/types.d.ts +17 -0
  54. package/node_modules/@archest/core/dist/shared/sharedCheckHaveMaxCyclomaticComplexity.d.ts +1 -0
  55. package/node_modules/@archest/core/dist/shared/sharedCheckHaveMinMaintainabilityIndex.d.ts +1 -0
  56. package/node_modules/@archest/core/dist/shared/sharedCheckHaveModifier.d.ts +7 -0
  57. package/node_modules/@archest/core/dist/shared/sharedCheckHaveNameMatchingFileName.d.ts +3 -0
  58. package/node_modules/@archest/core/dist/shared/sharedCheckMatchNamePattern.d.ts +1 -0
  59. package/node_modules/@archest/core/dist/slices/locateSlices.d.ts +3 -0
  60. package/node_modules/@archest/core/dist/slices/sliceCheckBeFreeOfCycles.d.ts +3 -0
  61. package/node_modules/@archest/core/dist/slices/sliceCheckHaveMaxDistanceFromMainSequence.d.ts +3 -0
  62. package/node_modules/@archest/core/dist/slices/types.d.ts +8 -0
  63. package/node_modules/@archest/core/dist/types.d.ts +11 -0
  64. package/node_modules/@archest/core/dist/utils/ruleBuilder.d.ts +6 -0
  65. package/node_modules/@archest/core/package.json +49 -0
  66. package/node_modules/@archest/core-rust/core-rust.darwin-arm64.node +0 -0
  67. package/node_modules/@archest/core-rust/core-rust.linux-x64-gnu.node +0 -0
  68. package/node_modules/@archest/core-rust/core-rust.win32-x64-msvc.node +0 -0
  69. package/node_modules/@archest/core-rust/index.d.ts +16 -0
  70. package/node_modules/@archest/core-rust/index.js +316 -0
  71. package/node_modules/@archest/core-rust/package.json +34 -0
  72. package/package.json +12 -1
  73. package/dist/src/core/ClassLocator.d.ts +0 -20
  74. package/dist/src/core/FileLocator.d.ts +0 -15
  75. package/dist/src/core/FunctionLocator.d.ts +0 -15
  76. package/dist/src/core/LayerLocator.d.ts +0 -23
  77. package/dist/src/core/Project.d.ts +0 -20
  78. package/dist/src/core/PropertyLocator.d.ts +0 -12
  79. package/dist/src/core/SliceLocator.d.ts +0 -10
  80. package/dist/src/core/types.d.ts +0 -4
  81. package/dist/src/index.d.ts +0 -9
  82. package/dist/src/matchers/index.d.ts +0 -15
  83. package/src/core/ClassLocator.ts +0 -226
  84. package/src/core/FileLocator.ts +0 -168
  85. package/src/core/FunctionLocator.ts +0 -105
  86. package/src/core/LayerLocator.ts +0 -119
  87. package/src/core/Project.ts +0 -171
  88. package/src/core/PropertyLocator.ts +0 -50
  89. package/src/core/SliceLocator.ts +0 -92
  90. package/src/core/types.ts +0 -4
  91. package/src/index.ts +0 -9
  92. package/src/matchers/index.ts +0 -113
  93. package/test/architecture.test.ts +0 -59
  94. package/tsconfig.json +0 -17
  95. package/vite.config.ts +0 -18
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/core/FileLocator.ts","../src/core/ClassLocator.ts","../src/core/LayerLocator.ts","../src/core/FunctionLocator.ts","../src/core/PropertyLocator.ts","../src/core/SliceLocator.ts","../src/core/Project.ts","../src/matchers/index.ts"],"sourcesContent":["import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport interface FileQueryOptions {\n inFolder?: string;\n matchNamePattern?: string | RegExp;\n}\n\nexport class FileLocator {\n public readonly files: ts.SourceFile[];\n\n constructor(sourceFiles: ts.SourceFile[], private program: ts.Program, options?: FileQueryOptions) {\n let filtered = sourceFiles;\n\n if (options?.inFolder) {\n filtered = filtered.filter((file) => file.fileName.includes(`/${options.inFolder}/`) || file.fileName.includes(`\\\\${options.inFolder}\\\\`));\n }\n if (options?.matchNamePattern) {\n const regex = typeof options.matchNamePattern === 'string' ? new RegExp(options.matchNamePattern) : options.matchNamePattern;\n filtered = filtered.filter((file) => regex.test(file.fileName));\n }\n\n this.files = filtered;\n }\n\n private getFileDependencies(sourceFile: ts.SourceFile): string[] {\n const dependencies: string[] = [];\n const compilerOptions = this.program.getCompilerOptions();\n\n const visit = (node: ts.Node) => {\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(\n moduleSpecifier,\n sourceFile.fileName,\n compilerOptions,\n ts.sys\n );\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName) {\n if (!resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n }\n } else if (ts.isExportDeclaration(node) && node.moduleSpecifier) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(\n moduleSpecifier,\n sourceFile.fileName,\n compilerOptions,\n ts.sys\n );\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName) {\n if (!resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return dependencies;\n }\n\n checkDependOnFilesInFolder(targetFolder: string, isNot: boolean): RuleResult {\n const violations: string[] = [];\n\n for (const file of this.files) {\n const dependencies = this.getFileDependencies(file);\n \n const dependsOnTarget = dependencies.some((depPath) => depPath.includes(`/${targetFolder}/`) || depPath.includes(`\\\\${targetFolder}\\\\`));\n\n if (isNot && dependsOnTarget) {\n violations.push(`File ${file.fileName} depends on files in ${targetFolder}, but it shouldn't.`);\n } else if (!isNot && !dependsOnTarget) {\n violations.push(`File ${file.fileName} does not depend on files in ${targetFolder}, but it should.`);\n }\n }\n\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkBeFreeOfCycles(isNot: boolean): RuleResult {\n const violations: string[] = [];\n const targetedFilePaths = new Set<string>(this.files.map(f => f.fileName));\n const graph = new Map<string, string[]>();\n\n for (const file of this.files) {\n const filePath = file.fileName;\n const dependencies = this.getFileDependencies(file)\n .filter((p) => targetedFilePaths.has(p));\n \n graph.set(filePath, dependencies);\n }\n\n const visited = new Set<string>();\n const recStack = new Set<string>();\n const cycles: string[][] = [];\n\n const isCyclicUtil = (node: string, path: string[]) => {\n if (recStack.has(node)) {\n const cycleStartIndex = path.indexOf(node);\n const cycleStr = [...path.slice(cycleStartIndex), node].join('->');\n if (!cycles.some(c => c.join('->') === cycleStr)) {\n cycles.push([...path.slice(cycleStartIndex), node]);\n }\n return true;\n }\n\n if (visited.has(node)) return false;\n\n visited.add(node);\n recStack.add(node);\n path.push(node);\n\n const neighbors = graph.get(node) || [];\n for (const neighbor of neighbors) {\n isCyclicUtil(neighbor, path);\n }\n\n recStack.delete(node);\n path.pop();\n return false;\n };\n\n for (const node of graph.keys()) {\n if (!visited.has(node)) {\n isCyclicUtil(node, []);\n }\n }\n\n if (isNot && cycles.length === 0) {\n violations.push('Expected cyclic dependencies, but found none.');\n } else if (!isNot && cycles.length > 0) {\n for (const cycle of cycles) {\n violations.push(`Cycle detected: ${cycle.join(' -> ')}`);\n }\n }\n\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkMatchNamePattern(pattern: string | RegExp, isNot: boolean): RuleResult {\n const violations: string[] = [];\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n\n for (const file of this.files) {\n const matches = regex.test(file.fileName);\n\n if (isNot && matches) {\n violations.push(`File ${file.fileName} matches pattern ${pattern}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`File ${file.fileName} does not match pattern ${pattern}, but it should.`);\n }\n }\n\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport interface ClassQueryOptions {\n inFolder?: string;\n matchNamePattern?: string | RegExp;\n withDecorator?: string;\n extending?: string;\n implementing?: string;\n havingModifier?: string;\n}\n\nexport class ClassLocator {\n public readonly classes: ts.ClassDeclaration[];\n\n constructor(classes: ts.ClassDeclaration[], private program: ts.Program, options?: ClassQueryOptions) {\n let filtered = classes;\n\n if (options?.inFolder) {\n filtered = filtered.filter((c) => {\n const sourceFile = c.getSourceFile();\n return sourceFile.fileName.includes(`/${options.inFolder}/`) || sourceFile.fileName.includes(`\\\\${options.inFolder}\\\\`);\n });\n }\n if (options?.matchNamePattern) {\n const regex = typeof options.matchNamePattern === 'string' ? new RegExp(options.matchNamePattern) : options.matchNamePattern;\n filtered = filtered.filter((c) => {\n const name = c.name?.text;\n return name && regex.test(name);\n });\n }\n if (options?.withDecorator) {\n filtered = filtered.filter((c) => {\n const decorators = ts.canHaveDecorators(c) ? ts.getDecorators(c) : undefined;\n let hasDecorator = false;\n if (decorators) {\n for (const dec of decorators) {\n const exp = dec.expression;\n let name = '';\n if (ts.isIdentifier(exp)) {\n name = exp.text;\n } else if (ts.isCallExpression(exp) && ts.isIdentifier(exp.expression)) {\n name = exp.expression.text;\n }\n if (name === options.withDecorator) {\n hasDecorator = true;\n }\n }\n }\n return hasDecorator;\n });\n }\n if (options?.extending) {\n filtered = filtered.filter((c) => {\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ExtendsKeyword) {\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression) && type.expression.text === options.extending) {\n return true;\n }\n }\n }\n }\n }\n return false;\n });\n }\n if (options?.implementing) {\n filtered = filtered.filter((c) => {\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ImplementsKeyword) {\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression) && type.expression.text === options.implementing) {\n return true;\n }\n }\n }\n }\n }\n return false;\n });\n }\n if (options?.havingModifier) {\n let targetKind: ts.SyntaxKind;\n switch (options.havingModifier) {\n case 'export': targetKind = ts.SyntaxKind.ExportKeyword; break;\n case 'default': targetKind = ts.SyntaxKind.DefaultKeyword; break;\n case 'abstract': targetKind = ts.SyntaxKind.AbstractKeyword; break;\n default:\n throw new Error(`Modifier ${options.havingModifier} is not fully supported.`);\n }\n filtered = filtered.filter((c) => {\n const modifiers = ts.canHaveModifiers(c) ? ts.getModifiers(c) : undefined;\n return modifiers && modifiers.some((m: ts.Modifier) => m.kind === targetKind);\n });\n }\n\n this.classes = filtered;\n }\n\n checkResideInFolder(targetFolder: string, isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const c of this.classes) {\n const className = c.name?.text || 'Anonymous Class';\n const sourceFile = c.getSourceFile();\n const inTargetFolder = sourceFile.fileName.includes(`/${targetFolder}/`) || sourceFile.fileName.includes(`\\\\${targetFolder}\\\\`);\n\n if (isNot && inTargetFolder) {\n violations.push(`Class ${className} resides in ${targetFolder}, but it shouldn't.`);\n } else if (!isNot && !inTargetFolder) {\n violations.push(`Class ${className} does not reside in ${targetFolder}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkMatchNamePattern(pattern: string | RegExp, isNot: boolean): RuleResult {\n const violations: string[] = [];\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n\n for (const c of this.classes) {\n const name = c.name?.text;\n const matches = name && regex.test(name);\n if (isNot && matches) {\n violations.push(`Class ${name} matches pattern ${pattern}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Class ${name || 'Anonymous'} does not match pattern ${pattern}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkExtendClass(className: string, isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const c of this.classes) {\n const name = c.name?.text || 'Anonymous';\n let matches = false;\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ExtendsKeyword) {\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression) && type.expression.text === className) {\n matches = true;\n break;\n }\n }\n }\n }\n }\n if (isNot && matches) {\n violations.push(`Class ${name} extends ${className}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Class ${name} does not extend ${className}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkImplementInterface(interfaceName: string, isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const c of this.classes) {\n const name = c.name?.text || 'Anonymous';\n let matches = false;\n if (c.heritageClauses) {\n for (const clause of c.heritageClauses) {\n if (clause.token === ts.SyntaxKind.ImplementsKeyword) {\n for (const type of clause.types) {\n if (ts.isIdentifier(type.expression) && type.expression.text === interfaceName) {\n matches = true;\n break;\n }\n }\n }\n }\n }\n if (isNot && matches) {\n violations.push(`Class ${name} implements ${interfaceName}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Class ${name} does not implement ${interfaceName}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkHaveModifier(modifierStr: string, isNot: boolean): RuleResult {\n let targetKind: ts.SyntaxKind;\n switch (modifierStr) {\n case 'export': targetKind = ts.SyntaxKind.ExportKeyword; break;\n case 'default': targetKind = ts.SyntaxKind.DefaultKeyword; break;\n case 'abstract': targetKind = ts.SyntaxKind.AbstractKeyword; break;\n default:\n throw new Error(`Modifier ${modifierStr} is not fully supported.`);\n }\n\n const violations: string[] = [];\n for (const c of this.classes) {\n const name = c.name?.text || 'Anonymous';\n const modifiers = ts.canHaveModifiers(c) ? ts.getModifiers(c) : undefined;\n const matches = modifiers && modifiers.some((m: ts.Modifier) => m.kind === targetKind);\n\n if (isNot && matches) {\n violations.push(`Class ${name} has modifier ${modifierStr}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Class ${name} does not have modifier ${modifierStr}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport class LayeredArchitectureBuilder {\n private files: ts.SourceFile[];\n private layers = new Map<string, string>();\n private assertions: Array<(files: ts.SourceFile[]) => string[]> = [];\n\n constructor(files: ts.SourceFile[], public program: ts.Program) {\n this.files = files;\n }\n\n layer(name: string, folderPattern: string): this {\n this.layers.set(name, folderPattern);\n return this;\n }\n\n whereLayer(name: string): LayerAssertionBuilder {\n if (!this.layers.has(name)) {\n throw new Error(`Layer ${name} is not defined`);\n }\n return new LayerAssertionBuilder(this, name);\n }\n\n addAssertion(assertion: (files: ts.SourceFile[]) => string[]) {\n this.assertions.push(assertion);\n }\n\n getFiles(): ts.SourceFile[] {\n return this.files;\n }\n\n getLayerPattern(name: string): string {\n return this.layers.get(name)!;\n }\n\n getFileDependencies(sourceFile: ts.SourceFile): string[] {\n const dependencies: string[] = [];\n const compilerOptions = this.program.getCompilerOptions();\n\n const visit = (node: ts.Node) => {\n if (ts.isImportDeclaration(node)) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(moduleSpecifier, sourceFile.fileName, compilerOptions, ts.sys);\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName && !resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n } else if (ts.isExportDeclaration(node) && node.moduleSpecifier) {\n const moduleSpecifier = (node.moduleSpecifier as ts.StringLiteral).text;\n const resolved = ts.resolveModuleName(moduleSpecifier, sourceFile.fileName, compilerOptions, ts.sys);\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName && !resolved.resolvedModule.isExternalLibraryImport) {\n dependencies.push(resolved.resolvedModule.resolvedFileName);\n }\n }\n ts.forEachChild(node, visit);\n };\n\n visit(sourceFile);\n return dependencies;\n }\n\n check(): RuleResult {\n const violations: string[] = [];\n for (const assertion of this.assertions) {\n violations.push(...assertion(this.files));\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n')\n };\n }\n}\n\nexport class LayerAssertionBuilder {\n constructor(private parent: LayeredArchitectureBuilder, private targetLayer: string) {}\n\n shouldNotBeAccessedByAnyLayer(): LayeredArchitectureBuilder {\n this.parent.addAssertion((files) => {\n const violations: string[] = [];\n const targetPattern = this.parent.getLayerPattern(this.targetLayer);\n\n for (const file of files) {\n const filePath = file.fileName;\n if (!filePath.includes(`/${targetPattern}/`) && !filePath.includes(`\\\\${targetPattern}\\\\`)) {\n const dependencies = this.parent.getFileDependencies(file);\n const importsTarget = dependencies.some(dep => dep.includes(`/${targetPattern}/`) || dep.includes(`\\\\${targetPattern}\\\\`));\n if (importsTarget) {\n violations.push(`File ${filePath} accesses layer ${this.targetLayer} but it shouldn't.`);\n }\n }\n }\n return violations;\n });\n return this.parent;\n }\n\n shouldOnlyBeAccessedBy(...allowedLayers: string[]): LayeredArchitectureBuilder {\n this.parent.addAssertion((files) => {\n const violations: string[] = [];\n const targetPattern = this.parent.getLayerPattern(this.targetLayer);\n const allowedPatterns = allowedLayers.map(l => this.parent.getLayerPattern(l));\n\n for (const file of files) {\n const filePath = file.fileName;\n const isInAllowedLayer = allowedPatterns.some(p => filePath.includes(`/${p}/`) || filePath.includes(`\\\\${p}\\\\`));\n \n if (!filePath.includes(`/${targetPattern}/`) && !filePath.includes(`\\\\${targetPattern}\\\\`) && !isInAllowedLayer) {\n const dependencies = this.parent.getFileDependencies(file);\n const importsTarget = dependencies.some(dep => dep.includes(`/${targetPattern}/`) || dep.includes(`\\\\${targetPattern}\\\\`));\n if (importsTarget) {\n violations.push(`File ${filePath} accesses layer ${this.targetLayer} but only ${allowedLayers.join(', ')} are allowed.`);\n }\n }\n }\n return violations;\n });\n return this.parent;\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport interface FunctionQueryOptions {\n inFolder?: string;\n matchNamePattern?: string | RegExp;\n isTopLevel?: boolean;\n}\n\nexport class FunctionLocator {\n public readonly functions: ts.FunctionLikeDeclaration[];\n\n constructor(functions: ts.FunctionLikeDeclaration[], private program: ts.Program, options?: FunctionQueryOptions) {\n let filtered = functions;\n\n if (options?.inFolder) {\n filtered = filtered.filter((f) => {\n const sourceFile = f.getSourceFile();\n return sourceFile.fileName.includes(`/${options.inFolder}/`) || sourceFile.fileName.includes(`\\\\${options.inFolder}\\\\`);\n });\n }\n\n if (options?.matchNamePattern) {\n const regex = typeof options.matchNamePattern === 'string' ? new RegExp(options.matchNamePattern) : options.matchNamePattern;\n filtered = filtered.filter((f) => {\n return f.name && ts.isIdentifier(f.name) && regex.test(f.name.text);\n });\n }\n\n if (options?.isTopLevel) {\n filtered = filtered.filter((f) => {\n return ts.isSourceFile(f.parent);\n });\n }\n\n this.functions = filtered;\n }\n\n checkHaveModifier(modifierStr: string, isNot: boolean): RuleResult {\n let targetKind: ts.SyntaxKind;\n switch (modifierStr) {\n case 'export': targetKind = ts.SyntaxKind.ExportKeyword; break;\n case 'async': targetKind = ts.SyntaxKind.AsyncKeyword; break;\n case 'private': targetKind = ts.SyntaxKind.PrivateKeyword; break;\n case 'public': targetKind = ts.SyntaxKind.PublicKeyword; break;\n default:\n throw new Error(`Modifier ${modifierStr} is not fully supported.`);\n }\n\n const violations: string[] = [];\n for (const f of this.functions) {\n const name = f.name && ts.isIdentifier(f.name) ? f.name.text : 'Anonymous Function';\n const modifiers = ts.canHaveModifiers(f) ? ts.getModifiers(f) : undefined;\n const matches = modifiers && modifiers.some((m: ts.Modifier) => m.kind === targetKind);\n\n if (isNot && matches) {\n violations.push(`Function ${name} has modifier ${modifierStr}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Function ${name} does not have modifier ${modifierStr}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkHaveExplicitReturnType(isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const f of this.functions) {\n const name = f.name && ts.isIdentifier(f.name) ? f.name.text : 'Anonymous Function';\n const hasType = !!f.type;\n\n if (isNot && hasType) {\n violations.push(`Function ${name} has an explicit return type, but it shouldn't.`);\n } else if (!isNot && !hasType) {\n violations.push(`Function ${name} does not have an explicit return type, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n\n checkMatchNamePattern(pattern: string | RegExp, isNot: boolean): RuleResult {\n const violations: string[] = [];\n const regex = typeof pattern === 'string' ? new RegExp(pattern) : pattern;\n\n for (const f of this.functions) {\n const name = f.name && ts.isIdentifier(f.name) ? f.name.text : undefined;\n const matches = name && regex.test(name);\n \n if (isNot && matches) {\n violations.push(`Function ${name} matches pattern ${pattern}, but it shouldn't.`);\n } else if (!isNot && !matches) {\n violations.push(`Function ${name || 'Anonymous Function'} does not match pattern ${pattern}, but it should.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport interface PropertyQueryOptions {\n inFolder?: string;\n matchNamePattern?: string | RegExp;\n}\n\nexport class PropertyLocator {\n public readonly properties: ts.PropertyDeclaration[];\n\n constructor(properties: ts.PropertyDeclaration[], private program: ts.Program, options?: PropertyQueryOptions) {\n let filtered = properties;\n\n if (options?.inFolder) {\n filtered = filtered.filter((p) => {\n const sourceFile = p.getSourceFile();\n return sourceFile.fileName.includes(`/${options.inFolder}/`) || sourceFile.fileName.includes(`\\\\${options.inFolder}\\\\`);\n });\n }\n\n if (options?.matchNamePattern) {\n const regex = typeof options.matchNamePattern === 'string' ? new RegExp(options.matchNamePattern) : options.matchNamePattern;\n filtered = filtered.filter((p) => {\n return ts.isIdentifier(p.name) && regex.test(p.name.text);\n });\n }\n\n this.properties = filtered;\n }\n\n checkBeReadonly(isNot: boolean): RuleResult {\n const violations: string[] = [];\n for (const p of this.properties) {\n const name = ts.isIdentifier(p.name) ? p.name.text : 'Anonymous Property';\n const modifiers = ts.canHaveModifiers(p) ? ts.getModifiers(p) : undefined;\n const matches = modifiers && modifiers.some((m: ts.Modifier) => m.kind === ts.SyntaxKind.ReadonlyKeyword);\n\n if (isNot && matches) {\n violations.push(`Property ${name} is readonly, but it shouldn't be.`);\n } else if (!isNot && !matches) {\n violations.push(`Property ${name} is not readonly, but it should be.`);\n }\n }\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n'),\n };\n }\n}\n","import * as ts from 'typescript';\nimport { RuleResult } from './types';\n\nexport class SliceLocator {\n private slicePattern: RegExp;\n private sliceIds: Set<string> = new Set();\n private sliceFiles: Map<string, ts.SourceFile[]> = new Map();\n\n constructor(sourceFiles: ts.SourceFile[], private program: ts.Program, pattern: string) {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const regexStr = escaped.replace(/\\*/g, '([^/\\\\\\\\]+)');\n this.slicePattern = new RegExp(regexStr);\n\n for (const sf of sourceFiles) {\n const match = sf.fileName.match(this.slicePattern);\n if (match && match[1]) {\n const sliceId = match[1];\n this.sliceIds.add(sliceId);\n if (!this.sliceFiles.has(sliceId)) {\n this.sliceFiles.set(sliceId, []);\n }\n this.sliceFiles.get(sliceId)!.push(sf);\n }\n }\n }\n\n checkBeFreeOfCycles(isNot: boolean): RuleResult {\n const graph: Map<string, Set<string>> = new Map();\n for (const slice of this.sliceIds) {\n graph.set(slice, new Set());\n }\n\n for (const [sliceId, files] of this.sliceFiles.entries()) {\n for (const sf of files) {\n ts.forEachChild(sf, (node) => {\n if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {\n const importPath = node.moduleSpecifier.text;\n const resolved = ts.resolveModuleName(importPath, sf.fileName, this.program.getCompilerOptions(), ts.sys);\n if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName) {\n const targetMatch = resolved.resolvedModule.resolvedFileName.match(this.slicePattern);\n if (targetMatch && targetMatch[1]) {\n const targetSlice = targetMatch[1];\n if (targetSlice !== sliceId && this.sliceIds.has(targetSlice)) {\n graph.get(sliceId)!.add(targetSlice);\n }\n }\n }\n }\n });\n }\n }\n\n const visited = new Set<string>();\n const recursionStack = new Set<string>();\n const violations: string[] = [];\n\n const dfs = (node: string, path: string[]): boolean => {\n visited.add(node);\n recursionStack.add(node);\n\n for (const neighbor of (graph.get(node) || [])) {\n if (!visited.has(neighbor)) {\n if (dfs(neighbor, [...path, neighbor])) return true;\n } else if (recursionStack.has(neighbor)) {\n violations.push(`Cycle detected between slices: ${path.join(' -> ')} -> ${neighbor}`);\n return true;\n }\n }\n\n recursionStack.delete(node);\n return false;\n };\n\n for (const slice of this.sliceIds) {\n if (!visited.has(slice)) {\n dfs(slice, [slice]);\n }\n }\n\n if (isNot) {\n return {\n pass: violations.length > 0,\n message: () => violations.length > 0 ? '' : 'Expected cycles between slices but found none.'\n };\n } else {\n return {\n pass: violations.length === 0,\n message: () => violations.join('\\n')\n };\n }\n }\n}\n","import * as ts from 'typescript';\nimport * as path from 'path';\nimport { FileLocator, FileQueryOptions } from './FileLocator';\nimport { ClassLocator, ClassQueryOptions } from './ClassLocator';\nimport { LayeredArchitectureBuilder } from './LayerLocator';\nimport { FunctionLocator, FunctionQueryOptions } from './FunctionLocator';\nimport { PropertyLocator, PropertyQueryOptions } from './PropertyLocator';\nimport { SliceLocator } from './SliceLocator';\n\nexport class Project {\n private program: ts.Program;\n private typeChecker: ts.TypeChecker;\n\n constructor(options: { tsConfigFilePath?: string } = {}) {\n let compilerOptions: ts.CompilerOptions = {};\n const configPath = options.tsConfigFilePath || ts.findConfigFile(\n process.cwd(),\n ts.sys.fileExists,\n 'tsconfig.json'\n );\n\n if (configPath) {\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile);\n const parsedCommandLine = ts.parseJsonConfigFileContent(\n configFile.config,\n ts.sys,\n path.dirname(configPath),\n undefined,\n configPath,\n undefined,\n [\n { extension: '.vue', isMixedContent: true, scriptKind: ts.ScriptKind.TS },\n { extension: '.svelte', isMixedContent: true, scriptKind: ts.ScriptKind.TS }\n ]\n );\n compilerOptions = parsedCommandLine.options;\n\n const host = ts.createCompilerHost(compilerOptions);\n const originalGetSourceFile = host.getSourceFile;\n\n let vueCompiler: any;\n try {\n vueCompiler = require('@vue/compiler-sfc');\n } catch (e) {\n // Not a Vue project\n }\n\n host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {\n if (fileName.endsWith('.vue')) {\n const content = ts.sys.readFile(fileName);\n if (content) {\n let scriptContent = '';\n if (vueCompiler) {\n const parsed = vueCompiler.parse(content);\n const script = parsed.descriptor.script;\n const scriptSetup = parsed.descriptor.scriptSetup;\n if (script) scriptContent += script.content + '\\n';\n if (scriptSetup) scriptContent += scriptSetup.content + '\\n';\n } else {\n // Fallback for Svelte or if compiler-sfc is missing (fragile but works for simple cases)\n const match = content.match(/<script[^>]*>(.*?)<\\/script>/s);\n if (match) scriptContent = match[1];\n }\n return ts.createSourceFile(fileName, scriptContent, languageVersion, true, ts.ScriptKind.TS);\n }\n }\n \n if (fileName.endsWith('.svelte')) {\n const content = ts.sys.readFile(fileName);\n if (content) {\n let scriptContent = '';\n const match = content.match(/<script[^>]*>(.*?)<\\/script>/s);\n if (match) scriptContent = match[1];\n return ts.createSourceFile(fileName, scriptContent, languageVersion, true, ts.ScriptKind.TS);\n }\n }\n\n return originalGetSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);\n };\n\n this.program = ts.createProgram({\n rootNames: parsedCommandLine.fileNames,\n options: compilerOptions,\n host: host\n });\n } else {\n throw new Error(\"Could not find tsconfig.json\");\n }\n\n this.typeChecker = this.program.getTypeChecker();\n }\n\n getFiles(options?: FileQueryOptions) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n return new FileLocator(sourceFiles, this.program, options);\n }\n\n getClasses(options?: ClassQueryOptions) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n \n const allClasses: ts.ClassDeclaration[] = [];\n for (const sf of sourceFiles) {\n const visit = (node: ts.Node) => {\n if (ts.isClassDeclaration(node)) {\n allClasses.push(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n return new ClassLocator(allClasses, this.program, options);\n }\n\n layeredArchitecture() {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n return new LayeredArchitectureBuilder(sourceFiles, this.program);\n }\n\n getFunctions(options?: FunctionQueryOptions) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n \n const allFunctions: ts.FunctionLikeDeclaration[] = [];\n for (const sf of sourceFiles) {\n const visit = (node: ts.Node) => {\n if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isArrowFunction(node)) {\n allFunctions.push(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n return new FunctionLocator(allFunctions, this.program, options);\n }\n\n getProperties(options?: PropertyQueryOptions) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n \n const allProperties: ts.PropertyDeclaration[] = [];\n for (const sf of sourceFiles) {\n const visit = (node: ts.Node) => {\n if (ts.isPropertyDeclaration(node)) {\n allProperties.push(node);\n }\n ts.forEachChild(node, visit);\n };\n visit(sf);\n }\n return new PropertyLocator(allProperties, this.program, options);\n }\n\n getSlices(pattern: string) {\n const sourceFiles = this.program.getSourceFiles().filter(\n sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')\n );\n return new SliceLocator(sourceFiles, this.program, pattern);\n }\n}\n\nexport function parseProject(tsConfigFilePath?: string): Project {\n return new Project({ tsConfigFilePath });\n}\n","import { expect } from 'vitest';\nimport { RuleResult } from '../core/types';\nimport { ClassLocator } from '../core/ClassLocator';\nimport { FunctionLocator } from '../core/FunctionLocator';\nimport { PropertyLocator } from '../core/PropertyLocator';\nimport { FileLocator } from '../core/FileLocator';\nimport { SliceLocator } from '../core/SliceLocator';\nimport { LayeredArchitectureBuilder } from '../core/LayerLocator';\n\nexport function setupMatchers() {\n expect.extend({\n toPass(received: RuleResult | LayeredArchitectureBuilder) {\n const result = received instanceof LayeredArchitectureBuilder ? received.check() : received;\n const { pass, message } = result;\n return {\n pass: this.isNot ? !pass : pass,\n message: pass \n ? () => 'Expected rule not to pass' \n : () => message()\n };\n },\n\n toResideInFolder(received: ClassLocator, folder: string) {\n const { pass, message } = received.checkResideInFolder(folder, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toHaveModifier(received: ClassLocator | FunctionLocator, modifier: string) {\n const { pass, message } = received.checkHaveModifier(modifier, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n\n\n toExtendClass(received: ClassLocator, className: string) {\n const { pass, message } = received.checkExtendClass(className, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toImplementInterface(received: ClassLocator, interfaceName: string) {\n const { pass, message } = received.checkImplementInterface(interfaceName, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toHaveExplicitReturnType(received: FunctionLocator) {\n const { pass, message } = received.checkHaveExplicitReturnType(this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toBeReadonly(received: PropertyLocator) {\n const { pass, message } = received.checkBeReadonly(this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toDependOnFilesInFolder(received: FileLocator, folder: string) {\n const { pass, message } = received.checkDependOnFilesInFolder(folder, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toBeFreeOfCycles(received: FileLocator | SliceLocator) {\n const { pass, message } = received.checkBeFreeOfCycles(this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n },\n\n toMatchNamePattern(received: FileLocator | ClassLocator | FunctionLocator, pattern: string | RegExp) {\n const { pass, message } = received.checkMatchNamePattern(pattern, this.isNot);\n return {\n pass: this.isNot ? !pass : pass,\n message\n };\n }\n });\n}\n\ndeclare module 'vitest' {\n interface Assertion<T = any> {\n toPass(): void;\n toResideInFolder(folder: string): void;\n toHaveModifier(modifier: 'export' | 'default' | 'abstract' | 'async' | 'private' | 'public'): void;\n\n toExtendClass(className: string): void;\n toImplementInterface(interfaceName: string): void;\n toHaveExplicitReturnType(): void;\n toBeReadonly(): void;\n toDependOnFilesInFolder(folder: string): void;\n toBeFreeOfCycles(): void;\n toMatchNamePattern(pattern: string | RegExp): void;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/matchers/index.ts"],"sourcesContent":["import {\n checkDependOnExternalModule,\n checkDependOnFilesInFolder,\n checkLayeredArchitecture,\n classCheckExtendClass,\n classCheckHaveMaxCyclomaticComplexity,\n classCheckHaveModifier,\n classCheckHaveNameMatchingFileName,\n classCheckImplementInterface,\n classCheckMatchNamePattern,\n classCheckResideInFolder,\n fileCheckBeFreeOfCycles,\n fileCheckHaveMaxCyclomaticComplexity,\n fileCheckHaveMaxExportedFunctions,\n fileCheckHaveMinMaintainabilityIndex,\n fileCheckMatchNamePattern,\n functionCheckHaveExplicitReturnType,\n functionCheckHaveMaxCyclomaticComplexity,\n functionCheckHaveMinMaintainabilityIndex,\n functionCheckHaveModifier,\n functionCheckHaveNameMatchingFileName,\n functionCheckMatchNamePattern,\n type LocatorData,\n propertyCheckBeReadonly,\n type RuleResult,\n sliceCheckBeFreeOfCycles,\n sliceCheckHaveMaxDistanceFromMainSequence,\n} from '@archest/core';\nimport { expect } from 'vitest';\nimport type { ArchestMatchers } from './models';\n\nexport * from './models';\n\n/**\n * Registers all Archest custom matchers (e.g., `toResideInFolder`, `toHaveModifier`)\n * with the global Vitest `expect` instance.\n *\n * This function must be called exactly once before any architectural tests are run.\n * The standard way to do this is to add it to a Vitest setup file.\n *\n * @example\n * ```typescript\n * // test/setup.ts\n * import { setupMatchers } from '@archest/vitest';\n * setupMatchers();\n * ```\n */\nexport function setupMatchers() {\n expect.extend({\n // biome-ignore lint/suspicious/noExplicitAny: Matcher signature\n toPass(received: any) {\n let result: RuleResult;\n\n if (received?.data && received.data.type === 'LayeredArchitecture') {\n result = checkLayeredArchitecture(received.data);\n } else {\n result = received as RuleResult;\n }\n\n const { pass, message } = result;\n return {\n pass: this.isNot ? !pass : pass,\n message: pass ? () => 'Expected rule not to pass' : () => message(),\n };\n },\n\n toResideInFolder(received: LocatorData, folder: string) {\n let result: RuleResult;\n if (received.type === 'ClassLocator') {\n result = classCheckResideInFolder(received, folder, this.isNot);\n } else {\n throw new Error(\n `toResideInFolder matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveModifier(received: LocatorData, modifier: string) {\n let result: RuleResult;\n if (received.type === 'ClassLocator') {\n result = classCheckHaveModifier(received, modifier, this.isNot);\n } else if (received.type === 'FunctionLocator') {\n result = functionCheckHaveModifier(received, modifier, this.isNot);\n } else {\n throw new Error(\n `toHaveModifier matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toExtendClass(received: LocatorData, className: string) {\n let result: RuleResult;\n if (received.type === 'ClassLocator') {\n result = classCheckExtendClass(received, className, this.isNot);\n } else {\n throw new Error(\n `toExtendClass matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toImplementInterface(received: LocatorData, interfaceName: string) {\n let result: RuleResult;\n if (received.type === 'ClassLocator') {\n result = classCheckImplementInterface(\n received,\n interfaceName,\n this.isNot,\n );\n } else {\n throw new Error(\n `toImplementInterface matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveExplicitReturnType(received: LocatorData) {\n let result: RuleResult;\n if (received.type === 'FunctionLocator') {\n result = functionCheckHaveExplicitReturnType(received, this.isNot);\n } else {\n throw new Error(\n `toHaveExplicitReturnType matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toBeReadonly(received: LocatorData) {\n let result: RuleResult;\n if (received.type === 'PropertyLocator') {\n result = propertyCheckBeReadonly(received, this.isNot);\n } else {\n throw new Error(\n `toBeReadonly matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toDependOnFilesInFolder(received: LocatorData, folder: string) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = checkDependOnFilesInFolder(received, folder, this.isNot);\n } else {\n throw new Error(\n `toDependOnFilesInFolder matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toDependOnExternalModule(\n received: LocatorData,\n moduleName: string | RegExp,\n ) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = checkDependOnExternalModule(received, moduleName, this.isNot);\n } else {\n throw new Error(\n `toDependOnExternalModule matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toBeFreeOfCycles(received: LocatorData) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckBeFreeOfCycles(received, this.isNot);\n } else if (received.type === 'SliceLocator') {\n result = sliceCheckBeFreeOfCycles(received, this.isNot);\n } else {\n throw new Error(\n `toBeFreeOfCycles matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toMatchNamePattern(received: LocatorData, pattern: string | RegExp) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckMatchNamePattern(received, pattern, this.isNot);\n } else if (received.type === 'ClassLocator') {\n result = classCheckMatchNamePattern(received, pattern, this.isNot);\n } else if (received.type === 'FunctionLocator') {\n result = functionCheckMatchNamePattern(received, pattern, this.isNot);\n } else {\n throw new Error(\n `toMatchNamePattern matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveMaxCyclomaticComplexity(received: LocatorData, max: number) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckHaveMaxCyclomaticComplexity(\n received,\n max,\n this.isNot,\n );\n } else if (received.type === 'ClassLocator') {\n result = classCheckHaveMaxCyclomaticComplexity(\n received,\n max,\n this.isNot,\n );\n } else if (received.type === 'FunctionLocator') {\n result = functionCheckHaveMaxCyclomaticComplexity(\n received,\n max,\n this.isNot,\n );\n } else {\n throw new Error(\n `toHaveMaxCyclomaticComplexity matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveMinMaintainabilityIndex(received: LocatorData, min: number) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckHaveMinMaintainabilityIndex(\n received,\n min,\n this.isNot,\n );\n } else if (received.type === 'FunctionLocator') {\n result = functionCheckHaveMinMaintainabilityIndex(\n received,\n min,\n this.isNot,\n );\n } else {\n throw new Error(\n `toHaveMinMaintainabilityIndex matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveMaxDistanceFromMainSequence(received: LocatorData, max: number) {\n let result: RuleResult;\n if (received.type === 'SliceLocator') {\n result = sliceCheckHaveMaxDistanceFromMainSequence(\n received,\n max,\n this.isNot,\n );\n } else {\n throw new Error(\n `toHaveMaxDistanceFromMainSequence matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveNameMatchingFileName(received: LocatorData) {\n let result: RuleResult;\n if (received.type === 'FunctionLocator') {\n result = functionCheckHaveNameMatchingFileName(received, this.isNot);\n } else if (received.type === 'ClassLocator') {\n result = classCheckHaveNameMatchingFileName(received, this.isNot);\n } else {\n throw new Error(\n `toHaveNameMatchingFileName matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n\n toHaveMaxExportedFunctions(received: LocatorData, max: number) {\n let result: RuleResult;\n if (received.type === 'FileLocator') {\n result = fileCheckHaveMaxExportedFunctions(received, max, this.isNot);\n } else {\n throw new Error(\n `toHaveMaxExportedFunctions matcher does not support ${received.type}`,\n );\n }\n return {\n pass: this.isNot ? !result.pass : result.pass,\n message: result.message,\n };\n },\n });\n}\n\ndeclare module 'vitest' {\n // biome-ignore lint/suspicious/noExplicitAny: Matcher signature\n interface Assertion<T = any> extends ArchestMatchers<T> {}\n}\n"],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { ArchestMatchers } from './models';
2
+ export * from './models';
3
+ /**
4
+ * Registers all Archest custom matchers (e.g., `toResideInFolder`, `toHaveModifier`)
5
+ * with the global Vitest `expect` instance.
6
+ *
7
+ * This function must be called exactly once before any architectural tests are run.
8
+ * The standard way to do this is to add it to a Vitest setup file.
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * // test/setup.ts
13
+ * import { setupMatchers } from '@archest/vitest';
14
+ * setupMatchers();
15
+ * ```
16
+ */
17
+ export declare function setupMatchers(): void;
18
+ declare module 'vitest' {
19
+ interface Assertion<T = any> extends ArchestMatchers<T> {
20
+ }
21
+ }
@@ -0,0 +1,201 @@
1
+ /**
2
+ * Native Vitest Matchers provided by Archest for architectural testing.
3
+ *
4
+ * This interface extends Vitest's `Assertion` interface to provide fluent assertions
5
+ * on your codebase's architectural structure.
6
+ */
7
+ export interface ArchestMatchers<_R = unknown> {
8
+ /**
9
+ * Asserts that the evaluated architectural rule passes.
10
+ * Primarily used for complex rules like LayeredArchitecture.
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * const architecture = project.layeredArchitecture()
15
+ * .layer('Domain', 'domain')
16
+ * .layer('Infrastructure', 'infrastructure');
17
+ *
18
+ * expect(architecture.whereLayer('Domain').shouldNotAccessAnyLayer().check()).toPass();
19
+ * ```
20
+ */
21
+ toPass(): void;
22
+ /**
23
+ * Asserts that the located elements physically reside within the specified folder.
24
+ * Supports ClassLocators.
25
+ *
26
+ * @param folder - The folder name or path pattern the elements must reside in.
27
+ * @example
28
+ * ```typescript
29
+ * const controllers = project.getClasses({ matchNamePattern: /Controller$/ });
30
+ * expect(controllers).toResideInFolder('controllers');
31
+ * ```
32
+ */
33
+ toResideInFolder(folder: string): void;
34
+ /**
35
+ * Asserts that the located elements have the specified TypeScript modifier.
36
+ * Supports ClassLocators and FunctionLocators.
37
+ *
38
+ * @param modifier - The AST modifier to enforce (e.g., 'export', 'abstract', 'async').
39
+ * @example
40
+ * ```typescript
41
+ * const helpers = project.getFunctions({ inFolder: 'utils' });
42
+ * expect(helpers).toHaveModifier('export');
43
+ * ```
44
+ */
45
+ toHaveModifier(modifier: 'export' | 'default' | 'abstract' | 'async' | 'private' | 'public'): void;
46
+ /**
47
+ * Asserts that the located classes extend the specified base class.
48
+ * Supports ClassLocators.
49
+ *
50
+ * @param className - The name of the class that must be extended.
51
+ * @example
52
+ * ```typescript
53
+ * const repositories = project.getClasses({ matchNamePattern: /Repository$/ });
54
+ * expect(repositories).toExtendClass('BaseRepository');
55
+ * ```
56
+ */
57
+ toExtendClass(className: string): void;
58
+ /**
59
+ * Asserts that the located classes implement the specified interface.
60
+ * Supports ClassLocators.
61
+ *
62
+ * @param interfaceName - The name of the interface that must be implemented.
63
+ * @example
64
+ * ```typescript
65
+ * const useCases = project.getClasses({ inFolder: 'use-cases' });
66
+ * expect(useCases).toImplementInterface('IUseCase');
67
+ * ```
68
+ */
69
+ toImplementInterface(interfaceName: string): void;
70
+ /**
71
+ * Asserts that the located functions have an explicit TypeScript return type.
72
+ * Supports FunctionLocators.
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const domainFunctions = project.getFunctions({ inFolder: 'domain' });
77
+ * expect(domainFunctions).toHaveExplicitReturnType();
78
+ * ```
79
+ */
80
+ toHaveExplicitReturnType(): void;
81
+ /**
82
+ * Asserts that the located properties are marked as readonly.
83
+ * Supports PropertyLocators.
84
+ *
85
+ * @example
86
+ * ```typescript
87
+ * const dtoProps = project.getProperties({ classPattern: /Dto$/ });
88
+ * expect(dtoProps).toBeReadonly();
89
+ * ```
90
+ */
91
+ toBeReadonly(): void;
92
+ /**
93
+ * Asserts that the located files import dependencies from the specified folder.
94
+ * Supports FileLocators.
95
+ *
96
+ * @param folder - The target folder that must be imported.
97
+ * @example
98
+ * ```typescript
99
+ * const uiFiles = project.getFiles({ inFolder: 'ui' });
100
+ * expect(uiFiles).not.toDependOnFilesInFolder('database');
101
+ * ```
102
+ */
103
+ toDependOnFilesInFolder(folder: string): void;
104
+ /**
105
+ * Asserts that a file locator depends on a specific external module (e.g. from node_modules).
106
+ * Supports FileLocators.
107
+ *
108
+ * @param moduleName - The exact string name or RegExp of the external package (e.g. 'vue', 'lodash').
109
+ * @example
110
+ * ```typescript
111
+ * it('should only use gql-tada inside the graphql module', () => {
112
+ * expect(
113
+ * project.files().not.matching(/src\/graphql\//)
114
+ * ).not.toDependOnExternalModule('gql-tada');
115
+ * });
116
+ * ```
117
+ */
118
+ toDependOnExternalModule(moduleName: string | RegExp): void;
119
+ /**
120
+ * Analyzes the AST dependency graph and asserts that the queried elements are entirely free of circular dependencies.
121
+ * Supports FileLocators and SliceLocators.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * const domainFiles = project.getFiles({ inFolder: 'domain' });
126
+ * expect(domainFiles).toBeFreeOfCycles();
127
+ * ```
128
+ */
129
+ toBeFreeOfCycles(): void;
130
+ /**
131
+ * Asserts that the name of the located element matches the provided string or RegExp pattern.
132
+ * Supports FileLocators, ClassLocators, and FunctionLocators.
133
+ *
134
+ * @param pattern - The string or RegExp pattern that must match the name.
135
+ * @example
136
+ * ```typescript
137
+ * const controllers = project.getClasses({ withDecorator: 'Controller' });
138
+ * expect(controllers).toMatchNamePattern(/Controller$/);
139
+ * ```
140
+ */
141
+ toMatchNamePattern(pattern: string | RegExp): void;
142
+ /**
143
+ * Computes the cyclomatic complexity of the AST and asserts it is less than or equal to the maximum.
144
+ * Supports FileLocators, ClassLocators, and FunctionLocators.
145
+ *
146
+ * @param max - The maximum allowed cyclomatic complexity.
147
+ * @example
148
+ * ```typescript
149
+ * const coreFunctions = project.getFunctions({ inFolder: 'core' });
150
+ * expect(coreFunctions).toHaveMaxCyclomaticComplexity(10);
151
+ * ```
152
+ */
153
+ toHaveMaxCyclomaticComplexity(max: number): void;
154
+ /**
155
+ * Computes the maintainability index based on Halstead metrics and asserts it is greater than or equal to the minimum.
156
+ * Supports FileLocators and FunctionLocators.
157
+ *
158
+ * @param min - The minimum acceptable maintainability index (0-100).
159
+ * @example
160
+ * ```typescript
161
+ * const coreFiles = project.getFiles({ inFolder: 'core' });
162
+ * expect(coreFiles).toHaveMinMaintainabilityIndex(65);
163
+ * ```
164
+ */
165
+ toHaveMinMaintainabilityIndex(min: number): void;
166
+ /**
167
+ * Computes the Robert C. Martin Distance from the Main Sequence for the slice and asserts it is less than or equal to the maximum.
168
+ * Supports SliceLocators.
169
+ *
170
+ * @param max - The maximum allowed distance from the main sequence (0 to 1).
171
+ * @example
172
+ * ```typescript
173
+ * const slices = project.getSlices('modules/(*)/');
174
+ * expect(slices).toHaveMaxDistanceFromMainSequence(0.3);
175
+ * ```
176
+ */
177
+ toHaveMaxDistanceFromMainSequence(max: number): void;
178
+ /**
179
+ * Asserts that the exported class or function name exactly matches the name of its parent file.
180
+ * Supports ClassLocators and FunctionLocators.
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * const allFunctions = project.getFunctions();
185
+ * expect(allFunctions).toHaveNameMatchingFileName();
186
+ * ```
187
+ */
188
+ toHaveNameMatchingFileName(): void;
189
+ /**
190
+ * Asserts that the located file does not export more than the specified maximum number of functions.
191
+ * Supports FileLocators.
192
+ *
193
+ * @param max - The maximum number of allowed exported functions per file.
194
+ * @example
195
+ * ```typescript
196
+ * const utils = project.getFiles({ inFolder: 'utils' });
197
+ * expect(utils).toHaveMaxExportedFunctions(5);
198
+ * ```
199
+ */
200
+ toHaveMaxExportedFunctions(max: number): void;
201
+ }
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { ClassLocatorData } from './types';
3
+ export declare function classCheckExtendClass(locator: ClassLocatorData, className: string, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { ClassLocatorData } from './types';
3
+ export declare function classCheckHaveMaxCyclomaticComplexity(locator: ClassLocatorData, max: number, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { ClassLocatorData } from './types';
3
+ export declare function classCheckHaveModifier(locator: ClassLocatorData, modifierStr: string, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { ClassLocatorData } from './types';
3
+ export declare function classCheckHaveNameMatchingFileName(locator: ClassLocatorData, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { ClassLocatorData } from './types';
3
+ export declare function classCheckImplementInterface(locator: ClassLocatorData, interfaceName: string, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { ClassLocatorData } from './types';
3
+ export declare function classCheckMatchNamePattern(locator: ClassLocatorData, pattern: string | RegExp, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { ClassLocatorData } from './types';
3
+ export declare function classCheckResideInFolder(locator: ClassLocatorData, targetFolder: string, isNot: boolean): RuleResult;
@@ -0,0 +1,5 @@
1
+ import { ClassData, ProjectData } from '../dto';
2
+ import { ClassLocatorData, ClassQueryOptions } from './types';
3
+ export declare function locateClasses(classes: (ClassData & {
4
+ _filePath: string;
5
+ })[], projectData: ProjectData, options?: ClassQueryOptions): ClassLocatorData;
@@ -0,0 +1,25 @@
1
+ import { ClassData, ProjectData } from '../dto';
2
+ export interface ClassLocatorData {
3
+ type: 'ClassLocator';
4
+ classes: (ClassData & {
5
+ _filePath: string;
6
+ })[];
7
+ projectData: ProjectData;
8
+ }
9
+ /**
10
+ * Options to filter classes when querying the AST via `getClasses()`.
11
+ */
12
+ export interface ClassQueryOptions {
13
+ /** Filters classes to only include those residing in a specific folder path. */
14
+ inFolder?: string;
15
+ /** Filters classes by a string or RegExp matching their name. */
16
+ matchNamePattern?: string | RegExp;
17
+ /** Filters classes to only include those that have the specified decorator applied. */
18
+ withDecorator?: string;
19
+ /** Filters classes to only include those extending the specified base class. */
20
+ extending?: string;
21
+ /** Filters classes to only include those implementing the specified interface. */
22
+ implementing?: string;
23
+ /** Filters classes to only include those with the specified AST modifier (e.g., 'export', 'abstract'). */
24
+ havingModifier?: string;
25
+ }
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Represents the entire parsed project structure containing all analyzed files.
3
+ * This is the root node returned by the native Rust parser.
4
+ */
5
+ export interface ProjectData {
6
+ /** A list of all files that were successfully parsed in the project workspace. */
7
+ files: FileData[];
8
+ }
9
+ /**
10
+ * Represents a single source file in the project.
11
+ * Contains information about its path, dependencies, and all nested code blocks.
12
+ */
13
+ export interface FileData {
14
+ /** The absolute path to the file. */
15
+ path: string;
16
+ /** An array of all classes defined within this file. */
17
+ classes: ClassData[];
18
+ /** An array of all top-level or exported functions defined within this file. */
19
+ functions: FunctionData[];
20
+ /** An array of properties extracted from classes or objects in the file. */
21
+ properties: PropertyData[];
22
+ /** An array of raw module paths this file imports (e.g., './utils', 'react'). */
23
+ dependencies?: string[];
24
+ /** An array of external module imports (e.g., 'react', 'lodash'). */
25
+ external_dependencies?: string[];
26
+ }
27
+ /**
28
+ * Represents a class declaration extracted from a TypeScript or JavaScript file.
29
+ * Includes architectural metadata such as its hierarchy and complexity.
30
+ */
31
+ export interface ClassData {
32
+ /** The name of the class, or null if it is an anonymous class. */
33
+ name: string | null;
34
+ /** True if the class has an 'export' modifier. */
35
+ is_exported: boolean;
36
+ /** True if the class has an 'export default' modifier. */
37
+ is_default: boolean;
38
+ /** True if the class is marked as abstract. */
39
+ is_abstract: boolean;
40
+ /** The name of the parent class it extends, if any. */
41
+ extends: string | null;
42
+ /** An array of interface names this class implements. */
43
+ implements: string[];
44
+ /** An array of decorator names applied to the class. */
45
+ decorators: string[];
46
+ /** The computed McCabe cyclomatic complexity of the class methods. */
47
+ cyclomatic_complexity?: number;
48
+ /** The computed Halstead maintainability index (0-100). */
49
+ maintainability_index?: number;
50
+ }
51
+ /**
52
+ * Represents a function declaration or arrow function extracted from a file.
53
+ */
54
+ export interface FunctionData {
55
+ /** The name of the function, or null if anonymous. */
56
+ name: string | null;
57
+ /** True if the function is exported from the file. */
58
+ is_exported: boolean;
59
+ /** True if the function is marked as async. */
60
+ is_async: boolean;
61
+ /** True if the function is defined at the root level of the file context. */
62
+ is_top_level: boolean;
63
+ /** True if the function explicitly declares a return type. */
64
+ has_explicit_return_type: boolean;
65
+ /** The computed McCabe cyclomatic complexity of the function body. */
66
+ cyclomatic_complexity?: number;
67
+ /** The computed Halstead maintainability index (0-100). */
68
+ maintainability_index?: number;
69
+ }
70
+ /**
71
+ * Represents a class property or interface member extracted from the AST.
72
+ */
73
+ export interface PropertyData {
74
+ /** The name of the property. */
75
+ name: string;
76
+ /** True if the property is marked with the 'readonly' modifier. */
77
+ is_readonly: boolean;
78
+ }
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FileLocatorData } from './types';
3
+ export declare function checkDependOnExternalModule(locator: FileLocatorData, moduleName: string | RegExp, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FileLocatorData } from './types';
3
+ export declare function checkDependOnFilesInFolder(locator: FileLocatorData, targetFolder: string, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FileLocatorData } from './types';
3
+ export declare function fileCheckBeFreeOfCycles(locator: FileLocatorData, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FileLocatorData } from './types';
3
+ export declare function fileCheckHaveMaxCyclomaticComplexity(locator: FileLocatorData, max: number, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FileLocatorData } from './types';
3
+ export declare function fileCheckHaveMaxExportedFunctions(locator: FileLocatorData, max: number, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FileLocatorData } from './types';
3
+ export declare function fileCheckHaveMinMaintainabilityIndex(locator: FileLocatorData, min: number, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FileLocatorData } from './types';
3
+ export declare function fileCheckMatchNamePattern(locator: FileLocatorData, pattern: string | RegExp, isNot: boolean): RuleResult;
@@ -0,0 +1,2 @@
1
+ import { FileData, ProjectData } from '../dto';
2
+ export declare function getFileDependencies(sourceFile: FileData, _projectData: ProjectData): string[];
@@ -0,0 +1,4 @@
1
+ import { ArchestProject } from '@archest/core-rust';
2
+ import { FileData, ProjectData } from '../dto';
3
+ import { FileLocatorData, FileQueryOptions } from './types';
4
+ export declare function locateFiles(sourceFiles: FileData[], projectData: ProjectData, archestProject?: ArchestProject, options?: FileQueryOptions): FileLocatorData;
@@ -0,0 +1,17 @@
1
+ import { ArchestProject } from '@archest/core-rust';
2
+ import { FileData, ProjectData } from '../dto';
3
+ export interface FileLocatorData {
4
+ type: 'FileLocator';
5
+ files: FileData[];
6
+ projectData: ProjectData;
7
+ archestProject?: ArchestProject;
8
+ }
9
+ /**
10
+ * Options to filter files when querying the AST via `getFiles()`.
11
+ */
12
+ export interface FileQueryOptions {
13
+ /** Filters files to only include those residing in a specific folder path. */
14
+ inFolder?: string;
15
+ /** Filters files by a string or RegExp matching their file name (excluding extension). */
16
+ matchNamePattern?: string | RegExp;
17
+ }
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FunctionLocatorData } from './types';
3
+ export declare function functionCheckHaveExplicitReturnType(locator: FunctionLocatorData, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FunctionLocatorData } from './types';
3
+ export declare function functionCheckHaveMaxCyclomaticComplexity(locator: FunctionLocatorData, max: number, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FunctionLocatorData } from './types';
3
+ export declare function functionCheckHaveMinMaintainabilityIndex(locator: FunctionLocatorData, min: number, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FunctionLocatorData } from './types';
3
+ export declare function functionCheckHaveModifier(locator: FunctionLocatorData, modifierStr: string, isNot: boolean): RuleResult;
@@ -0,0 +1,3 @@
1
+ import { RuleResult } from '../types';
2
+ import { FunctionLocatorData } from './types';
3
+ export declare function functionCheckHaveNameMatchingFileName(locator: FunctionLocatorData, isNot: boolean): RuleResult;