@@ -24,6 +24,7 @@ export type Rewrite = {
2424 basePath ?: false
2525 locale ?: false
2626 has ?: RouteHas [ ]
27+ missing ?: RouteHas [ ]
2728}
2829
2930export type Header = {
@@ -32,6 +33,7 @@ export type Header = {
3233 locale ?: false
3334 headers : Array < { key : string ; value : string } >
3435 has ?: RouteHas [ ]
36+ missing ?: RouteHas [ ]
3537}
3638
3739// internal type used for validation (not user facing)
@@ -41,6 +43,7 @@ export type Redirect = {
4143 basePath ?: false
4244 locale ?: false
4345 has ?: RouteHas [ ]
46+ missing ?: RouteHas [ ]
4447} & (
4548 | {
4649 statusCode ?: never
@@ -56,6 +59,7 @@ export type Middleware = {
5659 source : string
5760 locale ?: false
5861 has ?: RouteHas [ ]
62+ missing ?: RouteHas [ ]
5963}
6064
6165const allowedHasTypes = new Set ( [ 'header' , 'cookie' , 'query' , 'host' ] )
@@ -132,8 +136,9 @@ export function checkCustomRoutes(
132136 let numInvalidRoutes = 0
133137 let hadInvalidStatus = false
134138 let hadInvalidHas = false
139+ let hadInvalidMissing = false
135140
136- const allowedKeys = new Set < string > ( [ 'source' , 'locale' , 'has' ] )
141+ const allowedKeys = new Set < string > ( [ 'source' , 'locale' , 'has' , 'missing' ] )
137142
138143 if ( type === 'rewrite' ) {
139144 allowedKeys . add ( 'basePath' )
@@ -198,48 +203,65 @@ export function checkCustomRoutes(
198203 invalidParts . push ( '`locale` must be undefined or false' )
199204 }
200205
201- if ( typeof route . has !== 'undefined' && ! Array . isArray ( route . has ) ) {
202- invalidParts . push ( '`has` must be undefined or valid has object' )
203- hadInvalidHas = true
204- } else if ( route . has ) {
205- const invalidHasItems = [ ]
206+ const checkInvalidHasMissing = (
207+ items : any ,
208+ fieldName : 'has' | 'missing'
209+ ) => {
210+ let hadInvalidItem = false
206211
207- for ( const hasItem of route . has ) {
208- let invalidHasParts = [ ]
212+ if ( typeof items !== 'undefined' && ! Array . isArray ( items ) ) {
213+ invalidParts . push (
214+ `\`${ fieldName } \` must be undefined or valid has object`
215+ )
216+ hadInvalidItem = true
217+ } else if ( items ) {
218+ const invalidHasItems = [ ]
209219
210- if ( ! allowedHasTypes . has ( hasItem . type ) ) {
211- invalidHasParts . push ( `invalid type "${ hasItem . type } "` )
212- }
213- if ( typeof hasItem . key !== 'string' && hasItem . type !== 'host' ) {
214- invalidHasParts . push ( `invalid key "${ hasItem . key } "` )
215- }
216- if (
217- typeof hasItem . value !== 'undefined' &&
218- typeof hasItem . value !== 'string'
219- ) {
220- invalidHasParts . push ( `invalid value "${ hasItem . value } "` )
221- }
222- if ( typeof hasItem . value === 'undefined' && hasItem . type === 'host' ) {
223- invalidHasParts . push ( `value is required for "host" type` )
224- }
220+ for ( const hasItem of items ) {
221+ let invalidHasParts = [ ]
225222
226- if ( invalidHasParts . length > 0 ) {
227- invalidHasItems . push (
228- `${ invalidHasParts . join ( ', ' ) } for ${ JSON . stringify ( hasItem ) } `
229- )
223+ if ( ! allowedHasTypes . has ( hasItem . type ) ) {
224+ invalidHasParts . push ( `invalid type "${ hasItem . type } "` )
225+ }
226+ if ( typeof hasItem . key !== 'string' && hasItem . type !== 'host' ) {
227+ invalidHasParts . push ( `invalid key "${ hasItem . key } "` )
228+ }
229+ if (
230+ typeof hasItem . value !== 'undefined' &&
231+ typeof hasItem . value !== 'string'
232+ ) {
233+ invalidHasParts . push ( `invalid value "${ hasItem . value } "` )
234+ }
235+ if ( typeof hasItem . value === 'undefined' && hasItem . type === 'host' ) {
236+ invalidHasParts . push ( `value is required for "host" type` )
237+ }
238+
239+ if ( invalidHasParts . length > 0 ) {
240+ invalidHasItems . push (
241+ `${ invalidHasParts . join ( ', ' ) } for ${ JSON . stringify ( hasItem ) } `
242+ )
243+ }
230244 }
231- }
232245
233- if ( invalidHasItems . length > 0 ) {
234- hadInvalidHas = true
235- const itemStr = `item${ invalidHasItems . length === 1 ? '' : 's' } `
246+ if ( invalidHasItems . length > 0 ) {
247+ hadInvalidItem = true
248+ const itemStr = `item${ invalidHasItems . length === 1 ? '' : 's' } `
236249
237- console . error (
238- `Invalid \`has\` ${ itemStr } :\n` + invalidHasItems . join ( '\n' )
239- )
240- console . error ( )
241- invalidParts . push ( `invalid \`has\` ${ itemStr } found` )
250+ console . error (
251+ `Invalid \`${ fieldName } \` ${ itemStr } :\n` +
252+ invalidHasItems . join ( '\n' )
253+ )
254+ console . error ( )
255+ invalidParts . push ( `invalid \`${ fieldName } \` ${ itemStr } found` )
256+ }
242257 }
258+ return hadInvalidItem
259+ }
260+ if ( checkInvalidHasMissing ( route . has , 'has' ) ) {
261+ hadInvalidHas = true
262+ }
263+ if ( checkInvalidHasMissing ( route . missing , 'missing' ) ) {
264+ hadInvalidMissing = true
243265 }
244266
245267 if ( ! route . source ) {
@@ -421,6 +443,19 @@ export function checkCustomRoutes(
421443 ) } `
422444 )
423445 }
446+ if ( hadInvalidMissing ) {
447+ console . error (
448+ `\nValid \`missing\` object shape is ${ JSON . stringify (
449+ {
450+ type : [ ...allowedHasTypes ] . join ( ', ' ) ,
451+ key : 'the key to check for' ,
452+ value : 'undefined or a value string to match against' ,
453+ } ,
454+ null ,
455+ 2
456+ ) } `
457+ )
458+ }
424459 console . error ( )
425460 console . error (
426461 `Error: Invalid ${ type } ${ numInvalidRoutes === 1 ? '' : 's' } found`
0 commit comments