@@ -126,6 +126,36 @@ function getModuleRealName(resolved) {
126
126
return getFilePackageName ( resolved ) ;
127
127
}
128
128
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
+
129
159
function reportIfMissing ( context , deps , depsOptions , node , name ) {
130
160
// Do not report when importing types
131
161
if ( node . importKind === 'type' || ( node . parent && node . parent . importKind === 'type' ) || node . importKind === 'typeof' ) {
@@ -139,37 +169,49 @@ function reportIfMissing(context, deps, depsOptions, node, name) {
139
169
const resolved = resolve ( name , context ) ;
140
170
if ( ! resolved ) { return ; }
141
171
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 )
158
194
) {
159
195
return ;
160
196
}
161
197
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 ) ) ;
164
203
return ;
165
204
}
166
205
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 ) ) ;
169
211
return ;
170
212
}
171
213
172
- context . report ( node , missingErrorMessage ( packageName ) ) ;
214
+ context . report ( node , missingErrorMessage ( realPackageName ) ) ;
173
215
}
174
216
175
217
function testConfig ( config , filename ) {
0 commit comments