@@ -30,19 +30,20 @@ export function getCombinedMetas() {
3030 return combinedMetas ;
3131}
3232
33- function normalize ( depName : string , files : MetaFiles , fileObject : Meta = { } ) {
33+ function normalize (
34+ depName : string ,
35+ files : MetaFiles ,
36+ fileObject : Meta = { } ,
37+ rootPath : string
38+ ) {
3439 for ( let i = 0 ; i < files . length ; i += 1 ) {
3540 if ( files [ i ] . type === 'file' ) {
36- const absolutePath = pathUtils . join (
37- '/node_modules' ,
38- depName ,
39- files [ i ] . path
40- ) ;
41+ const absolutePath = pathUtils . join ( rootPath , files [ i ] . path ) ;
4142 fileObject [ absolutePath ] = true ; // eslint-disable-line no-param-reassign
4243 }
4344
4445 if ( files [ i ] . files ) {
45- normalize ( depName , files [ i ] . files , fileObject ) ;
46+ normalize ( depName , files [ i ] . files , fileObject , rootPath ) ;
4647 }
4748 }
4849
@@ -57,12 +58,7 @@ function getMeta(name: string, version: string) {
5758
5859 metas [ id ] = window
5960 . fetch ( `https://unpkg.com/${ name } @${ version } /?meta` )
60- . then ( x => x . json ( ) )
61- . then ( metaInfo => normalize ( name , metaInfo . files ) )
62- . then ( normalizedMetas => {
63- combinedMetas = { ...combinedMetas , ...normalizedMetas } ;
64- return normalizedMetas ;
65- } ) ;
61+ . then ( x => x . json ( ) ) ;
6662
6763 return metas [ id ] ;
6864}
@@ -73,7 +69,9 @@ function downloadDependency(depName: string, depVersion: string, path: string) {
7369 }
7470
7571 const relativePath = path . replace (
76- pathUtils . join ( '/node_modules' , depName ) ,
72+ new RegExp (
73+ `.*${ pathUtils . join ( '/node_modules' , depName ) } ` . replace ( '/' , '\\/' )
74+ ) ,
7775 ''
7876 ) ;
7977
@@ -99,42 +97,13 @@ function downloadDependency(depName: string, depVersion: string, path: string) {
9997 return packages [ path ] ;
10098}
10199
102- function findDependencyVersion ( manifest : Manifest , dependencyName : string ) {
103- let version = null ;
104-
105- if ( manifest . dependencyDependencies [ dependencyName ] ) {
106- version = manifest . dependencyDependencies [ dependencyName ] . resolved ;
107- } else {
108- const dep = manifest . dependencies . find ( m => m . name === dependencyName ) ;
109-
110- if ( dep ) {
111- version = dep . version ;
112- }
113- }
114-
115- if ( version ) {
116- return version ;
117- }
118-
119- return null ;
120- }
121-
122- export default async function fetchModule (
100+ function resolvePath (
123101 path : string ,
124102 currentPath : string ,
125103 manager : Manager ,
126- defaultExtensions : Array < string > = [ 'js' , 'jsx' , 'json' ]
127- ) : Promise < Module > {
128- const dependencyName = getDependencyName ( path ) ;
129-
130- const version = findDependencyVersion ( manager . manifest , dependencyName ) ;
131-
132- if ( ! version ) {
133- throw new DependencyNotFoundError ( path ) ;
134- }
135-
136- const meta = await getMeta ( dependencyName , version ) ;
137-
104+ defaultExtensions : Array < string > = [ 'js' , 'jsx' , 'json' ] ,
105+ meta = { }
106+ ) : Promise < string > {
138107 return new Promise ( ( res , reject ) => {
139108 resolve (
140109 path ,
@@ -145,22 +114,42 @@ export default async function fetchModule(
145114 'node_modules' ,
146115 manager . envVariables . NODE_PATH ,
147116 ] . filter ( x => x ) ,
148- isFile : ( p , c ) => c ( null , ! ! manager . transpiledModules [ p ] || ! ! meta [ p ] ) ,
117+ isFile : ( p , c , cb ) => {
118+ const callback = cb || c ;
119+
120+ callback ( null , ! ! manager . transpiledModules [ p ] || ! ! meta [ p ] ) ;
121+ } ,
149122 readFile : async ( p , c , cb ) => {
150123 const callback = cb || c ;
124+
151125 if ( manager . transpiledModules [ p ] ) {
152126 return callback ( null , manager . transpiledModules [ p ] . module . code ) ;
153127 }
154128
155129 const depPath = p . replace ( '/node_modules/' , '' ) ;
156130 const depName = getDependencyName ( depPath ) ;
157131
158- const subDepVersion = findDependencyVersion (
159- manager . manifest ,
132+ // We don't try to download package.json, because we can assume that
133+ // all package.json files have been included in the bundle sent by
134+ // the packager.
135+ if ( depPath . endsWith ( 'package.json' ) ) {
136+ const err = new Error ( 'Could not find ' + p ) ;
137+ err . code = 'ENOENT' ;
138+
139+ callback ( err ) ;
140+ return null ;
141+ }
142+
143+ // eslint-disable-next-line
144+ const subDepVersionVersionInfo = await findDependencyVersion (
145+ currentPath ,
146+ manager ,
147+ defaultExtensions ,
160148 depName
161149 ) ;
162150
163- if ( subDepVersion ) {
151+ if ( subDepVersionVersionInfo ) {
152+ const { version : subDepVersion } = subDepVersionVersionInfo ;
164153 try {
165154 const module = await downloadDependency (
166155 depName ,
@@ -192,16 +181,107 @@ export default async function fetchModule(
192181 return reject ( err ) ;
193182 }
194183
195- if ( resolvedPath === '//empty.js' ) {
196- return res ( {
197- path : '//empty.js' ,
198- code : 'module.exports = {};' ,
199- requires : [ ] ,
200- } ) ;
201- }
202-
203- return res ( downloadDependency ( dependencyName , version , resolvedPath ) ) ;
184+ return res ( resolvedPath ) ;
204185 }
205186 ) ;
206187 } ) ;
207188}
189+
190+ async function findDependencyVersion (
191+ currentPath : string ,
192+ manager : Manager ,
193+ defaultExtensions : Array < string > = [ 'js' , 'jsx' , 'json' ] ,
194+ dependencyName : string
195+ ) {
196+ const manifest = manager . manifest ;
197+
198+ try {
199+ const foundPackageJSONPath = await resolvePath (
200+ pathUtils . join ( dependencyName , 'package.json' ) ,
201+ currentPath ,
202+ manager ,
203+ defaultExtensions
204+ ) ;
205+
206+ const packageJSON =
207+ manager . transpiledModules [ foundPackageJSONPath ] &&
208+ manager . transpiledModules [ foundPackageJSONPath ] . module . code ;
209+ const { version } = JSON . parse ( packageJSON ) ;
210+
211+ if ( packageJSON !== '//empty.js' ) {
212+ return { packageJSONPath : foundPackageJSONPath , version } ;
213+ }
214+ } catch ( e ) {
215+ /* do nothing */
216+ }
217+
218+ let version = null ;
219+
220+ if ( manifest . dependencyDependencies [ dependencyName ] ) {
221+ version = manifest . dependencyDependencies [ dependencyName ] . resolved ;
222+ } else {
223+ const dep = manifest . dependencies . find ( m => m . name === dependencyName ) ;
224+
225+ if ( dep ) {
226+ version = dep . version ;
227+ }
228+ }
229+
230+ if ( version ) {
231+ return { packageJSONPath : null , version } ;
232+ }
233+
234+ return null ;
235+ }
236+
237+ export default async function fetchModule (
238+ path : string ,
239+ currentPath : string ,
240+ manager : Manager ,
241+ defaultExtensions : Array < string > = [ 'js' , 'jsx' , 'json' ]
242+ ) : Promise < Module > {
243+ const dependencyName = getDependencyName ( path ) ;
244+
245+ const versionInfo = await findDependencyVersion (
246+ currentPath ,
247+ manager ,
248+ defaultExtensions ,
249+ dependencyName
250+ ) ;
251+
252+ if ( ! versionInfo ) {
253+ throw new DependencyNotFoundError ( path ) ;
254+ }
255+
256+ const { packageJSONPath , version } = versionInfo ;
257+
258+ const meta = await getMeta ( dependencyName , version ) ;
259+
260+ const normalizedMeta = normalize (
261+ dependencyName ,
262+ meta . files ,
263+ { } ,
264+ packageJSONPath
265+ ? pathUtils . dirname ( packageJSONPath )
266+ : pathUtils . join ( '/node_modules' , dependencyName )
267+ ) ;
268+ combinedMetas = { ...combinedMetas , ...normalizedMeta } ;
269+
270+ const foundPath = await resolvePath (
271+ path ,
272+ currentPath ,
273+ manager ,
274+ defaultExtensions ,
275+ normalizedMeta
276+ ) ;
277+
278+ if ( foundPath === '//empty.js' ) {
279+ return {
280+ path : '/ / empty . js ',
281+ code : 'module.exports = {};' ,
282+ requires : [ ] ,
283+ } ;
284+ }
285+
286+ return downloadDependency ( dependencyName , version , foundPath ) ;
287+ }
0 commit comments