Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

serializr

Package Overview
Dependencies
Maintainers
5
Versions
38
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

serializr - npm Package Compare versions

Comparing version 1.5.4 to 2.0.0-beta1

lib/api/createModelSchema.d.ts

17

CHANGELOG.md

@@ -0,1 +1,16 @@

# 2.0.0
* #117 TypeScript conversion. Type definitions should now match behavior exactly. By @NaridaL
* **BREAKING CHANGE**: `@serializeAll("*": ModelSchema)` is no longer valid. Instead you should pass
`@serializeAll("*": object(ModelSchema))`.
* **BREAKING CHANGE**: `{"*": object(...)}` and `{"x": object(...)}` now behave the same when
deserializing `{"x": "str_not_object"}` (result: `{x: null}`). Previously the `"*"` schema would
have returned `{}`.
* **BREAKING CHANGE**: Removed deprecated `ref` and `child` functions. Use `reference` and `object`
instead.
* BREAKING CHANGE: Removed undocumented and untested code which possibly retried deserialization on
error.
* You can pass a `pattern` argument as `AdditionalPropArgs` instead of having to manually assign it
to a PropSchema: `@serializeAll("*": list(primitive(), { pattern: /^_.*/ }))`. Note this only make
sense together with the `"*"` property.
# 1.5.4

@@ -10,3 +25,3 @@ * #113: Fix interpolation problem with IE11 by @danfma

# 1.5.2
* Fixed potential memory leak, fixes #95 through #100 by @svennergr
* Fixed potential memory leak, fixes #95 through #100 by @svennergr

@@ -13,0 +28,0 @@ # 1.5.1

1514

lib/es/serializr.js

@@ -6,20 +6,20 @@ /**

* @example
* var todoSchema = createSimpleSchema({
* const todoSchema = createSimpleSchema({
* title: true,
* done: true,
* });
* })
*
* var json = serialize(todoSchema, { title: 'Test', done: false });
* var todo = deserialize(todoSchema, json);
* const json = serialize(todoSchema, { title: 'Test', done: false })
* const todo = deserialize(todoSchema, json)
*
* @param {object} props property mapping,
* @returns {object} model schema
* @param props property mapping,
* @returns model schema
*/
function createSimpleSchema(props) {
return {
factory: function() {
return {}
factory: function () {
return {};
},
props: props
}
};
}

@@ -30,37 +30,36 @@

try {
return JSON.stringify(v)
} catch (error) {
return "[UnexpectedJSONParseError]: " + error.message
return JSON.stringify(v);
}
catch (error) {
return "[UnexpectedJSONParseError]: " + error.message;
}
},
l: function symbol(s) {
return s.toString();
}
};
function invariant(condition, message) {
var variables = [];
for (var _i = 2; _i < arguments.length; _i++) {
variables[_i - 2] = arguments[_i];
}
if (!condition) {
var variables = Array.prototype.slice.call(arguments, 2);
var variablesToLog = [];
var index = 0;
var formattedMessage = message.replace(/%([a-zA-Z%])/g, function messageFormatter(match, format) {
if (match === "%%") return match
var variablesToLog_1 = [];
var index_1 = 0;
var formattedMessage = message.replace(/%([a-zA-Z%])/g, function (match, format) {
if (match === "%%")
return match;
var formatter = formatters[format];
if (typeof formatter === "function") {
var variable = variables[index++];
variablesToLog.push(variable);
return formatter(variable)
var variable = variables[index_1++];
variablesToLog_1.push(variable);
return formatter(variable);
}
return match
return match;
});
if (console && variablesToLog.length > 0) {
if (console && variablesToLog_1.length > 0) {
// eslint-disable-next-line no-console
console.log.apply(console, variablesToLog);
console.log.apply(console, variablesToLog_1);
}
throw new Error("[serializr] " + (formattedMessage || "Illegal State"))
throw new Error("[serializr] " + (formattedMessage || "Illegal State"));
}

@@ -70,6 +69,6 @@ }

function GUARDED_NOOP(err) {
if (err) // unguarded error...
throw new Error(err)
if (err)
// unguarded error...
throw new Error(err);
}
function once(fn) {

@@ -80,90 +79,77 @@ var fired = false;

fired = true;
return fn.apply(null, arguments)
return fn.apply(null, arguments);
}
invariant(false, "callback was invoked twice");
}
};
}
function parallel(ar, processor, cb) {
// TODO: limit parallelization?
if (ar.length === 0)
return void cb(null, [])
var left = ar.filter(function(){ return true }).length; // only count items processed by forEach
return void cb(null, []);
var left = ar.filter(function (x) { return true; }).length; // only count items processed by forEach
var resultArray = [];
var failed = false;
var processorCb = function (idx, err, result) {
if (err) {
if (!failed) {
failed = true;
cb(err);
ar.forEach(function (value, idx) {
processor(value, function (err, result) {
if (err) {
if (!failed) {
failed = true;
cb(err);
}
}
} else {
resultArray[idx] = result;
if (--left === 0)
cb(null, resultArray);
}
};
ar.forEach(function (value, idx) {
processor(value, processorCb.bind(null, idx), idx);
else {
resultArray[idx] = result;
if (--left === 0)
cb(null, resultArray);
}
}, idx);
});
}
function isPrimitive(value) {
if (value === null)
return true
return typeof value !== "object" && typeof value !== "function"
return true;
return typeof value !== "object" && typeof value !== "function";
}
function isModelSchema(thing) {
return thing && thing.factory && thing.props
return thing && thing.factory && thing.props;
}
function isPropSchema(thing) {
return thing && thing.serializer && thing.deserializer
return thing && thing.serializer && thing.deserializer;
}
function isAliasedPropSchema(propSchema) {
return typeof propSchema === "object" && !!propSchema.jsonname
return typeof propSchema === "object" && "string" == typeof propSchema.jsonname;
}
function isIdentifierPropSchema(propSchema) {
return typeof propSchema === "object" && propSchema.identifier === true
return typeof propSchema === "object" && propSchema.identifier === true;
}
function isAssignableTo(actualType, expectedType) {
while (actualType) {
if (actualType === expectedType)
return true
actualType = actualType.extends;
var currentActualType = actualType;
while (currentActualType) {
if (currentActualType === expectedType)
return true;
currentActualType = currentActualType.extends;
}
return false
return false;
}
function isMapLike(thing) {
return thing && typeof thing.keys === "function" && typeof thing.clear === "function"
return thing && typeof thing.keys === "function" && typeof thing.clear === "function";
}
function getIdentifierProp(modelSchema) {
invariant(isModelSchema(modelSchema));
invariant(isModelSchema(modelSchema), "modelSchema must be a ModelSchema");
// optimization: cache this lookup
while (modelSchema) {
for (var propName in modelSchema.props)
if (typeof modelSchema.props[propName] === "object" && modelSchema.props[propName].identifier === true)
return propName
modelSchema = modelSchema.extends;
var currentModelSchema = modelSchema;
while (currentModelSchema) {
for (var propName in currentModelSchema.props)
if (isIdentifierPropSchema(currentModelSchema.props[propName]))
return propName;
currentModelSchema = currentModelSchema.extends;
}
return null
return undefined;
}
function processAdditionalPropArgs(propSchema, additionalArgs) {
if (additionalArgs) {
invariant(isPropSchema(propSchema), "expected a propSchema");
var argNames = ["beforeDeserialize", "afterDeserialize"];
argNames.forEach(function(argName) {
if (typeof additionalArgs[argName] === "function") {
propSchema[argName] = additionalArgs[argName];
}
});
Object.assign(propSchema, additionalArgs);
}
return propSchema
return propSchema;
}

@@ -174,14 +160,12 @@

*
* @param {object} thing
* @returns {ModelSchema} model schema
*/
function getDefaultModelSchema(thing) {
if (!thing)
return null
return undefined;
if (isModelSchema(thing))
return thing
return thing;
if (isModelSchema(thing.serializeInfo))
return thing.serializeInfo
return thing.serializeInfo;
if (thing.constructor && thing.constructor.serializeInfo)
return thing.constructor.serializeInfo
return thing.constructor.serializeInfo;
}

@@ -197,9 +181,10 @@

*
* @param {constructor|class} clazz class or constructor function
* @param {ModelSchema} modelSchema - a model schema
* @returns {ModelSchema} model schema
* @param clazz class or constructor function
* @param modelSchema - a model schema
* @returns model schema
*/
function setDefaultModelSchema(clazz, modelSchema) {
invariant(isModelSchema(modelSchema));
return clazz.serializeInfo = modelSchema
invariant(isModelSchema(modelSchema), "expected modelSchema, got " + modelSchema);
clazz.serializeInfo = modelSchema;
return modelSchema;
}

@@ -214,4 +199,4 @@

* function Todo(title, done) {
* this.title = title;
* this.done = done;
* this.title = title
* this.done = done
* }

@@ -222,11 +207,11 @@ *

* done: true,
* });
* })
*
* var json = serialize(new Todo('Test', false));
* var todo = deserialize(Todo, json);
* const json = serialize(new Todo('Test', false))
* const todo = deserialize(Todo, json)
*
* @param {constructor|class} clazz class or constructor function
* @param {object} props property mapping
* @param {function} factory optional custom factory. Receives context as first arg
* @returns {object} model schema
* @param clazz class or constructor function
* @param props property mapping
* @param factory optional custom factory. Receives context as first arg
* @returns model schema
*/

@@ -238,5 +223,6 @@ function createModelSchema(clazz, props, factory) {

targetClass: clazz,
factory: factory || function() {
return new clazz()
},
factory: factory ||
function () {
return new clazz();
},
props: props

@@ -251,5 +237,28 @@ };

setDefaultModelSchema(clazz, model);
return model
return model;
}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */
function __spreadArrays() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
}
/**

@@ -261,9 +270,7 @@ * Indicates that this field contains a primitive value (or Date) which should be serialized literally to json.

* title: primitive(),
* });
* })
*
* console.dir(serialize(new Todo('test')));
* // outputs: { title : "test" }
* serialize(new Todo('test')) // { "title": "test" }
*
* @param {AdditionalPropArgs} additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
* @returns {ModelSchema}
* @param additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
*/

@@ -274,47 +281,58 @@ function primitive(additionalArgs) {

invariant(isPrimitive(value), "this value is not primitive: " + value);
return value
return value;
},
deserializer: function (jsonValue, done) {
if (!isPrimitive(jsonValue))
return void done("[serializr] this value is not primitive: " + jsonValue)
return void done(null, jsonValue)
return void done("[serializr] this value is not primitive: " + jsonValue);
return void done(null, jsonValue);
}
};
result = processAdditionalPropArgs(result, additionalArgs);
return result
return result;
}
/**
* In the event that a property needs to be deserialized, but not serialized, you can use the SKIP symbol to omit the property. This has to be used with the custom serializer.
* If you want to skip serialization or deserialization, you can use SKIP.
*
* @example
* var schema = _.createSimpleSchema({
* a: _.custom(
* function(v) {
* return _.SKIP
* },
* function(v) {
* return v;
* }
* const schema = createSimpleSchema({
* a: custom(
* () => SKIP,
* v => v,
* ),
* });
* t.deepEqual(_.serialize(s, { a: 4 }), { });
* t.deepEqual(_.deserialize(s, { a: 4 }), { a: 4 });
* })
* serialize(s, { a: 4 }) // {}
* deserialize(s, { "a": 4 }) // { a: 4 }
*
* @example
* // Skipping deserialization with computed mobx property.
*
* class TodoState {
* // Todo.category is @serializable(reference(...))
* \@serializable(list(object(Todo)))
* \@observable
* todos: Todo[]
*
* // we want to serialize the categories, so that the references in
* // this.todos can be resolved, but we don't want to set this property
* \@serializable(
* list(object(TodoCategory),
* { afterDeserialize: callback => callback(undefined, SKIP) }))
* \@computed
* get categories() {
* return this.todos.map(todo => todo.category)
* }
* }
*/
var SKIP = typeof Symbol !== "undefined" ? Symbol("SKIP") : { SKIP: true };
var _defaultPrimitiveProp = primitive();
// Ugly way to get the parameter names since they aren't easily retrievable via reflection
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
var ARGUMENT_NAMES = /([^\s,]+)/g;
function getParamNames(func) {
var _a;
var fnStr = func.toString().replace(STRIP_COMMENTS, "");
var result = fnStr.slice(fnStr.indexOf("(")+1, fnStr.indexOf(")")).match(ARGUMENT_NAMES);
if(result === null)
result = [];
return result
return _a = fnStr.slice(fnStr.indexOf("(") + 1, fnStr.indexOf(")")).match(ARGUMENT_NAMES), (_a !== null && _a !== void 0 ? _a : []);
}
function serializableDecorator(propSchema, target, propName, descriptor) {

@@ -324,7 +342,9 @@ invariant(arguments.length >= 2, "too few arguments. Please use @serializable as property decorator");

var factory;
if (propName === undefined && typeof target === "function"
&& target.prototype
&& descriptor !== undefined && typeof descriptor === "number") {
if (propName === undefined &&
typeof target === "function" &&
target.prototype &&
descriptor !== undefined &&
typeof descriptor === "number") {
invariant(isPropSchema(propSchema), "Constructor params must use alias(name)");
invariant(propSchema.jsonname, "Constructor params must use alias(name)");
invariant(isAliasedPropSchema(propSchema), "Constructor params must use alias(name)");
var paramNames = getParamNames(target);

@@ -337,5 +357,6 @@ if (paramNames.length >= descriptor) {

// Create a factory so the constructor is called properly
factory = function(context) {
factory = function (context) {
var _a;
var params = [];
for (var i = 0; i < target.constructor.length; i++) {
var _loop_1 = function (i) {
Object.keys(context.modelSchema.props).forEach(function (key) {

@@ -347,5 +368,7 @@ var prop = context.modelSchema.props[key];

});
};
for (var i = 0; i < target.constructor.length; i++) {
_loop_1(i);
}
return new (Function.prototype.bind.apply(target.constructor, [null].concat(params)))
return (_a = target.constructor).bind.apply(_a, __spreadArrays([undefined], params));
};

@@ -356,3 +379,2 @@ }

var info = getDefaultModelSchema(target);
if (!info || !target.constructor.hasOwnProperty("serializeInfo"))

@@ -367,82 +389,43 @@ info = createModelSchema(target.constructor, {}, factory);

descriptor.writable = true;
return descriptor
return descriptor;
}
/**
* Decorator that defines a new property mapping on the default model schema for the class
* it is used in.
*
* When using typescript, the decorator can also be used on fields declared as constructor arguments (using the `private` / `protected` / `public` keywords).
* The default factory will then invoke the constructor with the correct arguments as well.
*
* @example
* class Todo {
* @serializable(primitive())
* title; // shorthand for primitves
*
* @serializable done;
*
* constructor(title, done) {
* this.title = title;
* this.done = done;
* }
* }
*
* var json = serialize(new Todo('Test', false));
* var todo = deserialize(Todo, json);
*
* @param arg1
* @param arg2
* @param arg3
* @returns {PropertyDescriptor}
*/
function serializable(arg1, arg2, arg3) {
if (arguments.length === 1) {
function serializable(targetOrPropSchema, key, baseDescriptor) {
if (!key) {
// decorated with propSchema
var propSchema = arg1 === true ? _defaultPrimitiveProp : arg1;
var propSchema = targetOrPropSchema === true ? _defaultPrimitiveProp : targetOrPropSchema;
invariant(isPropSchema(propSchema), "@serializable expects prop schema");
return serializableDecorator.bind(null, propSchema)
} else {
var result = serializableDecorator.bind(null, propSchema);
return result;
}
else {
// decorated without arguments, treat as primitive
return serializableDecorator(primitive(), arg1, arg2, arg3)
serializableDecorator(primitive(), targetOrPropSchema, key, baseDescriptor);
}
}
/**
* Serializes an object (graph) into json using the provided model schema.
* The model schema can be omitted if the object type has a default model schema associated with it.
* If a list of objects is provided, they should have an uniform type.
*
* @param arg1 class or modelschema to use. Optional
* @param arg2 object(s) to serialize
* @returns {object} serialized representation of the object
*/
function serialize(arg1, arg2) {
function serialize(modelSchemaOrInstance, arg2) {
invariant(arguments.length === 1 || arguments.length === 2, "serialize expects one or 2 arguments");
var thing = arguments.length === 1 ? arg1 : arg2;
var schema = arguments.length === 1 ? null : arg1;
if (Array.isArray(thing)) {
if (thing.length === 0)
return [] // don't bother finding a schema
var instance = ((arg2 !== null && arg2 !== void 0 ? arg2 : modelSchemaOrInstance));
var schema = (arg2 && modelSchemaOrInstance);
if (Array.isArray(instance)) {
if (instance.length === 0)
return [];
// don't bother finding a schema
else if (!schema)
schema = getDefaultModelSchema(thing[0]);
schema = getDefaultModelSchema(instance[0]);
else if (typeof schema !== "object")
schema = getDefaultModelSchema(schema);
} else if (!schema) {
schema = getDefaultModelSchema(thing);
} else if (typeof schema !== "object") {
}
else if (!schema) {
schema = getDefaultModelSchema(instance);
}
else if (typeof schema !== "object") {
schema = getDefaultModelSchema(schema);
}
invariant(!!schema, "Failed to find default schema for " + arg1);
if (Array.isArray(thing))
return thing.map(function (item) {
return serializeWithSchema(schema, item)
})
return serializeWithSchema(schema, thing)
var foundSchema = schema;
invariant(foundSchema, "Failed to find default schema for " + modelSchemaOrInstance);
if (Array.isArray(instance))
return instance.map(function (item) { return serializeWithSchema(foundSchema, item); });
return serializeWithSchema(foundSchema, instance);
}
function checkStarSchemaInvariant(propDef) {
invariant(propDef === true || propDef.pattern, "prop schema '*' can only be used with 'true' or a prop def with a 'pattern': " + JSON.stringify(propDef));
}
function serializeWithSchema(schema, obj) {

@@ -460,42 +443,37 @@ invariant(schema && typeof schema === "object" && schema.props, "Expected schema");

var propDef = schema.props[key];
if (!propDef)
return;
if (key === "*") {
serializeStarProps(schema, propDef, obj, res);
return
return;
}
if (propDef === true)
propDef = _defaultPrimitiveProp;
if (propDef === false)
return
var jsonValue = propDef.serializer(obj[key], key, obj);
if (jsonValue === SKIP){
return
if (jsonValue === SKIP) {
return;
}
res[propDef.jsonname || key] = jsonValue;
});
return res
return res;
}
function serializeStarProps(schema, propDef, obj, target) {
checkStarSchemaInvariant(propDef);
for (var key in obj) if (obj.hasOwnProperty(key)) if (!(key in schema.props)) {
if ((propDef === true) || (propDef.pattern && propDef.pattern.test(key))) {
var value = obj[key];
if (propDef === true) {
if (isPrimitive(value)) {
target[key] = value;
for (var _i = 0, _a = Object.keys(obj); _i < _a.length; _i++) {
var key = _a[_i];
if (!(key in schema.props)) {
if (propDef === true || (propDef && (!propDef.pattern || propDef.pattern.test(key)))) {
var value = obj[key];
if (propDef === true) {
if (isPrimitive(value)) {
target[key] = value;
}
}
} else if (propDef.props) {
var jsonValue = serialize(propDef, value);
if (jsonValue === SKIP){
return
else {
var jsonValue = propDef.serializer(value, key, obj);
if (jsonValue === SKIP) {
return;
}
// TODO: propDef.jsonname could be a transform function on key
target[key] = jsonValue;
}
// todo: propDef.jsonname could be a transform function on key
target[key] = jsonValue;
} else {
var jsonValue = propDef.serializer(value, key, obj);
if (jsonValue === SKIP){
return
}
// todo: propDef.jsonname could be a transform function on key
target[key] = jsonValue;
}

@@ -507,122 +485,121 @@ }

var rootContextCache = new WeakMap();
function Context(parentContext, modelSchema, json, onReadyCb, customArgs) {
this.parentContext = parentContext;
this.isRoot = !parentContext;
this.pendingCallbacks = 0;
this.pendingRefsCount = 0;
this.onReadyCb = onReadyCb || GUARDED_NOOP;
this.json = json;
this.target = null; // always set this property using setTarget
this.hasError = false;
this.modelSchema = modelSchema;
if (this.isRoot) {
this.rootContext = this;
this.args = customArgs;
this.pendingRefs = {}; // uuid: [{ modelSchema, uuid, cb }]
this.resolvedRefs = {}; // uuid: [{ modelSchema, value }]
} else {
this.rootContext = parentContext.rootContext;
this.args = parentContext.args;
var Context = /** @class */ (function () {
function Context(parentContext, modelSchema, json, onReadyCb, customArgs) {
this.parentContext = parentContext;
this.modelSchema = modelSchema;
this.json = json;
this.onReadyCb = onReadyCb;
this.isRoot = !parentContext;
this.pendingCallbacks = 0;
this.pendingRefsCount = 0;
this.target = undefined; // always set this property using setTarget
this.hasError = false;
if (!parentContext) {
this.rootContext = this;
this.args = customArgs;
this.pendingRefs = {};
this.resolvedRefs = {};
}
else {
this.rootContext = parentContext.rootContext;
this.args = parentContext.args;
}
}
}
Context.prototype.createCallback = function (fn) {
this.pendingCallbacks++;
// once: defend against user-land calling 'done' twice
return once(function (err, value) {
if (err) {
if (!this.hasError) {
this.hasError = true;
this.onReadyCb(err);
rootContextCache.delete(this);
Context.prototype.createCallback = function (fn) {
var _this = this;
this.pendingCallbacks++;
// once: defend against user-land calling 'done' twice
return once(function (err, value) {
if (err) {
if (!_this.hasError) {
_this.hasError = true;
_this.onReadyCb(err);
rootContextCache.delete(_this);
}
}
} else if (!this.hasError) {
fn(value);
if (--this.pendingCallbacks === this.pendingRefsCount) {
if (this.pendingRefsCount > 0) {
// all pending callbacks are pending reference resolvers. not good.
this.onReadyCb(new Error(
"Unresolvable references in json: \"" +
Object.keys(this.pendingRefs).filter(function (uuid) {
return this.pendingRefs[uuid].length > 0
}, this).join("\", \"") +
"\""
));
rootContextCache.delete(this);
} else {
this.onReadyCb(null, this.target);
rootContextCache.delete(this);
else if (!_this.hasError) {
fn(value);
if (--_this.pendingCallbacks === _this.pendingRefsCount) {
if (_this.pendingRefsCount > 0) {
// all pending callbacks are pending reference resolvers. not good.
_this.onReadyCb(new Error('Unresolvable references in json: "' +
Object.keys(_this.pendingRefs)
.filter(function (uuid) { return _this.pendingRefs[uuid].length > 0; })
.join('", "') +
'"'));
rootContextCache.delete(_this);
}
else {
_this.onReadyCb(null, _this.target);
rootContextCache.delete(_this);
}
}
}
});
};
// given an object with uuid, modelSchema, callback, awaits until the given uuid is available
// resolve immediately if possible
Context.prototype.await = function (modelSchema, uuid, callback) {
invariant(this.isRoot, "await can only be called on the root context");
if (uuid in this.resolvedRefs) {
var match = this.resolvedRefs[uuid].filter(function (resolved) {
return isAssignableTo(resolved.modelSchema, modelSchema);
})[0];
if (match)
return void callback(null, match.value);
}
}.bind(this))
};
// given an object with uuid, modelSchema, callback, awaits until the given uuid is available
// resolve immediately if possible
Context.prototype.await = function (modelSchema, uuid, callback) {
invariant(this.isRoot);
if (uuid in this.resolvedRefs) {
var match = this.resolvedRefs[uuid].filter(function (resolved) {
return isAssignableTo(resolved.modelSchema, modelSchema)
})[0];
if (match)
return void callback(null, match.value)
}
this.pendingRefsCount++;
if (!this.pendingRefs[uuid])
this.pendingRefs[uuid] = [];
this.pendingRefs[uuid].push({
modelSchema: modelSchema,
uuid: uuid,
callback: callback
});
};
// given a model schema, uuid and value, resolve all references that where looking for this object
Context.prototype.resolve = function (modelSchema, uuid, value) {
invariant(this.isRoot);
if (!this.resolvedRefs[uuid])
this.resolvedRefs[uuid] = [];
this.resolvedRefs[uuid].push({
modelSchema: modelSchema, value: value
});
if (uuid in this.pendingRefs) {
for (var i = this.pendingRefs[uuid].length - 1; i >= 0; i--) {
var opts = this.pendingRefs[uuid][i];
if (isAssignableTo(modelSchema, opts.modelSchema)) {
this.pendingRefs[uuid].splice(i, 1);
this.pendingRefsCount--;
opts.callback(null, value);
this.pendingRefsCount++;
if (!this.pendingRefs[uuid])
this.pendingRefs[uuid] = [];
this.pendingRefs[uuid].push({
modelSchema: modelSchema,
uuid: uuid,
callback: callback
});
};
// given a model schema, uuid and value, resolve all references that were looking for this object
Context.prototype.resolve = function (modelSchema, uuid, value) {
invariant(this.isRoot, "resolve can only called on the root context");
if (!this.resolvedRefs[uuid])
this.resolvedRefs[uuid] = [];
this.resolvedRefs[uuid].push({
modelSchema: modelSchema,
value: value
});
if (uuid in this.pendingRefs) {
for (var i = this.pendingRefs[uuid].length - 1; i >= 0; i--) {
var opts = this.pendingRefs[uuid][i];
if (isAssignableTo(modelSchema, opts.modelSchema)) {
this.pendingRefs[uuid].splice(i, 1);
this.pendingRefsCount--;
opts.callback(null, value);
}
}
}
}
};
// set target and update root context cache
Context.prototype.setTarget = function (target) {
if (this.isRoot && this.target) {
rootContextCache.delete(this.target);
}
this.target = target;
rootContextCache.set(this.target, this);
};
// call all remaining reference lookup callbacks indicating an error during ref resolution
Context.prototype.cancelAwaits = function () {
invariant(this.isRoot);
var self = this;
Object.keys(this.pendingRefs).forEach(function (uuid) {
self.pendingRefs[uuid].forEach(function (refOpts) {
self.pendingRefsCount--;
refOpts.callback(new Error("Reference resolution canceled for " + uuid));
};
// set target and update root context cache
Context.prototype.setTarget = function (target) {
if (this.isRoot && this.target) {
rootContextCache.delete(this.target);
}
this.target = target;
rootContextCache.set(this.target, this);
};
// call all remaining reference lookup callbacks indicating an error during ref resolution
Context.prototype.cancelAwaits = function () {
invariant(this.isRoot, "cancelAwaits can only be called on the root context");
var self = this;
Object.keys(this.pendingRefs).forEach(function (uuid) {
self.pendingRefs[uuid].forEach(function (refOpts) {
self.pendingRefsCount--;
refOpts.callback(new Error("Reference resolution canceled for " + uuid));
});
});
});
this.pendingRefs = {};
this.pendingRefsCount = 0;
};
this.pendingRefs = {};
this.pendingRefsCount = 0;
};
return Context;
}());
function getTargetContext(target) {
return rootContextCache.get(target)
return rootContextCache.get(target);
}

@@ -633,85 +610,57 @@

*/
function schemaHasAlias(schema, name) {
for (var key in schema.props)
if (typeof schema.props[key] === "object" && schema.props[key].jsonname === name)
return true
return false
for (var key in schema.props) {
var propSchema = schema.props[key];
if (typeof propSchema === "object" && propSchema.jsonname === name)
return true;
}
return false;
}
function deserializeStarProps(context, schema, propDef, obj, json) {
checkStarSchemaInvariant(propDef);
for (var key in json) if (!(key in schema.props) && !schemaHasAlias(schema, key)) {
var jsonValue = json[key];
if (propDef === true) {
// when deserializing we don't want to silently ignore 'unparseable data' to avoid
// confusing bugs
invariant(isPrimitive(jsonValue),
"encountered non primitive value while deserializing '*' properties in property '" +
key + "': " + jsonValue);
obj[key] = jsonValue;
} else if (propDef.pattern.test(key)) {
if (propDef.factory) {
var resultValue = deserializeObjectWithSchema(context, propDef, jsonValue, context.callback || GUARDED_NOOP, {});
// deserializeObjectWithSchema returns undefined on error
if (resultValue !== undefined) {
obj[key] = resultValue;
}
} else {
function setValue(resultValue) {
if (resultValue !== SKIP) {
obj[key] = resultValue;
}
}
propDef.deserializer(jsonValue,
// for individual props, use root context based callbacks
// this allows props to complete after completing the object itself
// enabling reference resolving and such
context.rootContext.createCallback(setValue),
context);
var _loop_1 = function (key) {
if (!(key in schema.props) && !schemaHasAlias(schema, key)) {
var jsonValue = json[key];
if (propDef === true) {
// when deserializing we don't want to silently ignore 'unparseable data' to avoid
// confusing bugs
invariant(isPrimitive(jsonValue), "encountered non primitive value while deserializing '*' properties in property '" +
key +
"': " +
jsonValue);
obj[key] = jsonValue;
}
else if (propDef && (!propDef.pattern || propDef.pattern.test(key))) {
propDef.deserializer(jsonValue,
// for individual props, use root context based callbacks
// this allows props to complete after completing the object itself
// enabling reference resolving and such
context.rootContext.createCallback(function (r) { return r !== SKIP && (obj[key] = r); }), context);
}
}
};
for (var key in json) {
_loop_1(key);
}
}
/**
* Deserializes a json structure into an object graph.
*
* This process might be asynchronous (for example if there are references with an asynchronous
* lookup function). The function returns an object (or array of objects), but the returned object
* might be incomplete until the callback has fired as well (which might happen immediately)
*
* @param {object|array} schema to use for deserialization
* @param {json} json data to deserialize
* @param {function} callback node style callback that is invoked once the deserialization has
* finished. First argument is the optional error, second argument is the deserialized object
* (same as the return value)
* @param {*} customArgs custom arguments that are available as `context.args` during the
* deserialization process. This can be used as dependency injection mechanism to pass in, for
* example, stores.
* @returns {object|array} deserialized object, possibly incomplete.
*/
function deserialize(schema, json, callback, customArgs) {
function deserialize(clazzOrModelSchema, json, callback, customArgs) {
if (callback === void 0) { callback = GUARDED_NOOP; }
invariant(arguments.length >= 2, "deserialize expects at least 2 arguments");
schema = getDefaultModelSchema(schema);
var schema = getDefaultModelSchema(clazzOrModelSchema);
invariant(isModelSchema(schema), "first argument should be model schema");
if (Array.isArray(json)) {
var items = [];
parallel(
json,
function (childJson, itemDone) {
var instance = deserializeObjectWithSchema(null, schema, childJson, itemDone, customArgs);
// instance is created synchronously so can be pushed
items.push(instance);
},
callback || GUARDED_NOOP
);
return items
} else
return deserializeObjectWithSchema(null, schema, json, callback, customArgs)
var items_1 = [];
parallel(json, function (childJson, itemDone) {
var instance = deserializeObjectWithSchema(undefined, schema, childJson, itemDone, customArgs);
// instance is created synchronously so can be pushed
items_1.push(instance);
}, callback);
return items_1;
}
else {
return deserializeObjectWithSchema(undefined, schema, json, callback, customArgs);
}
}
function deserializeObjectWithSchema(parentContext, modelSchema, json, callback, customArgs) {
if (json === null || json === undefined || typeof json !== "object")
return void callback(null, null)
return void callback(null, null);
var context = new Context(parentContext, modelSchema, json, callback, customArgs);

@@ -728,94 +677,63 @@ var target = modelSchema.factory(context);

lock();
return target
return target;
}
function deserializePropsWithSchema(context, modelSchema, json, target) {
var _a;
if (modelSchema.extends)
deserializePropsWithSchema(context, modelSchema.extends, json, target);
function deserializeProp(propDef, jsonValue, propName) {
function setValue(value) {
if (value !== SKIP) {
target[propName] = value;
}
}
function preProcess(resultCallback) {
return function (err, newValue) {
function finalCallback(errPreliminary, finalOrRetryValue) {
if (errPreliminary && finalOrRetryValue !== undefined &&
typeof propDef.afterDeserialize === "function") {
propDef.deserializer(
finalOrRetryValue,
preProcess(resultCallback),
context,
target[propName]
);
} else {
resultCallback(errPreliminary, finalOrRetryValue);
}
}
onAfterDeserialize(finalCallback, err, newValue, jsonValue, json,
propName, context, propDef);
}
}
propDef.deserializer(
jsonValue,
// for individual props, use root context based callbacks
// this allows props to complete after completing the object itself
// enabling reference resolving and such
preProcess(context.rootContext.createCallback(setValue)),
context,
target[propName] // initial value
var whenDone = context.rootContext.createCallback(function (r) { return r !== SKIP && (target[propName] = r); });
propDef.deserializer(jsonValue,
// for individual props, use root context based callbacks
// this allows props to complete after completing the object itself
// enabling reference resolving and such
function (err, newValue) {
return onAfterDeserialize(whenDone, err, newValue, jsonValue, json, propName, context, propDef);
}, context, target[propName] // initial value
);
}
Object.keys(modelSchema.props).forEach(function (propName) {
var propDef = modelSchema.props[propName];
function callbackDeserialize(err, jsonValue) {
if (!err && jsonValue !== undefined) {
deserializeProp(propDef, jsonValue, propName);
}
}
if (propName === "*") {
var _loop_2 = function (key) {
var propDef = modelSchema.props[key];
if (!propDef)
return { value: void 0 };
if (key === "*") {
deserializeStarProps(context, modelSchema, propDef, target, json);
return
return { value: void 0 };
}
if (propDef === true)
propDef = _defaultPrimitiveProp;
if (propDef === false)
return
var jsonAttr = propDef.jsonname || propName;
var jsonAttr = (_a = propDef.jsonname, (_a !== null && _a !== void 0 ? _a : key));
invariant("symbol" !== typeof jsonAttr, "You must alias symbol properties. prop = %l", key);
var jsonValue = json[jsonAttr];
var propSchema = propDef;
var callbackDeserialize = function (err, jsonValue) {
if (!err && jsonValue !== undefined) {
deserializeProp(propSchema, jsonValue, key);
}
};
onBeforeDeserialize(callbackDeserialize, jsonValue, json, jsonAttr, context, propDef);
});
};
for (var _i = 0, _b = Object.keys(modelSchema.props); _i < _b.length; _i++) {
var key = _b[_i];
var state_1 = _loop_2(key);
if (typeof state_1 === "object")
return state_1.value;
}
}
function onBeforeDeserialize(
callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef) {
var onBeforeDeserialize = function (callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef) {
if (propDef && typeof propDef.beforeDeserialize === "function") {
propDef.beforeDeserialize(callback, jsonValue, jsonParentValue, propNameOrIndex, context,
propDef);
} else {
propDef.beforeDeserialize(callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef);
}
else {
callback(null, jsonValue);
}
}
function onAfterDeserialize(
callback, err, newValue, jsonValue, jsonParentValue, propNameOrIndex, context, propDef) {
};
var onAfterDeserialize = function (callback, err, newValue, jsonValue, jsonParentValue, propNameOrIndex, context, propDef) {
if (propDef && typeof propDef.afterDeserialize === "function") {
propDef.afterDeserialize(callback, err, newValue, jsonValue, jsonParentValue,
propNameOrIndex, context, propDef);
} else {
propDef.afterDeserialize(callback, err, newValue, jsonValue, jsonParentValue, propNameOrIndex, context, propDef);
}
else {
callback(err, newValue);
}
}
};

@@ -834,7 +752,7 @@ /**

* title: true,
* });
* })
* createModelSchema(Todo, {
* title: true,
* subTask: object(SubTask),
* });
* })
*

@@ -846,7 +764,6 @@ * const todo = deserialize(Todo, {

* },
* });
* })
*
* @param {ModelSchema} modelSchema to be used to (de)serialize the object
* @param {AdditionalPropArgs} additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
* @returns {PropSchema}
* @param modelSchema to be used to (de)serialize the object
* @param additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
*/

@@ -860,4 +777,4 @@ function object(modelSchema, additionalArgs) {

if (item === null || item === undefined)
return item
return serialize(modelSchema, item)
return item;
return serialize(modelSchema, item);
},

@@ -868,70 +785,40 @@ deserializer: function (childJson, done, context) {

if (childJson === null || childJson === undefined)
return void done(null, childJson)
return void deserializeObjectWithSchema(context, modelSchema, childJson, done, additionalArgs)
return void done(null, childJson);
return void deserializeObjectWithSchema(context, modelSchema, childJson, done, undefined);
}
};
result = processAdditionalPropArgs(result, additionalArgs);
return result
return result;
}
/**
* The `serializeAll` decorator can may used on a class to signal that all primitive properties,
* or complex properties with a name matching a `pattern`, should be serialized automatically.
*
* @example
* @serializeAll class Store {
* a = 3;
* b;
* }
*
* const store = new Store();
* store.c = 5;
* store.d = {};
* t.deepEqual(serialize(store), { c: 5 });
*
* @example
* class DataType {
* @serializable
* x;
* @serializable
* y;
* }
* @serializeAll(/^[a-z]$/, DataType) class ComplexStore {
* }
*
* const store = new ComplexStore();
* store.a = {x: 1, y: 2};
* store.b = {};
* store.somethingElse = 5;
* t.deepEqual(serialize(store), { a: {x: 1, y: 2}, b: { x: undefined, y: undefined } });
*/
function serializeAll(targetOrPattern, clazzOrSchema) {
let propSchema;
let invokeImmediately = false;
function serializeAll(targetOrPattern, propertyType) {
var propSchema;
if (arguments.length === 1) {
invariant(typeof targetOrPattern === "function", "@serializeAll can only be used as class decorator");
propSchema = true;
invokeImmediately = true;
return decorator(targetOrPattern);
}
else {
invariant(typeof targetOrPattern === "object" && targetOrPattern.test, "@serializeAll pattern doesn't have test");
if (typeof clazzOrSchema === "function") {
clazzOrSchema = object(clazzOrSchema);
if (typeof propertyType === "function") {
propertyType = object(propertyType);
}
invariant(typeof clazzOrSchema === "object" && clazzOrSchema.serializer, "couldn't resolve schema");
propSchema = Object.assign({}, clazzOrSchema, {pattern: targetOrPattern});
if (true === propertyType) {
propertyType = _defaultPrimitiveProp;
}
invariant(isPropSchema(propertyType), "couldn't resolve schema");
propSchema = Object.assign({}, propertyType, {
pattern: targetOrPattern
});
}
function result(target) {
function decorator(target) {
invariant(typeof target === "function", "@serializeAll can only be used as class decorator");
var info = getDefaultModelSchema(target);
if (!info || !target.hasOwnProperty("serializeInfo")) {
if (!info) {
info = createModelSchema(target, {});
setDefaultModelSchema(target, info);
}
getDefaultModelSchema(target).props["*"] = propSchema;
info.props["*"] = propSchema;
return target;
}
if (invokeImmediately) {
return result(targetOrPattern);
}
return result;
return decorator;
}

@@ -942,4 +829,2 @@

*/
/**

@@ -960,20 +845,4 @@ * Cancels an asynchronous deserialization or update operation for the specified target object.

*/
/**
* Similar to deserialize, but updates an existing object instance.
* Properties will always updated entirely, but properties not present in the json will be kept as is.
* Further this method behaves similar to deserialize.
*
* @param {object} modelSchema, optional if it can be inferred from the instance type
* @param {object} target target instance to update
* @param {object} json the json to deserialize
* @param {function} callback the callback to invoke once deserialization has completed.
* @param {*} customArgs custom arguments that are available as `context.args` during the deserialization process. This can be used as dependency injection mechanism to pass in, for example, stores.
* @returns {object|array} deserialized object, possibly incomplete.
*/
function update(modelSchema, target, json, callback, customArgs) {
var inferModelSchema =
arguments.length === 2 // only target and json
|| typeof arguments[2] === "function"; // callback as third arg
var inferModelSchema = arguments.length === 2 || typeof arguments[2] === "function"; // only target and json // callback as third arg
if (inferModelSchema) {

@@ -985,3 +854,4 @@ target = arguments[0];

customArgs = arguments[3];
} else {
}
else {
modelSchema = getDefaultModelSchema(modelSchema);

@@ -991,3 +861,3 @@ }

invariant(typeof target === "object" && target && !Array.isArray(target), "update needs an object");
var context = new Context(null, modelSchema, json, callback, customArgs);
var context = new Context(undefined, modelSchema, json, callback || GUARDED_NOOP, customArgs);
context.setTarget(target);

@@ -997,50 +867,16 @@ var lock = context.createCallback(GUARDED_NOOP);

lock();
return result
return result;
}
function defaultRegisterFunction(id, value, context) {
var defaultRegisterFunction = function (id, value, context) {
context.rootContext.resolve(context.modelSchema, id, context.target);
}
/**
*
*
* Similar to primitive, but this field will be marked as the identifier for the given Model type.
* This is used by for example `reference()` to serialize the reference
*
* Identifier accepts an optional `registerFn` with the signature:
* `(id, target, context) => void`
* that can be used to register this object in some store. note that not all fields of this object might
* have been deserialized yet.
*
* @example
* var todos = {};
*
* var s = _.createSimpleSchema({
* id: _.identifier((id, object) => (todos[id] = object)),
* title: true,
* });
*
* _.deserialize(s, {
* id: 1,
* title: 'test0',
* });
* _.deserialize(s, [{ id: 2, title: 'test2' }, { id: 1, title: 'test1' }]);
*
* t.deepEqual(todos, {
* 1: { id: 1, title: 'test1' },
* 2: { id: 2, title: 'test2' },
* });
*
* @param { RegisterFunction | AdditionalPropArgs } arg1 optional registerFn: function to register this object during creation.
* @param {AdditionalPropArgs} arg2 optional object that contains beforeDeserialize and/or afterDeserialize handlers
*
* @returns {PropSchema}
*/
};
function identifier(arg1, arg2) {
var registerFn, additionalArgs;
var registerFn;
var additionalArgs;
if (typeof arg1 === "function") {
registerFn = arg1;
additionalArgs = arg2;
} else {
}
else {
additionalArgs = arg1;

@@ -1053,3 +889,3 @@ }

deserializer: function (jsonValue, done, context) {
_defaultPrimitiveProp.deserializer(jsonValue, function(err, id) {
_defaultPrimitiveProp.deserializer(jsonValue, function (err, id) {
defaultRegisterFunction(id, context.target, context);

@@ -1059,7 +895,7 @@ if (registerFn)

done(err, id);
});
}, context);
}
};
result = processAdditionalPropArgs(result, additionalArgs);
return result
return result;
}

@@ -1070,4 +906,3 @@

*
* @param {AdditionalPropArgs} additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
* @returns {PropSchema}
* @param additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
*/

@@ -1077,16 +912,16 @@ function date(additionalArgs) {

var result = {
serializer: function(value) {
serializer: function (value) {
if (value === null || value === undefined)
return value
return value;
invariant(value instanceof Date, "Expected Date object");
return value.getTime()
return value.getTime();
},
deserializer: function (jsonValue, done) {
if (jsonValue === null || jsonValue === undefined)
return void done(null, jsonValue)
return void done(null, new Date(jsonValue))
return void done(null, jsonValue);
return void done(null, new Date(jsonValue));
}
};
result = processAdditionalPropArgs(result, additionalArgs);
return result
return result;
}

@@ -1101,14 +936,12 @@

* title: alias('task', primitive()),
* });
* })
*
* console.dir(serialize(new Todo('test')));
* // { task : "test" }
* serialize(new Todo('test')) // { "task": "test" }
*
* @param {string} name name of the json field to be used for this property
* @param {PropSchema} propSchema propSchema to (de)serialize the contents of this field
* @returns {PropSchema}
* @param name name of the json field to be used for this property
* @param propSchema propSchema to (de)serialize the contents of this field
*/
function alias(name, propSchema) {
invariant(name && typeof name === "string", "expected prop name as first argument");
propSchema = (!propSchema || propSchema === true) ? _defaultPrimitiveProp : propSchema;
propSchema = !propSchema || propSchema === true ? _defaultPrimitiveProp : propSchema;
invariant(isPropSchema(propSchema), "expected prop schema as second argument");

@@ -1120,75 +953,19 @@ invariant(!isAliasedPropSchema(propSchema), "provided prop is already aliased");

deserializer: propSchema.deserializer,
identifier: isIdentifierPropSchema(propSchema),
identifier: isIdentifierPropSchema(propSchema) || undefined,
beforeDeserialize: propSchema.beforeDeserialize,
afterDeserialize: propSchema.afterDeserialize
}
};
}
/**
* Can be used to create simple custom propSchema. Multiple things can be done inside of a custom propSchema, like deserializing and serializing other (polymorphic) objects, skipping the serialization of something or checking the context of the obj being (de)serialized.
* The `custom` function takes two parameters, the `serializer` function and the `deserializer` function.
* The `serializer` function has the signature:
* `(value, key, obj) => void`
* When serializing the object `{a: 1}` the `serializer` function will be called with `serializer(1, 'a', {a: 1})`.
* The `deserializer` function has the following signature for synchronous processing
* `(value, context, oldValue) => void`
* For asynchronous processing the function expects the following signature
* `(value, context, oldValue, callback) => void`
* When deserializing the object `{b: 2}` the `deserializer` function will be called with `deserializer(2, contextObj)` ([contextObj reference](https://github.com/mobxjs/serializr#deserialization-context)).
*
* @example
* var schemaDefault = _.createSimpleSchema({
* a: _.custom(
* function(v) {
* return v + 2;
* },
* function(v) {
* return v - 2;
* }
* ),
* });
* t.deepEqual(_.serialize(schemaDefault, { a: 4 }), { a: 6 });
* t.deepEqual(_.deserialize(schemaDefault, { a: 6 }), { a: 4 });
*
* var schemaWithAsyncProps = _.createSimpleSchema({
* a: _.customAsync(
* function(v) {
* return v + 2;
* },
* function(v, context, oldValue, callback) {
* somePromise(v, context, oldValue).then((result) => {
* callback(null, result - 2)
* }.catch((err) => {
* callback(err)
* }
* }
* ),
* });
* t.deepEqual(_.serialize(schemaWithAsyncProps, { a: 4 }), { a: 6 });
* _.deserialize(schemaWithAsyncProps, { a: 6 }, (err, res) => {
* t.deepEqual(res.a, 4)
* };
*
* @param {function} serializer function that takes a model value and turns it into a json value
* @param {function} deserializer function that takes a json value and turns it into a model value. It also takes context argument, which can allow you to deserialize based on the context of other parameters.
* @param {AdditionalPropArgs} additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
* @returns {PropSchema}
*/
function custom(serializer, deserializer, additionalArgs) {
invariant(typeof serializer === "function", "first argument should be function");
invariant((typeof deserializer === "function"), "second argument should be a function or promise");
invariant(typeof deserializer === "function", "second argument should be a function or promise");
var result = {
serializer: serializer,
deserializer: function (jsonValue, done, context, oldValue) {
if (deserializer.length === 4) {
deserializer(jsonValue, context, oldValue, done, additionalArgs);
} else {
done(null, deserializer(jsonValue, context, oldValue, null, additionalArgs));
var result = deserializer(jsonValue, context, oldValue, done);
// FIXME: checking for result === undefined instead of Function.length
// would be nicer, but strictly speaking a breaking change.
if (deserializer.length !== 4) {
done(null, result);
}

@@ -1198,3 +975,3 @@ }

result = processAdditionalPropArgs(result, additionalArgs);
return result
return result;
}

@@ -1208,23 +985,21 @@

* title: optional(primitive()),
* });
* })
*
* console.dir(serialize(new Todo()));
* // {}
* serialize(new Todo()) // {}
*
* @param {PropSchema} propSchema propSchema to (de)serialize the contents of this field
* @returns {PropSchema}
* @param propSchema propSchema to (de)serialize the contents of this field
*/
function optional(name, propSchema) {
propSchema = (!propSchema || propSchema === true) ? _defaultPrimitiveProp : propSchema;
function optional(propSchema) {
propSchema = !propSchema || propSchema === true ? _defaultPrimitiveProp : propSchema;
invariant(isPropSchema(propSchema), "expected prop schema as second argument");
const propSerializer = propSchema.serializer;
var propSerializer = propSchema.serializer;
invariant(typeof propSerializer === "function", "expected prop schema to have a callable serializer");
function serializer(...args) {
const result = propSerializer(...args);
var serializer = function (sourcePropertyValue, key, sourceObject) {
var result = propSerializer(sourcePropertyValue, key, sourceObject);
if (result === undefined) {
return SKIP
return SKIP;
}
return result
}
return Object.assign({}, propSchema, {serializer})
return result;
};
return Object.assign({}, propSchema, { serializer: serializer });
}

@@ -1235,75 +1010,21 @@

context.rootContext.await(modelSchema, uuid, cb);
}
};
}
/**
* `reference` can be used to (de)serialize references that point to other models.
*
* The first parameter should be either a ModelSchema that has an `identifier()` property (see identifier)
* or a string that represents which attribute in the target object represents the identifier of the object.
*
* The second parameter is a lookup function that is invoked during deserialization to resolve an identifier to
* an object. Its signature should be as follows:
*
* `lookupFunction(identifier, callback, context)` where:
* 1. `identifier` is the identifier being resolved
* 2. `callback` is a node style calblack function to be invoked with the found object (as second arg) or an error (first arg)
* 3. `context` see context.
*
* The lookupFunction is optional. If it is not provided, it will try to find an object of the expected type and required identifier within the same JSON document
*
* N.B. mind issues with circular dependencies when importing model schemas from other files! The module resolve algorithm might expose classes before `createModelSchema` is executed for the target class.
*
* @example
* class User {}
* class Post {}
*
* createModelSchema(User, {
* uuid: identifier(),
* displayname: primitive(),
* });
*
* createModelSchema(Post, {
* author: reference(User, findUserById),
* message: primitive(),
* });
*
* function findUserById(uuid, callback) {
* fetch('http://host/user/' + uuid)
* .then(userData => {
* deserialize(User, userData, callback);
* })
* .catch(callback);
* }
*
* deserialize(
* Post,
* {
* message: 'Hello World',
* author: 234,
* },
* (err, post) => {
* console.log(post);
* }
* );
*
* @param target: ModelSchema or string
* @param {RefLookupFunction | AdditionalPropArgs} lookupFn optional function or additionalArgs object
* @param {AdditionalPropArgs} additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
* @returns {PropSchema}
*/
function reference(target, lookupFn, additionalArgs) {
invariant(!!target, "No modelschema provided. If you are importing it from another file be aware of circular dependencies.");
function reference(target, lookupFnOrAdditionalPropArgs, additionalArgs) {
invariant(!!target, "No modelSchema provided. If you are importing it from another file be aware of circular dependencies.");
var lookupFn = "function" === typeof lookupFnOrAdditionalPropArgs
? lookupFnOrAdditionalPropArgs
: undefined;
additionalArgs =
additionalArgs ||
(lookupFn ? undefined : lookupFnOrAdditionalPropArgs);
var initialized = false;
var childIdentifierAttribute;
if (typeof lookupFn === "object" && additionalArgs === undefined) {
additionalArgs = lookupFn;
lookupFn = undefined;
}
function initialize() {
initialized = true;
invariant(typeof target !== "string" || lookupFn && typeof lookupFn === "function", "if the reference target is specified by attribute name, a lookup function is required");
invariant(typeof target !== "string" || typeof lookupFn === "function", "if the reference target is specified by attribute name, a lookup function is required");
invariant(!lookupFn || typeof lookupFn === "function", "second argument should be a lookup function or additional arguments object");
if (typeof target === "string")
if (typeof target === "string") {
childIdentifierAttribute = target;
}
else {

@@ -1321,5 +1042,5 @@ var modelSchema = getDefaultModelSchema(target);

initialize();
return item ? item[childIdentifierAttribute] : null
return item ? item[childIdentifierAttribute] : null;
},
deserializer: function(identifierValue, done, context) {
deserializer: function (identifierValue, done, context) {
if (!initialized)

@@ -1334,3 +1055,3 @@ initialize();

result = processAdditionalPropArgs(result, additionalArgs);
return result
return result;
}

@@ -1349,7 +1070,7 @@

* title: true,
* });
* })
* createModelSchema(Todo, {
* title: true,
* subTask: list(object(SubTask)),
* });
* })
*

@@ -1363,7 +1084,6 @@ * const todo = deserialize(Todo, {

* ],
* });
* })
*
* @param {PropSchema} propSchema to be used to (de)serialize the contents of the array
* @param {AdditionalPropArgs} additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
* @returns {PropSchema}
* @param propSchema to be used to (de)serialize the contents of the array
* @param additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
*/

@@ -1373,16 +1093,14 @@ function list(propSchema, additionalArgs) {

invariant(isPropSchema(propSchema), "expected prop schema as first argument");
invariant(!isAliasedPropSchema(propSchema),
"provided prop is aliased, please put aliases first");
invariant(!isAliasedPropSchema(propSchema), "provided prop is aliased, please put aliases first");
var result = {
serializer: function (ar) {
if (ar === undefined) {
return SKIP
return SKIP;
}
invariant(ar && "length" in ar && "map" in ar, "expected array (like) object");
return ar.map(propSchema.serializer)
return ar.map(propSchema.serializer);
},
deserializer: function (jsonArray, done, context) {
if (!Array.isArray(jsonArray))
return void done("[serializr] expected JSON array")
return void done("[serializr] expected JSON array");
function processItem(jsonValue, onItemDone, itemIndex) {

@@ -1392,43 +1110,22 @@ function callbackBefore(err, value) {

propSchema.deserializer(value, deserializeDone, context);
} else {
}
else {
onItemDone(err);
}
}
function deserializeDone(err, value) {
if (typeof propSchema.afterDeserialize === "function") {
onAfterDeserialize(callbackAfter, err, value, jsonValue, itemIndex, context,
propSchema);
} else {
onAfterDeserialize(onItemDone, err, value, jsonValue, jsonArray, itemIndex, context, propSchema);
}
else {
onItemDone(err, value);
}
}
function callbackAfter(errPreliminary, finalOrRetryValue) {
if (errPreliminary && finalOrRetryValue !== undefined &&
typeof propSchema.afterDeserialize === "function") {
propSchema.deserializer(
finalOrRetryValue,
deserializeDone,
context
);
} else {
onItemDone(errPreliminary, finalOrRetryValue);
}
}
onBeforeDeserialize(callbackBefore, jsonValue, jsonArray, itemIndex, context,
propSchema);
onBeforeDeserialize(callbackBefore, jsonValue, jsonArray, itemIndex, context, propSchema);
}
parallel(
jsonArray,
processItem,
done
);
parallel(jsonArray, processItem, done);
}
};
result = processAdditionalPropArgs(result, additionalArgs);
return result
return result;
}

@@ -1441,5 +1138,3 @@

*
* @param {*} propSchema
* @param {AdditionalPropArgs} additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
* @returns {PropSchema}
* @param additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
*/

@@ -1450,49 +1145,46 @@ function map(propSchema, additionalArgs) {

invariant(!isAliasedPropSchema(propSchema), "provided prop is aliased, please put aliases first");
var res = {
var result = {
serializer: function (m) {
invariant(m && typeof m === "object", "expected object or Map");
var isMap = isMapLike(m);
var result = {};
if (isMap)
m.forEach(function (value, key) {
result[key] = propSchema.serializer(value);
});
else for (var key in m)
result[key] = propSchema.serializer(m[key]);
return result
if (isMapLike(m)) {
m.forEach(function (value, key) { return (result[key] = propSchema.serializer(value, key, m)); });
}
else {
for (var key in m)
result[key] = propSchema.serializer(m[key], key, m);
}
return result;
},
deserializer: function (jsonObject, done, context, oldValue) {
if (!jsonObject || typeof jsonObject !== "object")
return void done("[serializr] expected JSON object")
return void done("[serializr] expected JSON object");
var keys = Object.keys(jsonObject);
list(propSchema, additionalArgs).deserializer(
keys.map(function (key) {
return jsonObject[key]
}),
function (err, values) {
if (err)
return void done(err)
var isMap = isMapLike(oldValue);
var newValue;
if (isMap) {
// if the oldValue is a map, we recycle it
// there are many variations and this way we don't have to
// know about the original constructor
oldValue.clear();
newValue = oldValue;
} else
newValue = {};
for (var i = 0, l = keys.length; i < l; i++)
if (isMap)
newValue.set(keys[i], values[i]);
else
newValue[keys[i]] = values[i];
done(null, newValue);
},
context
);
list(propSchema, additionalArgs).deserializer(keys.map(function (key) {
return jsonObject[key];
}), function (err, values) {
if (err)
return void done(err);
var isMap = isMapLike(oldValue);
var newValue;
if (isMap) {
// if the oldValue is a map, we recycle it
// there are many variations and this way we don't have to
// know about the original constructor
oldValue.clear();
newValue = oldValue;
}
else
newValue = {};
for (var i = 0, l = keys.length; i < l; i++)
if (isMap)
newValue.set(keys[i], values[i]);
else
newValue[keys[i]] = values[i];
done(null, newValue);
}, context);
}
};
res = processAdditionalPropArgs(res, additionalArgs);
return res
result = processAdditionalPropArgs(result, additionalArgs);
return result;
}

@@ -1509,6 +1201,4 @@

*
* @param {any} propSchema
* @param {string} keyPropertyName - the property of stored objects used as key in the map
* @param {AdditionalPropArgs} additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
* @returns {PropSchema}
* @param keyPropertyName - the property of stored objects used as key in the map
* @param additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
*/

@@ -1519,45 +1209,40 @@ function mapAsArray(propSchema, keyPropertyName, additionalArgs) {

invariant(!!keyPropertyName, "expected key property name as second argument");
var res = {
var result = {
serializer: function (m) {
invariant(m && typeof m === "object", "expected object or Map");
var isMap = isMapLike(m);
var result = [];
// eslint-disable-next-line no-unused-vars
if (isMap) {
m.forEach(function (value) {
result.push(propSchema.serializer(value));
});
} else for (var key in m) {
result.push(propSchema.serializer(m[key]));
// result[key] = propSchema.serializer(m[key])
if (isMapLike(m)) {
m.forEach(function (value, key) { return result.push(propSchema.serializer(value, key, m)); });
}
return result
else {
for (var key in m)
result.push(propSchema.serializer(m[key], key, m));
}
return result;
},
deserializer: function (jsonArray, done, context, oldValue) {
list(propSchema, additionalArgs).deserializer(
jsonArray,
function (err, values) {
if (err)
return void done(err)
var isMap = isMapLike(oldValue);
var newValue;
if (isMap) {
oldValue.clear();
newValue = oldValue;
} else {
newValue = {};
}
for (var i = 0, l = jsonArray.length; i < l; i++)
if (isMap)
newValue.set(values[i][keyPropertyName], values[i]);
else
newValue[values[i][keyPropertyName].toString()] = values[i];
done(null, newValue);
},
context
);
list(propSchema, additionalArgs).deserializer(jsonArray, function (err, values) {
if (err)
return void done(err);
var oldValueIsMap = isMapLike(oldValue);
var newValue;
if (oldValueIsMap) {
oldValue.clear();
newValue = oldValue;
}
else {
newValue = {};
}
for (var i = 0, l = jsonArray.length; i < l; i++)
if (oldValueIsMap)
newValue.set(values[i][keyPropertyName], values[i]);
else
newValue[values[i][keyPropertyName].toString()] = values[i];
done(null, newValue);
}, context, undefined);
}
};
res = processAdditionalPropArgs(res, additionalArgs);
return res
result = processAdditionalPropArgs(result, additionalArgs);
return result;
}

@@ -1572,9 +1257,8 @@

* rawData: raw(),
* });
* })
*
* console.dir(serialize(new Model({ rawData: { a: 1, b: [], c: {} } } })));
* // outputs: { rawData: { a: 1, b: [], c: {} } } }
* serialize(new Model({ rawData: { a: 1, b: [], c: {} } } }))
* // { "rawData": { a: 1, b: [], c: {} } } }
*
* @param {AdditionalPropArgs} additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
* @returns {ModelSchema}
* @param additionalArgs optional object that contains beforeDeserialize and/or afterDeserialize handlers
*/

@@ -1584,17 +1268,13 @@ function raw(additionalArgs) {

serializer: function (value) {
return value
return value;
},
deserializer: function (jsonValue, done) {
return void done(null, jsonValue)
return void done(null, jsonValue);
}
};
result = processAdditionalPropArgs(result, additionalArgs);
return result
return result;
}
/*
* ## Managing model schemas
*/
// ~ deprecated
export { createSimpleSchema, createModelSchema, getDefaultModelSchema, setDefaultModelSchema, serializable, serialize, serializeAll, cancelDeserialize, deserialize, update, primitive, identifier, date, alias, custom, object, object as child, optional, reference, reference as ref, list, map, mapAsArray, raw, SKIP };
export { SKIP, alias, cancelDeserialize, createModelSchema, createSimpleSchema, custom, date, deserialize, getDefaultModelSchema, identifier, list, map, mapAsArray, object, optional, primitive, raw, reference, serializable, serialize, serializeAll, setDefaultModelSchema, update };
//# sourceMappingURL=serializr.js.map
/** serializr - (c) Michel Weststrate 2016 - MIT Licensed */
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define("serializr",["exports"],t):t((e=e||self).serializr={})}(this,function(e){"use strict";var t={j:function(e){try{return JSON.stringify(e)}catch(t){return"[UnexpectedJSONParseError]: "+t.message}}};function n(e,n){if(!e){var r=Array.prototype.slice.call(arguments,2),i=[],o=0,a=n.replace(/%([a-zA-Z%])/g,function(e,n){if("%%"===e)return e;var a=t[n];if("function"==typeof a){var s=r[o++];return i.push(s),a(s)}return e});throw console&&i.length>0&&console.log.apply(console,i),new Error("[serializr] "+(a||"Illegal State"))}}function r(e){if(e)throw new Error(e)}function i(e,t,n){if(0!==e.length){var r=e.filter(function(){return!0}).length,i=[],o=!1;e.forEach(function(e,a){t(e,function(e,t,a){t?o||(o=!0,n(t)):(i[e]=a,0==--r&&n(null,i))}.bind(null,a),a)})}else n(null,[])}function o(e){return null===e||"object"!=typeof e&&"function"!=typeof e}function a(e){return e&&e.factory&&e.props}function s(e){return e&&e.serializer&&e.deserializer}function f(e){return"object"==typeof e&&!!e.jsonname}function c(e){return"object"==typeof e&&!0===e.identifier}function u(e,t){for(;e;){if(e===t)return!0;e=e["extends"]}return!1}function l(e){return e&&"function"==typeof e.keys&&"function"==typeof e.clear}function p(e,t){if(t){n(s(e),"expected a propSchema");["beforeDeserialize","afterDeserialize"].forEach(function(n){"function"==typeof t[n]&&(e[n]=t[n])})}return e}function d(e){return e?a(e)?e:a(e.serializeInfo)?e.serializeInfo:e.constructor&&e.constructor.serializeInfo?e.constructor.serializeInfo:void 0:null}function h(e,t){return n(a(t)),e.serializeInfo=t}function y(e,t,r){n(e!==Object,"one cannot simply put define a model schema for Object"),n("function"==typeof e,"expected constructor function");var i={targetClass:e,factory:r||function(){return new e},props:t};if(e.prototype.constructor!==Object){var o=d(e.prototype.constructor);o&&o.targetClass!==e&&(i["extends"]=o)}return h(e,i),i}function m(e){var t={serializer:function(e){return n(o(e),"this value is not primitive: "+e),e},deserializer:function(e,t){o(e)?t(null,e):t("[serializr] this value is not primitive: "+e)}};return t=p(t,e)}var g="undefined"!=typeof Symbol?Symbol("SKIP"):{SKIP:!0},b=m(),v=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,z=/([^\s,]+)/g;function j(e,t,r,i){var o,a,f;if(n(arguments.length>=2,"too few arguments. Please use @serializable as property decorator"),r===undefined&&"function"==typeof t&&t.prototype&&i!==undefined&&"number"==typeof i){n(s(e),"Constructor params must use alias(name)"),n(e.jsonname,"Constructor params must use alias(name)");var c=(a=t.toString().replace(v,""),null===(f=a.slice(a.indexOf("(")+1,a.indexOf(")")).match(z))&&(f=[]),f);c.length>=i&&(r=c[i],e.paramNumber=i,i=undefined,t=t.prototype,o=function(e){for(var n=[],r=0;r<t.constructor.length;r++)Object.keys(e.modelSchema.props).forEach(function(t){var i=e.modelSchema.props[t];i.paramNumber===r&&(n[r]=e.json[i.jsonname])});return new(Function.prototype.bind.apply(t.constructor,[null].concat(n)))})}n("string"==typeof r,"incorrect usage of @serializable decorator");var u=d(t);return u&&t.constructor.hasOwnProperty("serializeInfo")||(u=y(t.constructor,{},o)),u&&u.targetClass!==t.constructor&&(u=y(t.constructor,{},o)),u.props[r]=e,!i||i.get||i.set||(i.writable=!0),i}function x(e,t){n(1===arguments.length||2===arguments.length,"serialize expects one or 2 arguments");var r=1===arguments.length?e:t,i=1===arguments.length?null:e;if(Array.isArray(r)){if(0===r.length)return[];i?"object"!=typeof i&&(i=d(i)):i=d(r[0])}else i?"object"!=typeof i&&(i=d(i)):i=d(r);return n(!!i,"Failed to find default schema for "+e),Array.isArray(r)?r.map(function(e){return C(i,e)}):C(i,r)}function R(e){n(!0===e||e.pattern,"prop schema '*' can only be used with 'true' or a prop def with a 'pattern': "+JSON.stringify(e))}function C(e,t){var r;return n(e&&"object"==typeof e&&e.props,"Expected schema"),n(t&&"object"==typeof t,"Expected object"),r=e["extends"]?C(e["extends"],t):{},Object.keys(e.props).forEach(function(n){var i=e.props[n];if("*"!==n){if(!0===i&&(i=b),!1!==i){var a=i.serializer(t[n],n,t);a!==g&&(r[i.jsonname||n]=a)}}else!function(e,t,n,r){for(var i in R(t),n)if(n.hasOwnProperty(i)&&!(i in e.props)&&(!0===t||t.pattern&&t.pattern.test(i))){var a=n[i];if(!0===t)o(a)&&(r[i]=a);else if(t.props){var s=x(t,a);if(s===g)return;r[i]=s}else{var s=t.serializer(a,i,n);if(s===g)return;r[i]=s}}}(e,i,t,r)}),r}var S=new WeakMap;function w(e,t,n,i,o){this.parentContext=e,this.isRoot=!e,this.pendingCallbacks=0,this.pendingRefsCount=0,this.onReadyCb=i||r,this.json=n,this.target=null,this.hasError=!1,this.modelSchema=t,this.isRoot?(this.rootContext=this,this.args=o,this.pendingRefs={},this.resolvedRefs={}):(this.rootContext=e.rootContext,this.args=e.args)}function k(e,t){for(var n in e.props)if("object"==typeof e.props[n]&&e.props[n].jsonname===t)return!0;return!1}function A(e,t,i,o,a){if(null!==i&&i!==undefined&&"object"==typeof i){var s=new w(e,t,i,o,a),f=t.factory(s);n(!!f,"No object returned from factory"),s.setTarget(f);var c=s.createCallback(r);return O(s,t,i,f),c(),f}o(null,null)}function O(e,t,i,a){t["extends"]&&O(e,t["extends"],i,a),Object.keys(t.props).forEach(function(s){var f=t.props[s];if("*"!==s){if(!0===f&&(f=b),!1!==f){var c=f.jsonname||s;E(function(t,n){t||n===undefined||function(t,n,r){t.deserializer(n,function o(s){return function(f,c){D(function(n,i){n&&i!==undefined&&"function"==typeof t.afterDeserialize?t.deserializer(i,o(s),e,a[r]):s(n,i)},f,c,n,i,r,e,t)}}(e.rootContext.createCallback(function(e){e!==g&&(a[r]=e)})),e,a[r])}(f,n,s)},i[c],i,c,e,f)}}else!function(e,t,i,a,s){for(var f in R(i),s)if(!(f in t.props||k(t,f))){var c=s[f];if(!0===i)n(o(c),"encountered non primitive value while deserializing '*' properties in property '"+f+"': "+c),a[f]=c;else if(i.pattern.test(f))if(i.factory){var u=A(e,i,c,e.callback||r,{});u!==undefined&&(a[f]=u)}else{function l(e){e!==g&&(a[f]=e)}i.deserializer(c,e.rootContext.createCallback(l),e)}}}(e,t,f,a,i)})}function E(e,t,n,r,i,o){o&&"function"==typeof o.beforeDeserialize?o.beforeDeserialize(e,t,n,r,i,o):e(null,t)}function D(e,t,n,r,i,o,a,s){s&&"function"==typeof s.afterDeserialize?s.afterDeserialize(e,t,n,r,i,o,a,s):e(t,n)}function I(e,t){n("object"==typeof e||"function"==typeof e,"No modelschema provided. If you are importing it from another file be aware of circular dependencies.");var r={serializer:function(t){return n(a(e=d(e)),"expected modelSchema, got "+e),null===t||t===undefined?t:x(e,t)},deserializer:function(r,i,o){n(a(e=d(e)),"expected modelSchema, got "+e),null!==r&&r!==undefined?A(o,e,r,i,t):i(null,r)}};return r=p(r,t)}function N(e,t,r){n(!!e,"No modelschema provided. If you are importing it from another file be aware of circular dependencies.");var i,o=!1;function s(){if(o=!0,n("string"!=typeof e||t&&"function"==typeof t,"if the reference target is specified by attribute name, a lookup function is required"),n(!t||"function"==typeof t,"second argument should be a lookup function or additional arguments object"),"string"==typeof e)i=e;else{var r=d(e);n(a(r),"expected model schema or string as first argument for 'ref', got "+r),t=t||function(e){return function(t,n,r){r.rootContext.await(e,t,n)}}(r),i=function(e){for(n(a(e));e;){for(var t in e.props)if("object"==typeof e.props[t]&&!0===e.props[t].identifier)return t;e=e["extends"]}return null}(r),n(!!i,"provided model schema doesn't define an identifier() property and cannot be used by 'ref'.")}}"object"==typeof t&&r===undefined&&(r=t,t=undefined);var f={serializer:function(e){return o||s(),e?e[i]:null},deserializer:function(e,n,r){o||s(),null===e||e===undefined?n(null,e):t(e,n,r)}};return f=p(f,r)}function P(e,t){n(s(e=e||b),"expected prop schema as first argument"),n(!f(e),"provided prop is aliased, please put aliases first");var r={serializer:function(t){return t===undefined?g:(n(t&&"length"in t&&"map"in t,"expected array (like) object"),t.map(e.serializer))},deserializer:function(t,n,r){Array.isArray(t)?i(t,function(n,i,o){function a(t,a){"function"==typeof e.afterDeserialize?D(s,t,a,n,o,r,e):i(t,a)}function s(t,n){t&&n!==undefined&&"function"==typeof e.afterDeserialize?e.deserializer(n,a,r):i(t,n)}E(function(t,n){t?i(t):e.deserializer(n,a,r)},n,t,o,r,e)},n):n("[serializr] expected JSON array")}};return r=p(r,t)}w.prototype.createCallback=function(e){return this.pendingCallbacks++,function(e){var t=!1;return function(){if(!t)return t=!0,e.apply(null,arguments);n(!1,"callback was invoked twice")}}(function(t,n){t?this.hasError||(this.hasError=!0,this.onReadyCb(t),S["delete"](this)):this.hasError||(e(n),--this.pendingCallbacks===this.pendingRefsCount&&(this.pendingRefsCount>0?(this.onReadyCb(new Error('Unresolvable references in json: "'+Object.keys(this.pendingRefs).filter(function(e){return this.pendingRefs[e].length>0},this).join('", "')+'"')),S["delete"](this)):(this.onReadyCb(null,this.target),S["delete"](this))))}.bind(this))},w.prototype.await=function(e,t,r){if(n(this.isRoot),t in this.resolvedRefs){var i=this.resolvedRefs[t].filter(function(t){return u(t.modelSchema,e)})[0];if(i)return void r(null,i.value)}this.pendingRefsCount++,this.pendingRefs[t]||(this.pendingRefs[t]=[]),this.pendingRefs[t].push({modelSchema:e,uuid:t,callback:r})},w.prototype.resolve=function(e,t,r){if(n(this.isRoot),this.resolvedRefs[t]||(this.resolvedRefs[t]=[]),this.resolvedRefs[t].push({modelSchema:e,value:r}),t in this.pendingRefs)for(var i=this.pendingRefs[t].length-1;i>=0;i--){var o=this.pendingRefs[t][i];u(e,o.modelSchema)&&(this.pendingRefs[t].splice(i,1),this.pendingRefsCount--,o.callback(null,r))}},w.prototype.setTarget=function(e){this.isRoot&&this.target&&S["delete"](this.target),this.target=e,S.set(this.target,this)},w.prototype.cancelAwaits=function(){n(this.isRoot);var e=this;Object.keys(this.pendingRefs).forEach(function(t){e.pendingRefs[t].forEach(function(n){e.pendingRefsCount--,n.callback(new Error("Reference resolution canceled for "+t))})}),this.pendingRefs={},this.pendingRefsCount=0},e.createSimpleSchema=function(e){return{factory:function(){return{}},props:e}},e.createModelSchema=y,e.getDefaultModelSchema=d,e.setDefaultModelSchema=h,e.serializable=function(e,t,r){if(1===arguments.length){var i=!0===e?b:e;return n(s(i),"@serializable expects prop schema"),j.bind(null,i)}return j(m(),e,t,r)},e.serialize=x,e.serializeAll=function(e,t){let r,i=!1;function o(e){var t=d(e);return t&&e.hasOwnProperty("serializeInfo")||h(e,t=y(e,{})),d(e).props["*"]=r,e}return 1===arguments.length?(n("function"==typeof e,"@serializeAll can only be used as class decorator"),r=!0,i=!0):(n("object"==typeof e&&e.test,"@serializeAll pattern doesn't have test"),"function"==typeof t&&(t=I(t)),n("object"==typeof t&&t.serializer,"couldn't resolve schema"),r=Object.assign({},t,{pattern:e})),i?o(e):o},e.cancelDeserialize=function(e){n("object"==typeof e&&e&&!Array.isArray(e),"cancelDeserialize needs an object");var t,r=(t=e,S.get(t));r&&r.cancelAwaits()},e.deserialize=function(e,t,o,s){if(n(arguments.length>=2,"deserialize expects at least 2 arguments"),n(a(e=d(e)),"first argument should be model schema"),Array.isArray(t)){var f=[];return i(t,function(t,n){var r=A(null,e,t,n,s);f.push(r)},o||r),f}return A(null,e,t,o,s)},e.update=function(e,t,i,o,s){2===arguments.length||"function"==typeof arguments[2]?(e=d(t=arguments[0]),i=arguments[1],o=arguments[2],s=arguments[3]):e=d(e),n(a(e),"update failed to determine schema"),n("object"==typeof t&&t&&!Array.isArray(t),"update needs an object");var f=new w(null,e,i,o,s);f.setTarget(t);var c=f.createCallback(r),u=O(f,e,i,t);return c(),u},e.primitive=m,e.identifier=function(e,t){var r,i;"function"==typeof e?(r=e,i=t):i=e,n(!i||"object"==typeof i,"Additional property arguments should be an object, register function should be omitted or a funtion");var o={identifier:!0,serializer:b.serializer,deserializer:function(e,t,n){b.deserializer(e,function(e,i){!function(e,t,n){n.rootContext.resolve(n.modelSchema,e,n.target)}(i,n.target,n),r&&r(i,n.target,n),t(e,i)})}};return o=p(o,i)},e.date=function(e){var t={serializer:function(e){return null===e||e===undefined?e:(n(e instanceof Date,"Expected Date object"),e.getTime())},deserializer:function(e,t){null!==e&&e!==undefined?t(null,new Date(e)):t(null,e)}};return t=p(t,e)},e.alias=function(e,t){return n(e&&"string"==typeof e,"expected prop name as first argument"),n(s(t=t&&!0!==t?t:b),"expected prop schema as second argument"),n(!f(t),"provided prop is already aliased"),{jsonname:e,serializer:t.serializer,deserializer:t.deserializer,identifier:c(t),beforeDeserialize:t.beforeDeserialize,afterDeserialize:t.afterDeserialize}},e.custom=function(e,t,r){n("function"==typeof e,"first argument should be function"),n("function"==typeof t,"second argument should be a function or promise");var i={serializer:e,deserializer:function(e,n,i,o){4===t.length?t(e,i,o,n,r):n(null,t(e,i,o,null,r))}};return i=p(i,r)},e.object=I,e.child=I,e.optional=function(e,t){n(s(t=t&&!0!==t?t:b),"expected prop schema as second argument");const r=t.serializer;return n("function"==typeof r,"expected prop schema to have a callable serializer"),Object.assign({},t,{serializer:function(...e){const t=r(...e);return t===undefined?g:t}})},e.reference=N,e.ref=N,e.list=P,e.map=function(e,t){n(s(e=e||b),"expected prop schema as first argument"),n(!f(e),"provided prop is aliased, please put aliases first");var r={serializer:function(t){n(t&&"object"==typeof t,"expected object or Map");var r=l(t),i={};if(r)t.forEach(function(t,n){i[n]=e.serializer(t)});else for(var o in t)i[o]=e.serializer(t[o]);return i},deserializer:function(n,r,i,o){if(n&&"object"==typeof n){var a=Object.keys(n);P(e,t).deserializer(a.map(function(e){return n[e]}),function(e,t){if(e)r(e);else{var n,i=l(o);i?(o.clear(),n=o):n={};for(var s=0,f=a.length;s<f;s++)i?n.set(a[s],t[s]):n[a[s]]=t[s];r(null,n)}},i)}else r("[serializr] expected JSON object")}};return r=p(r,t)},e.mapAsArray=function(e,t,r){n(s(e=e||b),"expected prop schema as first argument"),n(!!t,"expected key property name as second argument");var i={serializer:function(t){n(t&&"object"==typeof t,"expected object or Map");var r=l(t),i=[];if(r)t.forEach(function(t){i.push(e.serializer(t))});else for(var o in t)i.push(e.serializer(t[o]));return i},deserializer:function(n,i,o,a){P(e,r).deserializer(n,function(e,r){if(e)i(e);else{var o,s=l(a);s?(a.clear(),o=a):o={};for(var f=0,c=n.length;f<c;f++)s?o.set(r[f][t],r[f]):o[r[f][t].toString()]=r[f];i(null,o)}},o)}};return i=p(i,r)},e.raw=function(e){var t={serializer:function(e){return e},deserializer:function(e,t){t(null,e)}};return t=p(t,e)},e.SKIP=g,Object.defineProperty(e,"__esModule",{value:!0})});
var e,n;e=this,n=function(e){"use strict";var n={j:function(e){try{return JSON.stringify(e)}catch(n){return"[UnexpectedJSONParseError]: "+n.message}},l:function(e){return e.toString()}};function t(e,t){for(var r=[],i=2;i<arguments.length;i++)r[i-2]=arguments[i];if(!e){var o=[],u=0,f=t.replace(/%([a-zA-Z%])/g,(function(e,t){if("%%"===e)return e;var i=n[t];if("function"==typeof i){var f=r[u++];return o.push(f),i(f)}return e}));throw console&&o.length>0&&console.log.apply(console,o),Error("[serializr] "+(f||"Illegal State"))}}function r(e){if(e)throw Error(e)}function i(e,n,t){if(0!==e.length){var r=e.filter((function(e){return!0})).length,i=[],o=!1;e.forEach((function(e,u){n(e,(function(e,n){e?o||(o=!0,t(e)):(i[u]=n,0==--r&&t(null,i))}),u)}))}else t(null,[])}function o(e){return null===e||"object"!=typeof e&&"function"!=typeof e}function u(e){return e&&e.factory&&e.props}function f(e){return e&&e.serializer&&e.deserializer}function a(e){return"object"==typeof e&&"string"==typeof e.jsonname}function c(e){return"object"==typeof e&&!0===e.identifier}function s(e,n){for(var t=e;t;){if(t===n)return!0;t=t["extends"]}return!1}function l(e){return e&&"function"==typeof e.keys&&"function"==typeof e.clear}function d(e,n){return n&&(t(f(e),"expected a propSchema"),Object.assign(e,n)),e}function p(e){return e?u(e)?e:u(e.serializeInfo)?e.serializeInfo:e.constructor&&e.constructor.serializeInfo?e.constructor.serializeInfo:void 0:undefined}function v(e,n){return t(u(n),"expected modelSchema, got "+n),e.serializeInfo=n,n}function h(e,n,r){t(e!==Object,"one cannot simply put define a model schema for Object"),t("function"==typeof e,"expected constructor function");var i={targetClass:e,factory:r||function(){return new e},props:n};if(e.prototype.constructor!==Object){var o=p(e.prototype.constructor);o&&o.targetClass!==e&&(i["extends"]=o)}return v(e,i),i}
/*! *****************************************************************************
Copyright (c) Microsoft Corporation. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); you may not use
this file except in compliance with the License. You may obtain a copy of the
License at http://www.apache.org/licenses/LICENSE-2.0
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
MERCHANTABLITY OR NON-INFRINGEMENT.
See the Apache Version 2.0 License for specific language governing permissions
and limitations under the License.
***************************************************************************** */function m(){for(var e=0,n=0,t=arguments.length;n<t;n++)e+=arguments[n].length;var r=Array(e),i=0;for(n=0;n<t;n++)for(var o=arguments[n],u=0,f=o.length;u<f;u++,i++)r[i]=o[u];return r}function y(e){return d({serializer:function(e){return t(o(e),"this value is not primitive: "+e),e},deserializer:function(e,n){o(e)?n(null,e):n("[serializr] this value is not primitive: "+e)}},e)}var b="undefined"!=typeof Symbol?Symbol("SKIP"):{SKIP:!0},j=y(),z=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,g=/([^\s,]+)/g;function x(e){var n,t=e.toString().replace(z,"");return null!=(n=t.slice(t.indexOf("(")+1,t.indexOf(")")).match(g))?n:[]}function S(e,n,r,i){var o;if(t(arguments.length>=2,"too few arguments. Please use @serializable as property decorator"),r===undefined&&"function"==typeof n&&n.prototype&&i!==undefined&&"number"==typeof i){t(f(e),"Constructor params must use alias(name)"),t(a(e),"Constructor params must use alias(name)");var u=x(n);u.length>=i&&(r=u[i],e.paramNumber=i,i=undefined,n=n.prototype,o=function(e){for(var t,r=[],i=function(n){Object.keys(e.modelSchema.props).forEach((function(t){var i=e.modelSchema.props[t];i.paramNumber===n&&(r[n]=e.json[i.jsonname])}))},o=0;o<n.constructor.length;o++)i(o);return(t=n.constructor).bind.apply(t,m([undefined],r))})}t("string"==typeof r,"incorrect usage of @serializable decorator");var c=p(n);return c&&n.constructor.hasOwnProperty("serializeInfo")||(c=h(n.constructor,{},o)),c&&c.targetClass!==n.constructor&&(c=h(n.constructor,{},o)),c.props[r]=e,!i||i.get||i.set||(i.writable=!0),i}function O(e,n){t(1===arguments.length||2===arguments.length,"serialize expects one or 2 arguments");var r=null!=n?n:e,i=n&&e;if(Array.isArray(r)){if(0===r.length)return[];i?"object"!=typeof i&&(i=p(i)):i=p(r[0])}else i?"object"!=typeof i&&(i=p(i)):i=p(r);var o=i;return t(o,"Failed to find default schema for "+e),Array.isArray(r)?r.map((function(e){return w(o,e)})):w(o,r)}function w(e,n){var r;return t(e&&"object"==typeof e&&e.props,"Expected schema"),t(n&&"object"==typeof n,"Expected object"),r=e["extends"]?w(e["extends"],n):{},Object.keys(e.props).forEach((function(t){var i=e.props[t];if(i)if("*"!==t){!0===i&&(i=j);var u=i.serializer(n[t],t,n);u!==b&&(r[i.jsonname||t]=u)}else!function(e,n,t,r){for(var i=0,u=Object.keys(t);i<u.length;i++){var f=u[i];if(!(f in e.props)&&(!0===n||n&&(!n.pattern||n.pattern.test(f)))){var a=t[f];if(!0===n)o(a)&&(r[f]=a);else{var c=n.serializer(a,f,t);if(c===b)return;r[f]=c}}}}(e,i,n,r)})),r}var A=new WeakMap,k=function(){function e(e,n,t,r,i){this.parentContext=e,this.modelSchema=n,this.json=t,this.onReadyCb=r,this.isRoot=!e,this.pendingCallbacks=0,this.pendingRefsCount=0,this.target=undefined,this.hasError=!1,e?(this.rootContext=e.rootContext,this.args=e.args):(this.rootContext=this,this.args=i,this.pendingRefs={},this.resolvedRefs={})}return e.prototype.createCallback=function(e){var n=this;return this.pendingCallbacks++,function(e){var n=!1;return function(){if(!n)return n=!0,e.apply(null,arguments);t(!1,"callback was invoked twice")}}((function(t,r){t?n.hasError||(n.hasError=!0,n.onReadyCb(t),A["delete"](n)):n.hasError||(e(r),--n.pendingCallbacks===n.pendingRefsCount&&(n.pendingRefsCount>0?(n.onReadyCb(Error('Unresolvable references in json: "'+Object.keys(n.pendingRefs).filter((function(e){return n.pendingRefs[e].length>0})).join('", "')+'"')),A["delete"](n)):(n.onReadyCb(null,n.target),A["delete"](n))))}))},e.prototype.await=function(e,n,r){if(t(this.isRoot,"await can only be called on the root context"),n in this.resolvedRefs){var i=this.resolvedRefs[n].filter((function(n){return s(n.modelSchema,e)}))[0];if(i)return void r(null,i.value)}this.pendingRefsCount++,this.pendingRefs[n]||(this.pendingRefs[n]=[]),this.pendingRefs[n].push({modelSchema:e,uuid:n,callback:r})},e.prototype.resolve=function(e,n,r){if(t(this.isRoot,"resolve can only called on the root context"),this.resolvedRefs[n]||(this.resolvedRefs[n]=[]),this.resolvedRefs[n].push({modelSchema:e,value:r}),n in this.pendingRefs)for(var i=this.pendingRefs[n].length-1;i>=0;i--){var o=this.pendingRefs[n][i];s(e,o.modelSchema)&&(this.pendingRefs[n].splice(i,1),this.pendingRefsCount--,o.callback(null,r))}},e.prototype.setTarget=function(e){this.isRoot&&this.target&&A["delete"](this.target),this.target=e,A.set(this.target,this)},e.prototype.cancelAwaits=function(){t(this.isRoot,"cancelAwaits can only be called on the root context");var e=this;Object.keys(this.pendingRefs).forEach((function(n){e.pendingRefs[n].forEach((function(t){e.pendingRefsCount--,t.callback(Error("Reference resolution canceled for "+n))}))})),this.pendingRefs={},this.pendingRefsCount=0},e}();function E(e,n,i,o,u){if(null!==i&&i!==undefined&&"object"==typeof i){var f=new k(e,n,i,o,u),a=n.factory(f);t(!!a,"No object returned from factory"),f.setTarget(a);var c=f.createCallback(r);return N(f,n,i,a),c(),a}o(null,null)}function N(e,n,r,i){var u;n["extends"]&&N(e,n["extends"],r,i);for(var f=function(f){var a=n.props[f];if(!a)return{value:void 0};if("*"===f)return function(e,n,r,i,u){var f=function(f){if(!(f in n.props||function(e,n){for(var t in e.props){var r=e.props[t];if("object"==typeof r&&r.jsonname===n)return!0}return!1}(n,f))){var a=u[f];!0===r?(t(o(a),"encountered non primitive value while deserializing '*' properties in property '"+f+"': "+a),i[f]=a):!r||r.pattern&&!r.pattern.test(f)||r.deserializer(a,e.rootContext.createCallback((function(e){return e!==b&&(i[f]=e)})),e)}};for(var a in u)f(a)}(e,n,a,i,r),{value:void 0};!0===a&&(a=j);var c=null!=(u=a.jsonname)?u:f;t("symbol"!=typeof c,"You must alias symbol properties. prop = %l",f);var s=r[c],l=a;D((function(n,t){n||t===undefined||function(n,t,o){var u=e.rootContext.createCallback((function(e){return e!==b&&(i[o]=e)}));n.deserializer(t,(function(i,f){return I(u,i,f,t,r,o,e,n)}),e,i[o])}(l,t,f)}),s,r,c,e,a)},a=0,c=Object.keys(n.props);a<c.length;a++){var s=f(c[a]);if("object"==typeof s)return s.value}}var D=function(e,n,t,r,i,o){o&&"function"==typeof o.beforeDeserialize?o.beforeDeserialize(e,n,t,r,i,o):e(null,n)},I=function(e,n,t,r,i,o,u,f){f&&"function"==typeof f.afterDeserialize?f.afterDeserialize(e,n,t,r,i,o,u,f):e(n,t)};function M(e,n){return t("object"==typeof e||"function"==typeof e,"No modelschema provided. If you are importing it from another file be aware of circular dependencies."),d({serializer:function(n){return t(u(e=p(e)),"expected modelSchema, got "+e),null===n||n===undefined?n:O(e,n)},deserializer:function(n,r,i){t(u(e=p(e)),"expected modelSchema, got "+e),null!==n&&n!==undefined?E(i,e,n,r,undefined):r(null,n)}},n)}function J(e,n){return t(f(e=e||j),"expected prop schema as first argument"),t(!a(e),"provided prop is aliased, please put aliases first"),d({serializer:function(n){return n===undefined?b:(t(n&&"length"in n&&"map"in n,"expected array (like) object"),n.map(e.serializer))},deserializer:function(n,t,r){Array.isArray(n)?i(n,(function(t,i,o){function u(u,f){"function"==typeof e.afterDeserialize?I(i,u,f,t,n,o,r,e):i(u,f)}D((function(n,t){n?i(n):e.deserializer(t,u,r)}),t,n,o,r,e)}),t):t("[serializr] expected JSON array")}},n)}e.SKIP=b,e.alias=function(e,n){return t(e&&"string"==typeof e,"expected prop name as first argument"),t(f(n=n&&!0!==n?n:j),"expected prop schema as second argument"),t(!a(n),"provided prop is already aliased"),{jsonname:e,serializer:n.serializer,deserializer:n.deserializer,identifier:c(n)||undefined,beforeDeserialize:n.beforeDeserialize,afterDeserialize:n.afterDeserialize}},e.cancelDeserialize=function(e){t("object"==typeof e&&e&&!Array.isArray(e),"cancelDeserialize needs an object");var n,r=(n=e,A.get(n));r&&r.cancelAwaits()},e.createModelSchema=h,e.createSimpleSchema=function(e){return{factory:function(){return{}},props:e}},e.custom=function(e,n,r){return t("function"==typeof e,"first argument should be function"),t("function"==typeof n,"second argument should be a function or promise"),d({serializer:e,deserializer:function(e,t,r,i){var o=n(e,r,i,t);4!==n.length&&t(null,o)}},r)},e.date=function(e){return d({serializer:function(e){return null===e||e===undefined?e:(t(e instanceof Date,"Expected Date object"),e.getTime())},deserializer:function(e,n){null!==e&&e!==undefined?n(null,new Date(e)):n(null,e)}},e)},e.deserialize=function(e,n,o,f){void 0===o&&(o=r),t(arguments.length>=2,"deserialize expects at least 2 arguments");var a=p(e);if(t(u(a),"first argument should be model schema"),Array.isArray(n)){var c=[];return i(n,(function(e,n){var t=E(undefined,a,e,n,f);c.push(t)}),o),c}return E(undefined,a,n,o,f)},e.getDefaultModelSchema=p,e.identifier=function(e,n){var r,i;return"function"==typeof e?(r=e,i=n):i=e,t(!i||"object"==typeof i,"Additional property arguments should be an object, register function should be omitted or a funtion"),d({identifier:!0,serializer:j.serializer,deserializer:function(e,n,t){j.deserializer(e,(function(e,i){!function(e,n,t){t.rootContext.resolve(t.modelSchema,e,t.target)}(i,t.target,t),r&&r(i,t.target,t),n(e,i)}),t)}},i)},e.list=J,e.map=function(e,n){return t(f(e=e||j),"expected prop schema as first argument"),t(!a(e),"provided prop is aliased, please put aliases first"),d({serializer:function(n){t(n&&"object"==typeof n,"expected object or Map");var r={};if(l(n))n.forEach((function(t,i){return r[i]=e.serializer(t,i,n)}));else for(var i in n)r[i]=e.serializer(n[i],i,n);return r},deserializer:function(t,r,i,o){if(t&&"object"==typeof t){var u=Object.keys(t);J(e,n).deserializer(u.map((function(e){return t[e]})),(function(e,n){if(e)r(e);else{var t,i=l(o);i?(o.clear(),t=o):t={};for(var f=0,a=u.length;f<a;f++)i?t.set(u[f],n[f]):t[u[f]]=n[f];r(null,t)}}),i)}else r("[serializr] expected JSON object")}},n)},e.mapAsArray=function(e,n,r){return t(f(e=e||j),"expected prop schema as first argument"),t(!!n,"expected key property name as second argument"),d({serializer:function(n){t(n&&"object"==typeof n,"expected object or Map");var r=[];if(l(n))n.forEach((function(t,i){return r.push(e.serializer(t,i,n))}));else for(var i in n)r.push(e.serializer(n[i],i,n));return r},deserializer:function(t,i,o,u){J(e,r).deserializer(t,(function(e,r){if(e)i(e);else{var o,f=l(u);f?(u.clear(),o=u):o={};for(var a=0,c=t.length;a<c;a++)f?o.set(r[a][n],r[a]):o[r[a][n].toString()]=r[a];i(null,o)}}),o,undefined)}},r)},e.object=M,e.optional=function(e){t(f(e=e&&!0!==e?e:j),"expected prop schema as second argument");var n=e.serializer;return t("function"==typeof n,"expected prop schema to have a callable serializer"),Object.assign({},e,{serializer:function(e,t,r){var i=n(e,t,r);return i===undefined?b:i}})},e.primitive=y,e.raw=function(e){return d({serializer:function(e){return e},deserializer:function(e,n){n(null,e)}},e)},e.reference=function(e,n,r){t(!!e,"No modelSchema provided. If you are importing it from another file be aware of circular dependencies.");var i="function"==typeof n?n:undefined;r=r||(i?undefined:n);var o,f=!1;function a(){if(f=!0,t("string"!=typeof e||"function"==typeof i,"if the reference target is specified by attribute name, a lookup function is required"),t(!i||"function"==typeof i,"second argument should be a lookup function or additional arguments object"),"string"==typeof e)o=e;else{var n=p(e);t(u(n),"expected model schema or string as first argument for 'ref', got "+n),i=i||function(e){return function(n,t,r){r.rootContext.await(e,n,t)}}(n),o=function(e){t(u(e),"modelSchema must be a ModelSchema");for(var n=e;n;){for(var r in n.props)if(c(n.props[r]))return r;n=n["extends"]}return undefined}(n),t(!!o,"provided model schema doesn't define an identifier() property and cannot be used by 'ref'.")}}return d({serializer:function(e){return f||a(),e?e[o]:null},deserializer:function(e,n,t){f||a(),null===e||e===undefined?n(null,e):i(e,n,t)}},r)},e.serializable=function(e,n,r){if(!n){var i=!0===e?j:e;return t(f(i),"@serializable expects prop schema"),S.bind(null,i)}S(y(),e,n,r)},e.serialize=O,e.serializeAll=function(e,n){var r;if(1===arguments.length)return r=!0,i(e);function i(e){t("function"==typeof e,"@serializeAll can only be used as class decorator");var n=p(e);return n||v(e,n=h(e,{})),n.props["*"]=r,e}return t("object"==typeof e&&e.test,"@serializeAll pattern doesn't have test"),"function"==typeof n&&(n=M(n)),!0===n&&(n=j),t(f(n),"couldn't resolve schema"),r=Object.assign({},n,{pattern:e}),i},e.setDefaultModelSchema=v,e.update=function(e,n,i,o,f){var a=2===arguments.length||"function"==typeof arguments[2];a?(e=p(n=arguments[0]),i=arguments[1],o=arguments[2],f=arguments[3]):e=p(e),t(u(e),"update failed to determine schema"),t("object"==typeof n&&n&&!Array.isArray(n),"update needs an object");var c=new k(undefined,e,i,o||r,f);c.setTarget(n);var s=c.createCallback(r),l=N(c,e,i,n);return s(),l},Object.defineProperty(e,"t",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e=e||self).serializr={});
//# sourceMappingURL=serializr.min.js.map
{
"name": "serializr",
"version": "1.5.4",
"description": "Serialize and deserialize complex object graphs to JSON",
"main": "lib/serializr.js",
"module": "lib/es/serializr.js",
"typings": "serializr.d.ts",
"scripts": {
"test": "npm run build-test && node test/index",
"lint": "eslint src",
"prepublish": "npm run build && npm run build-docs",
"build": "node scripts/build.js",
"build-docs": "documentation readme src/serializr.js --github --section API",
"build-test": "npm run build-test-babel && npm run build-test-ts",
"build-test-ts": "tsc -p test/typescript",
"build-test-babel": "babel test/babel/babel.js -o test/babel/babel-compiled.js",
"coverage": "npm run build-test && istanbul cover tape test/*.js"
},
"keywords": [
"serialize",
"deserialize",
"graph",
"json",
"mobx"
],
"repository": {
"type": "git",
"url": "https://github.com/mobxjs/serializr.git"
},
"author": "Michel Weststrate",
"license": "MIT",
"bugs": {
"url": "https://github.com/mobxjs/serializr/issues"
},
"files": [
"lib",
"serializr.d.ts"
],
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/plugin-proposal-class-properties": "^7.3.0",
"@babel/plugin-proposal-decorators": "^7.3.0",
"@babel/preset-env": "^7.3.1",
"babel-eslint": "^10.0.1",
"coveralls": "^3.0.2",
"documentation": "^9.1.1",
"eslint": "^5.13.0",
"eslint-plugin-import": "^2.16.0",
"istanbul": "^0.4.4",
"lodash.merge": "^4.6.0",
"mobx": "^2.4.1 || ^3.0.0 || ^4.0.0 || ^5.0.0",
"rollup": "^1.1.2",
"rollup-plugin-commonjs": "^9.2.0",
"rollup-plugin-node-resolve": "^4.0.0",
"rollup-plugin-terser": "^4.0.4",
"tape": "^4.9.2",
"typescript": "^3.3.3"
}
}
"name": "serializr",
"version": "2.0.0-beta1",
"description": "Serialize and deserialize complex object graphs to JSON",
"main": "lib/serializr.js",
"module": "lib/es/serializr.js",
"typings": "lib/serializr.d.ts",
"scripts": {
"test": "nyc --reporter lcov tape test/*.js",
"lint": "eslint src",
"prepare": "yarn run build && yarn run build-docs",
"build": "rollup --config",
"build-docs": "ts-node --transpile-only --project gendoc.tsconfig.json ./gendoc.tsx",
"build-test": "yarn run build-test-babel && yarn run build-test-ts",
"build-test-ts": "tsc -p test/typescript",
"build-test-babel": "babel test/babel/babel.js -o test/babel/babel-compiled.js",
"prettier": "prettier --write {src,test}/**/*.{ts,js}",
"clean": "rimraf lib test/typescript/ts.js test/babel/babel-compiled.js",
"watch-docs": "nodemon -w gendoc.tsx -w src -e ts,tsx,md -x ts-node --transpile-only --project gendoc.tsconfig.json ./gendoc.tsx"
},
"nyc": {
"all": true,
"include": [
"src/**/*",
"lib/**/*"
]
},
"keywords": [
"serialize",
"deserialize",
"graph",
"json",
"mobx"
],
"repository": {
"type": "git",
"url": "https://github.com/mobxjs/serializr.git"
},
"author": "Michel Weststrate",
"license": "MIT",
"bugs": {
"url": "https://github.com/mobxjs/serializr/issues"
},
"files": [
"lib",
"serializr.d.ts"
],
"devDependencies": {
"@babel/cli": "^7.2.3",
"@babel/plugin-proposal-class-properties": "^7.3.0",
"@babel/plugin-proposal-decorators": "^7.3.0",
"@babel/preset-env": "^7.3.1",
"@rollup/plugin-commonjs": "^11.0.2",
"@rollup/plugin-node-resolve": "^7.1.0",
"@types/react": "^16.9.19",
"@types/react-dom": "^16.9.5",
"@types/tape": "^4.2.33",
"babel-eslint": "^10.0.1",
"coveralls": "^3.0.2",
"documentation": "^12.1.4",
"eslint": "^5.13.0",
"eslint-plugin-import": "^2.16.0",
"lodash.merge": "^4.6.0",
"mobx": "^2.4.1 || ^3.0.0 || ^4.0.0 || ^5.0.0",
"nodemon": "^2.0.2",
"nyc": "^15.0.0",
"prettier": "^1.19.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-markdown": "^4.3.1",
"rimraf": "^3.0.1",
"rollup": "^1.1.2",
"rollup-plugin-terser": "^5.2.0",
"rollup-plugin-typescript2": "^0.25.3",
"tape": "^4.9.2",
"ts-node": "^8.6.2",
"turndown": "^5.0.3",
"turndown-plugin-gfm": "^1.0.2",
"typedoc": "^0.17.0-3",
"typescript": "^3.3.3",
"unescape": "^1.0.1"
},
"dependencies": {}
}

@@ -8,2 +8,3 @@ # Serializr

[![Join the chat at https://gitter.im/mobxjs/serializr](https://badges.gitter.im/mobxjs/serializr.svg)](https://gitter.im/mobxjs/serializr?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![NPM](https://img.shields.io/npm/v/serializr)](https://www.npmjs.com/package/serializr)

@@ -53,15 +54,15 @@ _Serializr is feature complete, and easily extendable. Since there are no active maintainers the project is frozen feature wise. Bug reports and well designed pull requests are welcome and will be addressed._

serialize,
deserialize,
} from 'serializr';
deserialize
} from "serializr"
// Example model classes
class User {
uuid = Math.floor(Math.random() * 10000);
displayName = 'John Doe';
uuid = Math.floor(Math.random() * 10000)
displayName = "John Doe"
}
class Message {
message = 'Test';
author = null;
comments = [];
message = "Test"
author = null
comments = []
}

@@ -72,6 +73,6 @@

// In a real app this might be a database query
const user = new User();
user.uuid = uuid;
user.displayName = `John Doe ${uuid}`;
return user;
const user = new User()
user.uuid = uuid
user.displayName = `John Doe ${uuid}`
return user
}

@@ -84,3 +85,3 @@

// context is an object detailing the execution context of the serializer now
callback(null, fetchUserSomewhere(uuid));
callback(null, fetchUserSomewhere(uuid))
}

@@ -92,25 +93,25 @@

author: reference(User, findUserById),
comments: list(object(Message)),
});
comments: list(object(Message))
})
createModelSchema(User, {
uuid: identifier(),
displayName: primitive(),
});
displayName: primitive()
})
// can now deserialize and serialize!
const message = deserialize(Message, {
message: 'Hello world',
message: "Hello world",
author: 17,
comments: [
{
message: 'Welcome!',
author: 23,
},
],
});
message: "Welcome!",
author: 23
}
]
})
const json = serialize(message);
const json = serialize(message)
console.dir(message, { colors: true, depth: 10 });
console.dir(message, { colors: true, depth: 10 })
```

@@ -133,21 +134,23 @@

getDefaultModelSchema,
serializable,
} from 'serializr';
serializable
} from "serializr"
class User {
@serializable(identifier())
uuid = Math.random();
uuid = Math.random()
@serializable displayName = 'John Doe';
@serializable
displayName = "John Doe"
}
class Message {
@serializable message = 'Test';
@serializable
message = "Test"
@serializable(object(User))
author = null;
author = null
// Self referencing decorators work in Babel 5.x and Typescript. See below for more.
@serializable(list(object(Message)))
comments = [];
comments = []
}

@@ -157,13 +160,13 @@

const message = deserialize(Message, {
message: 'Hello world',
author: { uuid: 1, displayName: 'Alice' },
message: "Hello world",
author: { uuid: 1, displayName: "Alice" },
comments: [
{
message: 'Welcome!',
author: { uuid: 1, displayName: 'Bob' },
},
],
});
message: "Welcome!",
author: { uuid: 1, displayName: "Bob" }
}
]
})
console.dir(message, { colors: true, depth: 10 });
console.dir(message, { colors: true, depth: 10 })

@@ -173,3 +176,3 @@ // We can call serialize without the first argument here

const json = serialize(message);
const json = serialize(message)
```

@@ -183,13 +186,11 @@

class Message {
@serializable message = 'Test';
@serializable message = "Test"
@serializable(object(User))
author = null;
author = null
comments = [];
comments = []
constructor() {
getDefaultModelSchema(Message).props['comments'] = list(
object(Message)
);
getDefaultModelSchema(Message).props["comments"] = list(object(Message))
}

@@ -213,4 +214,4 @@ }

"plugins": [
["@babel/plugin-proposal-decorators", { "legacy": true}],
["@babel/plugin-proposal-class-properties", { "loose": true}]
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }]
]

@@ -234,5 +235,5 @@ }

```json
{
"stage": 1
}
{
"stage": 1
}
```

@@ -259,5 +260,5 @@

props: {
modelfield: PropSchema,
},
};
modelfield: PropSchema
}
}
```

@@ -331,25 +332,41 @@

const myHandler = {
beforeDeserialize: function (callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef) {
if (typeof jsonValue === 'string') {
callback(null, jsonValue)
} else if (typeof jsonValue === 'number') {
callback(null, jsonValue.toString())
} else {
callback(new Error('something went wrong before deserialization'))
}
},
afterDeserialize: function (callback, error, newValue, jsonValue, jsonParentValue, propNameOrIndex, context,
propDef, numRetry) {
if (!error && newValue !== 'needs change') {
callback(null, newValue)
} else if (!error && newValue === 'needs change') {
callback(new Error(), 'changed value')
} else {
callback(error)
}
}
beforeDeserialize: function(
callback,
jsonValue,
jsonParentValue,
propNameOrIndex,
context,
propDef
) {
if (typeof jsonValue === "string") {
callback(null, jsonValue)
} else if (typeof jsonValue === "number") {
callback(null, jsonValue.toString())
} else {
callback(new Error("something went wrong before deserialization"))
}
},
afterDeserialize: function(
callback,
error,
newValue,
jsonValue,
jsonParentValue,
propNameOrIndex,
context,
propDef
) {
if (!error && newValue !== "needs change") {
callback(null, newValue)
} else if (!error && newValue === "needs change") {
callback(new Error(), "changed value")
} else {
callback(error)
}
}
}
class MyData {
@serializable(primitive(myHandler)) mySimpleField
@serializable(primitive(myHandler))
mySimpleField
}

@@ -360,496 +377,251 @@ ```

# API
<!-- START API AUTOGEN -->
<!-- THIS SECTION WAS AUTOGENERATED BY gendoc.tsx! DO NOT EDIT! -->
API
---
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
### _interface_ `ModelSchema`&lt;T&gt;<sub><a href="src/api/types.ts#L65">src</a></sub>
### Table of Contents
#### property `targetClass`?: [Clazz](#type-clazzt----src)&lt;any&gt;
- [ModelSchema](#modelschema)
- [Parameters](#parameters)
- [Properties](#properties)
- [createSimpleSchema](#createsimpleschema)
- [Parameters](#parameters-1)
- [Examples](#examples)
- [createModelSchema](#createmodelschema)
- [Parameters](#parameters-2)
- [Examples](#examples-1)
- [getDefaultModelSchema](#getdefaultmodelschema)
- [Parameters](#parameters-3)
- [setDefaultModelSchema](#setdefaultmodelschema)
- [Parameters](#parameters-4)
- [serializable](#serializable)
- [Parameters](#parameters-5)
- [Examples](#examples-2)
- [serialize](#serialize)
- [Parameters](#parameters-6)
- [serializeAll](#serializeall)
- [Parameters](#parameters-7)
- [Examples](#examples-3)
- [cancelDeserialize](#canceldeserialize)
- [Parameters](#parameters-8)
- [deserialize](#deserialize)
- [Parameters](#parameters-9)
- [update](#update)
- [Parameters](#parameters-10)
- [primitive](#primitive)
- [Parameters](#parameters-11)
- [Examples](#examples-4)
- [identifier](#identifier)
- [Parameters](#parameters-12)
- [Examples](#examples-5)
- [date](#date)
- [Parameters](#parameters-13)
- [alias](#alias)
- [Parameters](#parameters-14)
- [Examples](#examples-6)
- [custom](#custom)
- [Parameters](#parameters-15)
- [Examples](#examples-7)
- [object](#object)
- [Parameters](#parameters-16)
- [Examples](#examples-8)
- [optional](#optional)
- [Parameters](#parameters-17)
- [Examples](#examples-9)
- [reference](#reference)
- [Parameters](#parameters-18)
- [Examples](#examples-10)
- [list](#list)
- [Parameters](#parameters-19)
- [Examples](#examples-11)
- [map](#map)
- [Parameters](#parameters-20)
- [mapAsArray](#mapasarray)
- [Parameters](#parameters-21)
- [raw](#raw)
- [Parameters](#parameters-22)
- [Examples](#examples-12)
- [SKIP](#skip)
- [Examples](#examples-13)
#### property `factory`: (_context_: [Context](typedoc-id-undefined)) => T
## ModelSchema
#### property `props`: [Props](#type-propst----src)&lt;T&gt;
[src/serializr.js:52-52](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/serializr.js#L5-L51 "Source code on GitHub")
#### property `extends`?: [ModelSchema](#interface-modelschematsrc)&lt;any&gt;
JSDOC type defintions for usage w/o typescript.
### _interface_ `PropSchema`<sub><a href="src/api/types.ts#L22">src</a></sub>
Type: [object](#object)
#### property `serializer`: [PropSerializer](#type-propserializer--sourcepropertyvalue-any-key-string--number--symbol-sourceobject-any--any--typeof-skip-src)
### Parameters
#### property `deserializer`: [PropDeserializer](#type-propdeserializer--jsonvalue-any-callback-err-any-targetpropertyvalue-any--typeof-skip--void-context-context-currentpropertyvalue-any--void-src)
- `value` **any**
- `writeable` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
- `get` **([Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) \| [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
- `set` **([Function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function) \| [undefined](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/undefined))**
- `configurable` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
- `enumerable` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
- `sourcePropertyValue` **any**
- `jsonValue` **any**
- `callback` **cpsCallback**
- `context` **Context**
- `currentPropertyValue` **any**
- `id` **any**
- `target` **[object](#object)**
- `context` **Context**
- `result` **any**
- `error` **any**
- `id` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)**
- `callback` **cpsCallback**
- `factory`
- `props`
- `targetClass`
#### property `beforeDeserialize`?: [BeforeDeserializeFunc](#type-beforedeserializefunc--callback-err-any-value-any--void-jsonvalue-any-jsonparentvalue-any-propnameorindex-string--number-context-context-propdef-propschema--void-src)
### Properties
#### property `afterDeserialize`?: [AfterDeserializeFunc](#type-afterdeserializefunc--callback-err-any-value-any--void-err-any-newvalue-any-jsonvalue-any-jsonparentvalue-any-propnameorindex-string--number--symbol-context-context-propdef-propschema--void-src)
- `serializer` **serializerFunction**
- `deserializer` **deserializerFunction**
- `identifier` **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)**
#### property `pattern`?: undefined | { test: (_propName_: string) => boolean }
Returns **any** any - serialized object
Filter properties to which this schema applies. Used with `ModelSchema.props["*"]`.
Returns **any** void
#### property `jsonname`?: undefined | string
Returns **any** void
#### property `identifier`?: undefined | true
Returns **any** void
#### property `paramNumber`?: undefined | number
## createSimpleSchema
### _type_ `AdditionalPropArgs` = [Pick](typedoc-id-undefined)&lt;[PropSchema](#interface-propschemasrc), `"beforeDeserialize"` | `"afterDeserialize"` | `"pattern"`&gt; <sub><a href="src/api/types.ts#L7">src</a></sub>
[src/api/createSimpleSchema.js:17-24](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/api/createSimpleSchema.js#L17-L24 "Source code on GitHub")
Can be passed to function which create `PropSchema`s to set additional properties.
Creates a model schema that (de)serializes from / to plain javascript objects.
Its factory method is: `() => ({})`
### _type_ `AfterDeserializeFunc` = (_callback_: (_err_: any, _value_: any) => void, _err_: any, _newValue_: any, _jsonValue_: any, _jsonParentValue_: any, _propNameOrIndex_: string | number | symbol, _context_: [Context](typedoc-id-undefined), _propDef_: [PropSchema](#interface-propschemasrc)) => void <sub><a href="src/api/types.ts#L36">src</a></sub>
### Parameters
### _type_ `BeforeDeserializeFunc` = (_callback_: (_err_: any, _value_: any) => void, _jsonValue_: any, _jsonParentValue_: any, _propNameOrIndex_: string | number, _context_: [Context](typedoc-id-undefined), _propDef_: [PropSchema](#interface-propschemasrc)) => void <sub><a href="src/api/types.ts#L47">src</a></sub>
- `props` **[object](#object)** property mapping,
### _type_ `Clazz`&lt;T&gt; = { } <sub><a href="src/api/types.ts#L72">src</a></sub>
### Examples
### _type_ `ClazzOrModelSchema`&lt;T&gt; = [ModelSchema](#interface-modelschematsrc)&lt;T&gt; | [Clazz](#type-clazzt----src)&lt;T&gt; <sub><a href="src/api/types.ts#L73">src</a></sub>
```javascript
var todoSchema = createSimpleSchema({
title: true,
done: true,
});
### _type_ `PropDef` = [PropSchema](#interface-propschemasrc) | boolean | undefined <sub><a href="src/api/types.ts#L63">src</a></sub>
var json = serialize(todoSchema, { title: 'Test', done: false });
var todo = deserialize(todoSchema, json);
```
### _type_ `PropDeserializer` = (_jsonValue_: any, _callback_: (_err_?: any, _targetPropertyValue_?: any | typeof [SKIP](typedoc-id-undefined)) => void, _context_: [Context](typedoc-id-undefined), _currentPropertyValue_?: any) => void <sub><a href="src/api/types.ts#L16">src</a></sub>
Returns **[object](#object)** model schema
### _type_ `PropSerializer` = (_sourcePropertyValue_: any, _key_: string | number | symbol, _sourceObject_: any) => any | typeof [SKIP](typedoc-id-undefined) <sub><a href="src/api/types.ts#L11">src</a></sub>
## createModelSchema
### _type_ `Props`&lt;T&gt; = { } <sub><a href="src/api/types.ts#L60">src</a></sub>
[src/api/createModelSchema.js:29-47](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/api/createModelSchema.js#L29-L47 "Source code on GitHub")
true is shorthand for `primitive().` false/undefined will be ignored
Creates a model schema that (de)serializes an object created by a constructor function (class).
The created model schema is associated by the targeted type as default model schema, see setDefaultModelSchema.
Its factory method is `() => new clazz()` (unless overriden, see third arg).
### _type_ `RefLookupFunction` = (_id_: string, _callback_: (_err_: any, _result_: any) => void, _context_: [Context](typedoc-id-undefined)) => void <sub><a href="src/api/types.ts#L75">src</a></sub>
### Parameters
### _type_ `RegisterFunction` = (_id_: any, _object_: any, _context_: [Context](typedoc-id-undefined)) => void <sub><a href="src/api/types.ts#L80">src</a></sub>
- `clazz` **([constructor](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) | class)** class or constructor function
- `props` **[object](#object)** property mapping
- `factory` **[function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** optional custom factory. Receives context as first arg
### _const_ `SKIP`<sub><a href="src/constants.ts#L36">src</a></sub>
### Examples
If you want to skip serialization or deserialization, you can use SKIP.
```javascript
function Todo(title, done) {
this.title = title;
this.done = done;
}
createModelSchema(Todo, {
title: true,
done: true,
});
var json = serialize(new Todo('Test', false));
var todo = deserialize(Todo, json);
```ts
const schema = createSimpleSchema({
a: custom(
() => SKIP,
v => v,
),
})
serialize(s, { a: 4 }) // {}
deserialize(s, { "a": 4 }) // { a: 4 }
```
Returns **[object](#object)** model schema
```ts
// Skipping deserialization with computed mobx property.
## getDefaultModelSchema
class TodoState {
// Todo.category is @serializable(reference(...))
@serializable(list(object(Todo)))
@observable
todos: Todo[]
[src/api/getDefaultModelSchema.js:9-18](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/api/getDefaultModelSchema.js#L9-L18 "Source code on GitHub")
Returns the standard model schema associated with a class / constructor function
### Parameters
- `thing` **[object](#object)**
Returns **[ModelSchema](#modelschema)** model schema
## setDefaultModelSchema
[src/api/setDefaultModelSchema.js:15-18](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/api/setDefaultModelSchema.js#L15-L18 "Source code on GitHub")
Sets the default model schema for class / constructor function.
Everywhere where a model schema is required as argument, this class / constructor function
can be passed in as well (for example when using `object` or `ref`.
When passing an instance of this class to `serialize`, it is not required to pass the model schema
as first argument anymore, because the default schema will be inferred from the instance type.
### Parameters
- `clazz` **([constructor](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor) | class)** class or constructor function
- `modelSchema` **[ModelSchema](#modelschema)** a model schema
Returns **[ModelSchema](#modelschema)** model schema
## serializable
[src/api/serializable.js:93-103](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/api/serializable.js#L93-L103 "Source code on GitHub")
Decorator that defines a new property mapping on the default model schema for the class
it is used in.
When using typescript, the decorator can also be used on fields declared as constructor arguments (using the `private` / `protected` / `public` keywords).
The default factory will then invoke the constructor with the correct arguments as well.
### Parameters
- `arg1`
- `arg2`
- `arg3`
### Examples
```javascript
class Todo {
// we want to serialize the categories, so that the references in
// this.todos can be resolved, but we don't want to set this property
@serializable(
list(object(TodoCategory),
{ afterDeserialize: callback => callback(undefined, SKIP) }))
@computed
get categories() {
return this.todos.map(todo => todo.category)
}
}
```
Returns **PropertyDescriptor**
### _function_ `alias`(_name_: string, _propSchema_?: [PropDef](#type-propdef--propschema--boolean--undefined-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/alias.ts#L24">src</a></sub>
## serialize
Alias indicates that this model property should be named differently in the generated json. Alias should be the outermost propschema.
[src/core/serialize.js:14-36](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/core/serialize.js#L14-L36 "Source code on GitHub")
```ts
createModelSchema(Todo, {
title: alias('task', primitive()),
})
Serializes an object (graph) into json using the provided model schema.
The model schema can be omitted if the object type has a default model schema associated with it.
If a list of objects is provided, they should have an uniform type.
### Parameters
- `arg1` class or modelschema to use. Optional
- `arg2` object(s) to serialize
Returns **[object](#object)** serialized representation of the object
## serializeAll
[src/core/serializeAll.js:38-67](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/core/serializeAll.js#L38-L67 "Source code on GitHub")
The `serializeAll` decorator can may used on a class to signal that all primitive properties,
or complex properties with a name matching a `pattern`, should be serialized automatically.
### Parameters
- `targetOrPattern`
- `clazzOrSchema`
### Examples
```javascript
class DataType {
serialize(new Todo('test')) // { "task": "test" }
```
## cancelDeserialize
### _function_ `cancelDeserialize`&lt;T&gt;(_instance_: T): void <sub><a href="src/core/cancelDeserialize.ts#L11">src</a></sub>
[src/core/cancelDeserialize.js:12-18](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/core/cancelDeserialize.js#L12-L18 "Source code on GitHub")
Cancels an asynchronous deserialization or update operation for the specified target object.
### Parameters
### _function_ `createModelSchema`&lt;T&gt;(_clazz_: [Clazz](#type-clazzt----src)&lt;T&gt;, _props_: [Props](#type-propst----src), _factory_?: undefined | ((_context_: [Context](typedoc-id-undefined)) => T)): [ModelSchema](#interface-modelschematsrc)&lt;T&gt; <sub><a href="src/api/createModelSchema.ts#L31">src</a></sub>
- `instance` object that was previously returned from deserialize or update method
Creates a model schema that (de)serializes an object created by a constructor function (class). The created model schema is associated by the targeted type as default model schema, see setDefaultModelSchema. Its factory method is `() => new clazz()` (unless overriden, see third arg).
## deserialize
```ts
function Todo(title, done) {
this.title = title
this.done = done
}
[src/core/deserialize.js:69-87](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/core/deserialize.js#L69-L87 "Source code on GitHub")
Deserializes a json structure into an object graph.
This process might be asynchronous (for example if there are references with an asynchronous
lookup function). The function returns an object (or array of objects), but the returned object
might be incomplete until the callback has fired as well (which might happen immediately)
### Parameters
- `schema` **([object](#object) \| [array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array))** to use for deserialization
- `json` **[json](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/JSON)** data to deserialize
- `callback` **[function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** node style callback that is invoked once the deserialization has
finished. First argument is the optional error, second argument is the deserialized object
(same as the return value)
- `customArgs` **any** custom arguments that are available as `context.args` during the
deserialization process. This can be used as dependency injection mechanism to pass in, for
example, stores.
Returns **([object](#object) \| [array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array))** deserialized object, possibly incomplete.
## update
[src/core/update.js:22-44](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/core/update.js#L22-L44 "Source code on GitHub")
Similar to deserialize, but updates an existing object instance.
Properties will always updated entirely, but properties not present in the json will be kept as is.
Further this method behaves similar to deserialize.
### Parameters
- `modelSchema` **[object](#object)** , optional if it can be inferred from the instance type
- `target` **[object](#object)** target instance to update
- `json` **[object](#object)** the json to deserialize
- `callback` **[function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** the callback to invoke once deserialization has completed.
- `customArgs` **any** custom arguments that are available as `context.args` during the deserialization process. This can be used as dependency injection mechanism to pass in, for example, stores.
Returns **([object](#object) \| [array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array))** deserialized object, possibly incomplete.
## primitive
[src/types/primitive.js:18-32](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/primitive.js#L18-L32 "Source code on GitHub")
Indicates that this field contains a primitive value (or Date) which should be serialized literally to json.
### Parameters
- `additionalArgs` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
### Examples
```javascript
createModelSchema(Todo, {
title: primitive(),
});
title: true,
done: true,
})
console.dir(serialize(new Todo('test')));
// outputs: { title : "test" }
const json = serialize(new Todo('Test', false))
const todo = deserialize(Todo, json)
```
Returns **[ModelSchema](#modelschema)**
### _function_ `createSimpleSchema`&lt;T&gt;(_props_: [Props](#type-propst----src)): [ModelSchema](#interface-modelschematsrc)&lt;T&gt; <sub><a href="src/api/createSimpleSchema.ts#L19">src</a></sub>
## identifier
Creates a model schema that (de)serializes from / to plain javascript objects. Its factory method is: `() => ({})`
[src/types/identifier.js:43-66](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/identifier.js#L43-L66 "Source code on GitHub")
Similar to primitive, but this field will be marked as the identifier for the given Model type.
This is used by for example `reference()` to serialize the reference
Identifier accepts an optional `registerFn` with the signature:
`(id, target, context) => void`
that can be used to register this object in some store. note that not all fields of this object might
have been deserialized yet.
### Parameters
- `arg1` **(RegisterFunction | AdditionalPropArgs)** optional registerFn: function to register this object during creation.
- `arg2` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
### Examples
```javascript
var todos = {};
var s = _.createSimpleSchema({
id: _.identifier((id, object) => (todos[id] = object)),
```ts
const todoSchema = createSimpleSchema({
title: true,
});
done: true,
})
_.deserialize(s, {
id: 1,
title: 'test0',
});
_.deserialize(s, [{ id: 2, title: 'test2' }, { id: 1, title: 'test1' }]);
t.deepEqual(todos, {
1: { id: 1, title: 'test1' },
2: { id: 2, title: 'test2' },
});
const json = serialize(todoSchema, { title: 'Test', done: false })
const todo = deserialize(todoSchema, json)
```
Returns **PropSchema**
### _function_ `custom`(_serializer_: [PropSerializer](#type-propserializer--sourcepropertyvalue-any-key-string--number--symbol-sourceobject-any--any--typeof-skip-src), _deserializer_: (_jsonValue_: any, _context_: any, _oldValue_: any) => any | typeof [SKIP](typedoc-id-undefined), _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/custom.ts#L63">src</a></sub>
## date
Can be used to create simple custom propSchema. Multiple things can be done inside of a custom propSchema, like deserializing and serializing other (polymorphic) objects, skipping the serialization of something or checking the context of the obj being (de)serialized.
[src/types/date.js:9-26](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/date.js#L9-L26 "Source code on GitHub")
The `custom` function takes two parameters, the `serializer` function and the `deserializer` function.
Similar to primitive, serializes instances of Date objects
The `serializer` function has the signature: `(value, key, obj) => void`
### Parameters
When serializing the object `{a: 1}` the `serializer` function will be called with `serializer(1, 'a', {a: 1})`.
- `additionalArgs` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
The `deserializer` function has the following signature for synchronous processing `(value, context, oldValue) => void`
Returns **PropSchema**
For asynchronous processing the function expects the following signature `(value, context, oldValue, callback) => void`
## alias
When deserializing the object `{b: 2}` the `deserializer` function will be called with `deserializer(2, contextObj)` ([contextObj reference](https://github.com/mobxjs/serializr#deserialization-context)).
[src/types/alias.js:20-33](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/alias.js#L20-L33 "Source code on GitHub")
```ts
const schemaDefault = createSimpleSchema({
a: custom(
v => v + 2,
v => v - 2
)
})
serialize(schemaDefault, { a: 4 }) // { "a": 6 }
deserialize(schemaDefault, { "a": 6 }) // { a: 4 }
Alias indicates that this model property should be named differently in the generated json.
Alias should be the outermost propschema.
### Parameters
- `name` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** name of the json field to be used for this property
- `propSchema` **PropSchema** propSchema to (de)serialize the contents of this field
### Examples
```javascript
createModelSchema(Todo, {
title: alias('task', primitive()),
});
console.dir(serialize(new Todo('test')));
// { task : "test" }
const schemaWithAsyncProps = createSimpleSchema({
a: custom(
v => v + 2,
(v, context, oldValue, callback) =>
somePromise(v, context, oldValue)
.then(result => callback(null, result - 2))
.catch(err => callback(err))
)
})
serialize(schemaWithAsyncProps, { a: 4 }) // { "a": 6 }
deserialize(schemaWithAsyncProps, { "a": 6 }, (err, res) => {
res // { a: 4 }
}
```
Returns **PropSchema**
### _function_ `custom`(_serializer_: [PropSerializer](#type-propserializer--sourcepropertyvalue-any-key-string--number--symbol-sourceobject-any--any--typeof-skip-src), _deserializer_: (_jsonValue_: any, _context_: any, _oldValue_: any, _callback_: (_err_: any, _result_: any | typeof [SKIP](typedoc-id-undefined)) => void) => void, _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/custom.ts#L68">src</a></sub>
## custom
### _function_ `date`(_additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/date.ts#L9">src</a></sub>
[src/types/custom.js:60-75](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/custom.js#L60-L75 "Source code on GitHub")
Similar to primitive, serializes instances of Date objects
Can be used to create simple custom propSchema. Multiple things can be done inside of a custom propSchema, like deserializing and serializing other (polymorphic) objects, skipping the serialization of something or checking the context of the obj being (de)serialized.
### _function_ `deserialize`&lt;T&gt;(_modelschema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)&lt;T&gt;, _jsonArray_: any\[\], _callback_?: undefined | ((_err_: any, _result_: T\[\]) => void), _customArgs_?: any): T\[\] <sub><a href="src/core/deserialize.ts#L76">src</a></sub>
The `custom` function takes two parameters, the `serializer` function and the `deserializer` function.
Deserializes a json structure into an object graph.
The `serializer` function has the signature:
`(value, key, obj) => void`
This process might be asynchronous (for example if there are references with an asynchronous lookup function). The function returns an object (or array of objects), but the returned object might be incomplete until the callback has fired as well (which might happen immediately)
When serializing the object `{a: 1}` the `serializer` function will be called with `serializer(1, 'a', {a: 1})`.
### _function_ `deserialize`&lt;T&gt;(_modelschema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)&lt;T&gt;, _json_: any, _callback_?: undefined | ((_err_: any, _result_: T) => void), _customArgs_?: any): T <sub><a href="src/core/deserialize.ts#L82">src</a></sub>
The `deserializer` function has the following signature for synchronous processing
`(value, context, oldValue) => void`
### _function_ `getDefaultModelSchema`&lt;T&gt;(_thing_: any): [ModelSchema](#interface-modelschematsrc)&lt;T&gt; | undefined <sub><a href="src/api/getDefaultModelSchema.ts#L8">src</a></sub>
For asynchronous processing the function expects the following signature
`(value, context, oldValue, callback) => void`
Returns the standard model schema associated with a class / constructor function
When deserializing the object `{b: 2}` the `deserializer` function will be called with `deserializer(2, contextObj)` ([contextObj reference](https://github.com/mobxjs/serializr#deserialization-context)).
### _function_ `identifier`(_arg1_?: [RegisterFunction](#type-registerfunction--id-any-object-any-context-context--void-src) | [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src), _arg2_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/identifier.ts#L48">src</a></sub>
### Parameters
### _function_ `list`(_propSchema_: [PropSchema](#interface-propschemasrc), _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/list.ts#L42">src</a></sub>
- `serializer` **[function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** function that takes a model value and turns it into a json value
- `deserializer` **[function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** function that takes a json value and turns it into a model value. It also takes context argument, which can allow you to deserialize based on the context of other parameters.
- `additionalArgs` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
List indicates that this property contains a list of things. Accepts a sub model schema to serialize the contents
### Examples
```ts
class SubTask {}
class Task {}
class Todo {}
```javascript
var schemaDefault = _.createSimpleSchema({
a: _.custom(
function(v) {
return v + 2;
},
function(v) {
return v - 2;
}
),
});
t.deepEqual(_.serialize(schemaDefault, { a: 4 }), { a: 6 });
t.deepEqual(_.deserialize(schemaDefault, { a: 6 }), { a: 4 });
createModelSchema(SubTask, {
title: true,
})
createModelSchema(Todo, {
title: true,
subTask: list(object(SubTask)),
})
var schemaWithAsyncProps = _.createSimpleSchema({
a: _.customAsync(
function(v) {
return v + 2;
const todo = deserialize(Todo, {
title: 'Task',
subTask: [
{
title: 'Sub task 1',
},
function(v, context, oldValue, callback) {
somePromise(v, context, oldValue).then((result) => {
callback(null, result - 2)
}.catch((err) => {
callback(err)
}
}
),
});
t.deepEqual(_.serialize(schemaWithAsyncProps, { a: 4 }), { a: 6 });
_.deserialize(schemaWithAsyncProps, { a: 6 }, (err, res) => {
t.deepEqual(res.a, 4)
};
],
})
```
Returns **PropSchema**
### _function_ `map`(_propSchema_: [PropSchema](#interface-propschemasrc), _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/map.ts#L19">src</a></sub>
## object
Similar to list, but map represents a string keyed dynamic collection. This can be both plain objects (default) or ES6 Map like structures. This will be inferred from the initial value of the targetted attribute.
[src/types/object.js:35-55](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/object.js#L35-L55 "Source code on GitHub")
### _function_ `mapAsArray`(_propSchema_: [PropSchema](#interface-propschemasrc), _keyPropertyName_: string, _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/mapAsArray.ts#L18">src</a></sub>
`object` indicates that this property contains an object that needs to be (de)serialized
using its own model schema.
Similar to map, mapAsArray can be used to serialize a map-like collection where the key is contained in the 'value object'. Example: consider Map<id: number, customer: Customer> where the Customer object has the id stored on itself. mapAsArray stores all values from the map into an array which is serialized. Deserialization returns a ES6 Map or plain object object where the `keyPropertyName` of each object is used for keys. For ES6 maps this has the benefit of being allowed to have non-string keys in the map. The serialized json also may be slightly more compact.
N.B. mind issues with circular dependencies when importing model schema's from other files! The module resolve algorithm might expose classes before `createModelSchema` is executed for the target class.
### _function_ `object`(_modelSchema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)&lt;any&gt;, _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/object.ts#L35">src</a></sub>
### Parameters
`object` indicates that this property contains an object that needs to be (de)serialized using its own model schema.
- `modelSchema` **[ModelSchema](#modelschema)** to be used to (de)serialize the object
- `additionalArgs` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
N.B. mind issues with circular dependencies when importing model schema's from other files! The module resolve algorithm might expose classes before `createModelSchema` is executed for the target class.
### Examples
```javascript
```ts
class SubTask {}

@@ -860,7 +632,7 @@ class Todo {}

title: true,
});
})
createModelSchema(Todo, {
title: true,
subTask: object(SubTask),
});
})

@@ -872,47 +644,51 @@ const todo = deserialize(Todo, {

},
});
})
```
Returns **PropSchema**
### _function_ `optional`(_propSchema_?: [PropSchema](#interface-propschemasrc) | boolean): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/optional.ts#L17">src</a></sub>
## optional
Optional indicates that this model property shouldn't be serialized if it isn't present.
[src/types/optional.js:18-31](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/optional.js#L18-L31 "Source code on GitHub")
```ts
createModelSchema(Todo, {
title: optional(primitive()),
})
Optional indicates that this model property shouldn't be serialized if it isn't present.
serialize(new Todo()) // {}
```
### Parameters
### _function_ `primitive`(_additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/primitive.ts#L16">src</a></sub>
- `name`
- `propSchema` **PropSchema** propSchema to (de)serialize the contents of this field
Indicates that this field contains a primitive value (or Date) which should be serialized literally to json.
### Examples
```javascript
```ts
createModelSchema(Todo, {
title: optional(primitive()),
});
title: primitive(),
})
console.dir(serialize(new Todo()));
// {}
serialize(new Todo('test')) // { "title": "test" }
```
Returns **PropSchema**
### _function_ `raw`(_additionalArgs_: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/raw.ts#L18">src</a></sub>
## reference
Indicates that this field is only need to putted in the serialized json or deserialized instance, without any transformations. Stay with its original value
[src/types/reference.js:66-105](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/reference.js#L66-L105 "Source code on GitHub")
```ts
createModelSchema(Model, {
rawData: raw(),
})
serialize(new Model({ rawData: { a: 1, b: [], c: {} } } }))
// { "rawData": { a: 1, b: [], c: {} } } }
```
### _function_ `reference`(_modelSchema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)&lt;any&gt;, _lookupFn_?: [RefLookupFunction](#type-reflookupfunction--id-string-callback-err-any-result-any--void-context-context--void-src), _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/reference.ts#L82">src</a></sub>
`reference` can be used to (de)serialize references that point to other models.
The first parameter should be either a ModelSchema that has an `identifier()` property (see identifier)
or a string that represents which attribute in the target object represents the identifier of the object.
The first parameter should be either a ModelSchema that has an `identifier()` property (see identifier) or a string that represents which attribute in the target object represents the identifier of the object.
The second parameter is a lookup function that is invoked during deserialization to resolve an identifier to
an object. Its signature should be as follows:
The second parameter is a lookup function that is invoked during deserialization to resolve an identifier to an object. Its signature should be as follows:
`lookupFunction(identifier, callback, context)` where:
1\. `identifier` is the identifier being resolved
2\. `callback` is a node style calblack function to be invoked with the found object (as second arg) or an error (first arg)
3\. `context` see context.
`lookupFunction(identifier, callback, context)` where: 1. `identifier` is the identifier being resolved 2. `callback` is a node style calblack function to be invoked with the found object (as second arg) or an error (first arg) 3. `context` see context.

@@ -923,11 +699,3 @@ The lookupFunction is optional. If it is not provided, it will try to find an object of the expected type and required identifier within the same JSON document

### Parameters
- `target` : ModelSchema or string
- `lookupFn` **(RefLookupFunction | AdditionalPropArgs)** optional function or additionalArgs object
- `additionalArgs` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
### Examples
```javascript
```ts
class User {}

@@ -939,3 +707,3 @@ class Post {}

displayname: primitive(),
});
})

@@ -945,3 +713,3 @@ createModelSchema(Post, {

message: primitive(),
});
})

@@ -951,5 +719,5 @@ function findUserById(uuid, callback) {

.then(userData => {
deserialize(User, userData, callback);
deserialize(User, userData, callback)
})
.catch(callback);
.catch(callback)
}

@@ -964,130 +732,89 @@

(err, post) => {
console.log(post);
console.log(post)
}
);
)
```
Returns **PropSchema**
### _function_ `reference`(_modelSchema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)&lt;any&gt;, _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/reference.ts#L87">src</a></sub>
## list
### _function_ `reference`(_identifierAttr_: string, _lookupFn_: [RefLookupFunction](#type-reflookupfunction--id-string-callback-err-any-result-any--void-context-context--void-src), _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/reference.ts#L91">src</a></sub>
[src/types/list.js:43-105](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/list.js#L43-L105 "Source code on GitHub")
### _function_ `serializable`(_propSchema_: [PropDef](#type-propdef--propschema--boolean--undefined-src)): (_target_: any, _key_: string, _baseDescriptor_?: [PropertyDescriptor](typedoc-id-undefined)) => void <sub><a href="src/api/serializable.ts#L99">src</a></sub>
List indicates that this property contains a list of things.
Accepts a sub model schema to serialize the contents
Decorator that defines a new property mapping on the default model schema for the class it is used in.
### Parameters
When using typescript, the decorator can also be used on fields declared as constructor arguments (using the `private` / `protected` / `public` keywords). The default factory will then invoke the constructor with the correct arguments as well.
- `propSchema` **PropSchema** to be used to (de)serialize the contents of the array
- `additionalArgs` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
```ts
class Todo {
@serializable(primitive())
title // shorthand for primitves
### Examples
@serializable
done
```javascript
class SubTask {}
class Task {}
class Todo {}
constructor(title, done) {
this.title = title
this.done = done
}
}
createModelSchema(SubTask, {
title: true,
});
createModelSchema(Todo, {
title: true,
subTask: list(object(SubTask)),
});
const todo = deserialize(Todo, {
title: 'Task',
subTask: [
{
title: 'Sub task 1',
},
],
});
const json = serialize(new Todo('Test', false))
const todo = deserialize(Todo, json)
```
Returns **PropSchema**
### _function_ `serializable`(_target_: any, _key_: string, _baseDescriptor_?: [PropertyDescriptor](typedoc-id-undefined)): void <sub><a href="src/api/serializable.ts#L102">src</a></sub>
## map
### _function_ `serialize`&lt;T&gt;(_modelSchema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)&lt;T&gt;, _instance_: T): any <sub><a href="src/core/serialize.ts#L15">src</a></sub>
[src/types/map.js:14-65](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/map.js#L14-L65 "Source code on GitHub")
Serializes an object (graph) into json using the provided model schema. The model schema can be omitted if the object type has a default model schema associated with it. If a list of objects is provided, they should have an uniform type.
Similar to list, but map represents a string keyed dynamic collection.
This can be both plain objects (default) or ES6 Map like structures.
This will be inferred from the initial value of the targetted attribute.
### _function_ `serialize`&lt;T&gt;(_instance_: T): any <sub><a href="src/core/serialize.ts#L16">src</a></sub>
### Parameters
### _function_ `serializeAll`&lt;T&gt;(_clazz_: [Clazz](#type-clazzt----src)&lt;T&gt;): [Clazz](#type-clazzt----src)&lt;T&gt; <sub><a href="src/core/serializeAll.ts#L43">src</a></sub>
- `propSchema` **any**
- `additionalArgs` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
The `serializeAll` decorator can used on a class to signal that all primitive properties, or complex properties with a name matching a `pattern`, should be serialized automatically.
Returns **PropSchema**
```ts
@serializeAll
class Store {
a = 3
b
}
## mapAsArray
const store = new Store()
store.c = 5
store.d = {}
serialize(store) // { "c": 5 }
```
[src/types/mapAsArray.js:19-66](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/mapAsArray.js#L19-L66 "Source code on GitHub")
```ts
class DataType {
@serializable
x
@serializable
y
}
Similar to map, mapAsArray can be used to serialize a map-like collection where the key is
contained in the 'value object'. Example: consider Map&lt;id: number, customer: Customer> where the
Customer object has the id stored on itself. mapAsArray stores all values from the map into an
array which is serialized. Deserialization returns a ES6 Map or plain object object where the
`keyPropertyName` of each object is used for keys. For ES6 maps this has the benefit of being
allowed to have non-string keys in the map. The serialized json also may be slightly more
compact.
@serializeAll(/^[a-z]$/, DataType)
class ComplexStore {
}
### Parameters
- `propSchema` **any**
- `keyPropertyName` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the property of stored objects used as key in the map
- `additionalArgs` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
Returns **PropSchema**
## raw
[src/types/raw.js:18-29](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/types/raw.js#L18-L29 "Source code on GitHub")
Indicates that this field is only need to putted in the serialized json or
deserialized instance, without any transformations. Stay with its original value
### Parameters
- `additionalArgs` **AdditionalPropArgs** optional object that contains beforeDeserialize and/or afterDeserialize handlers
### Examples
```javascript
createModelSchema(Model, {
rawData: raw(),
});
console.dir(serialize(new Model({ rawData: { a: 1, b: [], c: {} } } })));
// outputs: { rawData: { a: 1, b: [], c: {} } } }
const store = new ComplexStore()
store.a = {x: 1, y: 2}
store.b = {}
store.somethingElse = 5
serialize(store) // { a: {x: 1, y: 2}, b: { x: undefined, y: undefined } }
```
Returns **[ModelSchema](#modelschema)**
### _function_ `serializeAll`(_pattern_: [RegExp](typedoc-id-undefined), _propertyType_: [PropDef](#type-propdef--propschema--boolean--undefined-src) | [Clazz](#type-clazzt----src)&lt;any&gt;): (_clazz_: [Clazz](#type-clazzt----src)&lt;any&gt;) => [Clazz](#type-clazzt----src)&lt;any&gt; <sub><a href="src/core/serializeAll.ts#L44">src</a></sub>
## SKIP
### _function_ `setDefaultModelSchema`&lt;T&gt;(_clazz_: [Clazz](#type-clazzt----src)&lt;T&gt;, _modelSchema_: [ModelSchema](#interface-modelschematsrc)&lt;T&gt;): [ModelSchema](#interface-modelschematsrc)&lt;T&gt; <sub><a href="src/api/setDefaultModelSchema.ts#L16">src</a></sub>
[src/constants.js:20-20](https://git@github.com/:mobxjs/serializr/blob/caa3000e9ec548fb2d63ea045cc9fdaef38454b2/src/constants.js#L20-L20 "Source code on GitHub")
Sets the default model schema for class / constructor function. Everywhere where a model schema is required as argument, this class / constructor function can be passed in as well (for example when using `object` or `ref`.
In the event that a property needs to be deserialized, but not serialized, you can use the SKIP symbol to omit the property. This has to be used with the custom serializer.
When passing an instance of this class to `serialize`, it is not required to pass the model schema as first argument anymore, because the default schema will be inferred from the instance type.
### Examples
### _function_ `update`(_modelSchema_: any, _target_: any, _json_: any, _callback_: any, _customArgs_?: any): void <sub><a href="src/core/update.ts#L36">src</a></sub><!-- END API AUTOGEN -->
```javascript
var schema = _.createSimpleSchema({
a: _.custom(
function(v) {
return _.SKIP
},
function(v) {
return v;
}
),
});
t.deepEqual(_.serialize(s, { a: 4 }), { });
t.deepEqual(_.deserialize(s, { a: 4 }), { a: 4 });
```
# Recipes and examples

@@ -1102,16 +829,16 @@

task: primitive(),
owner: reference('_userId', UserStore.findUserById), // attribute of the owner attribute of a todo + lookup function
subTasks: alias('children', list(object(todoSchema))),
},
};
owner: reference("_userId", UserStore.findUserById), // attribute of the owner attribute of a todo + lookup function
subTasks: alias("children", list(object(todoSchema)))
}
}
const todo = deserialize(
todoSchema,
{ task: 'grab coffee', owner: 17, children: [] },
{ task: "grab coffee", owner: 17, children: [] },
(err, todo) => {
console.log('finished loading todos');
console.log("finished loading todos")
}
);
)
const todoJson = serialize(todoSchema, todo);
const todoJson = serialize(todoSchema, todo)
```

@@ -1123,3 +850,3 @@

function Todo(parentTodo) {
this.parent = parentTodo; // available in subTasks
this.parent = parentTodo // available in subTasks
}

@@ -1131,17 +858,17 @@

task: primitive(),
owner: reference('_userId', UserStore.findUserById), // attribute of the owner attribute of a todo + lookup function
subTasks: alias('children', list(object(todoSchema))),
},
};
setDefaultModelSchema(Todo, todoSchema);
owner: reference("_userId", UserStore.findUserById), // attribute of the owner attribute of a todo + lookup function
subTasks: alias("children", list(object(todoSchema)))
}
}
setDefaultModelSchema(Todo, todoSchema)
const todo = deserialize(
Todo, // just pass the constructor name, schema will be picked up
{ task: 'grab coffee', owner: 17, children: [] },
{ task: "grab coffee", owner: 17, children: [] },
(err, todos) => {
console.log('finished loading todos');
console.log("finished loading todos")
}
);
)
const todoJson = serialize(todo); // no need to pass schema explicitly
const todoJson = serialize(todo) // no need to pass schema explicitly
```

@@ -1156,14 +883,12 @@

createModelSchema(Todo, {
task: primitive(),
});
task: primitive()
})
const todo = deserialize(
Todo, // just pass the constructor name, schema will be picked up
{ task: 'grab coffee', owner: 17, children: [] },
(err, todos) => {
console.log('finished loading todos');
}
);
{ task: "grab coffee", owner: 17, children: [] },
(err, todos) => console.log("finished loading todos")
)
const todoJson = serialize(todo); // no need to pass schema explicitly
const todoJson = serialize(todo) // no need to pass schema explicitly
```

@@ -1176,9 +901,9 @@

@serializable(primitive())
task = 'Grab coffee';
task = "Grab coffee"
@serializable(reference('_userId', UserStore.findUserById))
owner = null;
@serializable(reference("_userId", UserStore.findUserById))
owner = null
@serializable(alias('children', list(object(todoSchema))))
subTasks = [];
@serializable(alias("children", list(object(todoSchema))))
subTasks = []
}

@@ -1191,13 +916,11 @@

{
task: 'grab coffee',
task: "grab coffee",
owner: 17,
children: [],
},
children: []
}
],
(err, todos) => {
console.log('finished loading todos');
}
);
(err, todos) => console.log("finished loading todos")
)
const todoJson = serialize(todos);
const todoJson = serialize(todos)
```

@@ -1208,9 +931,9 @@

```javascript
const someTodoStoreById = {};
const someTodoStoreById = {}
getDefaultModelSchema(Todo).factory = context => {
const json = context.json;
if (someTodoStoreById[json.id]) return someTodoStoreById[json.id]; // reuse instance
return (someTodoStoreById[json.id] = new Todo());
};
const json = context.json
if (someTodoStoreById[json.id]) return someTodoStoreById[json.id] // reuse instance
return (someTodoStoreById[json.id] = new Todo())
}
```

@@ -1232,18 +955,11 @@

createModelSchema(User, { username: true }, context => {
return new User(context.args.someStore);
});
return new User(context.args.someStore)
})
// don't want singletons!
const someStore = new SomeStore();
const someStore = new SomeStore()
// provide somestore through context of the deserialization process
const user = deserialize(
User,
someJson,
(err, user) => {
console.log('done');
},
{
someStore: someStore,
}
);
const user = deserialize(User, someJson, (err, user) => console.log("done"), {
someStore: someStore
})
```

@@ -1255,23 +971,35 @@

// models.js:
import { observable, computed } from 'mobx';
import { serializable, identifier } from 'serializr';
import { observable, computed } from "mobx"
import { serializable, identifier } from "serializr"
function randomId() {
return Math.floor(Math.random() * 100000);
return Math.floor(Math.random() * 100000)
}
export class Box {
@serializable(identifier()) id = randomId();
@serializable @observable x = 0;
@serializable @observable y = 0;
@serializable @observable location = 0;
@serializable(identifier())
id = randomId()
@serializable
@observable
x = 0
@serializable
@observable
y = 0
@serializable
@observable
location = 0
constructor(location, x, y) {
this.location = location;
this.x = x;
this.y = y;
this.location = location
this.x = x
this.y = y
}
@serializable @computed get area() {
return this.x * this.y;
@serializable
@computed
get area() {
return this.x * this.y
}

@@ -1281,18 +1009,16 @@ }

export class Arrow {
@serializable(identifier()) id = randomId();
@serializable(reference(Box)) from;
@serializable(reference(Box)) to;
@serializable(identifier())
id = randomId()
@serializable(reference(Box))
from
@serializable(reference(Box))
to
}
// store.js:
import { observable, transaction } from 'mobx';
import {
createSimpleSchema,
identifier,
list,
serialize,
deserialize,
update,
} from 'serializr';
import { Box, Arrow } from './models';
import { observable, transaction } from "mobx"
import { createSimpleSchema, identifier, list, serialize, deserialize, update } from "serializr"
import { Box, Arrow } from "./models"

@@ -1303,4 +1029,4 @@ // The store that holds our domain: boxes and arrows

arrows: [],
selection: null,
});
selection: null
})

@@ -1311,8 +1037,8 @@ // Model of the store itself

arrows: list(object(Arrow)),
selection: reference(Box),
});
selection: reference(Box)
})
// Example Data
// You can push data in as a class
store.boxes.push(new Box('Rotterdam', 100, 100), new Box('Vienna', 650, 300));
store.boxes.push(new Box("Rotterdam", 100, 100), new Box("Vienna", 650, 300))

@@ -1323,8 +1049,8 @@ // Or it can be an raw javascript object with the right properties

from: store.boxes[0],
to: store.boxes[1],
});
to: store.boxes[1]
})
// (de) serialize functions
function serializeState(store) {
return serialize(storeModel, store);
return serialize(storeModel, store)
}

@@ -1334,11 +1060,11 @@

transaction(() => {
update(storeModel, store, json);
});
update(storeModel, store, json)
})
}
// Print ... out for debugging
console.dir(serializeState(store), { depth: 10, colors: true });
console.dir(serializeState(store), { depth: 10, colors: true })
```
* * *
---

@@ -1345,0 +1071,0 @@ # Future ideas

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc