22 MIT License http://www.opensource.org/licenses/mit-license.php
33 Author Gajus Kuizinas @gajus
44*/
5- var webpackOptionsSchema = require ( "../schemas/webpackOptionsSchema.json" ) ;
5+ "use strict" ;
66
7- function WebpackOptionsValidationError ( validationErrors ) {
8- Error . call ( this ) ;
9- Error . captureStackTrace ( this , WebpackOptionsValidationError ) ;
10- this . name = "WebpackOptionsValidationError" ;
11- this . message = "Invalid configuration object. " +
12- "Webpack has been initialised using a configuration object that does not match the API schema.\n" +
13- validationErrors . map ( function ( err ) {
14- return " - " + indent ( WebpackOptionsValidationError . formatValidationError ( err ) , " " , false ) ;
15- } ) . join ( "\n" ) ;
16- this . validationErrors = validationErrors ;
7+ const webpackOptionsSchema = require ( "../schemas/webpackOptionsSchema.json" ) ;
8+
9+ const getSchemaPart = ( path , parents , additionalPath ) => {
10+ parents = parents || 0 ;
11+ path = path . split ( "/" ) ;
12+ path = path . slice ( 0 , path . length - parents ) ;
13+ if ( additionalPath ) {
14+ additionalPath = additionalPath . split ( "/" ) ;
15+ path = path . concat ( additionalPath ) ;
16+ }
17+ let schemaPart = webpackOptionsSchema ;
18+ for ( let i = 1 ; i < path . length ; i ++ ) {
19+ const inner = schemaPart [ path [ i ] ] ;
20+ if ( inner )
21+ schemaPart = inner ;
22+ }
23+ return schemaPart ;
1724}
18- module . exports = WebpackOptionsValidationError ;
1925
20- WebpackOptionsValidationError . prototype = Object . create ( Error . prototype ) ;
21- WebpackOptionsValidationError . prototype . constructor = WebpackOptionsValidationError ;
26+ const getSchemaPartText = ( schemaPart , additionalPath ) => {
27+ if ( additionalPath ) {
28+ for ( let i = 0 ; i < additionalPath . length ; i ++ ) {
29+ const inner = schemaPart [ additionalPath [ i ] ] ;
30+ if ( inner )
31+ schemaPart = inner ;
32+ }
33+ }
34+ while ( schemaPart . $ref ) schemaPart = getSchemaPart ( schemaPart . $ref ) ;
35+ let schemaText = WebpackOptionsValidationError . formatSchema ( schemaPart ) ;
36+ if ( schemaPart . description )
37+ schemaText += `\n${ schemaPart . description } ` ;
38+ return schemaText ;
39+ }
40+
41+ const indent = ( str , prefix , firstLine ) => {
42+ if ( firstLine ) {
43+ return prefix + str . replace ( / \n (? ! $ ) / g, "\n" + prefix ) ;
44+ } else {
45+ return str . replace ( / \n (? ! $ ) / g, `\n${ prefix } ` ) ;
46+ }
47+ }
48+
49+ class WebpackOptionsValidationError extends Error {
50+
51+ constructor ( validationErrors ) {
52+ super ( ) ;
53+
54+ if ( Error . hasOwnProperty ( "captureStackTrace" ) ) {
55+ Error . captureStackTrace ( this , this . constructor ) ;
56+ }
57+ this . name = "WebpackOptionsValidationError" ;
58+
59+ this . message = "Invalid configuration object. " +
60+ "Webpack has been initialised using a configuration object that does not match the API schema.\n" +
61+ validationErrors . map ( err => " - " + indent ( WebpackOptionsValidationError . formatValidationError ( err ) , " " , false ) ) . join ( "\n" ) ;
62+ this . validationErrors = validationErrors ;
63+ }
64+
65+ static formatSchema ( schema , prevSchemas ) {
66+ prevSchemas = prevSchemas || [ ] ;
67+
68+ const formatInnerSchema = ( innerSchema , addSelf ) => {
69+ if ( ! addSelf ) return WebpackOptionsValidationError . formatSchema ( innerSchema , prevSchemas ) ;
70+ if ( prevSchemas . indexOf ( innerSchema ) >= 0 ) return "(recursive)" ;
71+ return WebpackOptionsValidationError . formatSchema ( innerSchema , prevSchemas . concat ( schema ) ) ;
72+ }
73+
74+ if ( schema . type === "string" ) {
75+ if ( schema . minLength === 1 )
76+ return "non-empty string" ;
77+ else if ( schema . minLength > 1 )
78+ return `string (min length ${ schema . minLength } )` ;
79+ return "string" ;
80+ } else if ( schema . type === "boolean" ) {
81+ return "boolean" ;
82+ } else if ( schema . type === "number" ) {
83+ return "number" ;
84+ } else if ( schema . type === "object" ) {
85+ if ( schema . properties ) {
86+ const required = schema . required || [ ] ;
87+ return `object { ${ Object . keys ( schema . properties ) . map ( property => {
88+ if ( required . indexOf ( property ) < 0 ) return property + "?" ;
89+ return property ;
90+ } ) . concat ( schema . additionalProperties ? [ "..." ] : [ ] ) . join ( ", " ) } }`;
91+ }
92+ if ( schema . additionalProperties ) {
93+ return `object { <key>: ${ formatInnerSchema ( schema . additionalProperties ) } }` ;
94+ }
95+ return "object" ;
96+ } else if ( schema . type === "array" ) {
97+ return `[${ formatInnerSchema ( schema . items ) } ]` ;
98+ }
99+
100+ switch ( schema . instanceof ) {
101+ case "Function" :
102+ return "function" ;
103+ case "RegExp" :
104+ return "RegExp" ;
105+ }
106+ if ( schema . $ref ) return formatInnerSchema ( getSchemaPart ( schema . $ref ) , true ) ;
107+ if ( schema . allOf ) return schema . allOf . map ( formatInnerSchema ) . join ( " & " ) ;
108+ if ( schema . oneOf ) return schema . oneOf . map ( formatInnerSchema ) . join ( " | " ) ;
109+ if ( schema . anyOf ) return schema . anyOf . map ( formatInnerSchema ) . join ( " | " ) ;
110+ if ( schema . enum ) return schema . enum . map ( item => JSON . stringify ( item ) ) . join ( " | " ) ;
111+ return JSON . stringify ( schema , 0 , 2 ) ;
112+ }
22113
23- WebpackOptionsValidationError . formatValidationError = function formatValidationError ( err ) {
24- var dataPath = "configuration" + err . dataPath ;
25- switch ( err . keyword ) {
26- case "additionalProperties" :
27- var baseMessage = dataPath + " has an unknown property '" + err . params . additionalProperty + "'. These properties are valid:\n" +
28- getSchemaPartText ( err . parentSchema ) ;
114+ static formatValidationError ( err ) {
115+ const dataPath = `configuration${ err . dataPath } ` ;
116+ if ( err . keyword === "additionalProperties" ) {
117+ const baseMessage = `${ dataPath } has an unknown property '${ err . params . additionalProperty } '. These properties are valid:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
29118 if ( ! err . dataPath ) {
30119 switch ( err . params . additionalProperty ) {
31120 case "debug" :
32- return baseMessage + "\n" +
121+ return ` ${ baseMessage } \n` +
33122 "The 'debug' property was removed in webpack 2.\n" +
34123 "Loaders should be updated to allow passing this option via loader options in module.rules.\n" +
35124 "Until loaders are updated one can use the LoaderOptionsPlugin to switch loaders into debug mode:\n" +
@@ -48,153 +137,55 @@ WebpackOptionsValidationError.formatValidationError = function formatValidationE
48137 " new webpack.LoaderOptionsPlugin({\n" +
49138 " // test: /\\.xxx$/, // may apply this only for some modules\n" +
50139 " options: {\n" +
51- " " + err . params . additionalProperty + " : ...\n" +
140+ ` ${ err . params . additionalProperty } : ...\n` +
52141 " }\n" +
53142 " })\n" +
54143 " ]" ;
55144 }
56145 return baseMessage ;
57- case "oneOf" :
58- case "anyOf" :
146+ } else if ( err . keyword === "oneOf" || err . keyword === "anyOf" ) {
59147 if ( err . children && err . children . length > 0 ) {
60- return dataPath + " should be one of these:\n" +
61- getSchemaPartText ( err . parentSchema ) + "\nDetails:\n" + err . children . map ( function ( err ) {
62- return " * " + indent ( WebpackOptionsValidationError . formatValidationError ( err ) , " " , false ) ;
63- } ) . join ( "\n" )
148+ return `${ dataPath } should be one of these:\n${ getSchemaPartText ( err . parentSchema ) } \n` +
149+ `Details:\n${ err . children . map ( err => " * " + indent ( WebpackOptionsValidationError . formatValidationError ( err ) , " " , false ) ) . join ( "\n" ) } `
64150 }
65- return dataPath + " should be one of these:\n" +
66- getSchemaPartText ( err . parentSchema ) ;
67- case "enum" :
151+ return ` ${ dataPath } should be one of these:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
152+
153+ } else if ( err . keyword === "enum" ) {
68154 if ( err . parentSchema && err . parentSchema . enum && err . parentSchema . enum . length === 1 ) {
69- return dataPath + " should be " + getSchemaPartText ( err . parentSchema ) ;
155+ return ` ${ dataPath } should be ${ getSchemaPartText ( err . parentSchema ) } ` ;
70156 }
71- return dataPath + " should be one of these:\n" +
72- getSchemaPartText ( err . parentSchema ) ;
73- case "allOf" :
74- return dataPath + " should be:\n" +
75- getSchemaPartText ( err . parentSchema ) ;
76- case "type" :
157+ return `${ dataPath } should be one of these:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
158+ } else if ( err . keyword === "allOf" ) {
159+ return `${ dataPath } should be:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
160+ } else if ( err . keyword === "type" ) {
77161 switch ( err . params . type ) {
78162 case "object" :
79- return dataPath + " should be an object." ;
163+ return ` ${ dataPath } should be an object.` ;
80164 case "string" :
81- return dataPath + " should be a string." ;
165+ return ` ${ dataPath } should be a string.` ;
82166 case "boolean" :
83- return dataPath + " should be a boolean." ;
167+ return ` ${ dataPath } should be a boolean.` ;
84168 case "number" :
85- return dataPath + " should be a number." ;
169+ return ` ${ dataPath } should be a number.` ;
86170 case "array" :
87- return dataPath + " should be an array:\n" +
88- getSchemaPartText ( err . parentSchema ) ;
171+ return `${ dataPath } should be an array:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
89172 }
90- return dataPath + " should be " + err . params . type + ":\n" +
91- getSchemaPartText ( err . parentSchema ) ;
92- case "instanceof" :
93- return dataPath + " should be an instance of " + getSchemaPartText ( err . parentSchema ) + "." ;
94- case "required" :
95- var missingProperty = err . params . missingProperty . replace ( / ^ \. / , "" ) ;
96- return dataPath + " misses the property '" + missingProperty + "'.\n" +
97- getSchemaPartText ( err . parentSchema , [ "properties" , missingProperty ] ) ;
98- case "minItems" :
99- case "minLength" :
173+ return `${ dataPath } should be ${ err . params . type } :\n${ getSchemaPartText ( err . parentSchema ) } ` ;
174+ } else if ( err . keyword === "instanceof" ) {
175+ return `${ dataPath } should be an instance of ${ getSchemaPartText ( err . parentSchema ) } .` ;
176+ } else if ( err . keyword === "required" ) {
177+ const missingProperty = err . params . missingProperty . replace ( / ^ \. / , "" ) ;
178+ return `${ dataPath } misses the property '${ missingProperty } '.\n${ getSchemaPartText ( err . parentSchema , [ "properties" , missingProperty ] ) } ` ;
179+ } else if ( err . keyword === "minLength" || err . keyword === "minItems" ) {
100180 if ( err . params . limit === 1 )
101- return dataPath + " should not be empty." ;
181+ return ` ${ dataPath } should not be empty.` ;
102182 else
103- return dataPath + " " + err . message ;
104- default : // eslint-disable-line no-fallthrough
105- return dataPath + " " + err . message + " (" + JSON . stringify ( err , 0 , 2 ) + ").\n" +
106- getSchemaPartText ( err . parentSchema ) ;
107- }
108- }
109-
110- function getSchemaPart ( path , parents , additionalPath ) {
111- parents = parents || 0 ;
112- path = path . split ( "/" ) ;
113- path = path . slice ( 0 , path . length - parents ) ;
114- if ( additionalPath ) {
115- additionalPath = additionalPath . split ( "/" ) ;
116- path = path . concat ( additionalPath ) ;
117- }
118- var schemaPart = webpackOptionsSchema ;
119- for ( var i = 1 ; i < path . length ; i ++ ) {
120- var inner = schemaPart [ path [ i ] ] ;
121- if ( inner )
122- schemaPart = inner ;
123- }
124- return schemaPart ;
125- }
126-
127- function getSchemaPartText ( schemaPart , additionalPath ) {
128- if ( additionalPath ) {
129- for ( var i = 0 ; i < additionalPath . length ; i ++ ) {
130- var inner = schemaPart [ additionalPath [ i ] ] ;
131- if ( inner )
132- schemaPart = inner ;
183+ return `${ dataPath } ${ err . message } ` ;
184+ } else {
185+ // eslint-disable-line no-fallthrough
186+ return `${ dataPath } ${ err . message } (${ JSON . stringify ( err , 0 , 2 ) } ).\n${ getSchemaPartText ( err . parentSchema ) } ` ;
133187 }
134188 }
135- while ( schemaPart . $ref ) schemaPart = getSchemaPart ( schemaPart . $ref ) ;
136- var schemaText = WebpackOptionsValidationError . formatSchema ( schemaPart ) ;
137- if ( schemaPart . description )
138- schemaText += "\n" + schemaPart . description ;
139- return schemaText ;
140- }
141-
142- function formatSchema ( schema , prevSchemas ) {
143- prevSchemas = prevSchemas || [ ] ;
144-
145- function formatInnerSchema ( innerSchema , addSelf ) {
146- if ( ! addSelf ) return formatSchema ( innerSchema , prevSchemas ) ;
147- if ( prevSchemas . indexOf ( innerSchema ) >= 0 ) return "(recursive)" ;
148- return formatSchema ( innerSchema , prevSchemas . concat ( schema ) ) ;
149- }
150- switch ( schema . type ) {
151- case "string" :
152- if ( schema . minLength === 1 )
153- return "non-empty string" ;
154- else if ( schema . minLength > 1 )
155- return "string (min length " + schema . minLength + ")" ;
156- return "string" ;
157- case "boolean" :
158- return "boolean" ;
159- case "number" :
160- return "number" ;
161- case "object" :
162- if ( schema . properties ) {
163- var required = schema . required || [ ] ;
164- return "object { " + Object . keys ( schema . properties ) . map ( function ( property ) {
165- if ( required . indexOf ( property ) < 0 ) return property + "?" ;
166- return property ;
167- } ) . concat ( schema . additionalProperties ? [ "..." ] : [ ] ) . join ( ", " ) + " }" ;
168- }
169- if ( schema . additionalProperties ) {
170- return "object { <key>: " + formatInnerSchema ( schema . additionalProperties ) + " }" ;
171- }
172- return "object" ;
173- case "array" :
174- return "[" + formatInnerSchema ( schema . items ) + "]" ;
175- }
176- switch ( schema . instanceof ) {
177- case "Function" :
178- return "function" ;
179- case "RegExp" :
180- return "RegExp" ;
181- }
182- if ( schema . $ref ) return formatInnerSchema ( getSchemaPart ( schema . $ref ) , true ) ;
183- if ( schema . allOf ) return schema . allOf . map ( formatInnerSchema ) . join ( " & " ) ;
184- if ( schema . oneOf ) return schema . oneOf . map ( formatInnerSchema ) . join ( " | " ) ;
185- if ( schema . anyOf ) return schema . anyOf . map ( formatInnerSchema ) . join ( " | " ) ;
186- if ( schema . enum ) return schema . enum . map ( function ( item ) {
187- return JSON . stringify ( item ) ;
188- } ) . join ( " | " ) ;
189- return JSON . stringify ( schema , 0 , 2 ) ;
190189}
191190
192- function indent ( str , prefix , firstLine ) {
193- if ( firstLine ) {
194- return prefix + str . replace ( / \n (? ! $ ) / g, "\n" + prefix ) ;
195- } else {
196- return str . replace ( / \n (? ! $ ) / g, "\n" + prefix ) ;
197- }
198- }
199-
200- WebpackOptionsValidationError . formatSchema = formatSchema ;
191+ module . exports = WebpackOptionsValidationError ;
0 commit comments