2
2
3
3
const optionsSchema = require ( "./optionsSchema.json" ) ;
4
4
5
- function OptionsValidationError ( validationErrors ) {
6
- Error . call ( this ) ;
7
- Error . captureStackTrace ( this , OptionsValidationError ) ;
8
- this . name = "WebpackDevServerOptionsValidationError" ;
9
- this . message = `${ "Invalid configuration object. " +
10
- "webpack-dev-server has been initialised using a configuration object that does not match the API schema.\n" } ${
11
- validationErrors . map ( function ( err ) {
12
- return ` - ${ indent ( OptionsValidationError . formatValidationError ( err ) , " " , false ) } ` ;
13
- } ) . join ( "\n" ) } `;
14
- this . validationErrors = validationErrors ;
15
- }
16
- module . exports = OptionsValidationError ;
17
-
18
- OptionsValidationError . prototype = Object . create ( Error . prototype ) ;
19
- OptionsValidationError . prototype . constructor = OptionsValidationError ;
20
-
21
- OptionsValidationError . formatValidationError = function formatValidationError ( err ) {
22
- const dataPath = `configuration${ err . dataPath } ` ;
23
- switch ( err . keyword ) {
24
- case "additionalProperties" :
25
- return `${ dataPath } has an unknown property '${ err . params . additionalProperty } '. These properties are valid:\n${
26
- getSchemaPartText ( err . parentSchema ) } `;
27
- case "oneOf" :
28
- case "anyOf" :
29
- case "enum" :
30
- return `${ dataPath } should be one of these:\n${
31
- getSchemaPartText ( err . parentSchema ) } `;
32
- case "allOf" :
33
- return `${ dataPath } should be:\n${
34
- getSchemaPartText ( err . parentSchema ) } `;
35
- case "type" :
36
- switch ( err . params . type ) {
37
- case "object" :
38
- return `${ dataPath } should be an object.` ;
39
- case "array" :
40
- return `${ dataPath } should be an array.` ;
41
- case "string" :
42
- return `${ dataPath } should be a string.` ;
43
- case "boolean" :
44
- return `${ dataPath } should be a boolean.` ;
45
- case "number" :
46
- return `${ dataPath } should be a number.` ;
47
- }
48
- return `${ dataPath } should be ${ err . params . type } :\n${
49
- getSchemaPartText ( err . parentSchema ) } `;
50
- case "instanceof" :
51
- return `${ dataPath } should be an instance of ${ getSchemaPartText ( err . parentSchema ) } .` ;
52
- case "required" : // eslint-disable-line no-case-declarations
53
- const missingProperty = err . params . missingProperty . replace ( / ^ \. / , "" ) ;
54
- return `${ dataPath } misses the property '${ missingProperty } '.\n${
55
- getSchemaPartText ( err . parentSchema , [ "properties" , missingProperty ] ) } `;
56
- case "minLength" :
57
- if ( err . params . limit === 1 )
58
- return `${ dataPath } should not be empty.` ;
59
- else
60
- return `${ dataPath } ${ err . message } ` ;
61
- default :
62
- return `${ dataPath } ${ err . message } (${ JSON . stringify ( err , 0 , 2 ) } ).\n${
63
- getSchemaPartText ( err . parentSchema ) } `;
64
- }
65
- }
66
-
67
- function getSchemaPart ( path , parents , additionalPath ) {
5
+ const getSchemaPart = ( path , parents , additionalPath ) => {
68
6
parents = parents || 0 ;
69
7
path = path . split ( "/" ) ;
70
8
path = path . slice ( 0 , path . length - parents ) ;
@@ -79,9 +17,9 @@ function getSchemaPart(path, parents, additionalPath) {
79
17
schemaPart = inner ;
80
18
}
81
19
return schemaPart ;
82
- }
20
+ } ;
83
21
84
- function getSchemaPartText ( schemaPart , additionalPath ) {
22
+ const getSchemaPartText = ( schemaPart , additionalPath ) => {
85
23
if ( additionalPath ) {
86
24
for ( let i = 0 ; i < additionalPath . length ; i ++ ) {
87
25
const inner = schemaPart [ additionalPath [ i ] ] ;
@@ -94,60 +32,128 @@ function getSchemaPartText(schemaPart, additionalPath) {
94
32
if ( schemaPart . description )
95
33
schemaText += `\n${ schemaPart . description } ` ;
96
34
return schemaText ;
97
- }
35
+ } ;
98
36
99
- function formatSchema ( schema , prevSchemas ) {
100
- prevSchemas = prevSchemas || [ ] ;
37
+ const indent = ( str , prefix , firstLine ) => {
38
+ if ( firstLine ) {
39
+ return prefix + str . replace ( / \n (? ! $ ) / g, "\n" + prefix ) ;
40
+ } else {
41
+ return str . replace ( / \n (? ! $ ) / g, `\n${ prefix } ` ) ;
42
+ }
43
+ } ;
44
+
45
+ class OptionsValidationError extends Error {
46
+
47
+ constructor ( validationErrors ) {
48
+ super ( ) ;
49
+
50
+ if ( Error . hasOwnProperty ( "captureStackTrace" ) ) {
51
+ Error . captureStackTrace ( this , this . constructor ) ;
52
+ }
53
+ this . name = "WebpackDevServerOptionsValidationError" ;
101
54
102
- function formatInnerSchema ( innerSchema , addSelf ) {
103
- if ( ! addSelf ) return formatSchema ( innerSchema , prevSchemas ) ;
104
- if ( prevSchemas . indexOf ( innerSchema ) >= 0 ) return "(recursive)" ;
105
- return formatSchema ( innerSchema , prevSchemas . concat ( schema ) ) ;
55
+ this . message = "Invalid configuration object. " +
56
+ "webpack-dev-server has been initialised using a configuration object that does not match the API schema.\n" +
57
+ validationErrors . map ( err => " - " + indent ( OptionsValidationError . formatValidationError ( err ) , " " , false ) ) . join ( "\n" ) ;
58
+ this . validationErrors = validationErrors ;
106
59
}
107
- switch ( schema . type ) {
108
- case "string" :
60
+
61
+ static formatSchema ( schema , prevSchemas ) {
62
+ prevSchemas = prevSchemas || [ ] ;
63
+
64
+ const formatInnerSchema = ( innerSchema , addSelf ) => {
65
+ if ( ! addSelf ) return OptionsValidationError . formatSchema ( innerSchema , prevSchemas ) ;
66
+ if ( prevSchemas . indexOf ( innerSchema ) >= 0 ) return "(recursive)" ;
67
+ return OptionsValidationError . formatSchema ( innerSchema , prevSchemas . concat ( schema ) ) ;
68
+ } ;
69
+
70
+ if ( schema . type === "string" ) {
71
+ if ( schema . minLength === 1 )
72
+ return "non-empty string" ;
73
+ else if ( schema . minLength > 1 )
74
+ return `string (min length ${ schema . minLength } )` ;
109
75
return "string" ;
110
- case "boolean" :
76
+ } else if ( schema . type === "boolean" ) {
111
77
return "boolean" ;
112
- case "number" :
78
+ } else if ( schema . type === "number" ) {
113
79
return "number" ;
114
- case "object" :
80
+ } else if ( schema . type === "object" ) {
115
81
if ( schema . properties ) {
116
82
const required = schema . required || [ ] ;
117
- return `object { ${ Object . keys ( schema . properties ) . map ( function ( property ) {
118
- if ( required . indexOf ( property ) < 0 ) return ` ${ property } ?` ;
83
+ return `object { ${ Object . keys ( schema . properties ) . map ( property => {
84
+ if ( required . indexOf ( property ) < 0 ) return property + "?" ;
119
85
return property ;
120
86
} ) . concat ( schema . additionalProperties ? [ "..." ] : [ ] ) . join ( ", " ) } }`;
121
87
}
122
88
if ( schema . additionalProperties ) {
123
89
return `object { <key>: ${ formatInnerSchema ( schema . additionalProperties ) } }` ;
124
90
}
125
91
return "object" ;
126
- case "array" :
92
+ } else if ( schema . type === "array" ) {
127
93
return `[${ formatInnerSchema ( schema . items ) } ]` ;
94
+ }
95
+
96
+ switch ( schema . instanceof ) {
97
+ case "Function" :
98
+ return "function" ;
99
+ case "RegExp" :
100
+ return "RegExp" ;
101
+ }
102
+ if ( schema . $ref ) return formatInnerSchema ( getSchemaPart ( schema . $ref ) , true ) ;
103
+ if ( schema . allOf ) return schema . allOf . map ( formatInnerSchema ) . join ( " & " ) ;
104
+ if ( schema . oneOf ) return schema . oneOf . map ( formatInnerSchema ) . join ( " | " ) ;
105
+ if ( schema . anyOf ) return schema . anyOf . map ( formatInnerSchema ) . join ( " | " ) ;
106
+ if ( schema . enum ) return schema . enum . map ( item => JSON . stringify ( item ) ) . join ( " | " ) ;
107
+ return JSON . stringify ( schema , 0 , 2 ) ;
128
108
}
129
- switch ( schema . instanceof ) {
130
- case "Function" :
131
- return "function" ;
132
- case "RegExp" :
133
- return "RegExp" ;
134
- }
135
- if ( schema . $ref ) return formatInnerSchema ( getSchemaPart ( schema . $ref ) , true ) ;
136
- if ( schema . allOf ) return schema . allOf . map ( formatInnerSchema ) . join ( " & " ) ;
137
- if ( schema . oneOf ) return schema . oneOf . map ( formatInnerSchema ) . join ( " | " ) ;
138
- if ( schema . anyOf ) return schema . anyOf . map ( formatInnerSchema ) . join ( " | " ) ;
139
- if ( schema . enum ) return schema . enum . map ( function ( item ) {
140
- return JSON . stringify ( item ) ;
141
- } ) . join ( " | " ) ;
142
- return JSON . stringify ( schema , 0 , 2 ) ;
143
- }
144
109
145
- function indent ( str , prefix , firstLine ) {
146
- if ( firstLine ) {
147
- return prefix + str . replace ( / \n (? ! $ ) / g, `\n${ prefix } ` ) ;
148
- } else {
149
- return str . replace ( / \n (? ! $ ) / g, `\n${ prefix } ` ) ;
110
+ static formatValidationError ( err ) {
111
+ const dataPath = `configuration${ err . dataPath } ` ;
112
+ if ( err . keyword === "additionalProperties" ) {
113
+ return `${ dataPath } has an unknown property '${ err . params . additionalProperty } '. These properties are valid:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
114
+ } else if ( err . keyword === "oneOf" || err . keyword === "anyOf" ) {
115
+ if ( err . children && err . children . length > 0 ) {
116
+ return `${ dataPath } should be one of these:\n${ getSchemaPartText ( err . parentSchema ) } \n` +
117
+ `Details:\n${ err . children . map ( err => " * " + indent ( OptionsValidationError . formatValidationError ( err ) , " " , false ) ) . join ( "\n" ) } ` ;
118
+ }
119
+ return `${ dataPath } should be one of these:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
120
+
121
+ } else if ( err . keyword === "enum" ) {
122
+ if ( err . parentSchema && err . parentSchema . enum && err . parentSchema . enum . length === 1 ) {
123
+ return `${ dataPath } should be ${ getSchemaPartText ( err . parentSchema ) } ` ;
124
+ }
125
+ return `${ dataPath } should be one of these:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
126
+ } else if ( err . keyword === "allOf" ) {
127
+ return `${ dataPath } should be:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
128
+ } else if ( err . keyword === "type" ) {
129
+ switch ( err . params . type ) {
130
+ case "object" :
131
+ return `${ dataPath } should be an object.` ;
132
+ case "string" :
133
+ return `${ dataPath } should be a string.` ;
134
+ case "boolean" :
135
+ return `${ dataPath } should be a boolean.` ;
136
+ case "number" :
137
+ return `${ dataPath } should be a number.` ;
138
+ case "array" :
139
+ return `${ dataPath } should be an array:\n${ getSchemaPartText ( err . parentSchema ) } ` ;
140
+ }
141
+ return `${ dataPath } should be ${ err . params . type } :\n${ getSchemaPartText ( err . parentSchema ) } ` ;
142
+ } else if ( err . keyword === "instanceof" ) {
143
+ return `${ dataPath } should be an instance of ${ getSchemaPartText ( err . parentSchema ) } .` ;
144
+ } else if ( err . keyword === "required" ) {
145
+ const missingProperty = err . params . missingProperty . replace ( / ^ \. / , "" ) ;
146
+ return `${ dataPath } misses the property '${ missingProperty } '.\n${ getSchemaPartText ( err . parentSchema , [ "properties" , missingProperty ] ) } ` ;
147
+ } else if ( err . keyword === "minLength" || err . keyword === "minItems" ) {
148
+ if ( err . params . limit === 1 )
149
+ return `${ dataPath } should not be empty.` ;
150
+ else
151
+ return `${ dataPath } ${ err . message } ` ;
152
+ } else {
153
+ // eslint-disable-line no-fallthrough
154
+ return `${ dataPath } ${ err . message } (${ JSON . stringify ( err , 0 , 2 ) } ).\n${ getSchemaPartText ( err . parentSchema ) } ` ;
155
+ }
150
156
}
151
157
}
152
158
153
- OptionsValidationError . formatSchema = formatSchema ;
159
+ module . exports = OptionsValidationError ;
0 commit comments