-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
191 additions
and
145 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import { | ||
addInputPrefix, | ||
addDefinitionPrefix, | ||
addKeywordPrefix, | ||
} from './prefix.js' | ||
import { | ||
addCurrentDefinition, | ||
addExampleDefinition, | ||
addCurrentInput, | ||
addExampleInput, | ||
} from './suffix.js' | ||
|
||
// Handle errors in `keyword.test|normalize|main()` or in keyword functions | ||
export const handleError = function ({ | ||
error, | ||
input, | ||
example, | ||
prefix, | ||
originalName, | ||
hasInput, | ||
test, | ||
keyword, | ||
definition, | ||
exampleDefinition, | ||
errorType, | ||
bugType, | ||
}) { | ||
const isValidation = isValidateError(error) | ||
const type = isValidation ? errorType : bugType | ||
return ERROR_HANDLERS[type]({ | ||
error, | ||
input, | ||
example, | ||
prefix, | ||
originalName, | ||
hasInput, | ||
test, | ||
keyword, | ||
definition, | ||
exampleDefinition, | ||
isValidation, | ||
}) | ||
} | ||
|
||
// Consumers can distinguish users errors from system bugs by checking | ||
// the `error.validation` boolean property. | ||
// User errors are distinguished by having error message starting with "must". | ||
// We fail on the first error, as opposed to aggregating all errors | ||
// - Otherwise, a failed property might be used by another property, which | ||
// would also appear as failed, even if it has no issues | ||
// We detect this using the error message instead of the error class because: | ||
// - It is simpler for users | ||
// - It works both on browsers and in Node.js | ||
// - It ensures the error message looks good | ||
const isValidateError = function (error) { | ||
return error instanceof Error && error.message.startsWith('must') | ||
} | ||
|
||
const handleInputError = function ({ | ||
error, | ||
input, | ||
example, | ||
prefix, | ||
originalName, | ||
hasInput, | ||
test, | ||
}) { | ||
error.validation = true | ||
const errorA = addInputPrefix(error, prefix, originalName) | ||
const errorB = addCurrentInput(errorA, input, hasInput) | ||
const errorC = addExampleInput({ error: errorB, example, hasInput, test }) | ||
return errorC | ||
} | ||
|
||
const handleDefinitionError = function ({ | ||
error, | ||
prefix, | ||
originalName, | ||
keyword, | ||
definition, | ||
exampleDefinition, | ||
isValidation, | ||
}) { | ||
const errorA = addDefinitionPrefix({ | ||
error, | ||
prefix, | ||
originalName, | ||
keyword, | ||
isValidation, | ||
}) | ||
const errorB = addCurrentDefinition(errorA, definition) | ||
const errorC = addExampleDefinition(errorB, exampleDefinition) | ||
return errorC | ||
} | ||
|
||
const handleKeywordError = function ({ | ||
error, | ||
input, | ||
prefix, | ||
originalName, | ||
hasInput, | ||
keyword, | ||
definition, | ||
}) { | ||
const errorA = addKeywordPrefix({ error, prefix, originalName, keyword }) | ||
const errorB = addCurrentDefinition(errorA, definition) | ||
const errorC = addCurrentInput(errorB, input, hasInput) | ||
return errorC | ||
} | ||
|
||
const ERROR_HANDLERS = { | ||
input: handleInputError, | ||
definition: handleDefinitionError, | ||
keyword: handleKeywordError, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { wrapError } from '../../../../error/wrap.js' | ||
|
||
// The `prefix` is the name of the type of property to show in error | ||
// message and warnings such as "Option". | ||
export const addInputPrefix = function (error, prefix, originalName) { | ||
return wrapError(error, `${prefix} "${originalName}"`) | ||
} | ||
|
||
export const addDefinitionPrefix = function ({ | ||
error, | ||
prefix, | ||
originalName, | ||
keyword, | ||
isValidation, | ||
}) { | ||
const suffix = isValidation ? 'definition' : 'must have a valid definition:\n' | ||
return wrapError( | ||
error, | ||
`${prefix} "${originalName}"'s keyword "${keyword}" ${suffix}`, | ||
) | ||
} | ||
|
||
export const addKeywordPrefix = function ({ | ||
error, | ||
prefix, | ||
originalName, | ||
keyword, | ||
}) { | ||
return wrapError( | ||
error, | ||
`${prefix} "${originalName}"'s keyword "${keyword}" bug:`, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import { inspect } from 'util' | ||
|
||
import { wrapError } from '../../../../error/wrap.js' | ||
|
||
// Add the current definition as error suffix | ||
export const addCurrentDefinition = function (error, definition) { | ||
return definition === undefined | ||
? error | ||
: wrapErrorValue(error, 'Current definition', definition) | ||
} | ||
|
||
// Add the example definition as error suffix | ||
export const addExampleDefinition = function (error, exampleDefinition) { | ||
return exampleDefinition === undefined | ||
? error | ||
: wrapErrorValue(error, 'Example definition', exampleDefinition) | ||
} | ||
|
||
// Add the current input as error suffix | ||
export const addCurrentInput = function (error, input, hasInput) { | ||
return hasInput ? wrapErrorValue(error, 'Current input', input) : error | ||
} | ||
|
||
// Add the example input as error suffix | ||
export const addExampleInput = function ({ error, example, hasInput, test }) { | ||
return example !== undefined && (hasInput || test !== undefined) | ||
? wrapErrorValue(error, 'Example input', example) | ||
: error | ||
} | ||
|
||
const wrapErrorValue = function (error, name, value) { | ||
return wrapError(error, `\n${name}:${serializeValue(value)}`) | ||
} | ||
|
||
const serializeValue = function (value) { | ||
const valueStr = inspect(value) | ||
const separator = valueStr.includes('\n') ? '\n' : ' ' | ||
return `${separator}${valueStr}` | ||
} |