1
- import { ResourceProtocol } from "../resources/BaseResource.js" ;
2
- import { join , dirname } from "path" ;
3
- import { promises as fs } from "fs" ;
4
- import { logger } from "../core/Logger.js" ;
1
+ import { ResourceProtocol } from '../resources/BaseResource.js' ;
2
+ import { join , dirname } from 'path' ;
3
+ import { promises as fs } from 'fs' ;
4
+ import { logger } from '../core/Logger.js' ;
5
+ import { discoverFilesRecursively , hasValidFiles } from '../utils/fileDiscovery.js' ;
5
6
6
7
export class ResourceLoader {
7
8
private readonly RESOURCES_DIR : string ;
8
- private readonly EXCLUDED_FILES = [
9
- "BaseResource.js" ,
10
- "*.test.js" ,
11
- "*.spec.js" ,
12
- ] ;
9
+ private readonly EXCLUDED_FILES = [ 'BaseResource.js' , '*.test.js' , '*.spec.js' ] ;
13
10
14
11
constructor ( basePath ?: string ) {
15
- const mainModulePath = basePath || process . argv [ 1 ] ;
16
- this . RESOURCES_DIR = join ( dirname ( mainModulePath ) , "resources" ) ;
17
- logger . debug (
18
- `Initialized ResourceLoader with directory: ${ this . RESOURCES_DIR } `
19
- ) ;
12
+ if ( basePath ) {
13
+ // If basePath is provided, it should be the directory containing the resources folder
14
+ this . RESOURCES_DIR = join ( basePath , 'resources' ) ;
15
+ } else {
16
+ // For backwards compatibility, use the old behavior with process.argv[1]
17
+ const mainModulePath = process . argv [ 1 ] ;
18
+ this . RESOURCES_DIR = join ( dirname ( mainModulePath ) , 'resources' ) ;
19
+ }
20
+ logger . debug ( `Initialized ResourceLoader with directory: ${ this . RESOURCES_DIR } ` ) ;
20
21
}
21
22
22
23
async hasResources ( ) : Promise < boolean > {
23
24
try {
24
- const stats = await fs . stat ( this . RESOURCES_DIR ) ;
25
- if ( ! stats . isDirectory ( ) ) {
26
- logger . debug ( "Resources path exists but is not a directory" ) ;
27
- return false ;
28
- }
29
-
30
- const files = await fs . readdir ( this . RESOURCES_DIR ) ;
31
- const hasValidFiles = files . some ( ( file ) => this . isResourceFile ( file ) ) ;
32
- logger . debug ( `Resources directory has valid files: ${ hasValidFiles } ` ) ;
33
- return hasValidFiles ;
25
+ return await hasValidFiles ( this . RESOURCES_DIR , {
26
+ extensions : [ '.js' ] ,
27
+ excludePatterns : this . EXCLUDED_FILES ,
28
+ } ) ;
34
29
} catch ( error ) {
35
30
logger . debug ( `No resources directory found: ${ ( error as Error ) . message } ` ) ;
36
31
return false ;
37
32
}
38
33
}
39
34
40
- private isResourceFile ( file : string ) : boolean {
41
- if ( ! file . endsWith ( ".js" ) ) return false ;
42
- const isExcluded = this . EXCLUDED_FILES . some ( ( pattern ) => {
43
- if ( pattern . includes ( "*" ) ) {
44
- const regex = new RegExp ( pattern . replace ( "*" , ".*" ) ) ;
45
- return regex . test ( file ) ;
46
- }
47
- return file === pattern ;
48
- } ) ;
49
-
50
- logger . debug (
51
- `Checking file ${ file } : ${ isExcluded ? "excluded" : "included" } `
52
- ) ;
53
- return ! isExcluded ;
54
- }
55
-
56
35
private validateResource ( resource : any ) : resource is ResourceProtocol {
57
36
const isValid = Boolean (
58
37
resource &&
59
- typeof resource . uri === " string" &&
60
- typeof resource . name === " string" &&
38
+ typeof resource . uri === ' string' &&
39
+ typeof resource . name === ' string' &&
61
40
resource . resourceDefinition &&
62
- typeof resource . read === " function"
41
+ typeof resource . read === ' function'
63
42
) ;
64
43
65
44
if ( isValid ) {
@@ -75,29 +54,21 @@ export class ResourceLoader {
75
54
try {
76
55
logger . debug ( `Attempting to load resources from: ${ this . RESOURCES_DIR } ` ) ;
77
56
78
- let stats ;
79
- try {
80
- stats = await fs . stat ( this . RESOURCES_DIR ) ;
81
- } catch ( error ) {
82
- logger . debug ( `No resources directory found: ${ ( error as Error ) . message } ` ) ;
83
- return [ ] ;
84
- }
57
+ const resourceFiles = await discoverFilesRecursively ( this . RESOURCES_DIR , {
58
+ extensions : [ '.js' ] ,
59
+ excludePatterns : this . EXCLUDED_FILES ,
60
+ } ) ;
85
61
86
- if ( ! stats . isDirectory ( ) ) {
87
- logger . error ( `Path is not a directory: ${ this . RESOURCES_DIR } ` ) ;
62
+ if ( resourceFiles . length === 0 ) {
63
+ logger . debug ( 'No resource files found' ) ;
88
64
return [ ] ;
89
65
}
90
66
91
- const files = await fs . readdir ( this . RESOURCES_DIR ) ;
92
- logger . debug ( `Found files in directory: ${ files . join ( ", " ) } ` ) ;
67
+ logger . debug ( `Found resource files: ${ resourceFiles . join ( ', ' ) } ` ) ;
93
68
94
69
const resources : ResourceProtocol [ ] = [ ] ;
95
70
96
- for ( const file of files ) {
97
- if ( ! this . isResourceFile ( file ) ) {
98
- continue ;
99
- }
100
-
71
+ for ( const file of resourceFiles ) {
101
72
try {
102
73
const fullPath = join ( this . RESOURCES_DIR , file ) ;
103
74
logger . debug ( `Attempting to load resource from: ${ fullPath } ` ) ;
@@ -120,9 +91,7 @@ export class ResourceLoader {
120
91
}
121
92
122
93
logger . debug (
123
- `Successfully loaded ${ resources . length } resources: ${ resources
124
- . map ( ( r ) => r . name )
125
- . join ( ", " ) } `
94
+ `Successfully loaded ${ resources . length } resources: ${ resources . map ( ( r ) => r . name ) . join ( ', ' ) } `
126
95
) ;
127
96
return resources ;
128
97
} catch ( error ) {
0 commit comments