@@ -11,6 +11,7 @@ import {
1111 AstAnalyser ,
1212 DefaultCollectableSet ,
1313 warnings ,
14+ TsSourceParser ,
1415 type AstAnalyserOptions
1516} from "@nodesecure/js-x-ray" ;
1617
@@ -31,6 +32,14 @@ export interface ScannedFilesResult {
3132 code : SourceCodeReport ;
3233}
3334
35+ export interface NpmTarballScanFilesOptions {
36+ /**
37+ * List of files and directories to exclude from the scan.
38+ * Support glob patterns (e.g., "node_modules/**", "dist/**")
39+ */
40+ exclude ?: string [ ] ;
41+ }
42+
3443export type NpmTarballOptions = {
3544 resolver ?: Resolver ;
3645} ;
@@ -58,8 +67,11 @@ export class NpmTarball {
5867 }
5968
6069 async scanFiles (
61- astAnalyserOptions ?: AstAnalyserOptions
70+ astAnalyserOptions ?: AstAnalyserOptions ,
71+ options : NpmTarballScanFilesOptions = { }
6272 ) : Promise < ScannedFilesResult > {
73+ const { exclude = [ ] } = options ;
74+
6375 const location = this . manifest . location ;
6476 const [
6577 composition ,
@@ -74,17 +86,21 @@ export class NpmTarball {
7486 code = new SourceCodeReport ( ) ;
7587 }
7688 else {
77- const options = this . #optionsWithHostnameSet( astAnalyserOptions ?? { } ) ;
89+ const options = this . #optionsWithHostnameSet(
90+ astAnalyserOptions ?? { }
91+ ) ;
7892
79- const hostNameSet = options ?. collectables ?. find ( ( collectable ) => collectable . type === "hostname" ) ! ;
93+ const hostNameSet = options ?. collectables ?. find (
94+ ( collectable ) => collectable . type === "hostname"
95+ ) ! ;
8096
8197 const astAnalyser = new AstAnalyser ( options ) ;
8298
8399 code = await new SourceCodeScanner ( this . manifest , { astAnalyser } ) . iterate ( {
84100 manifest : [ ...this . manifest . getEntryFiles ( ) ]
85- . flatMap ( filterJavaScriptFiles ( ) ) ,
101+ . flatMap ( filterJavaScriptFiles ( exclude ) ) ,
86102 javascript : composition . files
87- . flatMap ( filterJavaScriptFiles ( ) )
103+ . flatMap ( filterJavaScriptFiles ( exclude ) )
88104 } ) ;
89105
90106 if ( hostNameSet instanceof DefaultCollectableSet ) {
@@ -117,19 +133,46 @@ export class NpmTarball {
117133 } ;
118134 }
119135
120- #optionsWithHostnameSet( options : AstAnalyserOptions ) : AstAnalyserOptions {
121- const hasHostnameSet = options ?. collectables ?. some ( ( collectable ) => collectable . type === "hostname" ) ;
136+ #optionsWithHostnameSet(
137+ options : AstAnalyserOptions
138+ ) : AstAnalyserOptions {
139+ const hasHostnameSet = options ?. collectables ?. some (
140+ ( collectable ) => collectable . type === "hostname"
141+ ) ;
122142 if ( hasHostnameSet ) {
123143 return options ;
124144 }
125145
126- return { ...options , collectables : [ ...options . collectables ?? [ ] , new DefaultCollectableSet ( "hostname" ) ] } ;
146+ return {
147+ ...options ,
148+ collectables : [
149+ ...options . collectables ?? [ ] ,
150+ new DefaultCollectableSet ( "hostname" )
151+ ]
152+ } ;
127153 }
128154}
129155
130- function filterJavaScriptFiles ( ) {
156+ function filterJavaScriptFiles (
157+ exclude : string [ ] = [ ]
158+ ) {
131159 return ( file : string ) => {
132- if ( NpmTarball . JS_EXTENSIONS . has ( path . extname ( file ) ) ) {
160+ // Exclude .d.ts files
161+ if ( file . includes ( "d.ts" ) ) {
162+ return [ ] ;
163+ }
164+
165+ // Exclude files matching any glob pattern
166+ if ( exclude . some ( ( pattern ) => path . matchesGlob ( file , pattern ) ) ) {
167+ return [ ] ;
168+ }
169+
170+ const fileExt = path . extname ( file ) ;
171+
172+ if ( NpmTarball . JS_EXTENSIONS . has ( fileExt ) ) {
173+ return file ;
174+ }
175+ if ( TsSourceParser . FileExtensions . has ( fileExt ) ) {
133176 return file ;
134177 }
135178
0 commit comments