From 78a9f2e32df71b56f1dfc6e3c2fcc497d85a0e4d Mon Sep 17 00:00:00 2001 From: Nikhil Fadnis Date: Sat, 2 Jun 2018 10:24:34 +0530 Subject: [PATCH] Cherry-pick Lodash modules Smaller build! --- lib/JSONAPISerializer.js | 82 ++++++++++++++++++++++++---------------- 1 file changed, 49 insertions(+), 33 deletions(-) diff --git a/lib/JSONAPISerializer.js b/lib/JSONAPISerializer.js index c0fd122..d511153 100644 --- a/lib/JSONAPISerializer.js +++ b/lib/JSONAPISerializer.js @@ -1,6 +1,22 @@ 'use strict'; -const _ = require('lodash'); +const _get = require('lodash/get'); +const _set = require('lodash/set'); +const _pick = require('lodash/pick'); +const _difference = require('lodash/difference'); +const _isPlainObject = require('lodash/isPlainObject'); +const _find = require('lodash/find'); +const _isEmpty = require('lodash/isEmpty'); +const _uniqWith = require('lodash/uniqWith'); +const _isEqual = require('lodash/isEqual'); +const _isObjectLike = require('lodash/isObjectLike'); +const _omitBy = require('lodash/omitBy'); +const _isUndefined = require('lodash/isUndefined'); +const _transform = require('lodash/transform'); +const _snakeCase = require('lodash/snakeCase'); +const _kebabCase = require('lodash/kebabCase'); +const _camelCase = require('lodash/camelCase'); + const joi = require('joi'); const intoStream = require('into-stream'); const through = require('through2'); @@ -107,7 +123,7 @@ module.exports = class JSONAPISerializer { schema = schema || 'default'; options = Object.assign({}, this.opts, options); - _.set(this.schemas, [type, schema].join('.'), this.validateOptions(options)); + _set(this.schemas, [type, schema].join('.'), this.validateOptions(options)); } /** @@ -125,7 +141,7 @@ module.exports = class JSONAPISerializer { serialize(type, data, schema, extraData) { // Support optional arguments (schema) if (arguments.length === 3) { - if (_.isPlainObject(schema)) { + if (_isPlainObject(schema)) { extraData = schema; schema = 'default'; } @@ -138,7 +154,7 @@ module.exports = class JSONAPISerializer { let serializedData; let options; - if (_.isPlainObject(type)) { // Serialize data with the dynamic type + if (_isPlainObject(type)) { // Serialize data with the dynamic type options = this.validateDynamicTypeOptions(type); // Override top level data serializedData = this.serializeMixedData(options, data, included, extraData); @@ -180,7 +196,7 @@ module.exports = class JSONAPISerializer { serializeAsync(type, data, schema, extraData) { // Support optional arguments (schema) if (arguments.length === 3) { - if (_.isPlainObject(schema)) { + if (_isPlainObject(schema)) { extraData = schema; schema = 'default'; } @@ -191,7 +207,7 @@ module.exports = class JSONAPISerializer { const included = []; const isDataArray = Array.isArray(data); - const isDynamicType = _.isPlainObject(type); + const isDynamicType = _isPlainObject(type); let serializedData; let serializedIncludes; let options; @@ -268,7 +284,7 @@ module.exports = class JSONAPISerializer { deserialize(type, data, schema) { schema = schema || 'default'; - if (!_.isPlainObject(type)) { + if (!_isPlainObject(type)) { if (!this.schemas[type]) { throw new Error(`No type registered for ${type}`); } @@ -306,7 +322,7 @@ module.exports = class JSONAPISerializer { deserializeAsync(type, data, schema) { schema = schema || 'default'; - if (!_.isPlainObject(type)) { + if (!_isPlainObject(type)) { if (!this.schemas[type]) { throw new Error(`No type registered for ${type}`); } @@ -348,8 +364,8 @@ module.exports = class JSONAPISerializer { * @return {Object} deserialized data. */ deserializeResource(type, data, schema, included) { - if (_.isPlainObject(type)) { - type = (typeof type.type === 'function') ? type.type(data) : _.get(data, type.type); + if (_isPlainObject(type)) { + type = (typeof type.type === 'function') ? type.type(data) : _get(data, type.type); if (!type) { throw new Error(`No type can be resolved from data: ${JSON.stringify(data)}`); @@ -370,12 +386,12 @@ module.exports = class JSONAPISerializer { // whitelistOnDeserialize option if (resourceOpts.whitelistOnDeserialize.length > 0) { - data.attributes = _.pick(data.attributes, resourceOpts.whitelistOnDeserialize); + data.attributes = _pick(data.attributes, resourceOpts.whitelistOnDeserialize); } // Remove unwanted keys (blacklistOnDeserialize option) if (resourceOpts.blacklistOnDeserialize.length > 0) { - data.attributes = _.pick(data.attributes, _.difference(Object.keys(data.attributes), resourceOpts.blacklistOnDeserialize)); + data.attributes = _pick(data.attributes, _difference(Object.keys(data.attributes), resourceOpts.blacklistOnDeserialize)); } Object.assign(deserializedData, data.attributes); @@ -394,15 +410,15 @@ module.exports = class JSONAPISerializer { if (relationship.data !== undefined) { if (Array.isArray(relationship.data)) { // Array data - _.set(deserializedData, relationshipKey, relationship.data.map(d => (included + _set(deserializedData, relationshipKey, relationship.data.map(d => (included ? this.deserializeIncluded(d.type, d.id, resourceOpts.relationships[relationshipProperty], included) : d.id))); } else if (relationship.data === null) { // null data - _.set(deserializedData, relationshipKey, null); + _set(deserializedData, relationshipKey, null); } else { // Object data - _.set(deserializedData, relationshipKey, included + _set(deserializedData, relationshipKey, included ? this.deserializeIncluded(relationship.data.type, relationship.data.id, resourceOpts.relationships[relationshipProperty], included) : relationship.data.id); } @@ -426,7 +442,7 @@ module.exports = class JSONAPISerializer { } deserializeIncluded(type, id, relationshipOpts, included) { - const includedResource = _.find(included, { + const includedResource = _find(included, { type, id, }); @@ -453,7 +469,7 @@ module.exports = class JSONAPISerializer { */ serializeData(type, data, options, included, extraData) { // Empty data - if (_.isEmpty(data)) { + if (_isEmpty(data)) { // Return [] or null return Array.isArray(data) ? data : null; } @@ -487,7 +503,7 @@ module.exports = class JSONAPISerializer { */ serializeMixedData(typeOption, data, included, extraData) { // Empty data - if (_.isEmpty(data)) { + if (_isEmpty(data)) { // Return [] or null return Array.isArray(data) ? data : null; } @@ -501,7 +517,7 @@ module.exports = class JSONAPISerializer { // Resolve type from data (can be a string or a function deriving a type-string from each data-item) const type = (typeof typeOption.type === 'function') ? typeOption.type(data) - : _.get(data, typeOption.type); + : _get(data, typeOption.type); if (!type) { throw new Error(`No type can be resolved from data: ${JSON.stringify(data)}`); @@ -524,7 +540,7 @@ module.exports = class JSONAPISerializer { * @return {Object[]} included. */ serializeIncluded(included) { - const serializedIncluded = _.uniqWith(included, _.isEqual); + const serializedIncluded = _uniqWith(included, _isEqual); return Object.keys(serializedIncluded).length > 0 ? serializedIncluded : undefined; } @@ -565,7 +581,7 @@ module.exports = class JSONAPISerializer { */ serializeAttributes(data, options) { if (options.whitelist.length > 0) { - data = _.pick(data, options.whitelist); + data = _pick(data, options.whitelist); } // Support alternativeKey options for relationships @@ -578,7 +594,7 @@ module.exports = class JSONAPISerializer { }); // Remove unwanted keys (id, blacklist, relationships, alternativeKeys) - let serializedAttributes = _.pick(data, _.difference(Object.keys(data), [options.id].concat(Object.keys(options.relationships), alternativeKeys, options.blacklist))); + let serializedAttributes = _pick(data, _difference(Object.keys(data), [options.id].concat(Object.keys(options.relationships), alternativeKeys, options.blacklist))); if (options.convertCase) { serializedAttributes = this._convertCase(serializedAttributes, options.convertCase); @@ -623,7 +639,7 @@ module.exports = class JSONAPISerializer { let serializeRelationship = { links: this.processOptionsValues(data, extraData, rOptions.links), meta: this.processOptionsValues(data, extraData, rOptions.meta), - data: this.serializeRelationship(rOptions.type, _.get(data, relationshipKey), this.schemas[rOptions.type][schema], included, extraData), + data: this.serializeRelationship(rOptions.type, _get(data, relationshipKey), this.schemas[rOptions.type][schema], included, extraData), }; // Avoid empty relationship object @@ -635,7 +651,7 @@ module.exports = class JSONAPISerializer { relationship = (options.convertCase) ? this._convertCase(relationship, options.convertCase) : relationship; - _.set(serializedRelationships, relationship, serializeRelationship); + _set(serializedRelationships, relationship, serializeRelationship); }); return Object.keys(serializedRelationships).length > 0 ? serializedRelationships : undefined; @@ -661,7 +677,7 @@ module.exports = class JSONAPISerializer { } // Empty relationship data - if (!(typeof rData === 'number') && _.isEmpty(rData)) { + if (!(typeof rData === 'number') && _isEmpty(rData)) { // Return [] or null return Array.isArray(rData) ? rData : null; } @@ -677,7 +693,7 @@ module.exports = class JSONAPISerializer { }; // Support for unpopulated relationships (an id, or array of ids) - if (!_.isObjectLike(rData)) { + if (!_isObjectLike(rData)) { serializedRelationship.id = rData.toString(); } else if (rData._bsontype && rData._bsontype === 'ObjectID') { // Support for unpopulated relationships (with mongoDB BSON ObjectId) @@ -722,7 +738,7 @@ module.exports = class JSONAPISerializer { } // Clean all undefined values - processedOptions = _.omitBy(processedOptions, _.isUndefined); + processedOptions = _omitBy(processedOptions, _isUndefined); return Object.keys(processedOptions).length > 0 ? processedOptions : undefined; } @@ -738,9 +754,9 @@ module.exports = class JSONAPISerializer { */ _convertCase(data, convertCaseOptions) { let converted; - if (Array.isArray(data) || _.isPlainObject(data)) { - converted = _.transform(data, (result, value, key) => { - if (Array.isArray(value) || _.isPlainObject(value)) { + if (Array.isArray(data) || _isPlainObject(data)) { + converted = _transform(data, (result, value, key) => { + if (Array.isArray(value) || _isPlainObject(value)) { result[this._convertCase(key, convertCaseOptions)] = this._convertCase(value, convertCaseOptions); } else { result[this._convertCase(key, convertCaseOptions)] = value; @@ -749,13 +765,13 @@ module.exports = class JSONAPISerializer { } else { switch (convertCaseOptions) { case 'snake_case': - converted = _.snakeCase(data); + converted = _snakeCase(data); break; case 'kebab-case': - converted = _.kebabCase(data); + converted = _kebabCase(data); break; case 'camelCase': - converted = _.camelCase(data); + converted = _camelCase(data); break; default: // Do nothing }