@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,171 +0,0 @@
1
- import * as ts from 'typescript';
2
- import * as path from 'path';
3
- import { FileLocator, FileQueryOptions } from './FileLocator';
4
- import { ClassLocator, ClassQueryOptions } from './ClassLocator';
5
- import { LayeredArchitectureBuilder } from './LayerLocator';
6
- import { FunctionLocator, FunctionQueryOptions } from './FunctionLocator';
7
- import { PropertyLocator, PropertyQueryOptions } from './PropertyLocator';
8
- import { SliceLocator } from './SliceLocator';
9
-
10
- export class Project {
11
- private program: ts.Program;
12
- private typeChecker: ts.TypeChecker;
13
-
14
- constructor(options: { tsConfigFilePath?: string } = {}) {
15
- let compilerOptions: ts.CompilerOptions = {};
16
- const configPath = options.tsConfigFilePath || ts.findConfigFile(
17
- process.cwd(),
18
- ts.sys.fileExists,
19
- 'tsconfig.json'
20
- );
21
-
22
- if (configPath) {
23
- const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
24
- const parsedCommandLine = ts.parseJsonConfigFileContent(
25
- configFile.config,
26
- ts.sys,
27
- path.dirname(configPath),
28
- undefined,
29
- configPath,
30
- undefined,
31
- [
32
- { extension: '.vue', isMixedContent: true, scriptKind: ts.ScriptKind.TS },
33
- { extension: '.svelte', isMixedContent: true, scriptKind: ts.ScriptKind.TS }
34
- ]
35
- );
36
- compilerOptions = parsedCommandLine.options;
37
-
38
- const host = ts.createCompilerHost(compilerOptions);
39
- const originalGetSourceFile = host.getSourceFile;
40
-
41
- let vueCompiler: any;
42
- try {
43
- vueCompiler = require('@vue/compiler-sfc');
44
- } catch (e) {
45
- // Not a Vue project
46
- }
47
-
48
- host.getSourceFile = (fileName, languageVersion, onError, shouldCreateNewSourceFile) => {
49
- if (fileName.endsWith('.vue')) {
50
- const content = ts.sys.readFile(fileName);
51
- if (content) {
52
- let scriptContent = '';
53
- if (vueCompiler) {
54
- const parsed = vueCompiler.parse(content);
55
- const script = parsed.descriptor.script;
56
- const scriptSetup = parsed.descriptor.scriptSetup;
57
- if (script) scriptContent += script.content + '\n';
58
- if (scriptSetup) scriptContent += scriptSetup.content + '\n';
59
- } else {
60
- // Fallback for Svelte or if compiler-sfc is missing (fragile but works for simple cases)
61
- const match = content.match(/<script[^>]*>(.*?)<\/script>/s);
62
- if (match) scriptContent = match[1];
63
- }
64
- return ts.createSourceFile(fileName, scriptContent, languageVersion, true, ts.ScriptKind.TS);
65
- }
66
- }
67
-
68
- if (fileName.endsWith('.svelte')) {
69
- const content = ts.sys.readFile(fileName);
70
- if (content) {
71
- let scriptContent = '';
72
- const match = content.match(/<script[^>]*>(.*?)<\/script>/s);
73
- if (match) scriptContent = match[1];
74
- return ts.createSourceFile(fileName, scriptContent, languageVersion, true, ts.ScriptKind.TS);
75
- }
76
- }
77
-
78
- return originalGetSourceFile(fileName, languageVersion, onError, shouldCreateNewSourceFile);
79
- };
80
-
81
- this.program = ts.createProgram({
82
- rootNames: parsedCommandLine.fileNames,
83
- options: compilerOptions,
84
- host: host
85
- });
86
- } else {
87
- throw new Error("Could not find tsconfig.json");
88
- }
89
-
90
- this.typeChecker = this.program.getTypeChecker();
91
- }
92
-
93
- getFiles(options?: FileQueryOptions) {
94
- const sourceFiles = this.program.getSourceFiles().filter(
95
- sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')
96
- );
97
- return new FileLocator(sourceFiles, this.program, options);
98
- }
99
-
100
- getClasses(options?: ClassQueryOptions) {
101
- const sourceFiles = this.program.getSourceFiles().filter(
102
- sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')
103
- );
104
-
105
- const allClasses: ts.ClassDeclaration[] = [];
106
- for (const sf of sourceFiles) {
107
- const visit = (node: ts.Node) => {
108
- if (ts.isClassDeclaration(node)) {
109
- allClasses.push(node);
110
- }
111
- ts.forEachChild(node, visit);
112
- };
113
- visit(sf);
114
- }
115
- return new ClassLocator(allClasses, this.program, options);
116
- }
117
-
118
- layeredArchitecture() {
119
- const sourceFiles = this.program.getSourceFiles().filter(
120
- sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')
121
- );
122
- return new LayeredArchitectureBuilder(sourceFiles, this.program);
123
- }
124
-
125
- getFunctions(options?: FunctionQueryOptions) {
126
- const sourceFiles = this.program.getSourceFiles().filter(
127
- sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')
128
- );
129
-
130
- const allFunctions: ts.FunctionLikeDeclaration[] = [];
131
- for (const sf of sourceFiles) {
132
- const visit = (node: ts.Node) => {
133
- if (ts.isFunctionDeclaration(node) || ts.isMethodDeclaration(node) || ts.isArrowFunction(node)) {
134
- allFunctions.push(node);
135
- }
136
- ts.forEachChild(node, visit);
137
- };
138
- visit(sf);
139
- }
140
- return new FunctionLocator(allFunctions, this.program, options);
141
- }
142
-
143
- getProperties(options?: PropertyQueryOptions) {
144
- const sourceFiles = this.program.getSourceFiles().filter(
145
- sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')
146
- );
147
-
148
- const allProperties: ts.PropertyDeclaration[] = [];
149
- for (const sf of sourceFiles) {
150
- const visit = (node: ts.Node) => {
151
- if (ts.isPropertyDeclaration(node)) {
152
- allProperties.push(node);
153
- }
154
- ts.forEachChild(node, visit);
155
- };
156
- visit(sf);
157
- }
158
- return new PropertyLocator(allProperties, this.program, options);
159
- }
160
-
161
- getSlices(pattern: string) {
162
- const sourceFiles = this.program.getSourceFiles().filter(
163
- sf => !sf.isDeclarationFile && !sf.fileName.includes('node_modules')
164
- );
165
- return new SliceLocator(sourceFiles, this.program, pattern);
166
- }
167
- }
168
-
169
- export function parseProject(tsConfigFilePath?: string): Project {
170
- return new Project({ tsConfigFilePath });
171
- }
@@ -1,50 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { RuleResult } from './types';
3
-
4
- export interface PropertyQueryOptions {
5
- inFolder?: string;
6
- matchNamePattern?: string | RegExp;
7
- }
8
-
9
- export class PropertyLocator {
10
- public readonly properties: ts.PropertyDeclaration[];
11
-
12
- constructor(properties: ts.PropertyDeclaration[], private program: ts.Program, options?: PropertyQueryOptions) {
13
- let filtered = properties;
14
-
15
- if (options?.inFolder) {
16
- filtered = filtered.filter((p) => {
17
- const sourceFile = p.getSourceFile();
18
- return sourceFile.fileName.includes(`/${options.inFolder}/`) || sourceFile.fileName.includes(`\\${options.inFolder}\\`);
19
- });
20
- }
21
-
22
- if (options?.matchNamePattern) {
23
- const regex = typeof options.matchNamePattern === 'string' ? new RegExp(options.matchNamePattern) : options.matchNamePattern;
24
- filtered = filtered.filter((p) => {
25
- return ts.isIdentifier(p.name) && regex.test(p.name.text);
26
- });
27
- }
28
-
29
- this.properties = filtered;
30
- }
31
-
32
- checkBeReadonly(isNot: boolean): RuleResult {
33
- const violations: string[] = [];
34
- for (const p of this.properties) {
35
- const name = ts.isIdentifier(p.name) ? p.name.text : 'Anonymous Property';
36
- const modifiers = ts.canHaveModifiers(p) ? ts.getModifiers(p) : undefined;
37
- const matches = modifiers && modifiers.some((m: ts.Modifier) => m.kind === ts.SyntaxKind.ReadonlyKeyword);
38
-
39
- if (isNot && matches) {
40
- violations.push(`Property ${name} is readonly, but it shouldn't be.`);
41
- } else if (!isNot && !matches) {
42
- violations.push(`Property ${name} is not readonly, but it should be.`);
43
- }
44
- }
45
- return {
46
- pass: violations.length === 0,
47
- message: () => violations.join('\n'),
48
- };
49
- }
50
- }
@@ -1,92 +0,0 @@
1
- import * as ts from 'typescript';
2
- import { RuleResult } from './types';
3
-
4
- export class SliceLocator {
5
- private slicePattern: RegExp;
6
- private sliceIds: Set<string> = new Set();
7
- private sliceFiles: Map<string, ts.SourceFile[]> = new Map();
8
-
9
- constructor(sourceFiles: ts.SourceFile[], private program: ts.Program, pattern: string) {
10
- const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
11
- const regexStr = escaped.replace(/\*/g, '([^/\\\\]+)');
12
- this.slicePattern = new RegExp(regexStr);
13
-
14
- for (const sf of sourceFiles) {
15
- const match = sf.fileName.match(this.slicePattern);
16
- if (match && match[1]) {
17
- const sliceId = match[1];
18
- this.sliceIds.add(sliceId);
19
- if (!this.sliceFiles.has(sliceId)) {
20
- this.sliceFiles.set(sliceId, []);
21
- }
22
- this.sliceFiles.get(sliceId)!.push(sf);
23
- }
24
- }
25
- }
26
-
27
- checkBeFreeOfCycles(isNot: boolean): RuleResult {
28
- const graph: Map<string, Set<string>> = new Map();
29
- for (const slice of this.sliceIds) {
30
- graph.set(slice, new Set());
31
- }
32
-
33
- for (const [sliceId, files] of this.sliceFiles.entries()) {
34
- for (const sf of files) {
35
- ts.forEachChild(sf, (node) => {
36
- if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
37
- const importPath = node.moduleSpecifier.text;
38
- const resolved = ts.resolveModuleName(importPath, sf.fileName, this.program.getCompilerOptions(), ts.sys);
39
- if (resolved.resolvedModule && resolved.resolvedModule.resolvedFileName) {
40
- const targetMatch = resolved.resolvedModule.resolvedFileName.match(this.slicePattern);
41
- if (targetMatch && targetMatch[1]) {
42
- const targetSlice = targetMatch[1];
43
- if (targetSlice !== sliceId && this.sliceIds.has(targetSlice)) {
44
- graph.get(sliceId)!.add(targetSlice);
45
- }
46
- }
47
- }
48
- }
49
- });
50
- }
51
- }
52
-
53
- const visited = new Set<string>();
54
- const recursionStack = new Set<string>();
55
- const violations: string[] = [];
56
-
57
- const dfs = (node: string, path: string[]): boolean => {
58
- visited.add(node);
59
- recursionStack.add(node);
60
-
61
- for (const neighbor of (graph.get(node) || [])) {
62
- if (!visited.has(neighbor)) {
63
- if (dfs(neighbor, [...path, neighbor])) return true;
64
- } else if (recursionStack.has(neighbor)) {
65
- violations.push(`Cycle detected between slices: ${path.join(' -> ')} -> ${neighbor}`);
66
- return true;
67
- }
68
- }
69
-
70
- recursionStack.delete(node);
71
- return false;
72
- };
73
-
74
- for (const slice of this.sliceIds) {
75
- if (!visited.has(slice)) {
76
- dfs(slice, [slice]);
77
- }
78
- }
79
-
80
- if (isNot) {
81
- return {
82
- pass: violations.length > 0,
83
- message: () => violations.length > 0 ? '' : 'Expected cycles between slices but found none.'
84
- };
85
- } else {
86
- return {
87
- pass: violations.length === 0,
88
- message: () => violations.join('\n')
89
- };
90
- }
91
- }
92
- }
package/src/core/types.ts DELETED
@@ -1,4 +0,0 @@
1
- export interface RuleResult {
2
- pass: boolean;
3
- message: () => string;
4
- }
package/src/index.ts DELETED
@@ -1,9 +0,0 @@
1
- export { Project, parseProject } from './core/Project';
2
- export { setupMatchers } from './matchers';
3
- export * from './core/FileLocator';
4
- export * from './core/ClassLocator';
5
- export * from './core/FunctionLocator';
6
- export * from './core/PropertyLocator';
7
- export * from './core/SliceLocator';
8
- export * from './core/LayerLocator';
9
- export * from './core/types';
@@ -1,113 +0,0 @@
1
- import { expect } from 'vitest';
2
- import { RuleResult } from '../core/types';
3
- import { ClassLocator } from '../core/ClassLocator';
4
- import { FunctionLocator } from '../core/FunctionLocator';
5
- import { PropertyLocator } from '../core/PropertyLocator';
6
- import { FileLocator } from '../core/FileLocator';
7
- import { SliceLocator } from '../core/SliceLocator';
8
- import { LayeredArchitectureBuilder } from '../core/LayerLocator';
9
-
10
- export function setupMatchers() {
11
- expect.extend({
12
- toPass(received: RuleResult | LayeredArchitectureBuilder) {
13
- const result = received instanceof LayeredArchitectureBuilder ? received.check() : received;
14
- const { pass, message } = result;
15
- return {
16
- pass: this.isNot ? !pass : pass,
17
- message: pass
18
- ? () => 'Expected rule not to pass'
19
- : () => message()
20
- };
21
- },
22
-
23
- toResideInFolder(received: ClassLocator, folder: string) {
24
- const { pass, message } = received.checkResideInFolder(folder, this.isNot);
25
- return {
26
- pass: this.isNot ? !pass : pass,
27
- message
28
- };
29
- },
30
-
31
- toHaveModifier(received: ClassLocator | FunctionLocator, modifier: string) {
32
- const { pass, message } = received.checkHaveModifier(modifier, this.isNot);
33
- return {
34
- pass: this.isNot ? !pass : pass,
35
- message
36
- };
37
- },
38
-
39
-
40
-
41
- toExtendClass(received: ClassLocator, className: string) {
42
- const { pass, message } = received.checkExtendClass(className, this.isNot);
43
- return {
44
- pass: this.isNot ? !pass : pass,
45
- message
46
- };
47
- },
48
-
49
- toImplementInterface(received: ClassLocator, interfaceName: string) {
50
- const { pass, message } = received.checkImplementInterface(interfaceName, this.isNot);
51
- return {
52
- pass: this.isNot ? !pass : pass,
53
- message
54
- };
55
- },
56
-
57
- toHaveExplicitReturnType(received: FunctionLocator) {
58
- const { pass, message } = received.checkHaveExplicitReturnType(this.isNot);
59
- return {
60
- pass: this.isNot ? !pass : pass,
61
- message
62
- };
63
- },
64
-
65
- toBeReadonly(received: PropertyLocator) {
66
- const { pass, message } = received.checkBeReadonly(this.isNot);
67
- return {
68
- pass: this.isNot ? !pass : pass,
69
- message
70
- };
71
- },
72
-
73
- toDependOnFilesInFolder(received: FileLocator, folder: string) {
74
- const { pass, message } = received.checkDependOnFilesInFolder(folder, this.isNot);
75
- return {
76
- pass: this.isNot ? !pass : pass,
77
- message
78
- };
79
- },
80
-
81
- toBeFreeOfCycles(received: FileLocator | SliceLocator) {
82
- const { pass, message } = received.checkBeFreeOfCycles(this.isNot);
83
- return {
84
- pass: this.isNot ? !pass : pass,
85
- message
86
- };
87
- },
88
-
89
- toMatchNamePattern(received: FileLocator | ClassLocator | FunctionLocator, pattern: string | RegExp) {
90
- const { pass, message } = received.checkMatchNamePattern(pattern, this.isNot);
91
- return {
92
- pass: this.isNot ? !pass : pass,
93
- message
94
- };
95
- }
96
- });
97
- }
98
-
99
- declare module 'vitest' {
100
- interface Assertion<T = any> {
101
- toPass(): void;
102
- toResideInFolder(folder: string): void;
103
- toHaveModifier(modifier: 'export' | 'default' | 'abstract' | 'async' | 'private' | 'public'): void;
104
-
105
- toExtendClass(className: string): void;
106
- toImplementInterface(interfaceName: string): void;
107
- toHaveExplicitReturnType(): void;
108
- toBeReadonly(): void;
109
- toDependOnFilesInFolder(folder: string): void;
110
- toBeFreeOfCycles(): void;
111
- toMatchNamePattern(pattern: string | RegExp): void;
112
- }
113
- }
@@ -1,59 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { parseProject } from '../src/core/Project';
3
- import { setupMatchers } from '../src/matchers';
4
-
5
- setupMatchers();
6
-
7
- describe('@archest/vitest', () => {
8
- const project = parseProject(); // Automatically picks up tsconfig.json in the current directory
9
-
10
- describe('FileLocator (Dependency Checks)', () => {
11
- it('core classes should not depend on matchers', () => {
12
- const coreFiles = project.getFiles({ inFolder: 'core' });
13
- expect(coreFiles).not.toDependOnFilesInFolder('matchers');
14
- });
15
-
16
- it('matchers should depend on core', () => {
17
- const matcherFiles = project.getFiles({ inFolder: 'matchers' });
18
- expect(matcherFiles).toDependOnFilesInFolder('core');
19
- });
20
- });
21
-
22
- describe('ClassLocator (Declaration Checks)', () => {
23
- it('locators should have export modifier', () => {
24
- const locators = project.getClasses({ inFolder: 'core', matchNamePattern: /Locator$/ });
25
- expect(locators).toHaveModifier('export');
26
- });
27
-
28
- it('Project class should be exported', () => {
29
- const projectClasses = project.getClasses({ matchNamePattern: /Project$/ });
30
- expect(projectClasses).toHaveModifier('export');
31
- });
32
- });
33
-
34
- describe('FileLocator (Pattern matching)', () => {
35
- it('src files should match the src pattern', () => {
36
- const srcFiles = project.getFiles({ matchNamePattern: /src\/core\/.*/ });
37
- expect(srcFiles).not.toDependOnFilesInFolder('matchers');
38
- });
39
-
40
- it('core classes should be free of cycles', () => {
41
- const coreFiles = project.getFiles({ inFolder: 'core' });
42
- expect(coreFiles).toBeFreeOfCycles();
43
- });
44
- });
45
-
46
- describe('LayeredArchitectureBuilder', () => {
47
- it('core should not depend on matchers layer', () => {
48
- const architecture = project.layeredArchitecture()
49
- .layer('Core', 'core')
50
- .layer('Matchers', 'matchers')
51
- .layer('Root', 'src'); // src/index.ts is just under src
52
-
53
- const rule = architecture
54
- .whereLayer('Matchers').shouldOnlyBeAccessedBy('Core', 'Root');
55
-
56
- expect(rule).toPass();
57
- });
58
- });
59
- });
package/tsconfig.json DELETED
@@ -1,17 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "ES2022",
4
- "module": "NodeNext",
5
- "moduleResolution": "NodeNext",
6
- "lib": ["ES2022"],
7
- "types": ["node"],
8
- "declaration": true,
9
- "sourceMap": true,
10
- "strict": true,
11
- "esModuleInterop": true,
12
- "skipLibCheck": true,
13
- "forceConsistentCasingInFileNames": true,
14
- "outDir": "dist"
15
- },
16
- "include": ["src/**/*"]
17
- }
package/vite.config.ts DELETED
@@ -1,18 +0,0 @@
1
- import { defineConfig } from 'vite';
2
- import dts from 'vite-plugin-dts';
3
- import { resolve } from 'path';
4
-
5
- export default defineConfig({
6
- build: {
7
- lib: {
8
- entry: resolve(__dirname, 'src/index.ts'),
9
- name: 'VitestArch',
10
- fileName: (format) => `index.${format === 'es' ? 'mjs' : 'js'}`,
11
- },
12
- rollupOptions: {
13
- external: ['typescript', 'vitest', 'path', 'fs'],
14
- },
15
- sourcemap: true,
16
- },
17
- plugins: [dts()],
18
- });