A simple little library to validate and transform objects. It is inspired by the awesome .NET library AutoMapper but built for JavaScript.
Note: This is an experimental package. Please file an issue if you find one.
bower install morpheus --save<script src="bower_components/morpheus/dist/morpheus.js"></script>npm install morpheusjs --savelet Morpheus = require('morpheus')
let morpheus = new Morpheus()Morpheus uses JSONSchema to work with objects in a "typed" way. There is a two step process.
- Register: register all mappings (typically done when your app is bootstrapping).
fromSchemaandtoSchemaare JavaScript objects that comply with the JSONSchema spec. - Use one of the registered mappings to transform.
Register example:
let fromSchema = {
type: 'object',
properties: {
name: { type: 'string' },
address: { type: 'string' }
}
}
let toSchema = {
type: 'object',
properties: {
address: { type: 'string' }
}
}
let = morpheus = new Morpheus()
morpheus.register({
id: 'neo',
fromSchema: fromSchema,
toSchema: toSchema
})Map example:
let fromObj = { name: 'Mr. Anderson', address: 'Capital City, USA' }
let actual = morpheus.map('neo', fromObj)
expect(actual)
.to.have.property('name').equal('Mr. Anderson')
let isValid = morpheus.validate(actual, toSchema)
expect(isValid.errors).to.have.length(0)Note: Examples are taken from unit tests located in ./test
Validation with JSONSchema
Validation is enforced on both fromObj and toObj using the fromSchema and toSchema. If you are calling an external service and if the service changes the data model, you can get a validation error early. It also makes writing unit tests easier for the mapping logic.
let schema = {
type: 'number'
}
let instance = 4
let actual = morpheus.validate(instance, schema)
expect(actual.errors).to.have.length(0)Mapping arrays and transforming them
let fromSchema = {
type: 'array',
items: {
type: 'number'
}
}
let toSchema = {
type: 'array',
items: {
type: 'number'
},
morph: x => x.map(y => y * 2)
}
let fromArray = [1, 2, 3]
let actual = morpheus.map('array', fromArray)
//actual is now [2,4,6]Mapping objects with desired properties
let fromSchema = {
type: 'object',
properties: {
name: { type: 'string' },
address: { type: 'string' },
zip: { type: 'string' }
}
}
let toSchema = {
type: 'object',
properties: {
name: { type: 'string' },
zip: { type: 'string' }
}
}Default value for the zip property
let fromSchema = {
type: 'object',
properties: {
name: { type: 'string' },
zip: {
type: ['string', 'null']
}
}
}
let toSchema = {
type: 'object',
properties: {
name: { type: 'string' },
zip: {
type: 'string',
'default': '60075'
}
}
}Flatten an object using the camelCase property naming convention for the addressZip property.
let fromSchema = {
type: 'object',
properties: {
address: {
type: 'object',
properties: {
zip: {
type: ['string']
}
}
}
}
}
let toSchema = {
type: 'object',
properties: {
addressZip: {
type: 'string'
}
}
}Project over properties of an object and create new properties
let fromSchema = {
type: 'object',
properties: {
firstName: {
type: 'string'
},
lastName: {
type: 'string'
},
zip: {
type: 'number'
}
}
}
let toSchema = {
type: 'object',
properties: {
name: {
type: 'string',
morph: x => `${x.firstName} ${x.lastName}`
},
zip: {
type: 'string',
morph: x => x.zip.toString()
}
}
}