Skip to content

Commit

Permalink
Merge 6ae5bcc into 8a6e987
Browse files Browse the repository at this point in the history
  • Loading branch information
ablankenship10 committed Apr 20, 2020
2 parents 8a6e987 + 6ae5bcc commit 9c472b1
Show file tree
Hide file tree
Showing 4 changed files with 381 additions and 0 deletions.
5 changes: 5 additions & 0 deletions lib/Document.js
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,11 @@ function DocumentCarrier(model) {
return this[internalProperties].originalSettings.type === "fromDynamo" ? this[internalProperties].originalObject : null;
};

// Serializer
Document.prototype.serialize = function(...args) {
return model.serializer._serialize(this, ...args);
};

Document.Model = model;

return Document;
Expand Down
7 changes: 7 additions & 0 deletions lib/Model/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const ddb = require("../aws/ddb/internal");
const Internal = require("../Internal");
const DocumentRetriever = require("../DocumentRetriever");
const defaults = require("./defaults");
const Serializer = require("../Serializer");

// Model represents one DynamoDB table
class Model {
Expand Down Expand Up @@ -76,6 +77,7 @@ class Model {
}, Promise.resolve());
setupFlowPromise.then(() => this.ready = true).then(() => {this.pendingTasks.forEach((task) => task()); this.pendingTasks = [];});

this.serializer = new Serializer();
this.Document = Document(this);
const returnObject = this.Document;
returnObject.table = {
Expand Down Expand Up @@ -703,4 +705,9 @@ Model.prototype.methods = {
"document": customMethodFunctions("document")
};

// Serializer
Model.prototype.serializeMany = function(...args){
return this.serializer._serializeMany.apply(this, args);
};

module.exports = Model;
118 changes: 118 additions & 0 deletions lib/Serializer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
class Serializer {
constructor() {
this._serializers = {_default: _defaultSerializer};
this._defaultSerializer = "_default";
}

add(name, options) {
validateName(name);
validateOptions(options);
this._serializers[name] = options;
}

setDefault(name) {
validateName(name);
if (Object.prototype.hasOwnProperty.call(this._serializers, name)) {
this._defaultSerializer = name;
}
}

remove(name) {
validateName(name);
if (Object.prototype.hasOwnProperty.call(this._serializers, name)) {
delete this._serializers[name];
}
if (this._defaultSerializer === name) {
this._defaultSerializer = "_default";
}
}

_serializeMany(documentsArray = [], nameOrOptions) {
documentsArray = cleanAndValidateDocumentsArray(documentsArray);
return documentsArray.map(doc => doc.serialize(nameOrOptions));
}

_serialize(document, nameOrOptions = this._defaultSerializer) {
const inputType = typeof nameOrOptions;
let isArray = Array.isArray(nameOrOptions);
let options;

if (inputType === "string") {
options = this._serializers[nameOrOptions];
} else if (isArray || inputType === "object") {
options = nameOrOptions;
}

try {
validateOptions(options);
isArray = Array.isArray(options);
if (isArray) {
return includeHandler(document, options, {});
}

let serialized = {};
if (options.include) {
serialized = includeHandler(document, options.include, serialized);
}
if (options.exclude) {
if (!options.include) {
serialized = {...document};
}
serialized = excludeHandler(document, options.exclude, serialized);
}
if (options.modify && typeof options.modify === "function") {
if (!options.include && !options.exclude) {
serialized = {...document};
}
serialized = options.modify(serialized, document);
}
return serialized;
} catch (error) {
// Failing quietly and defaulting to dumping the whole object may not be safest idea, lest we expose sensitive data.
return {};
}
}
}

const includeHandler = (document, includeRules, serialized) =>
includeRules.reduce((_serialized, key) => {
if (Object.prototype.hasOwnProperty.call(document, key)) {
_serialized[key] = document[key];
}
return _serialized;
}, serialized);

const excludeHandler = (document, excludeRules, serialized) =>
excludeRules.reduce((_serialized, key) => {
if (Object.prototype.hasOwnProperty.call(_serialized, key)) {
delete _serialized[key];
}
return _serialized;
}, serialized);

const validateName = name => {
if (!name || typeof name !== "string") {
throw new Error("Field name is required and should be of type string");
}
};

const validateOptions = options => {
if (!options || !(Array.isArray(options) || typeof options === "object")) {
throw new Error("Field options is required and should be an object or array");
}
};

const cleanAndValidateDocumentsArray = documentsArray => {
if (!documentsArray || !Array.isArray(documentsArray)) {
throw new Error("documentsArray must be an array of document objects");
}
return documentsArray.filter(doc => typeof doc.serialize === "function");
};

const _defaultSerializer = {
modify: (s, o) => {
return {...o};
}
};

module.exports = Serializer;

0 comments on commit 9c472b1

Please sign in to comment.