![Oracle Drags Its Feet in the JavaScript Trademark Dispute](https://cdn.sanity.io/images/cgdhsj6q/production/919c3b22c24f93884c548d60cbb338e819ff2435-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Oracle Drags Its Feet in the JavaScript Trademark Dispute
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
common-schema
Advanced tools
Schema-handling utilities, including schema validators and checkers.
common-schema
provides a framework for handling schemas for data formats, and validating,
processing, and normalizing objects based on those schemas.
This README provides information on common use cases. More extensive documentation is
available in the docs
directory.
let createSchema = require('common-schema').createSchema;
let schema = createSchema({
foo: String,
bar: {
baz: [Number],
qux: {
type: Date,
required: true
}
}
});
schema.validate({
foo: 'Some String',
bar: {
baz: [ 1, 2, 3 ],
qux: new Date()
}
}); // true
schema.validate({
foo: true,
bar: {}
}); // throws with errors that foo is the wrong type and bar.qux is required
schema.normalize({
foo: 5,
bar: {
baz: [ 1, '2', '3.5' ],
qux: '2014-01-01T00:00:00Z'
}
});
// Results in:
// {
// foo: '5',
// bar: {
// baz: [ 1, 2, 3.5 ],
// qux: new Date('2014-01-01T00:00:00Z')
// }
// }
Schemas are stored in a strict internal format, but shorter, easier-to-write schemas can be supplied in several formats.
{
type: 'object',
properties: {
foo: {
type: 'string'
},
bar: {
type: 'object',
properties: {
baz: {
type: 'array',
elements: {
type: 'number'
}
},
qux: {
type: 'date',
required: true
}
}
}
}
}
If you do not need to specify any extra fields on the subschemas (such as required
),
you can provide the raw type. These are equivalent in this case:
{ type: 'string' }
'string'
Many types offer shorthand, mongoose-style ways to specify the type. These are usually used by supplying the constructor of the Javascript type. These are equivalent:
{ type: 'string' }
'string'
{ type: String }
String
Objects and arrays have special shorthand syntax:
{
myObj: {
prop1: String,
prop2: Boolean
},
myArr: [ Date ]
}
is equivalent to:
{
type: 'object',
properties: {
myObj: {
type: 'object',
properties: {
prop1: { type: 'string' },
prop2: { type: 'boolean' }
}
},
myArr: {
type: 'array',
elements: { type: 'date' }
}
}
}
Calling schema.validate(value)
will strictly validate the value against the schema.
This does not take into account type coercion or normalization. For example, the value
"5"
does not validate against the schema Number
.
Calling schema.normalize(value)
will attempt to coerce values into schema values.
Modification is done in-place as much as possible, and schema.normalize()
returns
the result. This will throw if it cannot coerce a value.
Both methods will throw ValidationError
on error.
For situations in which this is undesirable,
schema.isValid(value)
will return a Boolean
rather than throwing an error.
validate()
and normalize()
throw a ValidationError
(which can be accessed on
require('common-schema').ValidationError
)
on failure. A ValidationError
looks like this (and inherits from XError and Error):
{
code: 'validation_error',
message: 'Something human readable here',
data: {
fieldErrors: [ // note: only present sometimes
{
field: 'foo.bar.baz', // path to invalid field
code: 'too_large', // machine-readable field error code
message: 'Value is too big', // human-readable message specific to field
details: { ... } // sometimes includes additional info
},
{
// second error ...
}
]
}
}
The fieldError
code may be anything defined by the validation function, but the following values
are standard:
invalid_type
- If the field is the wrong typeinvalid_format
- If the format of a string field does not match a regex or validation routine;
details may optionally include a regex
field.required
- If a required field is missingduplicate
- If a field required to be unique has a duplicate valueinvalid
- Generic error codetoo_small
- Numeric value is too smalltoo_large
- Numeric value is too largetoo_short
- String is too shorttoo_long
- String is too longunrecognized
- Unrecognized value in an enum; details may optionally contain an enum
arrayunknown_field
- If a supplied field does not have an attached schemaBoth validate()
and normalize()
take a second argument; an options
object. This object can contain:
allowUnknownFields
- By default, an error is thrown if fields are
defined on an object that aren't defined on the schema. If this is set to true, that error
is suppressed and unknown fields are passed through.allowMissingFields
- By default, an error is thrown if a required
field is missing. If this is true, required field errors are suppressed.removeUnknownFields
- Only applies to normalize()
. Causes any unknown fields to be
removed from their object.serialize
- Only applied to normalize()
. Causes the normalizers to output serializable
values. Ie, dates will output ISO8601 strings instead of native Date
objects."object"
An object with defined child properties. Subschema should include a properties
object, which
is a map from property names to subschemas.
createSchema({
type: 'object',
properties: {
foo: { type: 'string' },
bar: { type: 'string' }
}
})
// Shorthand
createSchema({
foo: String,
bar: String
})
"array"
An array of elements that share the same schema. Subschema should include an elements
property which is the schema for array elements.
createSchema({
type: 'array',
elements: {
type: 'number'
}
})
// Shorthand
createSchema([ Number ])
"map"
A map (ie, object with variable keys) from strings to values that share the same schema. The
subschema should include a values
property which is the schema for the map values. Use it like
this:
createSchema({
type: 'object',
properties: {
foo: {
type: 'map',
required: true,
values: {
type: 'number'
}
}
}
})
// Shorthand
let map = require('common-schema').map;
createSchema({
// required field foo that's a map from strings to numbers
foo: map({
required: true
}, Number)
})
"or"
Special type of subschema that can match one of two or more alternative subschemas. For example, to match a string, a number, or an object containing a string "bar":
let or = require('common-schema').or;
createSchema({
foo: or({
required: true
}, String, Number, { bar: String })
})
Note that using or
with complex and similar subschemas (such as two objects) can incur an
additional performance penalty.
"string"
/ String
Matches a string. In normalize()
, will coerce any data type by calling .toString()
. If used
as a component in an or
, this will only match primitives (ie, it will not try to coerce objects
when used as part of or
).
String schemas support these additional builtin validations:
{
type: String,
minLength: 3,
maxLength: 10,
match: /^[a-z]*$/
}
Instead of using match
, you could also use enum
:
{
type: String,
minLength: 3,
maxLength: 10m
enum: [ 'abc', 'efg', 'hij' ]
}
"number"
/ Number
Matches a number. Will coerce numeric strings by parsing as a float, and will coerce dates by
converting to millisecond unix timestamp. Supports the additional builtin validations min
and max
.
{
type: Number,
min: 0,
max: 100
}
Or use enum
:
{
type: Number,
enum: [ 23, 35, 40, 57 ]
}
"date"
/ Date
Matches a date and time. Will parse strings as ISO8601 times. Will parse numbers as UNIX
timestamps in milliseconds. Supports min
and max
validators. Serializes into ISO8601
strings.
"binary"
/ Buffer
Binary data. The native type for this is Buffer
. It will parse strings as base64 and
will also accept arrays of numbers (byte values). Serializes into a base64 string.
"boolean"
/ Boolean
Will coerce the following: "yes"/"no", "true"/"false", "t"/"f", "yes"/"no", "y"/"n", "1"/"0", 1/0, "on"/"off", "totallydude"/"definitelynot".
"mixed"
/ MixedWildcard type; can be anything. Use like this:
let Mixed = require('common-schema').Mixed;
createSchema({
foo: Mixed
})
You can specify custom validator and normalizer functions inside of a schema. The validator should strictly validate the value, and is called after the normalizer when normalizing. When normalizing, the defined normalized is called after the standard normalizer.
Any validation errors should be reported by throwing a FieldError
.
createSchema({
foo: {
type: String,
validate: function(value, subschema, fieldPath, validateOptions) {
if (value[0] !== 'x') {
throw new commonSchema.FieldError('invalid', 'First character must be x');
}
},
normalize: function(value, subschema, fieldPath, normalizeOptions) {
return value.toLowerCase();
}
}
})
Functions are also provided for the following:
See the docs
directory for details.
All schemas are created by a SchemaFactory
that maintains the set of allowed types in the
schema. The exposed createSchema
function is actually an alias to createSchema
on a default
factory.
To create a custom type:
SchemaFactory
.SchemaType
or an existing type class, and override the appropriate methods. See
the default types for examples.SchemaFactory
.You can also use this process to override or extend existing types (for example, if you need to normalize a type into a different format for a specific database).
let SchemaFactory = require('common-schema').SchemaFactory;
let SchemaTypeDate = require('common-schema').coreSchemaTypes.SchemaTypeDate;
class YearSerializedDate extends SchemaTypeDate {
constructor() {
super();
}
normalize(value, subschema, field, options, schema) {
value = super.normalize(value, subschema, field, {}, schema);
if (options.serialize) {
return '' + value.getUTCYear();
} else {
return value;
}
}
}
let mySchemaFactory = new SchemaFactory();
mySchemaFactory.registerType('date', new YearSerializedDate());
let schema = mySchemaFactory.createSchema(...);
You can use Schema.isSchema
to test whether a given value is a schema instance.
Schema.isSchema(createSchema({ foo: String }));
// => true
Schema.isSchema('bar');
// => false
FAQs
Schema-handling utilities, including schema validators and checkers.
The npm package common-schema receives a total of 9 weekly downloads. As such, common-schema popularity was classified as not popular.
We found that common-schema demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.