Skip to content

Commit f40e816

Browse files
committed
refactor: remove all any types and fix TypeScript strict mode compliance
- Replace ALL 'any' types with proper TypeScript types across codebase - Add proper interfaces for complex data structures - Use 'unknown' type with type guards for truly unknown data - Fix all ESLint errors and warnings - Improve type safety in test fixtures and utility files - Add proper type assertions where needed - Fix import statements for vitest in test files - Resolve all TypeScript strict mode compilation errors All files now pass ESLint with zero errors and TypeScript strict mode
1 parent 07fa607 commit f40e816

14 files changed

+321
-180
lines changed

src/modules/build/services/collection/collection.service.claude-code.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@ import * as path from 'node:path';
88

99
import { Test, TestingModule } from '@nestjs/testing';
1010

11-
import { describe, it, expect, beforeEach, vi } from 'vitest';
11+
import { beforeEach, describe, expect, it, vi } from 'vitest';
1212

1313
import { CollectionService } from './collection.service';
1414

1515
import type {
1616
ClaudeCodeLocalSettingsData,
1717
ClaudeCodeGlobalSettingsData,
18-
McpServerConfig
18+
McpServerConfig,
1919
} from '../../interfaces/claude-code.interfaces';
2020

2121
// Mock os module

src/modules/build/services/transformation/transformation.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,7 @@ export class TransformationService {
389389
DataProcessingErrorHandler.logErrorResult(errorResult);
390390

391391
// Return partial data if available, otherwise empty object
392-
return errorResult.partialData || {};
392+
return (errorResult.partialData as ParsedData) || ({} as ParsedData);
393393
}
394394
}
395395

src/modules/build/test-fixtures/advanced-error-scenarios.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ export class ErrorScenarioFactory {
445445
return new AdvancedMockFileSystem(
446446
{
447447
files: Object.fromEntries(Array.from({ length: 100 }, (_, i) => [`/file${i}.txt`, `content ${i}`])
448-
.map(( [path, content]) => [path, content])),
448+
.map(([path, content]) => [path, content])),
449449
directories: ['/'],
450450
},
451451
{ concurrentOperationLimit: 3 }
@@ -569,7 +569,7 @@ export class ErrorScenarioTestUtilities {
569569
* Test that a function properly handles and retries on EAGAIN errors
570570
*/
571571
static async testRetryOnEAGAIN(
572-
operation: () => Promise<any>,
572+
operation: () => Promise<unknown>,
573573
maxRetries = 3
574574
): Promise<{ success: boolean; attempts: number; error?: Error }> {
575575
let attempts = 0;
@@ -580,14 +580,15 @@ export class ErrorScenarioTestUtilities {
580580
// eslint-disable-next-line no-await-in-loop
581581
await operation();
582582
return { success: true, attempts };
583-
} catch (error: any) {
584-
if (error.code === 'EAGAIN' && i < maxRetries) {
583+
} catch (error: unknown) {
584+
const err = error as { code?: string };
585+
if (err.code === 'EAGAIN' && i < maxRetries) {
585586
// Wait before retry
586587
// eslint-disable-next-line no-await-in-loop
587588
await new Promise(resolve => setTimeout(resolve, Math.pow(2, i) * 100));
588589
continue;
589590
}
590-
return { success: false, attempts, error };
591+
return { success: false, attempts, error: error as Error };
591592
}
592593
}
593594

@@ -598,16 +599,17 @@ export class ErrorScenarioTestUtilities {
598599
* Test that a function properly handles disk space errors
599600
*/
600601
static async testDiskSpaceHandling(
601-
writeOperation: () => Promise<any>
602+
writeOperation: () => Promise<unknown>
602603
): Promise<{ handledCorrectly: boolean; errorType?: string }> {
603604
try {
604605
await writeOperation();
605606
return { handledCorrectly: false }; // Should have failed
606-
} catch (error: any) {
607-
const isDiskSpaceError = error.code === 'ENOSPC' || error.code === 'EFBIG';
607+
} catch (error: unknown) {
608+
const err = error as { code?: string };
609+
const isDiskSpaceError = err.code === 'ENOSPC' || err.code === 'EFBIG';
608610
return {
609611
handledCorrectly: isDiskSpaceError,
610-
errorType: error.code
612+
errorType: err.code
611613
};
612614
}
613615
}
@@ -616,7 +618,7 @@ export class ErrorScenarioTestUtilities {
616618
* Test concurrent operation limits
617619
*/
618620
static async testConcurrencyLimits(
619-
operations: (() => Promise<any>)[],
621+
operations: (() => Promise<unknown>)[],
620622
_expectedFailures = 0
621623
): Promise<{ successes: number; failures: number; errors: Error[] }> {
622624
const results = await Promise.allSettled(
@@ -627,7 +629,7 @@ export class ErrorScenarioTestUtilities {
627629
const failures = results.filter(r => r.status === 'rejected').length;
628630
const errors = results
629631
.filter((r): r is PromiseRejectedResult => r.status === 'rejected')
630-
.map(r => r.reason);
632+
.map(r => r.reason as Error);
631633

632634
return { successes, failures, errors };
633635
}
@@ -636,7 +638,7 @@ export class ErrorScenarioTestUtilities {
636638
* Performance benchmark for file operations
637639
*/
638640
static async benchmarkOperation(
639-
operation: () => Promise<any>,
641+
operation: () => Promise<unknown>,
640642
iterations = 10
641643
): Promise<{
642644
averageTime: number;

src/modules/build/test-fixtures/mock-file-system.ts

Lines changed: 46 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,25 @@
33
* Mock file system utilities for testing with advanced error scenarios
44
*/
55

6+
/**
7+
* File system error with code property
8+
*/
9+
interface FileSystemError extends Error {
10+
code: string;
11+
}
12+
13+
/**
14+
* File system stats interface
15+
*/
16+
export interface MockFileStats {
17+
isDirectory(): boolean;
18+
isFile(): boolean;
19+
size: number;
20+
}
21+
22+
/**
23+
* Mock file system configuration
24+
*/
625
export interface MockFileSystemConfig {
726
files: Record<string, string>;
827
directories: string[];
@@ -51,15 +70,19 @@ export class MockFileSystem {
5170
// Check permissions
5271
const perms = this.permissions.get(filePath);
5372
if (perms && !perms.readable) {
54-
const error = new Error(`EACCES: permission denied, open '${filePath}'`);
55-
(error as any).code = 'EACCES';
73+
const error: FileSystemError = Object.assign(
74+
new Error(`EACCES: permission denied, open '${filePath}'`),
75+
{ code: 'EACCES' }
76+
);
5677
throw error;
5778
}
5879

5980
// Check if file exists
6081
if (!this.files.has(filePath)) {
61-
const error = new Error(`ENOENT: no such file or directory, open '${filePath}'`);
62-
(error as any).code = 'ENOENT';
82+
const error: FileSystemError = Object.assign(
83+
new Error(`ENOENT: no such file or directory, open '${filePath}'`),
84+
{ code: 'ENOENT' }
85+
);
6386
throw error;
6487
}
6588

@@ -75,8 +98,10 @@ export class MockFileSystem {
7598
// Check permissions
7699
const perms = this.permissions.get(filePath);
77100
if (perms && !perms.writable) {
78-
const error = new Error(`EACCES: permission denied, open '${filePath}'`);
79-
(error as any).code = 'EACCES';
101+
const error: FileSystemError = Object.assign(
102+
new Error(`EACCES: permission denied, open '${filePath}'`),
103+
{ code: 'EACCES' }
104+
);
80105
throw error;
81106
}
82107

@@ -91,14 +116,17 @@ export class MockFileSystem {
91116

92117
// Check if directory exists
93118
if (!this.directories.has(directoryPath)) {
94-
const error = new Error(`ENOENT: no such file or directory, scandir '${directoryPath}'`);
95-
(error as any).code = 'ENOENT';
119+
const error: FileSystemError = Object.assign(
120+
new Error(`ENOENT: no such file or directory, scandir '${directoryPath}'`),
121+
{ code: 'ENOENT' }
122+
);
96123
throw error;
97124
}
98125

99126
// Return files in directory
100127
const filesInDirectory: string[] = [];
101-
for (const filePath of this.files.keys()) {
128+
const filePathsArray = Array.from(this.files.keys());
129+
for (const filePath of filePathsArray) {
102130
if (filePath.startsWith(`${directoryPath }/`)) {
103131
const relativePath = filePath.slice(Math.max(0, directoryPath.length + 1));
104132
if (!relativePath.includes('/')) {
@@ -119,8 +147,10 @@ export class MockFileSystem {
119147
// Check permissions
120148
const perms = this.permissions.get(directoryPath);
121149
if (perms && !perms.writable) {
122-
const error = new Error(`EACCES: permission denied, mkdir '${directoryPath}'`);
123-
(error as any).code = 'EACCES';
150+
const error: FileSystemError = Object.assign(
151+
new Error(`EACCES: permission denied, mkdir '${directoryPath}'`),
152+
{ code: 'EACCES' }
153+
);
124154
throw error;
125155
}
126156

@@ -139,7 +169,7 @@ export class MockFileSystem {
139169
}
140170
}
141171

142-
async stat(filePath: string): Promise<{ isDirectory(): boolean; isFile(): boolean; size: number }> {
172+
async stat(filePath: string): Promise<MockFileStats> {
143173
// Check for errors first
144174
if (this.errors.has(filePath)) {
145175
throw this.errors.get(filePath);
@@ -162,8 +192,10 @@ export class MockFileSystem {
162192
};
163193
}
164194

165-
const error = new Error(`ENOENT: no such file or directory, stat '${filePath}'`);
166-
(error as any).code = 'ENOENT';
195+
const error: FileSystemError = Object.assign(
196+
new Error(`ENOENT: no such file or directory, stat '${filePath}'`),
197+
{ code: 'ENOENT' }
198+
);
167199
throw error;
168200
}
169201

0 commit comments

Comments
 (0)