Open claustres opened 2 years ago
Indeed IMHO most people submitting a set of objects expect that valid ones are created while an error is raised for invalid ones.
I agree
for instance maybe resolvers can help to do that?
@daffl today mentioned "converter" resolvers that maybe could help with this. I've not used them, yet.
I recently wrote something like this, let me know if it helps:
import errors from '@feathersjs/errors'
import commonHooks from 'feathers-hooks-common'
const { BadRequest } = errors
const { getItems, replaceItems } = commonHooks
export function validateData (schema) {
return async (hook) => {
let items = getItems(hook)
const isArray = Array.isArray(items)
items = (isArray ? items : [items])
// Perform validation
items = await Promise.allSettled(items.map((item) => schema.validate(item)))
// Keep track of validation errors, even if invalid data will be filtered this ensure
// original data with validation error will be "tagged"
items.forEach(item => {
if (item.status === 'rejected') {
item.validationError = (item.reason.ajv ? new BadRequest(item.reason.message, item.reason.errors) : item.reason)
}
})
// Filter errors/valid data
const errors = items.filter(item => item.validationError).map(item => item.validationError)
items = items.filter(item => !item.validationError).map(item => item.value)
// Raise if no valid data is found
const hasValidData = (items.length > 0)
const hasError = (errors.length > 0)
if (hasError) {
const firstError = errors[0]
// Single item case => raise the error
if (!isArray) throw firstError
// Multiple items case => raise if no valid data found
else if (!hasValidData) {
// Keep track of all errors
throw new BadRequest(firstError.message, errors)
}
}
replaceItems(hook, isArray ? items : items[0])
return hook
}
}
My use case is to validate input data according to a schema on a service, if any. Once my schema has been created I am using the following hook:
This works as expected when creating a single object: if the object is valid then it is created, otherwise an error is raised.
However, I wonder if the current behavior with an array of objects is the most useful. Indeed, the first invalid object found in the array will currently stop the validation process and throw the first encountered error. It seems to me that it would be more useful to process all objects anyway and return the array of invalid objects with associated errors instead of the first one only. That way we could probably do something like catching the error, filter invalid objects and create valid ones anyway if required. Indeed IMHO most people submitting a set of objects expect that valid ones are created while an error is raised for invalid ones.
Of course I can create a dedicated hook to do that but any insight is welcome as I am new to this module, for instance maybe resolvers can help to do that ? Any improvement in the module to address real-world app use cases could benefit the community, I will be glad to start a PR if enhancement is required.