Skip to content

Commit

Permalink
Add support for schema to mergeDeep
Browse files Browse the repository at this point in the history
  • Loading branch information
JaapRood committed May 3, 2018
1 parent 35e04f1 commit bf1f4c5
Showing 1 changed file with 49 additions and 1 deletion.
50 changes: 49 additions & 1 deletion src/merge.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
const Invariant = require('invariant')
const Immutable = require('immutable')
const _assign = require('lodash.assign')
const _isFunction = require('lodash.isfunction')
const _isPlainObject = require('lodash.isplainobject')
const _keys = require('lodash.keys')

const Schema = require('./schema')
const Props = require('./props')

const internals = {}
Expand All @@ -26,7 +28,53 @@ internals.mergeDeep = function(state, data) {
Invariant(this.instanceOf(state), `Instance of ${this.typeName()} is required to merge deep it with new attributes`)
Invariant(Immutable.Iterable.isIterable(data) || _isPlainObject(data), 'Plain object or Immutable Iterable required as source to merge deep with the state instance')

return state.mergeDeep(internals.mergableInstance.call(this, data));


const mergeDeep = function(current, next, schema) {
// merge schema props shallowly, the rest deeply
const withSchema = next.filter((modelValue, modelProp) => {
if (!schema) return false

const definition = Schema.getDefinition(schema, modelProp)

return definition && (Schema.isType(definition) || Schema.isSchema(definition))
})
const withoutSchema = next.filter((modelValue, modelProp) => {
return !withSchema.has(modelProp)
})

return current.mergeDeep(withoutSchema).mergeWith(function(currentValue, nextValue, modelProp) {
const definition = Schema.getDefinition(schema, modelProp)

if (Schema.isType(definition)) {
let type = definition

if (!_isFunction(type.mergeDeep)) {
return nextValue
} else {
return type.mergeDeep(currentValue, nextValue)
}
} else if (Schema.isSchema(definition)) {
let nestedSchema = definition

if (nestedSchema.getItemSchema && _isFunction(nestedSchema.mergeDeep)) { // could be an Iterable schema
return nestedSchema.mergeDeep(currentValue, nextValue)
} else if (
Immutable.Iterable.isKeyed(currentValue) && _isPlainObject(nestedSchema)
) {
return mergeDeep(currentValue, nextValue, nestedSchema)
}
}

// if we've arrived here, we didn't find a way to merge, so return the next value
return nextValue
}, withSchema)
}

const mergableInstance = internals.mergableInstance.call(this, data)
const modelSchema = this.schema && this.schema()

return mergeDeep(state, mergableInstance, modelSchema)
}

internals.mergableInstance = function(data) {
Expand Down

0 comments on commit bf1f4c5

Please sign in to comment.