diff --git a/lib/JSONAPISerializer.js b/lib/JSONAPISerializer.js index eb80f8f..f5c37ce 100644 --- a/lib/JSONAPISerializer.js +++ b/lib/JSONAPISerializer.js @@ -19,7 +19,6 @@ const { validateOptions, validateDynamicTypeOptions, validateError } = require(' /** * JSONAPISerializer class. - * * @example * const JSONAPISerializer = require('json-api-serializer'); * @@ -45,10 +44,9 @@ module.exports = class JSONAPISerializer { /** * Register a resource with its type, schema name, and configuration options. - * * @function JSONAPISerializer#register * @param {string} type resource's type. - * @param {string|Options} [schema='default'] schema name. + * @param {string|Options} [schema] schema name. * @param {Options} [options] options. */ register(type, schema, options) { @@ -67,15 +65,14 @@ module.exports = class JSONAPISerializer { /** * Serialze input data to a JSON API compliant response. * Input data can be a simple object or an array of objects. - * * @see {@link http://jsonapi.org/format/#document-top-level} * @function JSONAPISerializer#serialize * @param {string|DynamicTypeOptions} type resource's type as string or a dynamic type options as object. * @param {object|object[]} data input data. - * @param {string|object} [schema='default'] resource's schema name. + * @param {string|object} [schema] resource's schema name. * @param {object} [extraData] additional data that can be used in topLevelMeta options. * @param {boolean} [excludeData] boolean that can be set to exclude the `data` property in serialized data. - * @param {object} [overrideSchemaOptions={}] additional schema options, a map of types with options to override. + * @param {object} [overrideSchemaOptions] additional schema options, a map of types with options to override. * @returns {object|object[]} serialized data. */ serialize(type, data, schema, extraData, excludeData, overrideSchemaOptions = {}) { @@ -104,7 +101,7 @@ module.exports = class JSONAPISerializer { data, included, extraData, - overrideSchemaOptions + overrideSchemaOptions, ); } else { dataProperty = this.serializeResource( @@ -113,7 +110,7 @@ module.exports = class JSONAPISerializer { options, included, extraData, - overrideSchemaOptions + overrideSchemaOptions, ); } @@ -129,15 +126,14 @@ module.exports = class JSONAPISerializer { /** * Asynchronously serialize input data to a JSON API compliant response. * Input data can be a simple object or an array of objects. - * * @see {@link http://jsonapi.org/format/#document-top-level} * @function JSONAPISerializer#serializeAsync * @param {string|DynamicTypeOptions} type resource's type as string or a dynamic type options as object. * @param {object|object[]} data input data. - * @param {string} [schema='default'] resource's schema name. + * @param {string} [schema] resource's schema name. * @param {object} [extraData] additional data that can be used in topLevelMeta options. * @param {boolean} [excludeData] boolean that can be set to exclude the `data` property in serialized data. - * @param {object} [overrideSchemaOptions={}] additional schema options, a map of types with options to override. + * @param {object} [overrideSchemaOptions] additional schema options, a map of types with options to override. * @returns {Promise} resolves with serialized data. */ serializeAsync(type, data, schema, extraData, excludeData, overrideSchemaOptions = {}) { @@ -164,7 +160,6 @@ module.exports = class JSONAPISerializer { return new Promise((resolve, reject) => { /** * Non-blocking serialization using the immediate queue. - * * @see {@link https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/} */ function next() { @@ -184,7 +179,7 @@ module.exports = class JSONAPISerializer { arrayData[i], included, extraData, - overrideSchemaOptions + overrideSchemaOptions, ) : that.serializeResource( type, @@ -192,7 +187,7 @@ module.exports = class JSONAPISerializer { options, included, extraData, - overrideSchemaOptions + overrideSchemaOptions, ); if (serializedItem !== null) { @@ -235,11 +230,10 @@ module.exports = class JSONAPISerializer { /** * Deserialize JSON API document data. * Input data can be a simple object or an array of objects. - * * @function JSONAPISerializer#deserialize * @param {string|DynamicTypeOptions} type resource's type as string or a dynamic type options as object. * @param {object} data JSON API input data. - * @param {string} [schema='default'] resource's schema name. + * @param {string} [schema] resource's schema name. * @returns {object} deserialized data. */ deserialize(type, data, schema) { @@ -262,7 +256,7 @@ module.exports = class JSONAPISerializer { if (data.data) { deserializedData = Array.isArray(data.data) ? data.data.map((resource) => - this.deserializeResource(type, resource, schema, data.included) + this.deserializeResource(type, resource, schema, data.included), ) : this.deserializeResource(type, data.data, schema, data.included); } @@ -273,11 +267,10 @@ module.exports = class JSONAPISerializer { /** * Asynchronously Deserialize JSON API document data. * Input data can be a simple object or an array of objects. - * * @function JSONAPISerializer#deserializeAsync * @param {string|DynamicTypeOptions} type resource's type as string or a dynamic type options as object. * @param {object} data JSON API input data. - * @param {string} [schema='default'] resource's schema name. + * @param {string} [schema] resource's schema name. * @returns {Promise} resolves with serialized data. */ deserializeAsync(type, data, schema) { @@ -304,7 +297,6 @@ module.exports = class JSONAPISerializer { return new Promise((resolve, reject) => { /** * Non-blocking deserialization using the immediate queue. - * * @see {@link https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/} */ function next() { @@ -319,7 +311,7 @@ module.exports = class JSONAPISerializer { type, arrayData[i], schema, - data.included + data.included, ); deserializedData.push(deserializedItem); @@ -340,9 +332,8 @@ module.exports = class JSONAPISerializer { /** * Serialize any error into a JSON API error document. * Input data can be: - * - An `Error` or an array of `Error` instances. - * - A JSON API error object or an array of JSON API error objects. - * + * - An `Error` or an array of `Error` instances. + * - A JSON API error object or an array of JSON API error objects. * @see {@link http://jsonapi.org/format/#errors} * @function JSONAPISerializer#serializeError * @param {Error|Error[]|object|object[]} error an Error, an array of Error, a JSON API error object, an array of JSON API error object. @@ -359,12 +350,11 @@ module.exports = class JSONAPISerializer { /** * Deserialize a single JSON API resource. * Input data must be a simple object. - * * @function JSONAPISerializer#deserializeResource * @private * @param {string|DynamicTypeOptions} type resource's type as string or an object with a dynamic type resolved from data. * @param {object} data JSON API resource data. - * @param {string} [schema='default'] resource's schema name. + * @param {string} [schema] resource's schema name. * @param {Map} included Included resources. * @param {string[]} lineage resource identifiers already deserialized to prevent circular references. * @returns {object} deserialized data. @@ -426,7 +416,7 @@ module.exports = class JSONAPISerializer { set( deserializedData, (relationshipOptions && relationshipOptions.alternativeKey) || relationshipKey, - null + null, ); } else { if ((relationshipOptions && relationshipOptions.alternativeKey) || !included) { @@ -435,7 +425,7 @@ module.exports = class JSONAPISerializer { (relationshipOptions && relationshipOptions.alternativeKey) || relationshipKey, Array.isArray(relationship.data) ? relationship.data.map((d) => deserializeFunction(d)) - : deserializeFunction(relationship.data) + : deserializeFunction(relationship.data), ); } @@ -457,7 +447,7 @@ module.exports = class JSONAPISerializer { relationshipOptions, included, lineageCopy, - deserializeFunction + deserializeFunction, ); }; @@ -503,7 +493,6 @@ module.exports = class JSONAPISerializer { /** * Deserialize included - * * @function JSONAPISerializer#deserializeIncluded * @private * @param {string} type resource's type as string or an object with a dynamic type resolved from data. @@ -516,7 +505,7 @@ module.exports = class JSONAPISerializer { */ deserializeIncluded(type, id, relationshipOpts, included, lineage, deserializeFunction) { const includedResource = included.find( - (resource) => resource.type === type && resource.id === id + (resource) => resource.type === type && resource.id === id, ); if (!includedResource) { @@ -532,13 +521,12 @@ module.exports = class JSONAPISerializer { includedResource, relationshipOpts.schema, included, - lineage + lineage, ); } /** * Serialize resource objects. - * * @see {@link http://jsonapi.org/format/#document-resource-objects} * @function JSONAPISerializer#serializeDocument * @private @@ -547,7 +535,7 @@ module.exports = class JSONAPISerializer { * @param {Options} options resource's configuration options. * @param {Map} [included] Included resources. * @param {object} [extraData] additional data. - * @param {object} [overrideSchemaOptions={}] additional schema options, a map of types with options to override. + * @param {object} [overrideSchemaOptions] additional schema options, a map of types with options to override. * @returns {object|object[]} serialized data. */ serializeResource(type, data, options, included, extraData, overrideSchemaOptions = {}) { @@ -558,7 +546,7 @@ module.exports = class JSONAPISerializer { if (Array.isArray(data)) { return data.map((d) => - this.serializeResource(type, d, options, included, extraData, overrideSchemaOptions) + this.serializeResource(type, d, options, included, extraData, overrideSchemaOptions), ); } @@ -575,7 +563,7 @@ module.exports = class JSONAPISerializer { options, included, extraData, - overrideSchemaOptions + overrideSchemaOptions, ), meta: this.processOptionsValues(data, extraData, options.meta), links: this.processOptionsValues(data, extraData, options.links), @@ -584,7 +572,6 @@ module.exports = class JSONAPISerializer { /** * Serialize mixed resource object with a dynamic type resolved from data - * * @see {@link http://jsonapi.org/format/#document-resource-objects} * @function JSONAPISerializer#serializeMixedResource * @private @@ -592,7 +579,7 @@ module.exports = class JSONAPISerializer { * @param {object|object[]} data input data. * @param {Map} [included] Included resources. * @param {object} [extraData] additional data. - * @param {object} [overrideSchemaOptions={}] additional schema options, a map of types with options to override. + * @param {object} [overrideSchemaOptions] additional schema options, a map of types with options to override. * @returns {object|object[]} serialized data. */ serializeMixedResource(typeOption, data, included, extraData, overrideSchemaOptions = {}) { @@ -603,7 +590,7 @@ module.exports = class JSONAPISerializer { if (Array.isArray(data)) { return data.map((d) => - this.serializeMixedResource(typeOption, d, included, extraData, overrideSchemaOptions) + this.serializeMixedResource(typeOption, d, included, extraData, overrideSchemaOptions), ); } @@ -626,7 +613,6 @@ module.exports = class JSONAPISerializer { /** * Serialize 'attributes' key of resource objects: an attributes object representing some of the resource's data. - * * @see {@link http://jsonapi.org/format/#document-resource-object-attributes} * @function JSONAPISerializer#serializeAttributes * @private @@ -665,7 +651,6 @@ module.exports = class JSONAPISerializer { /** * Serialize 'relationships' key of resource objects: a relationships object describing relationships between the resource and other JSON API resources. - * * @see {@link http://jsonapi.org/format/#document-resource-object-relationships} * @function JSONAPISerializer#serializeRelationships * @private @@ -673,7 +658,7 @@ module.exports = class JSONAPISerializer { * @param {Options} options resource's configuration options. * @param {Map} [included] Included resources. * @param {object} [extraData] additional data. - * @param {object} [overrideSchemaOptions={}] additional schema options, a map of types with options to override. + * @param {object} [overrideSchemaOptions] additional schema options, a map of types with options to override. * @returns {object} serialized relationships. */ serializeRelationships(data, options, included, extraData, overrideSchemaOptions = {}) { @@ -698,7 +683,7 @@ module.exports = class JSONAPISerializer { included, data, extraData, - overrideSchemaOptions + overrideSchemaOptions, ), }; @@ -721,7 +706,6 @@ module.exports = class JSONAPISerializer { /** * Serialize 'data' key of relationship's resource objects. - * * @see {@link http://jsonapi.org/format/#document-resource-object-linkage} * @function JSONAPISerializer#serializeRelationship * @private @@ -731,7 +715,7 @@ module.exports = class JSONAPISerializer { * @param {Map} [included] Included resources. * @param {object} [data] the entire resource's data. * @param {object} [extraData] additional data. - * @param {object} [overrideSchemaOptions={}] additional schema options, a map of types with options to override. + * @param {object} [overrideSchemaOptions] additional schema options, a map of types with options to override. * @returns {object|object[]} serialized relationship data. */ serializeRelationship( @@ -741,7 +725,7 @@ module.exports = class JSONAPISerializer { included, data, extraData, - overrideSchemaOptions = {} + overrideSchemaOptions = {}, ) { included = included || new Map(); const schema = rSchema || 'default'; @@ -765,8 +749,8 @@ module.exports = class JSONAPISerializer { included, data, extraData, - overrideSchemaOptions - ) + overrideSchemaOptions, + ), ); } @@ -804,7 +788,7 @@ module.exports = class JSONAPISerializer { rOptions, included, extraData, - overrideSchemaOptions + overrideSchemaOptions, ); serializedRelationship.id = serializedIncluded.id; @@ -837,7 +821,6 @@ module.exports = class JSONAPISerializer { /** * Process options values. * Allows options to be an object or a function with 1 or 2 arguments - * * @function JSONAPISerializer#processOptionsValues * @private * @param {object} data data passed to functions options. @@ -876,7 +859,6 @@ module.exports = class JSONAPISerializer { /** * Get the schema options for the given type and optional schema. - * * @function JSONAPISerializer#_getSchemaOptions * @private * @param {string|object} [type] the type to get schema options for. @@ -918,7 +900,6 @@ module.exports = class JSONAPISerializer { /** * Recursively convert object keys case - * * @function JSONAPISerializer#_convertCase * @private * @param {object|object[]|string} data to convert @@ -949,7 +930,7 @@ module.exports = class JSONAPISerializer { result[this._convertCase(key, convertCaseOptions)] = converted; return result; }, - {} + {}, ); } @@ -998,7 +979,7 @@ module.exports = class JSONAPISerializer { * @property {Function|object} [topLevelLinks] describes the top-level links * @property {Function|object} [topLevelMeta] describes the top-level meta * @property {Function|object} [meta] describes resource-level meta - * @property {object.} [relationships] an object defining some relationships + * @property {{[key: string]: RelationshipOptions}} [relationships] an object defining some relationships * @property {string[]} [blacklistOnDeserialize=[]] an array of blacklisted attributes. Default = [] * @property {string[]} [whitelistOnDeserialize=[]] an array of whitelisted attributes. Default = [] * @property {('kebab-case'|'snake_case'|'camelCase')} [convertCase] case conversion for serializing data diff --git a/lib/helpers.js b/lib/helpers.js index 0adb5c9..d2a4ea2 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -21,7 +21,7 @@ const set = (obj, path, value) => { ( a, c, - i // Iterate all of them except the last one + i, // Iterate all of them except the last one ) => Object(a[c]) === a[c] // Does the key exist and is its value an object? ? // Yes: then follow that path @@ -32,7 +32,7 @@ const set = (obj, path, value) => { Math.abs(path[i + 1]) >> 0 === +path[i + 1] ? [] // Yes: assign a new array object : {}), // No: assign a new plain object - obj + obj, )[path[path.length - 1]] = value; // Finally assign the value to the last key return obj; // Return the top-level object to allow chaining }; diff --git a/lib/validator.js b/lib/validator.js index 663a211..c5922e8 100644 --- a/lib/validator.js +++ b/lib/validator.js @@ -1,6 +1,5 @@ /** * Validate and apply default values to resource's configuration options. - * * @function validateOptions * @private * @param {object} options Configuration options. @@ -57,7 +56,7 @@ function validateOptions(options) { !['kebab-case', 'snake_case', 'camelCase'].includes(options.unconvertCase) ) throw new Error( - "option 'unconvertCase' must be one of 'kebab-case', 'snake_case', 'camelCase'" + "option 'unconvertCase' must be one of 'kebab-case', 'snake_case', 'camelCase'", ); if (options.beforeSerialize && typeof options.beforeSerialize !== 'function') @@ -109,7 +108,6 @@ function validateOptions(options) { /** * Validate and apply default values to the dynamic type object option. - * * @function validateDynamicTypeOptions * @private * @param {object} options dynamic type object option. @@ -145,7 +143,6 @@ function validateDynamicTypeOptions(options) { /** * Validate a JSON:API error object - * * @function validateError * @private * @throws Will throw an error if the argument is not an object @@ -164,9 +161,8 @@ function validateError(err) { * if present, contains valid members. From the JSON:API spec: * * links: a links object containing the following members: - * about: a link that leads to further details about this particular - * occurrence of the problem. - * + * about: a link that leads to further details about this particular + * occurrence of the problem. * @function isValidLink * @private * @see https://jsonapi.org/format/#error-objects @@ -201,13 +197,12 @@ function validateError(err) { * if present, contains valid members. From the JSON:API spec: * * source: an object containing references to the source of the error, - * optionally including any of the following members: - * pointer: a JSON Pointer [RFC6901] to the associated entity in the - * request document [e.g. "/data" for a primary data object, - * or "/data/attributes/title" for a specific attribute]. - * parameter: a string indicating which URI query parameter caused the - * error. - * + * optionally including any of the following members: + * pointer: a JSON Pointer [RFC6901] to the associated entity in the + * request document [e.g. "/data" for a primary data object, + * or "/data/attributes/title" for a specific attribute]. + * parameter: a string indicating which URI query parameter caused the + * error. * @function isValidSource * @private * @see https://jsonapi.org/format/#error-objects @@ -247,8 +242,7 @@ function validateError(err) { * the JSON:API spec: * * meta: a meta object containing non-standard meta-information about - * the error. - * + * the error. * @function isValidMeta * @private * @see https://jsonapi.org/format/#error-objects @@ -266,7 +260,6 @@ function validateError(err) { /** * Determines if the provided number is a valid HTTP status code. - * * @function isValidHttpStatusCode * @private * @see https://jsonapi.org/format/#error-objects @@ -301,8 +294,7 @@ function validateError(err) { * HTTP status code. From the JSON:API spec: * * status: the HTTP status code applicable to this problem, expressed - * as a string value. - * + * as a string value. * @function isValidStatus * @private * @see https://jsonapi.org/format/#error-objects diff --git a/test/unit/validator.test.js b/test/unit/validator.test.js index 60642f2..8818436 100644 --- a/test/unit/validator.test.js +++ b/test/unit/validator.test.js @@ -142,7 +142,7 @@ describe('validator', function () { }); }).to.throw( Error, - "option 'convertCase' must be one of 'kebab-case', 'snake_case', 'camelCase'" + "option 'convertCase' must be one of 'kebab-case', 'snake_case', 'camelCase'", ); done(); @@ -155,7 +155,7 @@ describe('validator', function () { }); }).to.throw( Error, - "option 'unconvertCase' must be one of 'kebab-case', 'snake_case', 'camelCase'" + "option 'unconvertCase' must be one of 'kebab-case', 'snake_case', 'camelCase'", ); done();