@notjustcoders/ioc-arise 1.0.2 → 1.0.3

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.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=project-analyzer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-analyzer.test.d.ts","sourceRoot":"","sources":["../../../src/__tests__/analyser/project-analyzer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,191 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const vitest_1 = require("vitest");
4
+ const project_analyzer_1 = require("../../analyser/project-analyzer");
5
+ const class_analyzer_1 = require("../../analyser/class-analyzer");
6
+ const file_discovery_1 = require("../../analyser/file-discovery");
7
+ // Mock the dependencies
8
+ vitest_1.vi.mock('../../analyser/class-analyzer');
9
+ vitest_1.vi.mock('../../analyser/file-discovery');
10
+ const MockedClassAnalyzer = vitest_1.vi.mocked(class_analyzer_1.ClassAnalyzer);
11
+ const MockedFileDiscovery = vitest_1.vi.mocked(file_discovery_1.FileDiscovery);
12
+ (0, vitest_1.describe)('ProjectAnalyzer', () => {
13
+ let projectAnalyzer;
14
+ let mockClassAnalyzer;
15
+ let mockFileDiscovery;
16
+ let options;
17
+ (0, vitest_1.beforeEach)(() => {
18
+ vitest_1.vi.clearAllMocks();
19
+ options = {
20
+ sourceDir: '/test/src',
21
+ interfacePattern: 'I*',
22
+ excludePatterns: ['**/*.spec.ts']
23
+ };
24
+ mockFileDiscovery = {
25
+ findTypeScriptFiles: vitest_1.vi.fn()
26
+ };
27
+ mockClassAnalyzer = {
28
+ analyzeFile: vitest_1.vi.fn()
29
+ };
30
+ MockedFileDiscovery.mockImplementation(() => mockFileDiscovery);
31
+ MockedClassAnalyzer.mockImplementation(() => mockClassAnalyzer);
32
+ projectAnalyzer = new project_analyzer_1.ProjectAnalyzer(options);
33
+ });
34
+ (0, vitest_1.describe)('analyzeProject', () => {
35
+ (0, vitest_1.it)('should analyze project successfully with unique interface implementations', async () => {
36
+ const mockFiles = ['/test/src/service1.ts', '/test/src/service2.ts'];
37
+ const mockClasses = [
38
+ {
39
+ name: 'UserService',
40
+ filePath: '/test/src/service1.ts',
41
+ dependencies: ['UserRepository'],
42
+ constructorParams: [],
43
+ interfaceName: 'IUserService',
44
+ importPath: './service1',
45
+ scope: 'singleton'
46
+ },
47
+ {
48
+ name: 'UserRepository',
49
+ filePath: '/test/src/service2.ts',
50
+ dependencies: [],
51
+ constructorParams: [],
52
+ interfaceName: 'IUserRepository',
53
+ importPath: './service2',
54
+ scope: 'singleton'
55
+ }
56
+ ];
57
+ mockFileDiscovery.findTypeScriptFiles.mockResolvedValue(mockFiles);
58
+ mockClassAnalyzer.analyzeFile
59
+ .mockResolvedValueOnce([mockClasses[0]])
60
+ .mockResolvedValueOnce([mockClasses[1]]);
61
+ const result = await projectAnalyzer.analyzeProject();
62
+ (0, vitest_1.expect)(result).toEqual(mockClasses);
63
+ (0, vitest_1.expect)(mockFileDiscovery.findTypeScriptFiles).toHaveBeenCalledOnce();
64
+ (0, vitest_1.expect)(mockClassAnalyzer.analyzeFile).toHaveBeenCalledTimes(2);
65
+ });
66
+ (0, vitest_1.it)('should throw error when multiple classes implement the same interface', async () => {
67
+ const mockFiles = ['/test/src/service1.ts', '/test/src/service2.ts'];
68
+ const mockClasses = [
69
+ {
70
+ name: 'UserService',
71
+ filePath: '/test/src/service1.ts',
72
+ dependencies: [],
73
+ constructorParams: [],
74
+ interfaceName: 'IUserService',
75
+ importPath: './service1',
76
+ scope: 'singleton'
77
+ },
78
+ {
79
+ name: 'AnotherUserService',
80
+ filePath: '/test/src/service2.ts',
81
+ dependencies: [],
82
+ constructorParams: [],
83
+ interfaceName: 'IUserService', // Same interface as above
84
+ importPath: './service2',
85
+ scope: 'singleton'
86
+ }
87
+ ];
88
+ mockFileDiscovery.findTypeScriptFiles.mockResolvedValue(mockFiles);
89
+ mockClassAnalyzer.analyzeFile
90
+ .mockResolvedValueOnce([mockClasses[0]])
91
+ .mockResolvedValueOnce([mockClasses[1]]);
92
+ // Mock console.error to avoid output during tests
93
+ const consoleSpy = vitest_1.vi.spyOn(console, 'error').mockImplementation(() => { });
94
+ await (0, vitest_1.expect)(projectAnalyzer.analyzeProject()).rejects.toThrow('Multiple classes implement the same interface(s): IUserService. Each interface should only be implemented by one class for proper dependency injection.');
95
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith("Error: Interface 'IUserService' is implemented by multiple classes:");
96
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(' - UserService (/test/src/service1.ts)');
97
+ (0, vitest_1.expect)(consoleSpy).toHaveBeenCalledWith(' - AnotherUserService (/test/src/service2.ts)');
98
+ consoleSpy.mockRestore();
99
+ });
100
+ (0, vitest_1.it)('should throw error when multiple interfaces have duplicate implementations', async () => {
101
+ const mockFiles = ['/test/src/service1.ts', '/test/src/service2.ts', '/test/src/service3.ts'];
102
+ const mockClasses = [
103
+ {
104
+ name: 'UserService1',
105
+ filePath: '/test/src/service1.ts',
106
+ dependencies: [],
107
+ constructorParams: [],
108
+ interfaceName: 'IUserService',
109
+ importPath: './service1',
110
+ scope: 'singleton'
111
+ },
112
+ {
113
+ name: 'UserService2',
114
+ filePath: '/test/src/service2.ts',
115
+ dependencies: [],
116
+ constructorParams: [],
117
+ interfaceName: 'IUserService', // Duplicate
118
+ importPath: './service2',
119
+ scope: 'singleton'
120
+ },
121
+ {
122
+ name: 'OrderService1',
123
+ filePath: '/test/src/service3.ts',
124
+ dependencies: [],
125
+ constructorParams: [],
126
+ interfaceName: 'IOrderService',
127
+ importPath: './service3',
128
+ scope: 'singleton'
129
+ },
130
+ {
131
+ name: 'OrderService2',
132
+ filePath: '/test/src/service3.ts',
133
+ dependencies: [],
134
+ constructorParams: [],
135
+ interfaceName: 'IOrderService', // Duplicate
136
+ importPath: './service3',
137
+ scope: 'singleton'
138
+ }
139
+ ];
140
+ mockFileDiscovery.findTypeScriptFiles.mockResolvedValue(mockFiles);
141
+ mockClassAnalyzer.analyzeFile
142
+ .mockResolvedValueOnce([mockClasses[0]])
143
+ .mockResolvedValueOnce([mockClasses[1]])
144
+ .mockResolvedValueOnce([mockClasses[2], mockClasses[3]]);
145
+ // Mock console.error to avoid output during tests
146
+ const consoleSpy = vitest_1.vi.spyOn(console, 'error').mockImplementation(() => { });
147
+ await (0, vitest_1.expect)(projectAnalyzer.analyzeProject()).rejects.toThrow('Multiple classes implement the same interface(s): IUserService, IOrderService. Each interface should only be implemented by one class for proper dependency injection.');
148
+ consoleSpy.mockRestore();
149
+ });
150
+ (0, vitest_1.it)('should filter out classes that are not used as dependencies and have no interfaces', async () => {
151
+ const mockFiles = ['/test/src/service1.ts'];
152
+ const mockClasses = [
153
+ {
154
+ name: 'UserService',
155
+ filePath: '/test/src/service1.ts',
156
+ dependencies: ['UnusedClass'],
157
+ constructorParams: [],
158
+ interfaceName: 'IUserService',
159
+ importPath: './service1',
160
+ scope: 'singleton'
161
+ },
162
+ {
163
+ name: 'UnusedClass',
164
+ filePath: '/test/src/service1.ts',
165
+ dependencies: [],
166
+ constructorParams: [],
167
+ interfaceName: undefined, // No interface
168
+ importPath: './service1',
169
+ scope: 'singleton'
170
+ },
171
+ {
172
+ name: 'AnotherUnusedClass',
173
+ filePath: '/test/src/service1.ts',
174
+ dependencies: [],
175
+ constructorParams: [],
176
+ interfaceName: undefined, // No interface and not used as dependency
177
+ importPath: './service1',
178
+ scope: 'singleton'
179
+ }
180
+ ];
181
+ mockFileDiscovery.findTypeScriptFiles.mockResolvedValue(mockFiles);
182
+ mockClassAnalyzer.analyzeFile.mockResolvedValueOnce(mockClasses);
183
+ const result = await projectAnalyzer.analyzeProject();
184
+ // Should include UserService (has interface) and UnusedClass (used as dependency)
185
+ // Should exclude AnotherUnusedClass (no interface and not used as dependency)
186
+ (0, vitest_1.expect)(result).toHaveLength(2);
187
+ (0, vitest_1.expect)(result.map(c => c.name)).toEqual(['UserService', 'UnusedClass']);
188
+ });
189
+ });
190
+ });
191
+ //# sourceMappingURL=project-analyzer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-analyzer.test.js","sourceRoot":"","sources":["../../../src/__tests__/analyser/project-analyzer.test.ts"],"names":[],"mappings":"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"}
@@ -5,5 +5,6 @@ export declare class ProjectAnalyzer {
5
5
  constructor(options: AnalyzerOptions);
6
6
  analyzeProject(): Promise<ClassInfo[]>;
7
7
  private filterClassesByDependencyUsage;
8
+ private validateUniqueInterfaceImplementations;
8
9
  }
9
10
  //# sourceMappingURL=project-analyzer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyser/project-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAKtD,qBAAa,eAAe;IAC1B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,OAAO,EAAE,eAAe;IAK9B,cAAc,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAgB5C,OAAO,CAAC,8BAA8B;CAuBvC"}
1
+ {"version":3,"file":"project-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyser/project-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAKtD,qBAAa,eAAe;IAC1B,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,aAAa,CAAgB;gBAEzB,OAAO,EAAE,eAAe;IAK9B,cAAc,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAmB5C,OAAO,CAAC,8BAA8B;IAwBtC,OAAO,CAAC,sCAAsC;CAgC/C"}
@@ -15,6 +15,8 @@ class ProjectAnalyzer {
15
15
  const allClasses = fileClassesArrays.flat();
16
16
  // Filter classes to only include those that are used as dependencies
17
17
  const filteredClasses = this.filterClassesByDependencyUsage(allClasses);
18
+ // Validate that no interface is implemented by multiple classes
19
+ this.validateUniqueInterfaceImplementations(filteredClasses);
18
20
  return filteredClasses;
19
21
  }
20
22
  filterClassesByDependencyUsage(classes) {
@@ -37,6 +39,33 @@ class ProjectAnalyzer {
37
39
  return allDependencies.has(classInfo.name);
38
40
  });
39
41
  }
42
+ validateUniqueInterfaceImplementations(classes) {
43
+ const interfaceToClassMap = new Map();
44
+ // Group classes by their interface names
45
+ for (const classInfo of classes) {
46
+ if (classInfo.interfaceName) {
47
+ if (!interfaceToClassMap.has(classInfo.interfaceName)) {
48
+ interfaceToClassMap.set(classInfo.interfaceName, []);
49
+ }
50
+ interfaceToClassMap.get(classInfo.interfaceName).push(classInfo);
51
+ }
52
+ }
53
+ // Check for duplicate implementations
54
+ const duplicateInterfaces = [];
55
+ for (const [interfaceName, implementingClasses] of interfaceToClassMap) {
56
+ if (implementingClasses.length > 1) {
57
+ duplicateInterfaces.push(interfaceName);
58
+ console.error(`Error: Interface '${interfaceName}' is implemented by multiple classes:`);
59
+ for (const classInfo of implementingClasses) {
60
+ console.error(` - ${classInfo.name} (${classInfo.filePath})`);
61
+ }
62
+ }
63
+ }
64
+ if (duplicateInterfaces.length > 0) {
65
+ throw new Error(`Multiple classes implement the same interface(s): ${duplicateInterfaces.join(', ')}. ` +
66
+ 'Each interface should only be implemented by one class for proper dependency injection.');
67
+ }
68
+ }
40
69
  }
41
70
  exports.ProjectAnalyzer = ProjectAnalyzer;
42
71
  //# sourceMappingURL=project-analyzer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"project-analyzer.js","sourceRoot":"","sources":["../../src/analyser/project-analyzer.ts"],"names":[],"mappings":";;;AACA,qDAAiD;AACjD,qDAAiD;AAGjD,MAAa,eAAe;IAI1B,YAAY,OAAwB;QAClC,IAAI,CAAC,aAAa,GAAG,IAAI,8BAAa,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;QACnF,IAAI,CAAC,aAAa,GAAG,IAAI,8BAAa,CAAC,OAAO,CAAC,SAAS,EAAE,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACtF,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,mBAAmB,EAAE,CAAC;QAE/D,MAAM,oBAAoB,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAClD,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,QAAQ,CAAC,CACzC,CAAC;QAEF,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClE,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,EAAE,CAAC;QAE5C,qEAAqE;QACrE,MAAM,eAAe,GAAG,IAAI,CAAC,8BAA8B,CAAC,UAAU,CAAC,CAAC;QAExE,OAAO,eAAe,CAAC;IACzB,CAAC;IAEO,8BAA8B,CAAC,OAAoB;QACzD,4CAA4C;QAC5C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;QAE1C,KAAK,MAAM,SAAS,IAAI,OAAO,EAAE,CAAC;YAChC,KAAK,MAAM,UAAU,IAAI,SAAS,CAAC,YAAY,EAAE,CAAC;gBAChD,eAAe,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QAED,kCAAkC;QAClC,mFAAmF;QACnF,+EAA+E;QAC/E,OAAO,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE;YAChC,yCAAyC;YACzC,IAAI,SAAS,CAAC,aAAa,EAAE,CAAC;gBAC5B,OAAO,IAAI,CAAC;YACd,CAAC;YAED,gFAAgF;YAChF,OAAO,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;IACL,CAAC;CACF;AAhDD,0CAgDC"}
1
+ {"version":3,"file":"project-analyzer.js","sourceRoot":"","sources":["../../src/analyser/project-analyzer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@notjustcoders/ioc-arise",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "A CLI tool to generate type-safe IoC containers for TypeScript projects with automatic dependency injection",
5
5
  "main": "dist/index.js",
6
6
  "bin": {