Comparing version 2.0.5 to 3.0.1
@@ -27,2 +27,2 @@ import { ModelSchema, Clazz, Props } from "./types"; | ||
*/ | ||
export default function createModelSchema<T extends Object>(clazz: Clazz<T>, props: Props, factory?: (context: Context) => T): ModelSchema<T>; | ||
export default function createModelSchema<T extends object>(clazz: Clazz<T>, props: Props, factory?: (context: Context) => T): ModelSchema<T>; |
@@ -18,2 +18,2 @@ import { Props, ModelSchema } from "./types"; | ||
*/ | ||
export default function createSimpleSchema<T extends Object>(props: Props): ModelSchema<T>; | ||
export default function createSimpleSchema<T extends object>(props: Props): ModelSchema<T>; |
@@ -34,2 +34,21 @@ import Context from "../core/Context"; | ||
export declare type PropDef = PropSchema | boolean | undefined; | ||
/** | ||
* Define an object exposing a couple of methods that are used | ||
* to discriminate between subschema. | ||
*/ | ||
export interface DiscriminatorSpec { | ||
/** | ||
* This method is invoked during deserialization to check if the | ||
* data should be deserialized as the specific type. | ||
* @param src An object to inspect | ||
* @returns `true` if the json matched the discriminator condition. | ||
*/ | ||
isActualType(src: any): boolean; | ||
/** | ||
* If available this method is invoked during serialization and is meant to | ||
* add discriminator information to the result json. | ||
* @param result The result of the deserialization | ||
*/ | ||
storeDiscriminator?(result: any): void; | ||
} | ||
export interface ModelSchema<T> { | ||
@@ -40,2 +59,4 @@ targetClass?: Clazz<any>; | ||
extends?: ModelSchema<any>; | ||
subSchemas?: ModelSchema<any>[]; | ||
discriminator?: DiscriminatorSpec; | ||
} | ||
@@ -42,0 +63,0 @@ export declare type Clazz<T> = new (...args: any[]) => T; |
@@ -37,2 +37,8 @@ /** | ||
}; | ||
/** | ||
* When using the decorator shorthand we store the given value in | ||
* a specific attribute of the result structure. This constant contains | ||
* the attribute name used in such scenario. | ||
*/ | ||
export declare const DEFAULT_DISCRIMINATOR_ATTR = "_type"; | ||
export declare const _defaultPrimitiveProp: import("./serializr").PropSchema; |
@@ -7,8 +7,9 @@ import { ModelSchema } from "../api/types"; | ||
private readonly onReadyCb; | ||
private static rootContextCache; | ||
private isRoot; | ||
private pendingCallbacks; | ||
private pendingRefsCount; | ||
private hasError; | ||
target: any; | ||
private hasError; | ||
rootContext: Context<any>; | ||
rootContext: Context; | ||
args: any; | ||
@@ -18,3 +19,3 @@ private pendingRefs; | ||
constructor(parentContext: Context<any> | undefined, modelSchema: ModelSchema<T>, json: any, onReadyCb: (err?: any, value?: T) => void, customArgs?: any[]); | ||
createCallback(fn: (value: T) => void): (err?: any, value?: T | undefined) => void; | ||
createCallback(fn: (value: T) => void): (err?: any, value?: T) => void; | ||
await(modelSchema: ModelSchema<any>, uuid: string, callback: (err?: any, value?: any) => void): undefined; | ||
@@ -24,3 +25,9 @@ resolve(modelSchema: ModelSchema<any>, uuid: string, value: any): void; | ||
cancelAwaits(): void; | ||
static getTargetContext(target: any): Context<any> | undefined; | ||
} | ||
export declare function getTargetContext(target: any): any; | ||
/** | ||
* @deprecated Use `Context.getTargetContext(target)` directly. | ||
* @param target | ||
* @returns | ||
*/ | ||
export declare function getTargetContext(target: any): Context<any> | undefined; |
@@ -23,4 +23,4 @@ import Context from "./Context"; | ||
export declare function deserializeObjectWithSchema(parentContext: Context<any> | undefined, modelSchema: ModelSchema<any>, json: any, callback: (err?: any, value?: any) => void, customArgs: any): any; | ||
export declare function deserializePropsWithSchema<T>(context: Context<T>, modelSchema: ModelSchema<T>, json: any, target: T): void; | ||
export declare const onBeforeDeserialize: BeforeDeserializeFunc; | ||
export declare const onAfterDeserialize: AfterDeserializeFunc; | ||
export declare function deserializePropsWithSchema<T>(context: Context<T>, modelSchema: ModelSchema<T>, json: any, target: T): void; |
@@ -13,1 +13,3 @@ import { ClazzOrModelSchema } from "../api/types"; | ||
export default function serialize<T>(instance: T): any; | ||
export default function serialize<T>(modelSchema: ClazzOrModelSchema<T>, instance: T[]): any; | ||
export default function serialize<T>(instance: T[]): any; |
@@ -9,2 +9,3 @@ export { default as createSimpleSchema } from "./api/createSimpleSchema"; | ||
export { default as serializeAll } from "./core/serializeAll"; | ||
export { default as subSchema } from "./core/subSchema"; | ||
export { default as cancelDeserialize } from "./core/cancelDeserialize"; | ||
@@ -25,2 +26,2 @@ export { default as deserialize } from "./core/deserialize"; | ||
export { default as raw } from "./types/raw"; | ||
export { SKIP } from "./constants"; | ||
export { SKIP, DEFAULT_DISCRIMINATOR_ATTR } from "./constants"; |
@@ -32,3 +32,3 @@ /** | ||
catch (error) { | ||
return "[UnexpectedJSONParseError]: " + error.message; | ||
return "[UnexpectedJSONParseError]: ".concat(error.message); | ||
} | ||
@@ -75,5 +75,9 @@ }, | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
if (!fired) { | ||
fired = true; | ||
return fn.apply(null, arguments); | ||
return fn.apply(void 0, args); | ||
} | ||
@@ -133,3 +137,7 @@ invariant(false, "callback was invoked twice"); | ||
function isMapLike(thing) { | ||
return thing && typeof thing.keys === "function" && typeof thing.clear === "function"; | ||
return (thing && | ||
typeof thing.keys === "function" && | ||
typeof thing.clear === "function" && | ||
typeof thing.forEach === "function" && | ||
typeof thing.set === "function"); | ||
} | ||
@@ -155,2 +163,5 @@ function getIdentifierProp(modelSchema) { | ||
} | ||
function isRegExp(obj) { | ||
return typeof obj === "object" && obj.test; | ||
} | ||
@@ -185,3 +196,3 @@ /** | ||
function setDefaultModelSchema(clazz, modelSchema) { | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got " + modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got ".concat(modelSchema)); | ||
clazz.serializeInfo = modelSchema; | ||
@@ -236,23 +247,25 @@ return modelSchema; | ||
/*! ***************************************************************************** | ||
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 | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
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. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
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; | ||
function __spreadArray(to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
} | ||
@@ -275,3 +288,3 @@ | ||
serializer: function (value) { | ||
invariant(isPrimitive(value), "this value is not primitive: " + value); | ||
invariant(isPrimitive(value), "this value is not primitive: ".concat(value)); | ||
return value; | ||
@@ -281,3 +294,3 @@ }, | ||
if (!isPrimitive(jsonValue)) | ||
return void done("[serializr] this value is not primitive: " + jsonValue); | ||
return void done("[serializr] this value is not primitive: ".concat(jsonValue)); | ||
return void done(null, jsonValue); | ||
@@ -324,2 +337,8 @@ }, | ||
var SKIP = typeof Symbol !== "undefined" ? Symbol("SKIP") : { SKIP: true }; | ||
/** | ||
* When using the decorator shorthand we store the given value in | ||
* a specific attribute of the result structure. This constant contains | ||
* the attribute name used in such scenario. | ||
*/ | ||
var DEFAULT_DISCRIMINATOR_ATTR = "_type"; | ||
var _defaultPrimitiveProp = primitive(); | ||
@@ -367,3 +386,3 @@ | ||
} | ||
return (_a = target.constructor).bind.apply(_a, __spreadArrays([undefined], params)); | ||
return (_a = target.constructor).bind.apply(_a, __spreadArray([undefined], params, false)); | ||
}; | ||
@@ -374,3 +393,3 @@ } | ||
var info = getDefaultModelSchema(target); | ||
if (!info || !target.constructor.hasOwnProperty("serializeInfo")) | ||
if (!info || !Object.prototype.hasOwnProperty.call(target.constructor, "serializeInfo")) | ||
info = createModelSchema(target.constructor, {}, factory); | ||
@@ -389,3 +408,5 @@ if (info && info.targetClass !== target.constructor) | ||
// decorated with propSchema | ||
var propSchema = targetOrPropSchema === true ? _defaultPrimitiveProp : targetOrPropSchema; | ||
var propSchema = targetOrPropSchema === true | ||
? _defaultPrimitiveProp | ||
: targetOrPropSchema; | ||
invariant(isPropSchema(propSchema), "@serializable expects prop schema"); | ||
@@ -401,31 +422,34 @@ var result = serializableDecorator.bind(null, propSchema); | ||
function serialize(modelSchemaOrInstance, arg2) { | ||
invariant(arguments.length === 1 || arguments.length === 2, "serialize expects one or 2 arguments"); | ||
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(instance[0]); | ||
else if (typeof schema !== "object") | ||
schema = getDefaultModelSchema(schema); | ||
function serialize() { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
else if (!schema) { | ||
schema = getDefaultModelSchema(instance); | ||
invariant(args.length === 1 || args.length === 2, "serialize expects one or 2 arguments"); | ||
var schema; | ||
var value; | ||
if (args.length === 1) { | ||
schema = undefined; | ||
value = args[0]; | ||
} | ||
else { | ||
schema = args[0], value = args[1]; | ||
} | ||
if (Array.isArray(value)) { | ||
return value.map(function (item) { return (schema ? serialize(schema, item) : serialize(item)); }); | ||
} | ||
if (!schema) { | ||
schema = getDefaultModelSchema(value); | ||
} | ||
else if (typeof schema !== "object") { | ||
schema = getDefaultModelSchema(schema); | ||
} | ||
var foundSchema = schema; | ||
if (!foundSchema) { | ||
if (!schema) { | ||
// only call modelSchemaOrInstance.toString() on error | ||
invariant(foundSchema, "Failed to find default schema for " + modelSchemaOrInstance); | ||
invariant(schema, "Failed to find default schema for ".concat(value)); | ||
} | ||
if (Array.isArray(instance)) | ||
return instance.map(function (item) { return serializeWithSchema(foundSchema, item); }); | ||
return serializeWithSchema(foundSchema, instance); | ||
return serializeWithSchema(schema, value); | ||
} | ||
function serializeWithSchema(schema, obj) { | ||
var _a; | ||
invariant(schema && typeof schema === "object" && schema.props, "Expected schema"); | ||
@@ -456,2 +480,5 @@ invariant(obj && typeof obj === "object", "Expected object"); | ||
}); | ||
if ((_a = schema.discriminator) === null || _a === void 0 ? void 0 : _a.storeDiscriminator) { | ||
schema.discriminator.storeDiscriminator(res); | ||
} | ||
return res; | ||
@@ -484,3 +511,2 @@ } | ||
var rootContextCache = new WeakMap(); | ||
var Context = /** @class */ (function () { | ||
@@ -517,3 +543,3 @@ function Context(parentContext, modelSchema, json, onReadyCb, customArgs) { | ||
_this.onReadyCb(err); | ||
rootContextCache.delete(_this); | ||
Context.rootContextCache.delete(_this); | ||
} | ||
@@ -526,12 +552,12 @@ } | ||
// 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); | ||
_this.onReadyCb(new Error("Unresolvable references in json: \"".concat(Object.keys(_this.pendingRefs) | ||
.filter(function (uuid) { return _this.pendingRefs[uuid].length > 0; }) | ||
.join( | ||
// prettier-ignore | ||
"\", \""), "\""))); | ||
Context.rootContextCache.delete(_this); | ||
} | ||
else { | ||
_this.onReadyCb(null, _this.target); | ||
rootContextCache.delete(_this); | ||
Context.rootContextCache.delete(_this); | ||
} | ||
@@ -585,14 +611,14 @@ } | ||
if (this.isRoot && this.target) { | ||
rootContextCache.delete(this.target); | ||
Context.rootContextCache.delete(this.target); | ||
} | ||
this.target = target; | ||
rootContextCache.set(this.target, this); | ||
Context.rootContextCache.set(this.target, this); | ||
}; | ||
// call all remaining reference lookup callbacks indicating an error during ref resolution | ||
Context.prototype.cancelAwaits = function () { | ||
var _this = this; | ||
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--; | ||
_this.pendingRefs[uuid].forEach(function (refOpts) { | ||
_this.pendingRefsCount--; | ||
refOpts.callback(new Error("Reference resolution canceled for " + uuid)); | ||
@@ -604,6 +630,15 @@ }); | ||
}; | ||
Context.getTargetContext = function (target) { | ||
return Context.rootContextCache.get(target); | ||
}; | ||
Context.rootContextCache = new WeakMap(); | ||
return Context; | ||
}()); | ||
/** | ||
* @deprecated Use `Context.getTargetContext(target)` directly. | ||
* @param target | ||
* @returns | ||
*/ | ||
function getTargetContext(target) { | ||
return rootContextCache.get(target); | ||
return Context.getTargetContext(target); | ||
} | ||
@@ -629,6 +664,3 @@ | ||
// confusing bugs | ||
invariant(isPrimitive(jsonValue), "encountered non primitive value while deserializing '*' properties in property '" + | ||
key + | ||
"': " + | ||
jsonValue); | ||
invariant(isPrimitive(jsonValue), "encountered non primitive value while deserializing '*' properties in property '".concat(key, "': ").concat(jsonValue)); | ||
obj[key] = jsonValue; | ||
@@ -649,2 +681,17 @@ } | ||
} | ||
function identifyActualSchema(json, baseSchema) { | ||
var _a; | ||
if ((_a = baseSchema.subSchemas) === null || _a === void 0 ? void 0 : _a.length) { | ||
for (var _i = 0, _b = baseSchema.subSchemas; _i < _b.length; _i++) { | ||
var subSchema = _b[_i]; | ||
if (subSchema.discriminator) { | ||
if (subSchema.discriminator.isActualType(json)) { | ||
return subSchema; | ||
} | ||
} | ||
} | ||
} | ||
// If we can't find a specific schema we go with the base. | ||
return baseSchema; | ||
} | ||
function deserialize(clazzOrModelSchema, json, callback, customArgs) { | ||
@@ -671,4 +718,5 @@ if (callback === void 0) { callback = GUARDED_NOOP; } | ||
return void callback(null, null); | ||
var context = new Context(parentContext, modelSchema, json, callback, customArgs); | ||
var target = modelSchema.factory(context); | ||
var actualSchema = identifyActualSchema(json, modelSchema); | ||
var context = new Context(parentContext, actualSchema, json, callback, customArgs); | ||
var target = actualSchema.factory(context); | ||
// todo async invariant | ||
@@ -681,6 +729,22 @@ invariant(!!target, "No object returned from factory"); | ||
var lock = context.createCallback(GUARDED_NOOP); | ||
deserializePropsWithSchema(context, modelSchema, json, target); | ||
deserializePropsWithSchema(context, actualSchema, json, target); | ||
lock(); | ||
return target; | ||
} | ||
var onBeforeDeserialize = function (callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef) { | ||
if (propDef && typeof propDef.beforeDeserialize === "function") { | ||
propDef.beforeDeserialize(callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef); | ||
} | ||
else { | ||
callback(null, jsonValue); | ||
} | ||
}; | ||
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 { | ||
callback(err, newValue); | ||
} | ||
}; | ||
function deserializePropsWithSchema(context, modelSchema, json, target) { | ||
@@ -715,5 +779,5 @@ var _a; | ||
var propSchema = propDef; | ||
var callbackDeserialize = function (err, jsonValue) { | ||
if (!err && jsonValue !== undefined) { | ||
deserializeProp(propSchema, jsonValue, key); | ||
var callbackDeserialize = function (err, jsonVal) { | ||
if (!err && jsonVal !== undefined) { | ||
deserializeProp(propSchema, jsonVal, key); | ||
} | ||
@@ -730,18 +794,2 @@ }; | ||
} | ||
var onBeforeDeserialize = function (callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef) { | ||
if (propDef && typeof propDef.beforeDeserialize === "function") { | ||
propDef.beforeDeserialize(callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef); | ||
} | ||
else { | ||
callback(null, jsonValue); | ||
} | ||
}; | ||
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 { | ||
callback(err, newValue); | ||
} | ||
}; | ||
@@ -781,3 +829,3 @@ /** | ||
modelSchema = getDefaultModelSchema(modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got " + modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got ".concat(modelSchema)); | ||
if (item === null || item === undefined) | ||
@@ -789,3 +837,3 @@ return item; | ||
modelSchema = getDefaultModelSchema(modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got " + modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got ".concat(modelSchema)); | ||
if (childJson === null || childJson === undefined) | ||
@@ -807,3 +855,3 @@ return void done(null, childJson); | ||
else { | ||
invariant(typeof targetOrPattern === "object" && targetOrPattern.test, "@serializeAll pattern doesn't have test"); | ||
invariant(isRegExp(targetOrPattern), "@serializeAll pattern doesn't have test"); | ||
if (typeof propertyType === "function") { | ||
@@ -833,2 +881,153 @@ propertyType = object(propertyType); | ||
/** | ||
* A simple util that retrieve the existing schema or create a default one. | ||
* @param src | ||
* @returns | ||
*/ | ||
var getOrCreateSchema = function (src) { | ||
if (isModelSchema(src)) { | ||
return src; | ||
} | ||
else { | ||
var schema = getDefaultModelSchema(src); | ||
if (!schema) { | ||
schema = createModelSchema(src, {}); | ||
} | ||
return schema; | ||
} | ||
}; | ||
/** | ||
* Sometimes, when working with schema hierarchies, we may want to deserialize an object to | ||
* a specific sub-schema. The `subSchema` decorator is used to handle such scenario. | ||
* What schema is picked among those available is decided using a "discriminator". The | ||
* discriminator can be a string (which is added to the serialized object) or a object | ||
* containing callbacks allowing for more complex behaviour. | ||
* | ||
* | ||
* @example | ||
* ```ts | ||
* class Todo { | ||
* @serializable | ||
* id: string; | ||
* | ||
* @serializable | ||
* text: string; | ||
* } | ||
* | ||
* @subSchema("picture") | ||
* class PictureTodo extends Todo { | ||
* @serializable | ||
* pictureUrl: string; | ||
* } | ||
* | ||
* const ser = serialize(Object.assign(new PictureTodo(), { | ||
* id: "pic1", | ||
* text: "Lorem Ipsum", | ||
* pictureUrl:"foobar", | ||
* })); | ||
* // ser now holds an object like the following result | ||
* // { | ||
* // id: "pic1", | ||
* // _type: "picture" | ||
* // text: "Lorem Ipsum", | ||
* // pictureUrl:"foobar", | ||
* // } | ||
* const deser = deserialize(Todo, ser); | ||
* console.log(deser instanceof PictureTodo); // true | ||
* ``` | ||
* | ||
* @example | ||
* Using the `parent` argument it's possible to specify the subschema parent instead | ||
* of relying on auto-detention. | ||
* ```ts | ||
* class Todo { | ||
* @serializable | ||
* id: string; | ||
* | ||
* @serializable | ||
* text: string; | ||
* } | ||
* | ||
* @subSchema("picture") | ||
* class PictureTodo extends Todo { | ||
* @serializable | ||
* pictureUrl: string; | ||
* } | ||
* | ||
* @subSchema("betterPicture", Todo) | ||
* class BetterPictureTodo extends PictureTodo { | ||
* @serializable | ||
* altText: string; | ||
* } | ||
* | ||
* | ||
* const ser = serialize(Object.assign(new BetterPictureTodo(), { | ||
* id: "pic1", | ||
* text: "Lorem Ipsum", | ||
* pictureUrl:"foobar", | ||
* altText: "Alt text", | ||
* })); | ||
* // ser now holds an object like the following result | ||
* // { | ||
* // id: "pic1", | ||
* // _type: "betterPicture" | ||
* // text: "Lorem Ipsum", | ||
* // pictureUrl:"foobar", | ||
* // altText: "Alt text", | ||
* // } | ||
* const deser = deserialize(Todo, ser); | ||
* console.log(deser instanceof BetterPictureTodo); // true | ||
* console.log(deser instanceof PictureTodo); // true | ||
* | ||
* const ser2 = serialize(Object.assign(new PictureTodo(), { | ||
* id: "pic2", | ||
* text: "Lorem Ipsum", | ||
* pictureUrl:"foobar", | ||
* })); | ||
* // ser2 now holds an object like the following result | ||
* // { | ||
* // id: "pic2", | ||
* // _type: "picture" | ||
* // text: "Lorem Ipsum", | ||
* // pictureUrl:"foobar", | ||
* // } | ||
* const deser2 = deserialize(Todo, ser2); | ||
* console.log(deser2 instanceof BetterPictureTodo); // false | ||
* console.log(deser2 instanceof PictureTodo); // true | ||
* ``` | ||
* | ||
* @param discriminator An object providing the discriminator logic or a string/number | ||
* that will be stored into the `_type` attribute. | ||
* @param parent When there are multiple levels of hierarchy involved you may provide this | ||
* argument to indicate the main schema used for deserialization. When not give the parent | ||
* schema is inferred as the direct parent (the class/schema that is extended). | ||
* | ||
* @returns | ||
*/ | ||
function subSchema(discriminator, parent) { | ||
return function (target) { | ||
var _a; | ||
var childSchema = getOrCreateSchema(target); | ||
invariant(childSchema === null || childSchema === void 0 ? void 0 : childSchema.extends, "Can not apply subSchema on a schema not extending another one."); | ||
var parentSchema = getOrCreateSchema(parent || childSchema.extends); | ||
parentSchema.subSchemas = (_a = parentSchema.subSchemas) !== null && _a !== void 0 ? _a : []; | ||
parentSchema.subSchemas.push(childSchema); | ||
if (typeof discriminator === "object") { | ||
childSchema.discriminator = discriminator; | ||
} | ||
else { | ||
childSchema.discriminator = { | ||
isActualType: function (src) { | ||
return src[DEFAULT_DISCRIMINATOR_ATTR] === discriminator; | ||
}, | ||
storeDiscriminator: function (result) { | ||
result[DEFAULT_DISCRIMINATOR_ATTR] = discriminator; | ||
}, | ||
}; | ||
} | ||
return target; | ||
}; | ||
} | ||
/* | ||
@@ -852,14 +1051,17 @@ * Deserialization | ||
*/ | ||
function update(modelSchema, target, json, callback, customArgs) { | ||
var inferModelSchema = arguments.length === 2 || typeof arguments[2] === "function"; // only target and json // callback as third arg | ||
if (inferModelSchema) { | ||
target = arguments[0]; | ||
modelSchema = getDefaultModelSchema(target); | ||
json = arguments[1]; | ||
callback = arguments[2]; | ||
customArgs = arguments[3]; | ||
function update() { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
var modelSchema; | ||
if (typeof args[0] === "function" || isModelSchema(args[0])) { | ||
// First overload | ||
modelSchema = getDefaultModelSchema(args[0]); | ||
args.shift(); | ||
} | ||
else { | ||
modelSchema = getDefaultModelSchema(modelSchema); | ||
modelSchema = getDefaultModelSchema(args[0]); | ||
} | ||
var target = args[0], json = args[1], callback = args[2], customArgs = args[3]; | ||
invariant(isModelSchema(modelSchema), "update failed to determine schema"); | ||
@@ -964,7 +1166,7 @@ invariant(typeof target === "object" && target && !Array.isArray(target), "update needs an object"); | ||
deserializer: function (jsonValue, done, context, oldValue) { | ||
var result = deserializer(jsonValue, context, oldValue, done); | ||
var result2 = 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); | ||
done(null, result2); | ||
} | ||
@@ -1034,3 +1236,3 @@ }, | ||
var modelSchema = getDefaultModelSchema(target); | ||
invariant(isModelSchema(modelSchema), "expected model schema or string as first argument for 'ref', got " + modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected model schema or string as first argument for 'ref', got ".concat(modelSchema)); | ||
lookupFn = lookupFn || createDefaultRefLookup(modelSchema); | ||
@@ -1098,2 +1300,5 @@ childIdentifierAttribute = getIdentifierProp(modelSchema); | ||
} | ||
if (ar === null) { | ||
return null; | ||
} | ||
invariant(ar && "length" in ar && "map" in ar, "expected array (like) object"); | ||
@@ -1103,2 +1308,4 @@ return ar.map(propSchema.serializer); | ||
deserializer: function (jsonArray, done, context) { | ||
if (jsonArray === null) | ||
return void done(null, jsonArray); | ||
if (!Array.isArray(jsonArray)) | ||
@@ -1125,7 +1332,7 @@ return void done("[serializr] expected JSON array"); | ||
} | ||
parallel(jsonArray, processItem, function (err, result) { | ||
parallel(jsonArray, processItem, function (err, result2) { | ||
if (err) { | ||
return void done(err); | ||
} | ||
done(undefined, result.filter(function (x) { return SKIP !== x; })); | ||
done(undefined, result2.filter(function (x) { return SKIP !== x; })); | ||
}); | ||
@@ -1152,11 +1359,11 @@ }, | ||
invariant(m && typeof m === "object", "expected object or Map"); | ||
var result = {}; | ||
var result2 = {}; | ||
if (isMapLike(m)) { | ||
m.forEach(function (value, key) { return (result[key] = propSchema.serializer(value, key, m)); }); | ||
m.forEach(function (value, key) { return (result2[key] = propSchema.serializer(value, key, m)); }); | ||
} | ||
else { | ||
for (var key in m) | ||
result[key] = propSchema.serializer(m[key], key, m); | ||
result2[key] = propSchema.serializer(m[key], key, m); | ||
} | ||
return result; | ||
return result2; | ||
}, | ||
@@ -1167,5 +1374,3 @@ deserializer: function (jsonObject, done, context, oldValue) { | ||
var keys = Object.keys(jsonObject); | ||
list(propSchema, additionalArgs).deserializer(keys.map(function (key) { | ||
return jsonObject[key]; | ||
}), function (err, values) { | ||
list(propSchema, additionalArgs).deserializer(keys.map(function (key) { return jsonObject[key]; }), function (err, values) { | ||
if (err) | ||
@@ -1184,3 +1389,3 @@ return void done(err); | ||
newValue = {}; | ||
for (var i = 0, l = keys.length; i < l; i++) | ||
for (var i = 0, l = keys.length; i < l; i++) { | ||
if (isMap) | ||
@@ -1190,2 +1395,3 @@ newValue.set(keys[i], values[i]); | ||
newValue[keys[i]] = values[i]; | ||
} | ||
done(null, newValue); | ||
@@ -1218,12 +1424,11 @@ }, context); | ||
invariant(m && typeof m === "object", "expected object or Map"); | ||
var result = []; | ||
// eslint-disable-next-line no-unused-vars | ||
var result2 = []; | ||
if (isMapLike(m)) { | ||
m.forEach(function (value, key) { return result.push(propSchema.serializer(value, key, m)); }); | ||
m.forEach(function (value, key) { return result2.push(propSchema.serializer(value, key, m)); }); | ||
} | ||
else { | ||
for (var key in m) | ||
result.push(propSchema.serializer(m[key], key, m)); | ||
result2.push(propSchema.serializer(m[key], key, m)); | ||
} | ||
return result; | ||
return result2; | ||
}, | ||
@@ -1247,3 +1452,4 @@ deserializer: function (jsonArray, done, context, oldValue) { | ||
else | ||
newValue[values[i][keyPropertyName].toString()] = values[i]; | ||
newValue[values[i][keyPropertyName].toString()] = | ||
values[i]; | ||
done(null, newValue); | ||
@@ -1284,3 +1490,3 @@ }, context, undefined); | ||
export { SKIP, alias, cancelDeserialize, createModelSchema, createSimpleSchema, custom, date, deserialize, getDefaultModelSchema, identifier, list, map, mapAsArray, object, optional, primitive, raw, reference, serializable, serialize, serializeAll, setDefaultModelSchema, update }; | ||
export { DEFAULT_DISCRIMINATOR_ATTR, SKIP, alias, cancelDeserialize, createModelSchema, createSimpleSchema, custom, date, deserialize, getDefaultModelSchema, identifier, list, map, mapAsArray, object, optional, primitive, raw, reference, serializable, serialize, serializeAll, setDefaultModelSchema, subSchema, update }; | ||
//# sourceMappingURL=serializr.es.js.map |
/** serializr - (c) Michel Weststrate 2016 - MIT Licensed */ | ||
function e(e){return{factory:function(){return{}},props:e}}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))&&void 0!==n?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,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)}function w(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 o||t(o,"Failed to find default schema for "+e),Array.isArray(r)?r.map((function(e){return A(o,e)})):A(o,r)}function A(e,n){var r;return t(e&&"object"==typeof e&&e.props,"Expected schema"),t(n&&"object"==typeof n,"Expected object"),r=e["extends"]?A(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 k=new WeakMap,E=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),k["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('", "')+'"')),k["delete"](n)):(n.onReadyCb(null,n.target),k["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&&k["delete"](this.target),this.target=e,k.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 N(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=D(undefined,a,e,n,f);c.push(t)}),o),c}return D(undefined,a,n,o,f)}function D(e,n,i,o,u){if(null!==i&&i!==undefined&&"object"==typeof i){var f=new E(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 I(f,n,i,a),c(),a}o(null,null)}function I(e,n,r,i){var u;n["extends"]&&I(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)&&void 0!==u?u:f;t("symbol"!=typeof c,"You must alias symbol properties. prop = %l",f);var s=r[c],l=a;J((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 M(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 J=function(e,n,t,r,i,o){o&&"function"==typeof o.beforeDeserialize?o.beforeDeserialize(e,n,t,r,i,o):e(null,n)},M=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 P(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:w(e,n)},deserializer:function(n,r,i){t(u(e=p(e)),"expected modelSchema, got "+e),null!==n&&n!==undefined?D(i,e,n,r,undefined):r(null,n)}},n)}function C(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=P(n)),!0===n&&(n=j),t(f(n),"couldn't resolve schema"),r=Object.assign({},n,{pattern:e}),i}function K(e){t("object"==typeof e&&e&&!Array.isArray(e),"cancelDeserialize needs an object");var n,r=(n=e,k.get(n));r&&r.cancelAwaits()}function U(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 E(undefined,e,i,o||r,f);c.setTarget(n);var s=c.createCallback(r),l=I(c,e,i,n);return s(),l}function q(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)}function F(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)}function R(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}}function W(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)}function Y(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}})}function Z(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)}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){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?M(i,u,f,t,n,o,r,e):i(u,f)}J((function(n,t){n?i(n):e.deserializer(t,u,r)}),t,n,o,r,e)}),(function(e,n){e?t(e):t(undefined,n.filter((function(e){return b!==e})))})):t("[serializr] expected JSON array")}},n)}function B(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);$(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)}function G(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){$(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)}function H(e){return d({serializer:function(e){return e},deserializer:function(e,n){n(null,e)}},e)}export{b as SKIP,R as alias,K as cancelDeserialize,h as createModelSchema,e as createSimpleSchema,W as custom,F as date,N as deserialize,p as getDefaultModelSchema,q as identifier,$ as list,B as map,G as mapAsArray,P as object,Y as optional,y as primitive,H as raw,Z as reference,O as serializable,w as serialize,C as serializeAll,v as setDefaultModelSchema,U as update}; | ||
function e(e){return{factory:function(){return{}},props:e}}var n={j:function(e){try{return JSON.stringify(e)}catch(n){return"[UnexpectedJSONParseError]: ".concat(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"==typeof e.forEach&&"function"==typeof e.set}function d(e,n){return n&&(t(f(e),"expected a propSchema"),Object.assign(e,n)),e}function p(e){return"object"==typeof e&&e.test}function v(e){return e?u(e)?e:u(e.serializeInfo)?e.serializeInfo:e.constructor&&e.constructor.serializeInfo?e.constructor.serializeInfo:void 0:undefined}function h(e,n){return t(u(n),"expected modelSchema, got ".concat(n)),e.serializeInfo=n,n}function m(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=v(e.prototype.constructor);o&&o.targetClass!==e&&(i["extends"]=o)}return h(e,i),i}function y(e,n,t){if(t||2===arguments.length)for(var r,i=0,o=n.length;i<o;i++)!r&&i in n||(r||(r=Array.prototype.slice.call(n,0,i)),r[i]=n[i]);return e.concat(r||Array.prototype.slice.call(n))}function b(e){return d({serializer:function(e){return t(o(e),"this value is not primitive: ".concat(e)),e},deserializer:function(e,n){o(e)?n(null,e):n("[serializr] this value is not primitive: ".concat(e))}},e)}var j="undefined"!=typeof Symbol?Symbol("SKIP"):{SKIP:!0},z="_type",g=b(),x=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,S=/([^\s,]+)/g;function O(e){var n,t=e.toString().replace(x,"");return null!==(n=t.slice(t.indexOf("(")+1,t.indexOf(")")).match(S))&&void 0!==n?n:[]}function w(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=O(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,y([undefined],r,!1))})}t("string"==typeof r,"incorrect usage of @serializable decorator");var c=v(n);return c&&Object.prototype.hasOwnProperty.call(n.constructor,"serializeInfo")||(c=m(n.constructor,{},o)),c&&c.targetClass!==n.constructor&&(c=m(n.constructor,{},o)),c.props[r]=e,!i||i.get||i.set||(i.writable=!0),i}function A(e,n,r){if(!n){var i=!0===e?g:e;return t(f(i),"@serializable expects prop schema"),w.bind(null,i)}w(b(),e,n,r)}function k(){for(var e,n,r=[],i=0;i<arguments.length;i++)r[i]=arguments[i];return t(1===r.length||2===r.length,"serialize expects one or 2 arguments"),1===r.length?(e=undefined,n=r[0]):(e=r[0],n=r[1]),Array.isArray(n)?n.map((function(n){return e?k(e,n):k(n)})):(e?"object"!=typeof e&&(e=v(e)):e=v(n),e||t(e,"Failed to find default schema for ".concat(n)),E(e,n))}function E(e,n){var r,i;return t(e&&"object"==typeof e&&e.props,"Expected schema"),t(n&&"object"==typeof n,"Expected object"),i=e["extends"]?E(e["extends"],n):{},Object.keys(e.props).forEach((function(t){var r=e.props[t];if(r)if("*"!==t){!0===r&&(r=g);var u=r.serializer(n[t],t,n);u!==j&&(i[r.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===j)return;r[f]=c}}}}(e,r,n,i)})),(null===(r=e.discriminator)||void 0===r?void 0:r.storeDiscriminator)&&e.discriminator.storeDiscriminator(i),i}var D=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(n){var r=this;return this.pendingCallbacks++,function(e){var n=!1;return function(){for(var r=[],i=0;i<arguments.length;i++)r[i]=arguments[i];if(!n)return n=!0,e.apply(void 0,r);t(!1,"callback was invoked twice")}}((function(t,i){t?r.hasError||(r.hasError=!0,r.onReadyCb(t),e.rootContextCache["delete"](r)):r.hasError||(n(i),--r.pendingCallbacks===r.pendingRefsCount&&(r.pendingRefsCount>0?(r.onReadyCb(Error('Unresolvable references in json: "'.concat(Object.keys(r.pendingRefs).filter((function(e){return r.pendingRefs[e].length>0})).join('", "'),'"'))),e.rootContextCache["delete"](r)):(r.onReadyCb(null,r.target),e.rootContextCache["delete"](r))))}))},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(n){this.isRoot&&this.target&&e.rootContextCache["delete"](this.target),this.target=n,e.rootContextCache.set(this.target,this)},e.prototype.cancelAwaits=function(){var e=this;t(this.isRoot,"cancelAwaits can only be called on the root context"),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.getTargetContext=function(n){return e.rootContextCache.get(n)},e.rootContextCache=new WeakMap,e}();function N(e,n,o,f){void 0===o&&(o=r),t(arguments.length>=2,"deserialize expects at least 2 arguments");var a=v(e);if(t(u(a),"first argument should be model schema"),Array.isArray(n)){var c=[];return i(n,(function(e,n){var t=I(undefined,a,e,n,f);c.push(t)}),o),c}return I(undefined,a,n,o,f)}function I(e,n,i,o,u){if(null!==i&&i!==undefined&&"object"==typeof i){var f=function(e,n){var t;if(null===(t=n.subSchemas)||void 0===t?void 0:t.length)for(var r=0,i=n.subSchemas;r<i.length;r++){var o=i[r];if(o.discriminator&&o.discriminator.isActualType(e))return o}return n}(i,n),a=new D(e,f,i,o,u),c=f.factory(a);t(!!c,"No object returned from factory"),a.setTarget(c);var s=a.createCallback(r);return M(a,f,i,c),s(),c}o(null,null)}var C=function(e,n,t,r,i,o){o&&"function"==typeof o.beforeDeserialize?o.beforeDeserialize(e,n,t,r,i,o):e(null,n)},J=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,r,i){var u;n["extends"]&&M(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 '".concat(f,"': ").concat(a)),i[f]=a):!r||r.pattern&&!r.pattern.test(f)||r.deserializer(a,e.rootContext.createCallback((function(e){return e!==j&&(i[f]=e)})),e)}};for(var a in u)f(a)}(e,n,a,i,r),{value:void 0};!0===a&&(a=g);var c=null!==(u=a.jsonname)&&void 0!==u?u:f;t("symbol"!=typeof c,"You must alias symbol properties. prop = %l",f);var s=r[c],l=a;C((function(n,t){n||t===undefined||function(n,t,o){var u=e.rootContext.createCallback((function(e){return e!==j&&(i[o]=e)}));n.deserializer(t,(function(i,f){return J(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}}function P(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=v(e)),"expected modelSchema, got ".concat(e)),null===n||n===undefined?n:k(e,n)},deserializer:function(n,r,i){t(u(e=v(e)),"expected modelSchema, got ".concat(e)),null!==n&&n!==undefined?I(i,e,n,r,undefined):r(null,n)}},n)}function K(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=v(e);return n||h(e,n=m(e,{})),n.props["*"]=r,e}return t(p(e),"@serializeAll pattern doesn't have test"),"function"==typeof n&&(n=P(n)),!0===n&&(n=g),t(f(n),"couldn't resolve schema"),r=Object.assign({},n,{pattern:e}),i}var U=function(e){if(u(e))return e;var n=v(e);return n||(n=m(e,{})),n};function q(e,n){return function(r){var i,o=U(r);t(null==o?void 0:o["extends"],"Can not apply subSchema on a schema not extending another one.");var u=U(n||o["extends"]);return u.subSchemas=null!==(i=u.subSchemas)&&void 0!==i?i:[],u.subSchemas.push(o),o.discriminator="object"==typeof e?e:{isActualType:function(n){return n.t===e},storeDiscriminator:function(n){n.t=e}},r}}function F(e){t("object"==typeof e&&e&&!Array.isArray(e),"cancelDeserialize needs an object");var n,r=(n=e,D.getTargetContext(n));r&&r.cancelAwaits()}function R(){for(var e,n=[],i=0;i<arguments.length;i++)n[i]=arguments[i];"function"==typeof n[0]||u(n[0])?(e=v(n[0]),n.shift()):e=v(n[0]);var o=n[0],f=n[1],a=n[2],c=n[3];t(u(e),"update failed to determine schema"),t("object"==typeof o&&o&&!Array.isArray(o),"update needs an object");var s=new D(undefined,e,f,a||r,c);s.setTarget(o);var l=s.createCallback(r),d=M(s,e,f,o);return l(),d}function T(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:g.serializer,deserializer:function(e,n,t){g.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)}function W(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)}function Y(e,n){return t(e&&"string"==typeof e,"expected prop name as first argument"),t(f(n=n&&!0!==n?n:g),"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}}function Z(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)}function $(e){t(f(e=e&&!0!==e?e:g),"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?j:i}})}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=v(e);t(u(n),"expected model schema or string as first argument for 'ref', got ".concat(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)}function B(e,n){return t(f(e=e||g),"expected prop schema as first argument"),t(!a(e),"provided prop is aliased, please put aliases first"),d({serializer:function(n){return n===undefined?j:null===n?null:(t(n&&"length"in n&&"map"in n,"expected array (like) object"),n.map(e.serializer))},deserializer:function(n,t,r){null!==n?Array.isArray(n)?i(n,(function(t,i,o){function u(u,f){"function"==typeof e.afterDeserialize?J(i,u,f,t,n,o,r,e):i(u,f)}C((function(n,t){n?i(n):e.deserializer(t,u,r)}),t,n,o,r,e)}),(function(e,n){e?t(e):t(undefined,n.filter((function(e){return j!==e})))})):t("[serializr] expected JSON array"):t(null,n)}},n)}function G(e,n){return t(f(e=e||g),"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);B(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)}function H(e,n,r){return t(f(e=e||g),"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){B(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)}function L(e){return d({serializer:function(e){return e},deserializer:function(e,n){n(null,e)}},e)}export{z as DEFAULT_DISCRIMINATOR_ATTR,j as SKIP,Y as alias,F as cancelDeserialize,m as createModelSchema,e as createSimpleSchema,Z as custom,W as date,N as deserialize,v as getDefaultModelSchema,T as identifier,B as list,G as map,H as mapAsArray,P as object,$ as optional,b as primitive,L as raw,_ as reference,A as serializable,k as serialize,K as serializeAll,h as setDefaultModelSchema,q as subSchema,R as update}; | ||
//# sourceMappingURL=serializr.es.min.js.map |
@@ -5,3 +5,3 @@ (function (global, factory) { | ||
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.serializr = {})); | ||
}(this, (function (exports) { 'use strict'; | ||
})(this, (function (exports) { 'use strict'; | ||
@@ -39,3 +39,3 @@ /** | ||
catch (error) { | ||
return "[UnexpectedJSONParseError]: " + error.message; | ||
return "[UnexpectedJSONParseError]: ".concat(error.message); | ||
} | ||
@@ -82,5 +82,9 @@ }, | ||
return function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
if (!fired) { | ||
fired = true; | ||
return fn.apply(null, arguments); | ||
return fn.apply(void 0, args); | ||
} | ||
@@ -140,3 +144,7 @@ invariant(false, "callback was invoked twice"); | ||
function isMapLike(thing) { | ||
return thing && typeof thing.keys === "function" && typeof thing.clear === "function"; | ||
return (thing && | ||
typeof thing.keys === "function" && | ||
typeof thing.clear === "function" && | ||
typeof thing.forEach === "function" && | ||
typeof thing.set === "function"); | ||
} | ||
@@ -162,2 +170,5 @@ function getIdentifierProp(modelSchema) { | ||
} | ||
function isRegExp(obj) { | ||
return typeof obj === "object" && obj.test; | ||
} | ||
@@ -192,3 +203,3 @@ /** | ||
function setDefaultModelSchema(clazz, modelSchema) { | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got " + modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got ".concat(modelSchema)); | ||
clazz.serializeInfo = modelSchema; | ||
@@ -243,23 +254,25 @@ return modelSchema; | ||
/*! ***************************************************************************** | ||
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 | ||
/****************************************************************************** | ||
Copyright (c) Microsoft Corporation. | ||
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. | ||
Permission to use, copy, modify, and/or distribute this software for any | ||
purpose with or without fee is hereby granted. | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | ||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | ||
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | ||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | ||
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | ||
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | ||
PERFORMANCE OF THIS SOFTWARE. | ||
***************************************************************************** */ | ||
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; | ||
function __spreadArray(to, from, pack) { | ||
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { | ||
if (ar || !(i in from)) { | ||
if (!ar) ar = Array.prototype.slice.call(from, 0, i); | ||
ar[i] = from[i]; | ||
} | ||
} | ||
return to.concat(ar || Array.prototype.slice.call(from)); | ||
} | ||
@@ -282,3 +295,3 @@ | ||
serializer: function (value) { | ||
invariant(isPrimitive(value), "this value is not primitive: " + value); | ||
invariant(isPrimitive(value), "this value is not primitive: ".concat(value)); | ||
return value; | ||
@@ -288,3 +301,3 @@ }, | ||
if (!isPrimitive(jsonValue)) | ||
return void done("[serializr] this value is not primitive: " + jsonValue); | ||
return void done("[serializr] this value is not primitive: ".concat(jsonValue)); | ||
return void done(null, jsonValue); | ||
@@ -331,2 +344,8 @@ }, | ||
var SKIP = typeof Symbol !== "undefined" ? Symbol("SKIP") : { SKIP: true }; | ||
/** | ||
* When using the decorator shorthand we store the given value in | ||
* a specific attribute of the result structure. This constant contains | ||
* the attribute name used in such scenario. | ||
*/ | ||
var DEFAULT_DISCRIMINATOR_ATTR = "_type"; | ||
var _defaultPrimitiveProp = primitive(); | ||
@@ -374,3 +393,3 @@ | ||
} | ||
return (_a = target.constructor).bind.apply(_a, __spreadArrays([undefined], params)); | ||
return (_a = target.constructor).bind.apply(_a, __spreadArray([undefined], params, false)); | ||
}; | ||
@@ -381,3 +400,3 @@ } | ||
var info = getDefaultModelSchema(target); | ||
if (!info || !target.constructor.hasOwnProperty("serializeInfo")) | ||
if (!info || !Object.prototype.hasOwnProperty.call(target.constructor, "serializeInfo")) | ||
info = createModelSchema(target.constructor, {}, factory); | ||
@@ -396,3 +415,5 @@ if (info && info.targetClass !== target.constructor) | ||
// decorated with propSchema | ||
var propSchema = targetOrPropSchema === true ? _defaultPrimitiveProp : targetOrPropSchema; | ||
var propSchema = targetOrPropSchema === true | ||
? _defaultPrimitiveProp | ||
: targetOrPropSchema; | ||
invariant(isPropSchema(propSchema), "@serializable expects prop schema"); | ||
@@ -408,31 +429,34 @@ var result = serializableDecorator.bind(null, propSchema); | ||
function serialize(modelSchemaOrInstance, arg2) { | ||
invariant(arguments.length === 1 || arguments.length === 2, "serialize expects one or 2 arguments"); | ||
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(instance[0]); | ||
else if (typeof schema !== "object") | ||
schema = getDefaultModelSchema(schema); | ||
function serialize() { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
else if (!schema) { | ||
schema = getDefaultModelSchema(instance); | ||
invariant(args.length === 1 || args.length === 2, "serialize expects one or 2 arguments"); | ||
var schema; | ||
var value; | ||
if (args.length === 1) { | ||
schema = undefined; | ||
value = args[0]; | ||
} | ||
else { | ||
schema = args[0], value = args[1]; | ||
} | ||
if (Array.isArray(value)) { | ||
return value.map(function (item) { return (schema ? serialize(schema, item) : serialize(item)); }); | ||
} | ||
if (!schema) { | ||
schema = getDefaultModelSchema(value); | ||
} | ||
else if (typeof schema !== "object") { | ||
schema = getDefaultModelSchema(schema); | ||
} | ||
var foundSchema = schema; | ||
if (!foundSchema) { | ||
if (!schema) { | ||
// only call modelSchemaOrInstance.toString() on error | ||
invariant(foundSchema, "Failed to find default schema for " + modelSchemaOrInstance); | ||
invariant(schema, "Failed to find default schema for ".concat(value)); | ||
} | ||
if (Array.isArray(instance)) | ||
return instance.map(function (item) { return serializeWithSchema(foundSchema, item); }); | ||
return serializeWithSchema(foundSchema, instance); | ||
return serializeWithSchema(schema, value); | ||
} | ||
function serializeWithSchema(schema, obj) { | ||
var _a; | ||
invariant(schema && typeof schema === "object" && schema.props, "Expected schema"); | ||
@@ -463,2 +487,5 @@ invariant(obj && typeof obj === "object", "Expected object"); | ||
}); | ||
if ((_a = schema.discriminator) === null || _a === void 0 ? void 0 : _a.storeDiscriminator) { | ||
schema.discriminator.storeDiscriminator(res); | ||
} | ||
return res; | ||
@@ -491,3 +518,2 @@ } | ||
var rootContextCache = new WeakMap(); | ||
var Context = /** @class */ (function () { | ||
@@ -524,3 +550,3 @@ function Context(parentContext, modelSchema, json, onReadyCb, customArgs) { | ||
_this.onReadyCb(err); | ||
rootContextCache.delete(_this); | ||
Context.rootContextCache.delete(_this); | ||
} | ||
@@ -533,12 +559,12 @@ } | ||
// 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); | ||
_this.onReadyCb(new Error("Unresolvable references in json: \"".concat(Object.keys(_this.pendingRefs) | ||
.filter(function (uuid) { return _this.pendingRefs[uuid].length > 0; }) | ||
.join( | ||
// prettier-ignore | ||
"\", \""), "\""))); | ||
Context.rootContextCache.delete(_this); | ||
} | ||
else { | ||
_this.onReadyCb(null, _this.target); | ||
rootContextCache.delete(_this); | ||
Context.rootContextCache.delete(_this); | ||
} | ||
@@ -592,14 +618,14 @@ } | ||
if (this.isRoot && this.target) { | ||
rootContextCache.delete(this.target); | ||
Context.rootContextCache.delete(this.target); | ||
} | ||
this.target = target; | ||
rootContextCache.set(this.target, this); | ||
Context.rootContextCache.set(this.target, this); | ||
}; | ||
// call all remaining reference lookup callbacks indicating an error during ref resolution | ||
Context.prototype.cancelAwaits = function () { | ||
var _this = this; | ||
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--; | ||
_this.pendingRefs[uuid].forEach(function (refOpts) { | ||
_this.pendingRefsCount--; | ||
refOpts.callback(new Error("Reference resolution canceled for " + uuid)); | ||
@@ -611,6 +637,15 @@ }); | ||
}; | ||
Context.getTargetContext = function (target) { | ||
return Context.rootContextCache.get(target); | ||
}; | ||
Context.rootContextCache = new WeakMap(); | ||
return Context; | ||
}()); | ||
/** | ||
* @deprecated Use `Context.getTargetContext(target)` directly. | ||
* @param target | ||
* @returns | ||
*/ | ||
function getTargetContext(target) { | ||
return rootContextCache.get(target); | ||
return Context.getTargetContext(target); | ||
} | ||
@@ -636,6 +671,3 @@ | ||
// confusing bugs | ||
invariant(isPrimitive(jsonValue), "encountered non primitive value while deserializing '*' properties in property '" + | ||
key + | ||
"': " + | ||
jsonValue); | ||
invariant(isPrimitive(jsonValue), "encountered non primitive value while deserializing '*' properties in property '".concat(key, "': ").concat(jsonValue)); | ||
obj[key] = jsonValue; | ||
@@ -656,2 +688,17 @@ } | ||
} | ||
function identifyActualSchema(json, baseSchema) { | ||
var _a; | ||
if ((_a = baseSchema.subSchemas) === null || _a === void 0 ? void 0 : _a.length) { | ||
for (var _i = 0, _b = baseSchema.subSchemas; _i < _b.length; _i++) { | ||
var subSchema = _b[_i]; | ||
if (subSchema.discriminator) { | ||
if (subSchema.discriminator.isActualType(json)) { | ||
return subSchema; | ||
} | ||
} | ||
} | ||
} | ||
// If we can't find a specific schema we go with the base. | ||
return baseSchema; | ||
} | ||
function deserialize(clazzOrModelSchema, json, callback, customArgs) { | ||
@@ -678,4 +725,5 @@ if (callback === void 0) { callback = GUARDED_NOOP; } | ||
return void callback(null, null); | ||
var context = new Context(parentContext, modelSchema, json, callback, customArgs); | ||
var target = modelSchema.factory(context); | ||
var actualSchema = identifyActualSchema(json, modelSchema); | ||
var context = new Context(parentContext, actualSchema, json, callback, customArgs); | ||
var target = actualSchema.factory(context); | ||
// todo async invariant | ||
@@ -688,6 +736,22 @@ invariant(!!target, "No object returned from factory"); | ||
var lock = context.createCallback(GUARDED_NOOP); | ||
deserializePropsWithSchema(context, modelSchema, json, target); | ||
deserializePropsWithSchema(context, actualSchema, json, target); | ||
lock(); | ||
return target; | ||
} | ||
var onBeforeDeserialize = function (callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef) { | ||
if (propDef && typeof propDef.beforeDeserialize === "function") { | ||
propDef.beforeDeserialize(callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef); | ||
} | ||
else { | ||
callback(null, jsonValue); | ||
} | ||
}; | ||
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 { | ||
callback(err, newValue); | ||
} | ||
}; | ||
function deserializePropsWithSchema(context, modelSchema, json, target) { | ||
@@ -722,5 +786,5 @@ var _a; | ||
var propSchema = propDef; | ||
var callbackDeserialize = function (err, jsonValue) { | ||
if (!err && jsonValue !== undefined) { | ||
deserializeProp(propSchema, jsonValue, key); | ||
var callbackDeserialize = function (err, jsonVal) { | ||
if (!err && jsonVal !== undefined) { | ||
deserializeProp(propSchema, jsonVal, key); | ||
} | ||
@@ -737,18 +801,2 @@ }; | ||
} | ||
var onBeforeDeserialize = function (callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef) { | ||
if (propDef && typeof propDef.beforeDeserialize === "function") { | ||
propDef.beforeDeserialize(callback, jsonValue, jsonParentValue, propNameOrIndex, context, propDef); | ||
} | ||
else { | ||
callback(null, jsonValue); | ||
} | ||
}; | ||
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 { | ||
callback(err, newValue); | ||
} | ||
}; | ||
@@ -788,3 +836,3 @@ /** | ||
modelSchema = getDefaultModelSchema(modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got " + modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got ".concat(modelSchema)); | ||
if (item === null || item === undefined) | ||
@@ -796,3 +844,3 @@ return item; | ||
modelSchema = getDefaultModelSchema(modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got " + modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected modelSchema, got ".concat(modelSchema)); | ||
if (childJson === null || childJson === undefined) | ||
@@ -814,3 +862,3 @@ return void done(null, childJson); | ||
else { | ||
invariant(typeof targetOrPattern === "object" && targetOrPattern.test, "@serializeAll pattern doesn't have test"); | ||
invariant(isRegExp(targetOrPattern), "@serializeAll pattern doesn't have test"); | ||
if (typeof propertyType === "function") { | ||
@@ -840,2 +888,153 @@ propertyType = object(propertyType); | ||
/** | ||
* A simple util that retrieve the existing schema or create a default one. | ||
* @param src | ||
* @returns | ||
*/ | ||
var getOrCreateSchema = function (src) { | ||
if (isModelSchema(src)) { | ||
return src; | ||
} | ||
else { | ||
var schema = getDefaultModelSchema(src); | ||
if (!schema) { | ||
schema = createModelSchema(src, {}); | ||
} | ||
return schema; | ||
} | ||
}; | ||
/** | ||
* Sometimes, when working with schema hierarchies, we may want to deserialize an object to | ||
* a specific sub-schema. The `subSchema` decorator is used to handle such scenario. | ||
* What schema is picked among those available is decided using a "discriminator". The | ||
* discriminator can be a string (which is added to the serialized object) or a object | ||
* containing callbacks allowing for more complex behaviour. | ||
* | ||
* | ||
* @example | ||
* ```ts | ||
* class Todo { | ||
* @serializable | ||
* id: string; | ||
* | ||
* @serializable | ||
* text: string; | ||
* } | ||
* | ||
* @subSchema("picture") | ||
* class PictureTodo extends Todo { | ||
* @serializable | ||
* pictureUrl: string; | ||
* } | ||
* | ||
* const ser = serialize(Object.assign(new PictureTodo(), { | ||
* id: "pic1", | ||
* text: "Lorem Ipsum", | ||
* pictureUrl:"foobar", | ||
* })); | ||
* // ser now holds an object like the following result | ||
* // { | ||
* // id: "pic1", | ||
* // _type: "picture" | ||
* // text: "Lorem Ipsum", | ||
* // pictureUrl:"foobar", | ||
* // } | ||
* const deser = deserialize(Todo, ser); | ||
* console.log(deser instanceof PictureTodo); // true | ||
* ``` | ||
* | ||
* @example | ||
* Using the `parent` argument it's possible to specify the subschema parent instead | ||
* of relying on auto-detention. | ||
* ```ts | ||
* class Todo { | ||
* @serializable | ||
* id: string; | ||
* | ||
* @serializable | ||
* text: string; | ||
* } | ||
* | ||
* @subSchema("picture") | ||
* class PictureTodo extends Todo { | ||
* @serializable | ||
* pictureUrl: string; | ||
* } | ||
* | ||
* @subSchema("betterPicture", Todo) | ||
* class BetterPictureTodo extends PictureTodo { | ||
* @serializable | ||
* altText: string; | ||
* } | ||
* | ||
* | ||
* const ser = serialize(Object.assign(new BetterPictureTodo(), { | ||
* id: "pic1", | ||
* text: "Lorem Ipsum", | ||
* pictureUrl:"foobar", | ||
* altText: "Alt text", | ||
* })); | ||
* // ser now holds an object like the following result | ||
* // { | ||
* // id: "pic1", | ||
* // _type: "betterPicture" | ||
* // text: "Lorem Ipsum", | ||
* // pictureUrl:"foobar", | ||
* // altText: "Alt text", | ||
* // } | ||
* const deser = deserialize(Todo, ser); | ||
* console.log(deser instanceof BetterPictureTodo); // true | ||
* console.log(deser instanceof PictureTodo); // true | ||
* | ||
* const ser2 = serialize(Object.assign(new PictureTodo(), { | ||
* id: "pic2", | ||
* text: "Lorem Ipsum", | ||
* pictureUrl:"foobar", | ||
* })); | ||
* // ser2 now holds an object like the following result | ||
* // { | ||
* // id: "pic2", | ||
* // _type: "picture" | ||
* // text: "Lorem Ipsum", | ||
* // pictureUrl:"foobar", | ||
* // } | ||
* const deser2 = deserialize(Todo, ser2); | ||
* console.log(deser2 instanceof BetterPictureTodo); // false | ||
* console.log(deser2 instanceof PictureTodo); // true | ||
* ``` | ||
* | ||
* @param discriminator An object providing the discriminator logic or a string/number | ||
* that will be stored into the `_type` attribute. | ||
* @param parent When there are multiple levels of hierarchy involved you may provide this | ||
* argument to indicate the main schema used for deserialization. When not give the parent | ||
* schema is inferred as the direct parent (the class/schema that is extended). | ||
* | ||
* @returns | ||
*/ | ||
function subSchema(discriminator, parent) { | ||
return function (target) { | ||
var _a; | ||
var childSchema = getOrCreateSchema(target); | ||
invariant(childSchema === null || childSchema === void 0 ? void 0 : childSchema.extends, "Can not apply subSchema on a schema not extending another one."); | ||
var parentSchema = getOrCreateSchema(parent || childSchema.extends); | ||
parentSchema.subSchemas = (_a = parentSchema.subSchemas) !== null && _a !== void 0 ? _a : []; | ||
parentSchema.subSchemas.push(childSchema); | ||
if (typeof discriminator === "object") { | ||
childSchema.discriminator = discriminator; | ||
} | ||
else { | ||
childSchema.discriminator = { | ||
isActualType: function (src) { | ||
return src[DEFAULT_DISCRIMINATOR_ATTR] === discriminator; | ||
}, | ||
storeDiscriminator: function (result) { | ||
result[DEFAULT_DISCRIMINATOR_ATTR] = discriminator; | ||
}, | ||
}; | ||
} | ||
return target; | ||
}; | ||
} | ||
/* | ||
@@ -859,14 +1058,17 @@ * Deserialization | ||
*/ | ||
function update(modelSchema, target, json, callback, customArgs) { | ||
var inferModelSchema = arguments.length === 2 || typeof arguments[2] === "function"; // only target and json // callback as third arg | ||
if (inferModelSchema) { | ||
target = arguments[0]; | ||
modelSchema = getDefaultModelSchema(target); | ||
json = arguments[1]; | ||
callback = arguments[2]; | ||
customArgs = arguments[3]; | ||
function update() { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
var modelSchema; | ||
if (typeof args[0] === "function" || isModelSchema(args[0])) { | ||
// First overload | ||
modelSchema = getDefaultModelSchema(args[0]); | ||
args.shift(); | ||
} | ||
else { | ||
modelSchema = getDefaultModelSchema(modelSchema); | ||
modelSchema = getDefaultModelSchema(args[0]); | ||
} | ||
var target = args[0], json = args[1], callback = args[2], customArgs = args[3]; | ||
invariant(isModelSchema(modelSchema), "update failed to determine schema"); | ||
@@ -971,7 +1173,7 @@ invariant(typeof target === "object" && target && !Array.isArray(target), "update needs an object"); | ||
deserializer: function (jsonValue, done, context, oldValue) { | ||
var result = deserializer(jsonValue, context, oldValue, done); | ||
var result2 = 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); | ||
done(null, result2); | ||
} | ||
@@ -1041,3 +1243,3 @@ }, | ||
var modelSchema = getDefaultModelSchema(target); | ||
invariant(isModelSchema(modelSchema), "expected model schema or string as first argument for 'ref', got " + modelSchema); | ||
invariant(isModelSchema(modelSchema), "expected model schema or string as first argument for 'ref', got ".concat(modelSchema)); | ||
lookupFn = lookupFn || createDefaultRefLookup(modelSchema); | ||
@@ -1105,2 +1307,5 @@ childIdentifierAttribute = getIdentifierProp(modelSchema); | ||
} | ||
if (ar === null) { | ||
return null; | ||
} | ||
invariant(ar && "length" in ar && "map" in ar, "expected array (like) object"); | ||
@@ -1110,2 +1315,4 @@ return ar.map(propSchema.serializer); | ||
deserializer: function (jsonArray, done, context) { | ||
if (jsonArray === null) | ||
return void done(null, jsonArray); | ||
if (!Array.isArray(jsonArray)) | ||
@@ -1132,7 +1339,7 @@ return void done("[serializr] expected JSON array"); | ||
} | ||
parallel(jsonArray, processItem, function (err, result) { | ||
parallel(jsonArray, processItem, function (err, result2) { | ||
if (err) { | ||
return void done(err); | ||
} | ||
done(undefined, result.filter(function (x) { return SKIP !== x; })); | ||
done(undefined, result2.filter(function (x) { return SKIP !== x; })); | ||
}); | ||
@@ -1159,11 +1366,11 @@ }, | ||
invariant(m && typeof m === "object", "expected object or Map"); | ||
var result = {}; | ||
var result2 = {}; | ||
if (isMapLike(m)) { | ||
m.forEach(function (value, key) { return (result[key] = propSchema.serializer(value, key, m)); }); | ||
m.forEach(function (value, key) { return (result2[key] = propSchema.serializer(value, key, m)); }); | ||
} | ||
else { | ||
for (var key in m) | ||
result[key] = propSchema.serializer(m[key], key, m); | ||
result2[key] = propSchema.serializer(m[key], key, m); | ||
} | ||
return result; | ||
return result2; | ||
}, | ||
@@ -1174,5 +1381,3 @@ deserializer: function (jsonObject, done, context, oldValue) { | ||
var keys = Object.keys(jsonObject); | ||
list(propSchema, additionalArgs).deserializer(keys.map(function (key) { | ||
return jsonObject[key]; | ||
}), function (err, values) { | ||
list(propSchema, additionalArgs).deserializer(keys.map(function (key) { return jsonObject[key]; }), function (err, values) { | ||
if (err) | ||
@@ -1191,3 +1396,3 @@ return void done(err); | ||
newValue = {}; | ||
for (var i = 0, l = keys.length; i < l; i++) | ||
for (var i = 0, l = keys.length; i < l; i++) { | ||
if (isMap) | ||
@@ -1197,2 +1402,3 @@ newValue.set(keys[i], values[i]); | ||
newValue[keys[i]] = values[i]; | ||
} | ||
done(null, newValue); | ||
@@ -1225,12 +1431,11 @@ }, context); | ||
invariant(m && typeof m === "object", "expected object or Map"); | ||
var result = []; | ||
// eslint-disable-next-line no-unused-vars | ||
var result2 = []; | ||
if (isMapLike(m)) { | ||
m.forEach(function (value, key) { return result.push(propSchema.serializer(value, key, m)); }); | ||
m.forEach(function (value, key) { return result2.push(propSchema.serializer(value, key, m)); }); | ||
} | ||
else { | ||
for (var key in m) | ||
result.push(propSchema.serializer(m[key], key, m)); | ||
result2.push(propSchema.serializer(m[key], key, m)); | ||
} | ||
return result; | ||
return result2; | ||
}, | ||
@@ -1254,3 +1459,4 @@ deserializer: function (jsonArray, done, context, oldValue) { | ||
else | ||
newValue[values[i][keyPropertyName].toString()] = values[i]; | ||
newValue[values[i][keyPropertyName].toString()] = | ||
values[i]; | ||
done(null, newValue); | ||
@@ -1291,2 +1497,3 @@ }, context, undefined); | ||
exports.DEFAULT_DISCRIMINATOR_ATTR = DEFAULT_DISCRIMINATOR_ATTR; | ||
exports.SKIP = SKIP; | ||
@@ -1314,2 +1521,3 @@ exports.alias = alias; | ||
exports.setDefaultModelSchema = setDefaultModelSchema; | ||
exports.subSchema = subSchema; | ||
exports.update = update; | ||
@@ -1319,3 +1527,3 @@ | ||
}))); | ||
})); | ||
//# sourceMappingURL=serializr.umd.js.map |
/** serializr - (c) Michel Weststrate 2016 - MIT Licensed */ | ||
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(),g=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,z=/([^\s,]+)/g;function x(e){var n,t=e.toString().replace(g,"");return null!==(n=t.slice(t.indexOf("(")+1,t.indexOf(")")).match(z))&&void 0!==n?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 o||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)&&void 0!==u?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)}),(function(e,n){e?t(e):t(undefined,n.filter((function(e){return b!==e})))})):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="undefined"!=typeof globalThis?globalThis:e||self).serializr={}); | ||
var e,n;e=this,n=function(e){"use strict";var n={j:function(e){try{return JSON.stringify(e)}catch(n){return"[UnexpectedJSONParseError]: ".concat(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"==typeof e.forEach&&"function"==typeof e.set}function d(e,n){return n&&(t(f(e),"expected a propSchema"),Object.assign(e,n)),e}function p(e){return"object"==typeof e&&e.test}function v(e){return e?u(e)?e:u(e.serializeInfo)?e.serializeInfo:e.constructor&&e.constructor.serializeInfo?e.constructor.serializeInfo:void 0:undefined}function h(e,n){return t(u(n),"expected modelSchema, got ".concat(n)),e.serializeInfo=n,n}function m(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=v(e.prototype.constructor);o&&o.targetClass!==e&&(i["extends"]=o)}return h(e,i),i}function y(e,n,t){if(t||2===arguments.length)for(var r,i=0,o=n.length;i<o;i++)!r&&i in n||(r||(r=Array.prototype.slice.call(n,0,i)),r[i]=n[i]);return e.concat(r||Array.prototype.slice.call(n))}function b(e){return d({serializer:function(e){return t(o(e),"this value is not primitive: ".concat(e)),e},deserializer:function(e,n){o(e)?n(null,e):n("[serializr] this value is not primitive: ".concat(e))}},e)}var j="undefined"!=typeof Symbol?Symbol("SKIP"):{SKIP:!0},g=b(),z=/((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm,x=/([^\s,]+)/g;function S(e){var n,t=e.toString().replace(z,"");return null!==(n=t.slice(t.indexOf("(")+1,t.indexOf(")")).match(x))&&void 0!==n?n:[]}function O(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=S(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,y([undefined],r,!1))})}t("string"==typeof r,"incorrect usage of @serializable decorator");var c=v(n);return c&&Object.prototype.hasOwnProperty.call(n.constructor,"serializeInfo")||(c=m(n.constructor,{},o)),c&&c.targetClass!==n.constructor&&(c=m(n.constructor,{},o)),c.props[r]=e,!i||i.get||i.set||(i.writable=!0),i}function w(){for(var e,n,r=[],i=0;i<arguments.length;i++)r[i]=arguments[i];return t(1===r.length||2===r.length,"serialize expects one or 2 arguments"),1===r.length?(e=undefined,n=r[0]):(e=r[0],n=r[1]),Array.isArray(n)?n.map((function(n){return e?w(e,n):w(n)})):(e?"object"!=typeof e&&(e=v(e)):e=v(n),e||t(e,"Failed to find default schema for ".concat(n)),A(e,n))}function A(e,n){var r,i;return t(e&&"object"==typeof e&&e.props,"Expected schema"),t(n&&"object"==typeof n,"Expected object"),i=e["extends"]?A(e["extends"],n):{},Object.keys(e.props).forEach((function(t){var r=e.props[t];if(r)if("*"!==t){!0===r&&(r=g);var u=r.serializer(n[t],t,n);u!==j&&(i[r.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===j)return;r[f]=c}}}}(e,r,n,i)})),(null===(r=e.discriminator)||void 0===r?void 0:r.storeDiscriminator)&&e.discriminator.storeDiscriminator(i),i}var 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(n){var r=this;return this.pendingCallbacks++,function(e){var n=!1;return function(){for(var r=[],i=0;i<arguments.length;i++)r[i]=arguments[i];if(!n)return n=!0,e.apply(void 0,r);t(!1,"callback was invoked twice")}}((function(t,i){t?r.hasError||(r.hasError=!0,r.onReadyCb(t),e.rootContextCache["delete"](r)):r.hasError||(n(i),--r.pendingCallbacks===r.pendingRefsCount&&(r.pendingRefsCount>0?(r.onReadyCb(Error('Unresolvable references in json: "'.concat(Object.keys(r.pendingRefs).filter((function(e){return r.pendingRefs[e].length>0})).join('", "'),'"'))),e.rootContextCache["delete"](r)):(r.onReadyCb(null,r.target),e.rootContextCache["delete"](r))))}))},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(n){this.isRoot&&this.target&&e.rootContextCache["delete"](this.target),this.target=n,e.rootContextCache.set(this.target,this)},e.prototype.cancelAwaits=function(){var e=this;t(this.isRoot,"cancelAwaits can only be called on the root context"),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.getTargetContext=function(n){return e.rootContextCache.get(n)},e.rootContextCache=new WeakMap,e}();function E(e,n,i,o,u){if(null!==i&&i!==undefined&&"object"==typeof i){var f=function(e,n){var t;if(null===(t=n.subSchemas)||void 0===t?void 0:t.length)for(var r=0,i=n.subSchemas;r<i.length;r++){var o=i[r];if(o.discriminator&&o.discriminator.isActualType(e))return o}return n}(i,n),a=new k(e,f,i,o,u),c=f.factory(a);t(!!c,"No object returned from factory"),a.setTarget(c);var s=a.createCallback(r);return I(a,f,i,c),s(),c}o(null,null)}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)},N=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 I(e,n,r,i){var u;n["extends"]&&I(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 '".concat(f,"': ").concat(a)),i[f]=a):!r||r.pattern&&!r.pattern.test(f)||r.deserializer(a,e.rootContext.createCallback((function(e){return e!==j&&(i[f]=e)})),e)}};for(var a in u)f(a)}(e,n,a,i,r),{value:void 0};!0===a&&(a=g);var c=null!==(u=a.jsonname)&&void 0!==u?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!==j&&(i[o]=e)}));n.deserializer(t,(function(i,f){return N(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}}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=v(e)),"expected modelSchema, got ".concat(e)),null===n||n===undefined?n:w(e,n)},deserializer:function(n,r,i){t(u(e=v(e)),"expected modelSchema, got ".concat(e)),null!==n&&n!==undefined?E(i,e,n,r,undefined):r(null,n)}},n)}var C=function(e){if(u(e))return e;var n=v(e);return n||(n=m(e,{})),n};function J(e,n){return t(f(e=e||g),"expected prop schema as first argument"),t(!a(e),"provided prop is aliased, please put aliases first"),d({serializer:function(n){return n===undefined?j:null===n?null:(t(n&&"length"in n&&"map"in n,"expected array (like) object"),n.map(e.serializer))},deserializer:function(n,t,r){null!==n?Array.isArray(n)?i(n,(function(t,i,o){function u(u,f){"function"==typeof e.afterDeserialize?N(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)}),(function(e,n){e?t(e):t(undefined,n.filter((function(e){return j!==e})))})):t("[serializr] expected JSON array"):t(null,n)}},n)}e.DEFAULT_DISCRIMINATOR_ATTR="_type",e.SKIP=j,e.alias=function(e,n){return t(e&&"string"==typeof e,"expected prop name as first argument"),t(f(n=n&&!0!==n?n:g),"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,k.getTargetContext(n));r&&r.cancelAwaits()},e.createModelSchema=m,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=v(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=v,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:g.serializer,deserializer:function(e,n,t){g.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||g),"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||g),"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:g),"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?j:i}})},e.primitive=b,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=v(e);t(u(n),"expected model schema or string as first argument for 'ref', got ".concat(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?g:e;return t(f(i),"@serializable expects prop schema"),O.bind(null,i)}O(b(),e,n,r)},e.serialize=w,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=v(e);return n||h(e,n=m(e,{})),n.props["*"]=r,e}return t(p(e),"@serializeAll pattern doesn't have test"),"function"==typeof n&&(n=M(n)),!0===n&&(n=g),t(f(n),"couldn't resolve schema"),r=Object.assign({},n,{pattern:e}),i},e.setDefaultModelSchema=h,e.subSchema=function(e,n){return function(r){var i,o=C(r);t(null==o?void 0:o["extends"],"Can not apply subSchema on a schema not extending another one.");var u=C(n||o["extends"]);return u.subSchemas=null!==(i=u.subSchemas)&&void 0!==i?i:[],u.subSchemas.push(o),o.discriminator="object"==typeof e?e:{isActualType:function(n){return n.t===e},storeDiscriminator:function(n){n.t=e}},r}},e.update=function(){for(var e,n=[],i=0;i<arguments.length;i++)n[i]=arguments[i];"function"==typeof n[0]||u(n[0])?(e=v(n[0]),n.shift()):e=v(n[0]);var o=n[0],f=n[1],a=n[2],c=n[3];t(u(e),"update failed to determine schema"),t("object"==typeof o&&o&&!Array.isArray(o),"update needs an object");var s=new k(undefined,e,f,a||r,c);s.setTarget(o);var l=s.createCallback(r),d=I(s,e,f,o);return l(),d},Object.defineProperty(e,"i",{value:!0})},"object"==typeof exports&&"undefined"!=typeof module?n(exports):"function"==typeof define&&define.amd?define(["exports"],n):n((e="undefined"!=typeof globalThis?globalThis:e||self).serializr={}); | ||
//# sourceMappingURL=serializr.umd.min.js.map |
@@ -0,6 +1,6 @@ | ||
import { AdditionalPropArgs, ModelSchema, PropSchema } from "../api/types"; | ||
import invariant from "./invariant"; | ||
import { ModelSchema, AdditionalPropArgs, PropSchema } from "../api/types"; | ||
export declare function GUARDED_NOOP(err?: any): void; | ||
export declare function once<F extends Function>(fn: F): F; | ||
export declare function parallel<T, R>(ar: T[], processor: (val: T, cb: (err?: any, result?: R) => void, idx: number) => void, cb: (err?: any, result?: R[]) => void): undefined; | ||
export declare function once<F extends (...args: any[]) => any>(fn: F): F; | ||
export declare function parallel<T, R>(ar: T[], processor: (val: T, cb2: (err?: any, result?: R) => void, idx: number) => void, cb: (err?: any, result?: R[]) => void): undefined; | ||
export declare function isPrimitive(value: any): value is number | string | undefined | null | bigint; | ||
@@ -14,5 +14,7 @@ export declare function isModelSchema(thing: any): thing is ModelSchema<any>; | ||
export declare function isAssignableTo(actualType: ModelSchema<any>, expectedType: ModelSchema<any>): boolean; | ||
export declare function isMapLike(thing: any): thing is Pick<Map<any, any>, "keys" | "clear" | "forEach">; | ||
export declare type MapLike = Pick<Map<any, any>, "keys" | "clear" | "forEach" | "set">; | ||
export declare function isMapLike(thing: any): thing is MapLike; | ||
export declare function getIdentifierProp(modelSchema: ModelSchema<any>): string | undefined; | ||
export declare function processAdditionalPropArgs<T extends PropSchema>(propSchema: T, additionalArgs?: AdditionalPropArgs): T; | ||
export declare function isRegExp(obj: any): obj is RegExp; | ||
export { invariant }; |
{ | ||
"name": "serializr", | ||
"version": "2.0.5", | ||
"version": "3.0.1", | ||
"description": "Serialize and deserialize complex object graphs to JSON", | ||
@@ -9,15 +9,15 @@ "main": "lib/serializr.umd.js", | ||
"scripts": { | ||
"test": "nyc --reporter lcov tape test/*.js", | ||
"lint": "eslint src", | ||
"test": "yarn build-test && nyc --reporter lcov tape test/*.js", | ||
"lint": "eslint src --ext .ts", | ||
"prepare": "yarn run build && yarn run build-docs", | ||
"build": "rollup --config", | ||
"build-docs": "ts-node --transpile-only --project gendoc.tsconfig.json ./gendoc.tsx", | ||
"build-docs": "typedoc", | ||
"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", | ||
"build-test-babel": "babel test/babel/babel.js test/babel/mobx-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", | ||
"postversion": "git push && git push --tags", | ||
"preversion": "yarn build && yarn build-test && yarn test && git diff --exit-code" | ||
"preversion": "yarn build && yarn build-test && yarn test && git diff --exit-code", | ||
"watch-docs": "typedoc --watch" | ||
}, | ||
@@ -53,2 +53,3 @@ "nyc": { | ||
"@babel/cli": "^7.2.3", | ||
"@babel/core": "^7.18.10", | ||
"@babel/plugin-proposal-class-properties": "^7.3.0", | ||
@@ -58,30 +59,25 @@ "@babel/plugin-proposal-decorators": "^7.3.0", | ||
"@rollup/plugin-typescript": "^8.1.0", | ||
"@types/react": "^16.9.19", | ||
"@types/react-dom": "^16.9.5", | ||
"@types/tape": "^4.2.33", | ||
"@typescript-eslint/eslint-plugin": "^5.33.0", | ||
"@typescript-eslint/parser": "^5.33.0", | ||
"babel-eslint": "^10.0.1", | ||
"coveralls": "^3.0.2", | ||
"documentation": "^12.1.4", | ||
"eslint": "^5.13.0", | ||
"eslint": "^8.21.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", | ||
"mobx": "^6.6.1", | ||
"nodemon": "^2.0.2", | ||
"nyc": "^15.0.0", | ||
"prettier": "^2.0.4", | ||
"react": "^16.12.0", | ||
"react-dom": "^16.12.0", | ||
"react-markdown": "^4.3.1", | ||
"rimraf": "^3.0.1", | ||
"rollup": "^2.35.1", | ||
"rollup": "^2.77.3", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"tape": "^4.9.2", | ||
"ts-node": "^8.6.2", | ||
"turndown": "^5.0.3", | ||
"turndown-plugin-gfm": "^1.0.2", | ||
"typedoc": "0.17.0-3", | ||
"tslib": "^2.4.0", | ||
"typedoc": "0.23.10", | ||
"typescript": "^4.1.3", | ||
"unescape": "^1.0.1" | ||
}, | ||
"dependencies": {} | ||
"packageManager": "yarn@3.2.2" | ||
} |
806
README.md
@@ -14,2 +14,7 @@ # Serializr | ||
# Api Documentation | ||
The auto-generated documentation for the APIs is published using gitpages at: | ||
https://mobxjs.github.io/serializr/ | ||
# Introduction | ||
@@ -54,15 +59,15 @@ | ||
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 = []; | ||
} | ||
@@ -73,6 +78,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; | ||
} | ||
@@ -85,3 +90,3 @@ | ||
// context is an object detailing the execution context of the serializer now | ||
callback(null, fetchUserSomewhere(uuid)) | ||
callback(null, fetchUserSomewhere(uuid)); | ||
} | ||
@@ -93,9 +98,9 @@ | ||
author: reference(User, findUserById), | ||
comments: list(object(Message)) | ||
}) | ||
comments: list(object(Message)), | ||
}); | ||
createModelSchema(User, { | ||
uuid: identifier(), | ||
displayName: primitive() | ||
}) | ||
displayName: primitive(), | ||
}); | ||
@@ -109,10 +114,10 @@ // can now deserialize and serialize! | ||
message: "Welcome!", | ||
author: 23 | ||
} | ||
] | ||
}) | ||
author: 23, | ||
}, | ||
], | ||
}); | ||
const json = serialize(message) | ||
const json = serialize(message); | ||
console.dir(message, { colors: true, depth: 10 }) | ||
console.dir(message, { colors: true, depth: 10 }); | ||
``` | ||
@@ -135,11 +140,11 @@ | ||
getDefaultModelSchema, | ||
serializable | ||
} from "serializr" | ||
serializable, | ||
} from "serializr"; | ||
class User { | ||
@serializable(identifier()) | ||
uuid = Math.random() | ||
uuid = Math.random(); | ||
@serializable | ||
displayName = "John Doe" | ||
displayName = "John Doe"; | ||
} | ||
@@ -149,10 +154,10 @@ | ||
@serializable | ||
message = "Test" | ||
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 = []; | ||
} | ||
@@ -167,8 +172,8 @@ | ||
message: "Welcome!", | ||
author: { uuid: 1, displayName: "Bob" } | ||
} | ||
] | ||
}) | ||
author: { uuid: 1, displayName: "Bob" }, | ||
}, | ||
], | ||
}); | ||
console.dir(message, { colors: true, depth: 10 }) | ||
console.dir(message, { colors: true, depth: 10 }); | ||
@@ -178,3 +183,3 @@ // We can call serialize without the first argument here | ||
const json = serialize(message) | ||
const json = serialize(message); | ||
``` | ||
@@ -188,11 +193,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)); | ||
} | ||
@@ -257,8 +262,8 @@ } | ||
const todoSchema = { | ||
factory: context => new Todo(), | ||
factory: (context) => new Todo(), | ||
extends: ModelSchema, | ||
props: { | ||
modelfield: PropSchema | ||
} | ||
} | ||
modelfield: PropSchema, | ||
}, | ||
}; | ||
``` | ||
@@ -295,3 +300,3 @@ | ||
```typings | ||
```typescript | ||
{ | ||
@@ -312,5 +317,5 @@ serializer: (sourcePropertyValue: any) => jsonValue, | ||
2. third argument of the lookup callback of `ref` prop schema's (see below) | ||
3. third argument of the `deserializer` of a custom propSchema | ||
3. second argument of the `deserializer` of a custom propSchema | ||
When deserializing a model elememt / property, the following fields are available on the context object: | ||
When deserializing a model element / property, the following fields are available on the context object: | ||
@@ -334,3 +339,3 @@ - `json`: Returns the complete current json object that is being deserialized | ||
const myHandler = { | ||
beforeDeserialize: function( | ||
beforeDeserialize: function ( | ||
callback, | ||
@@ -344,10 +349,10 @@ jsonValue, | ||
if (typeof jsonValue === "string") { | ||
callback(null, jsonValue) | ||
callback(null, jsonValue); | ||
} else if (typeof jsonValue === "number") { | ||
callback(null, jsonValue.toString()) | ||
callback(null, jsonValue.toString()); | ||
} else { | ||
callback(new Error("something went wrong before deserialization")) | ||
callback(new Error("something went wrong before deserialization")); | ||
} | ||
}, | ||
afterDeserialize: function( | ||
afterDeserialize: function ( | ||
callback, | ||
@@ -363,14 +368,14 @@ error, | ||
if (!error && newValue !== "needs change") { | ||
callback(null, newValue) | ||
callback(null, newValue); | ||
} else if (!error && newValue === "needs change") { | ||
callback(new Error(), "changed value") | ||
callback(new Error(), "changed value"); | ||
} else { | ||
callback(error) | ||
callback(error); | ||
} | ||
} | ||
} | ||
}, | ||
}; | ||
class MyData { | ||
@serializable(primitive(myHandler)) | ||
mySimpleField | ||
mySimpleField; | ||
} | ||
@@ -381,680 +386,41 @@ ``` | ||
<!-- START API AUTOGEN --> | ||
<!-- THIS SECTION WAS AUTOGENERATED BY gendoc.tsx! DO NOT EDIT! --> | ||
API | ||
--- | ||
# Inheritance | ||
### _interface_ `ModelSchema`<T><sub><a href="src/api/types.ts#L65">src</a></sub> | ||
When defining schemas or serializing Inheritance is automatically handled. When deserializing, to | ||
deserialize into the right type based on a discriminator use the `@subSchema` decorator. | ||
#### property `targetClass`?: [Clazz](#type-clazzt----src)<any> | ||
#### property `factory`: (_context_: [Context](typedoc-id-undefined)) => T | ||
#### property `props`: [Props](#type-propst----src)<T> | ||
#### property `extends`?: [ModelSchema](#interface-modelschematsrc)<any> | ||
### _interface_ `PropSchema`<sub><a href="src/api/types.ts#L22">src</a></sub> | ||
#### property `serializer`: [PropSerializer](#type-propserializer--sourcepropertyvalue-any-key-string--number--symbol-sourceobject-any--any--typeof-skip-src) | ||
#### property `deserializer`: [PropDeserializer](#type-propdeserializer--jsonvalue-any-callback-err-any-targetpropertyvalue-any--typeof-skip--void-context-context-currentpropertyvalue-any--void-src) | ||
#### property `beforeDeserialize`?: [BeforeDeserializeFunc](#type-beforedeserializefunc--callback-err-any-value-any--void-jsonvalue-any-jsonparentvalue-any-propnameorindex-string--number-context-context-propdef-propschema--void-src) | ||
#### 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) | ||
#### property `pattern`?: undefined | { test: (_propName_: string) => boolean } | ||
Filter properties to which this schema applies. Used with `ModelSchema.props["*"]`. | ||
#### property `jsonname`?: undefined | string | ||
#### property `identifier`?: undefined | true | ||
#### property `paramNumber`?: undefined | number | ||
### _type_ `AdditionalPropArgs` = [Pick](typedoc-id-undefined)<[PropSchema](#interface-propschemasrc), `"beforeDeserialize"` | `"afterDeserialize"` | `"pattern"`> <sub><a href="src/api/types.ts#L7">src</a></sub> | ||
Can be passed to function which create `PropSchema`s to set additional properties. | ||
### _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> | ||
### _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> | ||
### _type_ `Clazz`<T> = { } <sub><a href="src/api/types.ts#L72">src</a></sub> | ||
### _type_ `ClazzOrModelSchema`<T> = [ModelSchema](#interface-modelschematsrc)<T> | [Clazz](#type-clazzt----src)<T> <sub><a href="src/api/types.ts#L73">src</a></sub> | ||
### _type_ `PropDef` = [PropSchema](#interface-propschemasrc) | boolean | undefined <sub><a href="src/api/types.ts#L63">src</a></sub> | ||
### _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> | ||
### _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> | ||
### _type_ `Props`<T> = { } <sub><a href="src/api/types.ts#L60">src</a></sub> | ||
true is shorthand for `primitive().` false/undefined will be ignored | ||
### _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> | ||
### _type_ `RegisterFunction` = (_id_: any, _object_: any, _context_: [Context](typedoc-id-undefined)) => void <sub><a href="src/api/types.ts#L80">src</a></sub> | ||
### _const_ `SKIP`<sub><a href="src/constants.ts#L36">src</a></sub> | ||
If you want to skip serialization or deserialization, you can use SKIP. | ||
```ts | ||
const schema = createSimpleSchema({ | ||
a: custom( | ||
() => SKIP, | ||
v => v, | ||
), | ||
}) | ||
serialize(s, { a: 4 }) // {} | ||
deserialize(s, { "a": 4 }) // { a: 4 } | ||
``` | ||
```ts | ||
// 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) | ||
} | ||
} | ||
``` | ||
### _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> | ||
Alias indicates that this model property should be named differently in the generated json. Alias should be the outermost propschema. | ||
```ts | ||
createModelSchema(Todo, { | ||
title: alias('task', primitive()), | ||
}) | ||
serialize(new Todo('test')) // { "task": "test" } | ||
``` | ||
### _function_ `cancelDeserialize`<T>(_instance_: T): void <sub><a href="src/core/cancelDeserialize.ts#L11">src</a></sub> | ||
Cancels an asynchronous deserialization or update operation for the specified target object. | ||
### _function_ `createModelSchema`<T>(_clazz_: [Clazz](#type-clazzt----src)<T>, _props_: [Props](#type-propst----src), _factory_?: undefined | ((_context_: [Context](typedoc-id-undefined)) => T)): [ModelSchema](#interface-modelschematsrc)<T> <sub><a href="src/api/createModelSchema.ts#L31">src</a></sub> | ||
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). | ||
```ts | ||
function Todo(title, done) { | ||
this.title = title | ||
this.done = done | ||
} | ||
createModelSchema(Todo, { | ||
title: true, | ||
done: true, | ||
}) | ||
const json = serialize(new Todo('Test', false)) | ||
const todo = deserialize(Todo, json) | ||
``` | ||
### _function_ `createSimpleSchema`<T>(_props_: [Props](#type-propst----src)): [ModelSchema](#interface-modelschematsrc)<T> <sub><a href="src/api/createSimpleSchema.ts#L19">src</a></sub> | ||
Creates a model schema that (de)serializes from / to plain javascript objects. Its factory method is: `() => ({})` | ||
```ts | ||
const todoSchema = createSimpleSchema({ | ||
title: true, | ||
done: true, | ||
}) | ||
const json = serialize(todoSchema, { title: 'Test', done: false }) | ||
const todo = deserialize(todoSchema, json) | ||
``` | ||
### _function_ `custom`(_serializer_: [PropSerializer](#type-propserializer--sourcepropertyvalue-any-key-string--number--symbol-sourceobject-any--any--typeof-skip-src), _deserializer_: (_jsonValue_: any, _context_: [Context](typedoc-id-undefined), _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#L64">src</a></sub> | ||
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)). | ||
```ts | ||
const schemaDefault = createSimpleSchema({ | ||
a: custom( | ||
v => v + 2, | ||
v => v - 2 | ||
) | ||
}) | ||
serialize(schemaDefault, { a: 4 }) // { "a": 6 } | ||
deserialize(schemaDefault, { "a": 6 }) // { a: 4 } | ||
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 } | ||
} | ||
``` | ||
### _function_ `custom`(_serializer_: [PropSerializer](#type-propserializer--sourcepropertyvalue-any-key-string--number--symbol-sourceobject-any--any--typeof-skip-src), _deserializer_: (_jsonValue_: any, _context_: [Context](typedoc-id-undefined), _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#L74">src</a></sub> | ||
### _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> | ||
Similar to primitive, serializes instances of Date objects | ||
### _function_ `deserialize`<T>(_modelschema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)<T>, _jsonArray_: any\[\], _callback_?: undefined | ((_err_: any, _result_: T\[\]) => void), _customArgs_?: any): T\[\] <sub><a href="src/core/deserialize.ts#L76">src</a></sub> | ||
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) | ||
### _function_ `deserialize`<T>(_modelschema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)<T>, _json_: any, _callback_?: undefined | ((_err_: any, _result_: T) => void), _customArgs_?: any): T <sub><a href="src/core/deserialize.ts#L82">src</a></sub> | ||
### _function_ `getDefaultModelSchema`<T>(_thing_: any): [ModelSchema](#interface-modelschematsrc)<T> | undefined <sub><a href="src/api/getDefaultModelSchema.ts#L8">src</a></sub> | ||
Returns the standard model schema associated with a class / constructor function | ||
### _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> | ||
### _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> | ||
List indicates that this property contains a list of things. Accepts a sub model schema to serialize the contents | ||
```ts | ||
class SubTask {} | ||
class Task {} | ||
class Todo {} | ||
createModelSchema(SubTask, { | ||
title: true, | ||
}) | ||
createModelSchema(Todo, { | ||
title: true, | ||
subTask: list(object(SubTask)), | ||
}) | ||
const todo = deserialize(Todo, { | ||
title: 'Task', | ||
subTask: [ | ||
{ | ||
title: 'Sub task 1', | ||
}, | ||
], | ||
}) | ||
``` | ||
### _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> | ||
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_ `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> | ||
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. | ||
### _function_ `object`(_modelSchema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)<any>, _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/object.ts#L35">src</a></sub> | ||
`object` indicates that this property contains an object that needs to be (de)serialized using its own model schema. | ||
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. | ||
```ts | ||
class SubTask {} | ||
class Todo {} | ||
createModelSchema(SubTask, { | ||
title: true, | ||
}) | ||
createModelSchema(Todo, { | ||
title: true, | ||
subTask: object(SubTask), | ||
}) | ||
const todo = deserialize(Todo, { | ||
title: 'Task', | ||
subTask: { | ||
title: 'Sub task', | ||
}, | ||
}) | ||
``` | ||
### _function_ `optional`(_propSchema_?: [PropSchema](#interface-propschemasrc) | boolean): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/optional.ts#L23">src</a></sub> | ||
Optional indicates that this model property shouldn't be serialized if it isn't present. | ||
Note that if we use `optional` together with another prop schema such as `custom`, the prop schema for `custom` will be applied first and the result of that serialization will be used to feed into `optional`. As such, it might be better to just use `custom` with `SKIP` to achieve the same goal. | ||
```ts | ||
createModelSchema(Todo, { | ||
title: optional(primitive()), | ||
user: optional(custom(value => value?.name, () => SKIP)) | ||
}) | ||
serialize(new Todo()) // {} | ||
``` | ||
### _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> | ||
Indicates that this field contains a primitive value (or Date) which should be serialized literally to json. | ||
```ts | ||
createModelSchema(Todo, { | ||
title: primitive(), | ||
}) | ||
serialize(new Todo('test')) // { "title": "test" } | ||
``` | ||
### _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> | ||
Indicates that this field is only need to putted in the serialized json or deserialized instance, without any transformations. Stay with its original value | ||
```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)<any>, _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 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. | ||
```ts | ||
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) | ||
} | ||
) | ||
``` | ||
### _function_ `reference`(_modelSchema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)<any>, _additionalArgs_?: [AdditionalPropArgs](#type-additionalpropargs--pickpropschema-beforedeserialize--afterdeserialize--pattern-src)): [PropSchema](#interface-propschemasrc) <sub><a href="src/types/reference.ts#L87">src</a></sub> | ||
### _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> | ||
### _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> | ||
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. | ||
```ts | ||
class Todo { | ||
@serializable(primitive()) | ||
title // shorthand for primitves | ||
@serializable | ||
done | ||
id: string; | ||
constructor(title, done) { | ||
this.title = title | ||
this.done = done | ||
} | ||
} | ||
const json = serialize(new Todo('Test', false)) | ||
const todo = deserialize(Todo, json) | ||
``` | ||
### _function_ `serializable`(_target_: any, _key_: string, _baseDescriptor_?: [PropertyDescriptor](typedoc-id-undefined)): void <sub><a href="src/api/serializable.ts#L102">src</a></sub> | ||
### _function_ `serialize`<T>(_modelSchema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)<T>, _instance_: T): any <sub><a href="src/core/serialize.ts#L15">src</a></sub> | ||
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. | ||
### _function_ `serialize`<T>(_instance_: T): any <sub><a href="src/core/serialize.ts#L16">src</a></sub> | ||
### _function_ `serializeAll`<T>(_clazz_: [Clazz](#type-clazzt----src)<T>): [Clazz](#type-clazzt----src)<T> <sub><a href="src/core/serializeAll.ts#L43">src</a></sub> | ||
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. | ||
```ts | ||
@serializeAll | ||
class Store { | ||
a = 3 | ||
b | ||
} | ||
const store = new Store() | ||
store.c = 5 | ||
store.d = {} | ||
serialize(store) // { "c": 5 } | ||
``` | ||
```ts | ||
class DataType { | ||
@serializable | ||
x | ||
@serializable | ||
y | ||
text: string; | ||
} | ||
@serializeAll(/^[a-z]$/, DataType) | ||
class ComplexStore { | ||
} | ||
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 } } | ||
``` | ||
### _function_ `serializeAll`(_pattern_: [RegExp](typedoc-id-undefined), _propertyType_: [PropDef](#type-propdef--propschema--boolean--undefined-src) | [Clazz](#type-clazzt----src)<any>): (_clazz_: [Clazz](#type-clazzt----src)<any>) => [Clazz](#type-clazzt----src)<any> <sub><a href="src/core/serializeAll.ts#L44">src</a></sub> | ||
### _function_ `setDefaultModelSchema`<T>(_clazz_: [Clazz](#type-clazzt----src)<T>, _modelSchema_: [ModelSchema](#interface-modelschematsrc)<T>): [ModelSchema](#interface-modelschematsrc)<T> <sub><a href="src/api/setDefaultModelSchema.ts#L16">src</a></sub> | ||
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. | ||
### _function_ `update`<T>(_modelschema_: [ClazzOrModelSchema](#type-clazzormodelschemat--modelschemat--clazzt-src)<T>, _instance_: T, _json_: any, _callback_?: undefined | ((_err_: any, _result_: T) => void), _customArgs_?: any): void <sub><a href="src/core/update.ts#L23">src</a></sub> | ||
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. | ||
### _function_ `update`<T>(_instance_: T, _json_: any, _callback_?: undefined | ((_err_: any, _result_: T) => void), _customArgs_?: any): void <sub><a href="src/core/update.ts#L30">src</a></sub><!-- END API AUTOGEN --> | ||
# Recipes and examples | ||
## 1. Plain schema with plain objects | ||
```javascript | ||
const todoSchema = { | ||
factory: () => {}, | ||
props: { | ||
task: primitive(), | ||
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: [] }, | ||
(err, todo) => { | ||
console.log("finished loading todos") | ||
} | ||
) | ||
const todoJson = serialize(todoSchema, todo) | ||
``` | ||
## 2. Create schema and store it on constructor | ||
```javascript | ||
function Todo(parentTodo) { | ||
this.parent = parentTodo // available in subTasks | ||
} | ||
const todoSchema = { | ||
factory: context => new Todo(context.parent), | ||
props: { | ||
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) | ||
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") | ||
} | ||
) | ||
const todoJson = serialize(todo) // no need to pass schema explicitly | ||
``` | ||
## 3. Create schema for simple argumentless constructors | ||
```javascript | ||
function Todo() {} | ||
// creates a default factory, () => new Todo(), stores the schema as default model schema | ||
createModelSchema(Todo, { | ||
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") | ||
) | ||
const todoJson = serialize(todo) // no need to pass schema explicitly | ||
``` | ||
## 4. Create schema for simple argumentless constructors using decorators | ||
```javascript | ||
class Todo { | ||
@serializable(primitive()) | ||
task = "Grab coffee" | ||
@serializable(reference("_userId", UserStore.findUserById)) | ||
owner = null | ||
@serializable(alias("children", list(object(todoSchema)))) | ||
subTasks = [] | ||
} | ||
// note that (de)serialize also accepts lists | ||
const todos = deserialize( | ||
Todo, | ||
[ | ||
{ | ||
task: "grab coffee", | ||
owner: 17, | ||
children: [] | ||
} | ||
], | ||
(err, todos) => console.log("finished loading todos") | ||
) | ||
const todoJson = serialize(todos) | ||
``` | ||
## 5. use custom factory methods to reuse model object instances | ||
```javascript | ||
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()) | ||
} | ||
``` | ||
## 6. use custom arguments to inject stores to models | ||
This pattern is useful to avoid singletons but allow to pass context specific data to constructors. This can be done by passing custom data to `deserialize` / `update` as last argument, | ||
which will be available as `context.args` on all places where context is available: | ||
```javascript | ||
class User { | ||
constructor(someStore) { | ||
// User needs access to someStore, for whatever reason | ||
} | ||
} | ||
// create model schema with custom factory | ||
createModelSchema(User, { username: true }, context => { | ||
return new User(context.args.someStore) | ||
}) | ||
// don't want singletons! | ||
const someStore = new SomeStore() | ||
// provide somestore through context of the deserialization process | ||
const user = deserialize(User, someJson, (err, user) => console.log("done"), { | ||
someStore: someStore | ||
}) | ||
``` | ||
## 7. Putting it together: MobX store with plain objects, classes and internal references | ||
```javascript | ||
// models.js: | ||
import { observable, computed } from "mobx" | ||
import { serializable, identifier } from "serializr" | ||
function randomId() { | ||
return Math.floor(Math.random() * 100000) | ||
} | ||
export class Box { | ||
@serializable(identifier()) | ||
id = randomId() | ||
@subSchema("picture") | ||
class PictureTodo extends Todo { | ||
@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 | ||
} | ||
@serializable | ||
@computed | ||
get area() { | ||
return this.x * this.y | ||
} | ||
pictureUrl: string; | ||
} | ||
export class Arrow { | ||
@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" | ||
// The store that holds our domain: boxes and arrows | ||
const store = observable({ | ||
boxes: [], | ||
arrows: [], | ||
selection: null | ||
}) | ||
// Model of the store itself | ||
const storeModel = createSimpleSchema({ | ||
boxes: list(object(Box)), | ||
arrows: list(object(Arrow)), | ||
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)) | ||
// Or it can be an raw javascript object with the right properties | ||
store.arrows.push({ | ||
id: randomId(), | ||
from: store.boxes[0], | ||
to: store.boxes[1] | ||
}) | ||
// (de) serialize functions | ||
function serializeState(store) { | ||
return serialize(storeModel, store) | ||
} | ||
function deserializeState(store, json) { | ||
transaction(() => { | ||
update(storeModel, store, json) | ||
const ser = serialize( | ||
Object.assign(new PictureTodo(), { | ||
id: "pic1", | ||
text: "Lorem Ipsum", | ||
pictureUrl: "foobar", | ||
}) | ||
} | ||
// Print ... out for debugging | ||
console.dir(serializeState(store), { depth: 10, colors: true }) | ||
); | ||
// ser now holds an object like the following result | ||
// { | ||
// id: "pic1", | ||
// _type: "picture" | ||
// text: "Lorem Ipsum", | ||
// pictureUrl:"foobar", | ||
// } | ||
const deser = deserialize(Todo, ser); | ||
console.log(deser instanceof PictureTodo); // true | ||
``` | ||
--- | ||
See https://serializr.github.io/serializr/docs/functions/subSchema.html for more information. | ||
@@ -1061,0 +427,0 @@ # Future ideas |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
377242
27
41
3794
0
415