Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Joshua Pollak committed Sep 18, 2019
1 parent b4a56bd commit 7a80a82
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 18 deletions.
23 changes: 14 additions & 9 deletions src/core/deserialize.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { invariant, isPrimitive, isModelSchema, parallel, GUARDED_NOOP } from ".
import getDefaultModelSchema from "../api/getDefaultModelSchema"
import { SKIP, _defaultPrimitiveProp } from "../constants"
import Context from "./Context"
import {checkStarSchemaInvariant} from "./serialize";

function schemaHasAlias(schema, name) {
for (var key in schema.props)
Expand All @@ -13,15 +14,20 @@ function schemaHasAlias(schema, name) {
return false
}

function deserializeStarProps(schema, obj, json) {
function deserializeStarProps(context, schema, propDef, obj, json) {
checkStarSchemaInvariant(propDef)
for (var key in json) if (!(key in schema.props) && !schemaHasAlias(schema, key)) {
var value = json[key]
// when deserializing we don't want to silently ignore 'unparseable data' to avoid
// confusing bugs
invariant(isPrimitive(value),
"encountered non primitive value while deserializing '*' properties in property '" +
key + "': " + value)
obj[key] = value
if (propDef === true) {
// when deserializing we don't want to silently ignore 'unparseable data' to avoid
// confusing bugs
invariant(isPrimitive(value),
"encountered non primitive value while deserializing '*' properties in property '" +
key + "': " + value)
obj[key] = value
} else if (propDef.pattern.test(key)) {
obj[key] = deserializeObjectWithSchema(context, propDef, value, context.callback, {})
}
}
}

Expand Down Expand Up @@ -134,8 +140,7 @@ export function deserializePropsWithSchema(context, modelSchema, json, target) {
}

if (propName === "*") {
invariant(propDef === true, "prop schema '*' can only be used with 'true'")
deserializeStarProps(modelSchema, target, json)
deserializeStarProps(context, modelSchema, propDef, target, json)
return
}
if (propDef === true)
Expand Down
43 changes: 35 additions & 8 deletions src/core/serialize.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-console */
import { invariant, isPrimitive } from "../utils/utils"
import createModelSchema from "../api/createModelSchema"
import getDefaultModelSchema from "../api/getDefaultModelSchema"
Expand Down Expand Up @@ -37,6 +38,10 @@ export default function serialize(arg1, arg2) {
return serializeWithSchema(schema, thing)
}

export function checkStarSchemaInvariant(propDef) {
invariant(propDef === true || propDef.pattern, "prop schema '*' can only be used with 'true'")
}

export function serializeWithSchema(schema, obj) {
invariant(schema && typeof schema === "object", "Expected schema")
invariant(obj && typeof obj === "object", "Expected object")
Expand All @@ -50,8 +55,7 @@ export function serializeWithSchema(schema, obj) {
Object.keys(schema.props).forEach(function (key) {
var propDef = schema.props[key]
if (key === "*") {
invariant(propDef === true, "prop schema '*' can only be used with 'true'")
serializeStarProps(schema, obj, res)
serializeStarProps(schema, propDef, obj, res)
return
}
if (propDef === true)
Expand All @@ -67,12 +71,35 @@ export function serializeWithSchema(schema, obj) {
return res
}

export function serializeStarProps(schema, obj, target) {
for (var key in obj) if (obj.hasOwnProperty(key)) if (!(key in schema.props)) {
var value = obj[key]
// when serializing only serialize primitive props. Assumes other props (without schema) are local state that doesn't need serialization
if (isPrimitive(value))
target[key] = value
export function serializeStarProps(schema, propDef, obj, target) {
checkStarSchemaInvariant(propDef)
for (var key in obj) {
let hasOwnProp = obj.hasOwnProperty(key)
//console.log({obj, key, hasOwnProp})
if (hasOwnProp) {
if (!(key in schema.props)) {
let onlyPrimitives = propDef === true
let pattern = !onlyPrimitives && propDef.pattern
let matchesPattern = pattern && pattern.test(key)
//console.log({propDef, obj, key, pattern, onlyPrimitives, matchesPattern})
if (onlyPrimitives || matchesPattern) {
var value = obj[key]
//console.log({propDef, obj, key, value});
if (onlyPrimitives) {
// when serializing only serialize primitive props. Assumes other props (without schema) are local state that doesn't need serialization
if (isPrimitive(value)) {
target[key] = value
}
} else {
var jsonValue = serializeWithSchema(propDef, value)
if (jsonValue === SKIP) {
return
}
target[/*propDef.jsonname ||*/ key] = jsonValue
}
}
}
}
}
}

Expand Down
41 changes: 40 additions & 1 deletion test/simple.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ test("it should support 'false' and 'true' propSchemas", t => {
t.end()
})

test("it should respect `*` prop schemas", t => {
test("it should respect `*` : true (primitive) prop schemas", t => {
var s = _.createSimpleSchema({ "*" : true })
t.deepEqual(_.serialize(s, { a: 42, b: 17 }), { a: 42, b: 17 })
t.deepEqual(_.deserialize(s, { a: 42, b: 17 }), { a: 42, b: 17 })
Expand Down Expand Up @@ -96,6 +96,45 @@ test("it should respect `*` prop schemas", t => {
t.end()
})

test("it should respect `*` : schema prop schemas", t => {
var schema = {
factory: () => ({}),
pattern: /^\d.\d+$/,
props: {
x: primitive()
}
}

var s = _.createSimpleSchema({ "*" : schema} )
t.deepEqual(_.serialize(s, { "1.0": {x: 42}, "2.10": {x: 17 } }), { "1.0": {x: 42}, "2.10": {x: 17 } })
t.deepEqual(_.deserialize(s, { "1.0": {x: 42}, "2.10": {x: 17 } }), { "1.0": {x: 42}, "2.10": {x: 17 } })

t.deepEqual(_.serialize(s, { a: new Date(), d: 2 }), { d: 2 })
t.deepEqual(_.serialize(s, { a: {}, "2.10": {x: 17 } }), { "2.10": {x: 17 }})

t.throws(() => _.deserialize(s, { "1.0": new Date() }), /encountered non primitive value while deserializing/)
t.throws(() => _.deserialize(s, { "1.0": {} }), /encountered non primitive value while deserializing/)
var s2 = _.createSimpleSchema({
"*" : schema,
"1.0": _.date()
})
t.doesNotThrow(() => _.serialize(s2, { "1.0": new Date(), d: 2 }))
t.deepEqual(_.serialize(s2, { c: {}, d: 2 }), { "1.0": undefined, d: 2 })

t.doesNotThrow(() => _.deserialize(s2, { "1.0": new Date().getTime() }), /bla/)
t.throws(() => _.deserialize(s2, { c: {}, d: 2 }), /encountered non primitive value while deserializing/)

// don't assign aliased attrs
var s3 = _.createSimpleSchema({
a: _.alias("1.0", true),
"*" : schema,
})
t.deepEqual(_.deserialize(s3, { b: 4, a: 5}), { a: 4 })


t.end()
})

test("it should respect custom schemas", t => {
var s = _.createSimpleSchema({
a: _.custom(
Expand Down

0 comments on commit 7a80a82

Please sign in to comment.