@@ -120,8 +120,9 @@ const defaults: Config = {
120120 exclude : [ ]
121121}
122122
123- const isString = ( str : unknown ) : str is string =>
124- typeof str === 'string' && str . length > 0
123+ // Helpers.
124+ const isString = ( str : unknown ) : str is string => typeof str === 'string' && str . length > 0
125+ const fileExists = ( name : string ) => fs . stat ( name ) . then ( stat => stat . isFile ( ) ) . catch ( ( ) => false )
125126
126127/**
127128 * A Rollup/Vite plugin that automatically declares NodeJS built-in modules,
@@ -131,21 +132,20 @@ function nodeExternals(options: ExternalsOptions = {}): Plugin {
131132
132133 const config : Config = { ...defaults , ...options }
133134
134- let include : RegExp [ ] = [ ] , // Initialized to empty arrays as a workaround
135- exclude : RegExp [ ] = [ ] // to https://github.com/Septh/rollup-plugin-node-externals/issues/ 30
135+ let include : RegExp [ ] = [ ] , // Initialized to empty arrays
136+ exclude : RegExp [ ] = [ ] // as a workaround to issue # 30
136137
137138 const isIncluded = ( id : string ) => include . length > 0 && include . some ( rx => rx . test ( id ) ) ,
138139 isExcluded = ( id : string ) => exclude . length > 0 && exclude . some ( rx => rx . test ( id ) )
139140
140141 // Determine the root of the git repository, if any.
141142 //
142- // Note: it looks like Vite doesn't support async plugin factories
143- // (see https://github.com/Septh/rollup-plugin-node-externals/issues/37
144- // and https://github.com/vitejs/vite/issues/20717), so we don't await
145- // the result here but rather inside the buildStart hook.
146- const gitTopLevel = new Promise < string | null > ( resolve => {
143+ // Note: we can't await the promise here because this would require our factory function
144+ // to be async and that would break the old Vite compatibility trick
145+ // (see issue #37 and https://github.com/vitejs/vite/issues/20717).
146+ const gitTopLevel = new Promise < string > ( resolve => {
147147 cp . execFile ( 'git' , [ 'rev-parse' , '--show-toplevel' ] , ( error , stdout ) => {
148- return resolve ( error ? null : path . normalize ( stdout . trim ( ) ) )
148+ resolve ( error ? '' : path . normalize ( stdout . trim ( ) ) )
149149 } )
150150 } )
151151
@@ -178,65 +178,56 @@ function nodeExternals(options: ExternalsOptions = {}): Plugin {
178178 . concat ( config . packagePath )
179179 . filter ( isString )
180180 . map ( packagePath => path . resolve ( packagePath ) )
181-
182181 if ( packagePaths . length === 0 ) {
183- search:
184182 for ( let current = process . cwd ( ) , previous = '' ; previous !== current ; previous = current , current = path . dirname ( current ) ) {
185183
186184 // Gather package.json files.
187- let name = path . join ( current , 'package.json' )
188- if ( await fs . stat ( name ) . then ( stat => stat . isFile ( ) ) . catch ( ( ) => false ) )
185+ const name = path . join ( current , 'package.json' )
186+ if ( await fileExists ( name ) )
189187 packagePaths . push ( name )
190188
191- // Break early if we are at the root of a git repo.
192- if ( current === await gitTopLevel )
193- break
189+ // Break early if we are at the root of the git repo
190+ // or there is a known workspace root file.
191+ const breaks = await Promise . all ( [
192+ gitTopLevel . then ( topLevel => topLevel === current ) ,
193+ ...workspaceRootFiles . map ( name => fileExists ( path . join ( current , name ) ) )
194+ ] )
194195
195- // Break early is there is a known workspace root file.
196- for ( name of workspaceRootFiles ) {
197- if ( await fs . stat ( path . join ( current , name ) ) . then ( stat => stat . isFile ( ) ) . catch ( ( ) => false ) )
198- break search
199- }
196+ if ( breaks . some ( result => result ) )
197+ break
200198 }
201199 }
202200
203201 // Gather dependencies names.
204- const dependencies : Record < string , string > = { }
202+ const externals : Record < string , string > = { }
205203 for ( const packagePath of packagePaths ) {
206- const buffer = await fs . readFile ( packagePath ) . catch ( ( err : NodeJS . ErrnoException ) => err )
207- if ( buffer instanceof Error ) {
208- return this . error ( {
209- message : `Cannot read file ${ packagePath } , error: ${ buffer . code } .` ,
210- stack : undefined
211- } )
204+ const manifest = await fs . readFile ( packagePath )
205+ . then ( buffer => JSON . parse ( buffer . toString ( ) ) as PackageJson )
206+ . catch ( ( err : NodeJS . ErrnoException | SyntaxError ) => err )
207+ if ( manifest instanceof Error ) {
208+ const message = manifest instanceof SyntaxError
209+ ? `File ${ JSON . stringify ( packagePath ) } does not look like a valid package.json.`
210+ : `Cannot read ${ JSON . stringify ( packagePath ) } , error: ${ manifest . code } .`
211+ return this . error ( { message, stack : undefined } )
212212 }
213213
214- try {
215- const pkg = JSON . parse ( buffer . toString ( ) ) as PackageJson
216- Object . assign ( dependencies ,
217- config . deps ? pkg . dependencies : undefined ,
218- config . devDeps ? pkg . devDependencies : undefined ,
219- config . peerDeps ? pkg . peerDependencies : undefined ,
220- config . optDeps ? pkg . optionalDependencies : undefined
221- )
214+ Object . assign ( externals ,
215+ config . deps ? manifest . dependencies : undefined ,
216+ config . devDeps ? manifest . devDependencies : undefined ,
217+ config . peerDeps ? manifest . peerDependencies : undefined ,
218+ config . optDeps ? manifest . optionalDependencies : undefined
219+ )
222220
223- // Watch this package.json
224- this . addWatchFile ( packagePath )
221+ // Watch this package.json.
222+ this . addWatchFile ( packagePath )
225223
226- // Break early if this is an npm/yarn workspace root.
227- if ( Array . isArray ( pkg . workspaces ) )
228- break
229- }
230- catch {
231- this . error ( {
232- message : `File ${ JSON . stringify ( packagePath ) } does not look like a valid package.json file.` ,
233- stack : undefined
234- } )
235- }
224+ // Break early if this is an npm/yarn workspace root.
225+ if ( Array . isArray ( manifest . workspaces ) )
226+ break
236227 }
237228
238229 // Add all dependencies as an include RegEx.
239- const names = Object . keys ( dependencies )
230+ const names = Object . keys ( externals )
240231 if ( names . length > 0 )
241232 include . push ( new RegExp ( '^(?:' + names . join ( '|' ) + ')(?:/.+)?$' ) )
242233 } ,
0 commit comments