psvet / obey Goto Github PK
View Code? Open in Web Editor NEW:hammer: Asynchronous JavaScript Data Modelling and Validation
License: MIT License
:hammer: Asynchronous JavaScript Data Modelling and Validation
License: MIT License
Because the allow
rule is evaluated before empty
, empty strings will be erroneously declared invalid.
const model = obey.model({
foo: { type: 'string', allow: [ 'bar' ], empty: true }
})
model.validate({ foo: '' }) // Error: Value '' is not allowed
Besides some obvious current limitations that have already been discussed (such as extensions), the regex also fails on phone numbers formatted in the fairly standard (aaa) bbb-cccc
style.
(111) 222-3333 // fails
(111)222-3333 // fails (probably less common)
(111)-222-3333 // passes
Ironically my computer recognizes the first two as phone numbers, but not the last one.
Just browsin' through the source code and wanted to point it out just in case it wasn't intentional:
https://github.com/TechnologyAdvice/obey/blob/master/src/types/number.js
export default (context) => {
if (typeof context.value !== 'number') {
context.fail('Value must be a number')
}
}
import isNumber from 'types/number'
isNumber(Number('foo')) // passes
If NaN
isn't handled here, perhaps an additional type to catch this case? I've been bitten by this in the past and didn't want it to slip through.
Create util (CLI + import) that generates documentation (markdown) of a model object.
When an error occurs on a nested object only the current key
is shown. Need to pass a prefix
reference so errors from nested objects are meaningful
When a non-required field is passed with undefined
or not supplied the library still includes the property in a passing validation object. Need to remove properties from response that are undefined
.
obey.modifier('returnNullIfInvalid', val => {
return val && arrayOfValidValues.includes(val) ? val : null
})
const model = obey.model({
name: { type: 'string', modifier: 'returnNullIfInvalid', allowNull: true }
})
model.validate({ name: 'some invalid string' }) // 'Value must be a string'
Type array should have allowEmpty
property to allow placeholder array to be set in a property or represent 0-length collection.
Useful when enforcing fields that cannot be changed
When you use requireIf
, requireIfNot
or equalsTo
(soon) then you may find weird issue - first value of referenced fields are not updated.
let schema = obey.model({
phone: { type: "string" },
phoneType: { type: "string", requireIf: "phone" }
});
schema.validate({ phone: "123" }).then(() => {
console.error('Bad: Form is invalid, you should not see this message')
})
.catch(() => {
let muchNewSchema = obey.model({
phone: { type: "string" },
phoneType: { type: "string", requireIf: "phone" }
});
muchNewSchema.validate({}).then(() => {
console.log('Good: Bug is fixed');
})
.catch((e) => {
console.error('Bad: Form is valid, you should not see this message');
console.error(e.message);
})
})
Result:
- Bad: Form is valid, you should not see this message
- phoneType (undefined): Value required because 'phone' exists
The problem is when you run validation second time - obey.rules.initData
is already set so it doesn't updated.
https://github.com/TechnologyAdvice/obey/blob/master/src/rules.js#L85
Example:
const schema = obey.model({
email: { type: 'string', allowNull: true, default: null }
})
schema.validate({ email: '' })
.then(console.log)
.catch(console.log) // { message: "email (null): Value must be a string" }
Root cause is src/rules#L150
. Either the initial falsey value needs to persist (and not be assigned the default), or type strategies also need to check allowNull
.
Despite setting required: false
the following fails lname
because the type
check runs and fails. Need to only check present fields, then run check if required
fields are missing.
const test = obey.model({
fname: { type: 'string' },
lname: { type: 'string', required: false }
});
test.validate({ fname: 'bob' })
For common types which have the possibility of multiple variants, allow :
delimited pass-through for specific validation settings
For example; phone numbers could use type phone
or more specifically phone:us
, phone:uk
, etc to indicate specific regional format.
Ability to specify alternative object library file containing error messages.
const model = obey.model({
list: {
type: 'array',
values: {
type: 'object',
keys: {
someQualifier: {
type: 'string',
allow: [ 'a', 'b', 'c' ]
},
someDependentProp: {
type: 'string',
requiredIfNot: { 'list[thisIndex].someQualifier': 'b' } // This won't work
}
}
}
}
})
Specifically when the default is true
, but the record's value is false
:
obey.model({
enabled: { type: 'boolean', default: true }
})
// then elsewhere
validate({ enabled: false }) ==> { enabled: true }
Need to add a type check before returning the final value (for numbers as well, in case of 0
).
Since a schema property can be shared it can create a single-source for configurations. As such, one area where this applies well is allow
; it's accepted values and any metadata associated with those, for example:
status: { type: 'string', allow: [ 'prog', 'comp', 'arch' ] }
Maintaining enums in a separate location for the allow
"keys" ([ 'prog', 'comp', 'arch' ]
) presents the challenge of maintaining this in multiple locations.
Proposed Solution
Currently allow
supports either a string
or an array
. The proposal would be to expand this to also allow an object:
status: { type: 'string', allow: { 'prog': 'in progress', 'comp': 'completed', 'arch': 'archived' } }
The above would simply process to allow
the keys of the object as values, but the whole object could then be maintained in a lib (or in the model) and shared easily.
Allow properties to specify a conditional require based on presence of another property's value:
Example:
const user = Obey.model({
// ...
phone: { type: 'phone', description: 'User phone number' },
phoneType: { type: 'string', requireIf: 'phone', 'Type of phone, i.e. cell or home' }
// ...
})
The phoneType
property is only required if phone
is supplied.
Should support nesting using dot notation 'parent.child'
which refers to the parent
object-type with nested child
property.
const model = obey.model({
name: { type: 'string', allowNull: true }
})
await model.validate({ name: null }) // 'Value must be a string'
Hi, this project looks great!
Is it possible to add custom methods to a model, something like the following?
userModel.methods.getFullName = function() {
return this.fname + ' ' + this.lname;
}
The type checker for a string
currently also requires the string to have a length greater than 0. This causes issues for string fields that are not required (read: do not need to have any content).
https://github.com/TechnologyAdvice/obey/blob/master/src/typeStrategies/string.js:
default: context => {
if (typeof context.value !== 'string' || context.value.length === 0) {
context.fail('Value must be a string')
}
},
Allows an assert that a field exists in any form, without specifying what it should be.
When objects are validated we need a way to enforce strict checking to ensure other key-val's don't come through. Should have a flag for disabling strict-mode.
Will need to be applied to object rules, but also inherit from a model definition.
When I validate registration form, I want to validate password confirmation with schema like this:
let model = obey.model({
/* Unrelated fields omitted */
password: {
type: 'string',
min: 8
},
passwordConfirm: {
type: 'string',
equalsTo: 'password'
}
});
Currently requires protocol, add subtype to allow non-protocol'd URL's i.e. google.com
vs. http://google.com
Let schema property allow
be either a single or array of allowed values
Since the property name is required
(not require
) it makes more sense if the property name and API uses the same convention for requiredIf
and requiredIfNot
.
We have a number of fields (mostly timestamps) that should allow a null
value, but because they're specified as type: 'number'
in the obey models, they throw validation errors. The current work-around is including a custom type for every field that accepts null
along with its main type, but if allow: null
is passed, the default type check should be bypassed.
When a property in a model has a requireIf
or requireIfNot
set check the conditon's property for default
or creator
and handle error (as requireIf
, requireIfNot
become moot)
This type of thing should not happen:
ValidationError: keyName ([object Object],[object Object],[object Object]): [object Object]
This line: https://github.com/TechnologyAdvice/obey/blob/master/src/typeStrategies/array.js#L19 needs to be addressed; when a type: 'array'
is set without values it will pass/fail and return true
instead of the array value.
In cases where objects are validated against values, any keys are allowed. If a value is dependent on another nested inside an object, the requiredIf
or requiredIfNot
rules use dot notation for finding the target value (requiredIfNot: 'rootObj.someVal'
). This requires a user to explicitly declare the key name in the model definition, which does not play well with dynamic keys.
const model = obey.model({
admin: {
type: 'object',
values: {
type: 'object',
required: true,
keys: {
valA: {
type: 'string',
requiredIfNot: 'valB' // This would check for a top-level valB prop,
}, // instead of the intended admin.<whateverKey>.valB
valB: {
type: 'string',
requiredIfNot: 'valA' // and vice versa
}
}
}
}
})
Currently there's no way to tell if an invalid property is supplied, so for instance; if you misspelled modifer: 'someVal'
there's no indicator that the property won't be acted upon. Since we want to allow custom properties my suggestion is to "throw" a warning if the key in a definition is not recognized, then create a obey.customProps(<array|string>)
that allows for centrally declaring custom props to prevent the warning.
The email regex included with obey does not match many valid emails. I've created a regexr with valid email addresses for example: http://regexr.com/3d9cg
This was copied to one of our FE apps for validation, though it is too restrictive to use for validation as it would prevent users from submitting valid email addresses. We may use it as a warning, but I think we should consider a more permissive rule that does not rule out valid email addresses. If we can get a rule that does not rule out any valid email, then we can use it for submission validation.
For error response objects, currently:
{ key: 'fname', value: 1234, message: 'Value must be a string' }
Expand to include validation rule that failed:
{ type: 'string', sub: 'default', key: 'fname', value: 1234, message: 'Value must be a string' }
This will allow those parsing the error to setup rules-based responses.
Use { strip: true }
to denote keys which should not be included in the final object.
If true, empty strings are allowed. If false, field must contain something, or be undefined/null (if not required). Default to false.
const model = obey.model({
zip: { type: 'zip' }
})
await model.validate({ zip: 02680 }) ๐// ValidationError: zip (2680): Value must be a valid US zip code
await model.validate({ zip: '02680' }) ๐
Both should be valid.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.