@@ -62,6 +62,13 @@ const createEventEmitter = () => {
6262 * Only exact declared versions ("1.2.3") are compared: a range ("^1.2.3"), a
6363 * file/workspace protocol or a tag cannot be checked without resolving what npm
6464 * would pick, which is way beyond what is needed here.
65+ *
66+ * A status carries a severity so that every consumer (server log, browser
67+ * overlay, reload on install) reads the same decision: a missing package or an
68+ * outdated runtime dependency is a "warning", the page is not running what the
69+ * project asks for. An outdated devDependency is only "info": the installed
70+ * version runs, what may differ is tooling, and that is worth a line in the
71+ * console, not a dialog nor a reload once installed.
6572 */
6673
6774
@@ -93,13 +100,14 @@ const readDependencyStatus = (
93100 if ( ! packageJSON ) {
94101 return null ;
95102 }
96- const declaredVersion = readDeclaredVersion ( packageJSON , packageName ) ;
97- if ( ! declaredVersion ) {
103+ const declaration = readDeclaration ( packageJSON , packageName ) ;
104+ if ( ! declaration ) {
98105 return null ;
99106 }
100107 return createStatus ( packageDirectory , {
101108 packageName,
102- declaredVersion,
109+ declaredVersion : declaration . version ,
110+ declaredIn : declaration . field ,
103111 declaringDirectoryUrl,
104112 declaredBy : packageJSON . name ,
105113 } ) ;
@@ -126,6 +134,7 @@ const readDependencyStatuses = (packageDirectory) => {
126134 createStatus ( packageDirectory , {
127135 packageName,
128136 declaredVersion : dependencies [ packageName ] ,
137+ declaredIn : field ,
129138 declaringDirectoryUrl : packageDirectory . url ,
130139 declaredBy : packageJSON . name ,
131140 } ) ,
@@ -137,17 +146,25 @@ const readDependencyStatuses = (packageDirectory) => {
137146
138147const createStatus = (
139148 packageDirectory ,
140- { packageName, declaredVersion, declaringDirectoryUrl, declaredBy } ,
149+ {
150+ packageName,
151+ declaredVersion,
152+ declaredIn,
153+ declaringDirectoryUrl,
154+ declaredBy,
155+ } ,
141156) => {
142157 const status = {
143158 packageName,
144159 declaredVersion,
160+ declaredIn,
145161 declaredBy,
146162 installedVersion : null ,
147163 // the file telling this dependency apart; it is what an install rewrites and
148164 // what the dev server looks at to know the dependency became the declared one
149165 watchedPath : null ,
150166 state : "missing" ,
167+ severity : "warning" ,
151168 } ;
152169 const installedDirectoryUrl = findInstalledDirectoryUrl (
153170 declaringDirectoryUrl ,
@@ -169,11 +186,16 @@ const createStatus = (
169186 status . installedVersion = installedPackageJSON
170187 ? installedPackageJSON . version
171188 : null ;
172- status . state =
173- isExactVersion ( declaredVersion ) &&
174- status . installedVersion !== declaredVersion
175- ? "outdated"
176- : "installed" ;
189+ if (
190+ ! isExactVersion ( declaredVersion ) ||
191+ status . installedVersion === declaredVersion
192+ ) {
193+ status . state = "installed" ;
194+ status . severity = null ;
195+ return status ;
196+ }
197+ status . state = "outdated" ;
198+ status . severity = declaredIn === "devDependencies" ? "info" : "warning" ;
177199 return status ;
178200} ;
179201
@@ -201,11 +223,11 @@ const findInstalledDirectoryUrl = (declaringDirectoryUrl, packageName) => {
201223 return null ;
202224} ;
203225
204- const readDeclaredVersion = ( packageJSON , packageName ) => {
226+ const readDeclaration = ( packageJSON , packageName ) => {
205227 for ( const field of DEPENDENCY_FIELDS ) {
206228 const dependencies = packageJSON [ field ] ;
207229 if ( dependencies && dependencies [ packageName ] ) {
208- return dependencies [ packageName ] ;
230+ return { field , version : dependencies [ packageName ] } ;
209231 }
210232 }
211233 return null ;
@@ -12152,15 +12174,29 @@ const startDevServer = async ({
1215212174 onChange : ( problems ) => {
1215312175 dependencyProblemEventEmitter . emit ( problems ) ;
1215412176 } ,
12155- onProblem : ( { packageName, declaredVersion, installedVersion, state } ) => {
12156- logger . warn (
12177+ onProblem : ( {
12178+ packageName,
12179+ declaredVersion,
12180+ installedVersion,
12181+ declaredIn,
12182+ state,
12183+ severity,
12184+ } ) => {
12185+ const message =
1215712186 state === "missing"
1215812187 ? `"${ packageName } @${ declaredVersion } " is declared in package.json but not installed, run npm install`
12159- : `"${ packageName } " is installed in ${ installedVersion } but package.json declares ${ declaredVersion } , run npm install` ,
12160- ) ;
12188+ : `"${ packageName } " is installed in ${ installedVersion } but package.json declares ${ declaredVersion } in ${ declaredIn } , run npm install` ;
12189+ if ( severity === "warning" ) {
12190+ logger . warn ( message ) ;
12191+ } else {
12192+ logger . info ( message ) ;
12193+ }
1216112194 } ,
12162- onInstalled : ( { packageName, declaredVersion } ) => {
12195+ onInstalled : ( { packageName, declaredVersion, severity } ) => {
1216312196 logger . info ( `"${ packageName } @${ declaredVersion } " is now installed` ) ;
12197+ if ( severity !== "warning" ) {
12198+ return ;
12199+ }
1216412200 reloadRequestEventEmitter . emit ( {
1216512201 cause : `${ packageName } @${ declaredVersion } installed` ,
1216612202 reason : `a dependency became available in node_modules` ,
0 commit comments