@@ -126,6 +126,36 @@ function getModuleRealName(resolved) {
126126 return getFilePackageName ( resolved ) ;
127127}
128128
129+ function checkDependencyDeclaration ( deps , packageName ) {
130+ // in case of sub package.json inside a module
131+ // check the dependencies on all hierarchy
132+ const packageHierarchy = [ ] ;
133+ const packageNameParts = packageName . split ( '/' ) ;
134+ packageNameParts . forEach ( ( namePart , index ) => {
135+ if ( ! namePart . startsWith ( '@' ) ) {
136+ const ancestor = packageNameParts . slice ( 0 , index + 1 ) . join ( '/' ) ;
137+ packageHierarchy . push ( ancestor ) ;
138+ }
139+ } ) ;
140+
141+ return packageHierarchy . reduce ( ( result , ancestorName ) => {
142+ return {
143+ isInDeps : result . isInDeps || deps . dependencies [ ancestorName ] !== undefined ,
144+ isInDevDeps : result . isInDevDeps || deps . devDependencies [ ancestorName ] !== undefined ,
145+ isInOptDeps : result . isInOptDeps || deps . optionalDependencies [ ancestorName ] !== undefined ,
146+ isInPeerDeps : result . isInPeerDeps || deps . peerDependencies [ ancestorName ] !== undefined ,
147+ isInBundledDeps :
148+ result . isInBundledDeps || deps . bundledDependencies . indexOf ( ancestorName ) !== - 1 ,
149+ } ;
150+ } , {
151+ isInDeps : false ,
152+ isInDevDeps : false ,
153+ isInOptDeps : false ,
154+ isInPeerDeps : false ,
155+ isInBundledDeps : false ,
156+ } ) ;
157+ }
158+
129159function reportIfMissing ( context , deps , depsOptions , node , name ) {
130160 // Do not report when importing types
131161 if ( node . importKind === 'type' || ( node . parent && node . parent . importKind === 'type' ) || node . importKind === 'typeof' ) {
@@ -139,37 +169,49 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
139169 const resolved = resolve ( name , context ) ;
140170 if ( ! resolved ) { return ; }
141171
142- // get the real name from the resolved package.json
143- // if not aliased imports (alias/react for example) will not be correctly interpreted
144- // fallback on original name in case no package.json found
145- const packageName = getModuleRealName ( resolved ) || getModuleOriginalName ( name ) ;
146-
147- const isInDeps = deps . dependencies [ packageName ] !== undefined ;
148- const isInDevDeps = deps . devDependencies [ packageName ] !== undefined ;
149- const isInOptDeps = deps . optionalDependencies [ packageName ] !== undefined ;
150- const isInPeerDeps = deps . peerDependencies [ packageName ] !== undefined ;
151- const isInBundledDeps = deps . bundledDependencies . indexOf ( packageName ) !== - 1 ;
152-
153- if ( isInDeps ||
154- ( depsOptions . allowDevDeps && isInDevDeps ) ||
155- ( depsOptions . allowPeerDeps && isInPeerDeps ) ||
156- ( depsOptions . allowOptDeps && isInOptDeps ) ||
157- ( depsOptions . allowBundledDeps && isInBundledDeps )
172+ const importPackageName = getModuleOriginalName ( name ) ;
173+ const importPackageNameDeclaration = checkDependencyDeclaration ( deps , importPackageName ) ;
174+
175+ if ( importPackageNameDeclaration . isInDeps ||
176+ ( depsOptions . allowDevDeps && importPackageNameDeclaration . isInDevDeps ) ||
177+ ( depsOptions . allowPeerDeps && importPackageNameDeclaration . isInPeerDeps ) ||
178+ ( depsOptions . allowOptDeps && importPackageNameDeclaration . isInOptDeps ) ||
179+ ( depsOptions . allowBundledDeps && importPackageNameDeclaration . isInBundledDeps )
180+ ) {
181+ return ;
182+ }
183+
184+ // test the real name from the resolved package.json
185+ // if not aliased imports (alias/react for example), importPackageName can be misinterpreted
186+ const realPackageName = getModuleRealName ( resolved ) ;
187+ const realPackageNameDeclaration = checkDependencyDeclaration ( deps , realPackageName ) ;
188+
189+ if ( realPackageNameDeclaration . isInDeps ||
190+ ( depsOptions . allowDevDeps && realPackageNameDeclaration . isInDevDeps ) ||
191+ ( depsOptions . allowPeerDeps && realPackageNameDeclaration . isInPeerDeps ) ||
192+ ( depsOptions . allowOptDeps && realPackageNameDeclaration . isInOptDeps ) ||
193+ ( depsOptions . allowBundledDeps && realPackageNameDeclaration . isInBundledDeps )
158194 ) {
159195 return ;
160196 }
161197
162- if ( isInDevDeps && ! depsOptions . allowDevDeps ) {
163- context . report ( node , devDepErrorMessage ( packageName ) ) ;
198+ if ( (
199+ importPackageNameDeclaration . isInDevDeps ||
200+ realPackageNameDeclaration . isInDevDeps
201+ ) && ! depsOptions . allowDevDeps ) {
202+ context . report ( node , devDepErrorMessage ( realPackageName ) ) ;
164203 return ;
165204 }
166205
167- if ( isInOptDeps && ! depsOptions . allowOptDeps ) {
168- context . report ( node , optDepErrorMessage ( packageName ) ) ;
206+ if ( (
207+ importPackageNameDeclaration . isInOptDeps ||
208+ realPackageNameDeclaration . isInOptDeps
209+ ) && ! depsOptions . allowOptDeps ) {
210+ context . report ( node , optDepErrorMessage ( realPackageName ) ) ;
169211 return ;
170212 }
171213
172- context . report ( node , missingErrorMessage ( packageName ) ) ;
214+ context . report ( node , missingErrorMessage ( realPackageName ) ) ;
173215}
174216
175217function testConfig ( config , filename ) {
0 commit comments