leafo / tableshape

Test the shape or structure of a Lua table, inspired by React.PropTypes & LPeg
111 stars 9 forks source link

Get name of failed field #12

Closed luveti closed 1 year ago

luveti commented 4 years ago

Is this possible? I'm looking to replace lapis.validate with this but there doesn't appear to be a equivalent to the { keys = true } option that validate takes in lapis. I use this to know what field to show the error on in larger forms.

Maybe this could be added as a third return value to type(value), type:check_value(value) and type.transform(value)?

leafo commented 1 year ago

Sorry for not replying to this sooner. tableshape is designed for nested type checking, but as the validate function in lapis is designed validating list of fields on a single table. What your asking for is actually not trivial to add to tableshape because the requirements are actually not well defined for where error boundaries might exist.

When creating tableshape I decide to use strings for passing errors back though the type call chain, and composite types would use string operators (concatenation) to combine these errors into something useful. Unfortunately this means you do not have a reference to which fields/values triggered that particular error in a combined string. I don't recommend trying to parse the errors out of the string since the string format is not an API.

If you want 1 level of keys mapped to their error messages (similar to lapis validate), then I suggest making a helper function that takes a plain table of types checkers, and you iterate through them and call them individually, then store all the errors in a resulting object. (as opposed to using a single types.shape or types.partial to validate your entire parameters object in one call.

Alternatively, lapis support a special validator called test which takes any callable object to perform validation with, this works with any tableshape type, since they can be called to perform validation:

local types = require("tableshape").types

local errors = validate({
  { "username", test = types.string}
}, { keys = true})