From 0c608e3cfba700a6f01f6a554b6fdfd79fefb27a Mon Sep 17 00:00:00 2001 From: Nick Hilton Date: Mon, 15 Sep 2025 14:50:31 -0400 Subject: [PATCH] Improve join time of included fields by using a map instead of a Array.find --- src/deserializer.ts | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/deserializer.ts b/src/deserializer.ts index dec27a1..ca02cf5 100644 --- a/src/deserializer.ts +++ b/src/deserializer.ts @@ -2,6 +2,7 @@ import { AttributesObject, DocumentObject, ExistingResourceObject, Options, Reso import { caseTypes, changeCase } from './utils' type IncludedCache = Record> +type IncludedMap = Record> /** * Deserialize a JSON:API response @@ -18,17 +19,22 @@ export function deserialize( } const included = response.included || [] + const includedMap: IncludedMap = {} + for (const include of included) { + includedMap[include.type] ??= {} + includedMap[include.type][include.id] = include + } return Array.isArray(response.data) ? response.data.map((data) => { - return parseJsonApiSimpleResourceData(data, included, options, false, {}) + return parseJsonApiSimpleResourceData(data, includedMap, options, false, {}) }) - : parseJsonApiSimpleResourceData(response.data, included, options, false, {}) + : parseJsonApiSimpleResourceData(response.data, includedMap, options, false, {}) } function parseJsonApiSimpleResourceData( data: ResourceObject, - included: ExistingResourceObject[], + includedMap: IncludedMap, options: Options, useCache: boolean, includedCache: IncludedCache, @@ -77,11 +83,11 @@ function parseJsonApiSimpleResourceData( if (Array.isArray(relationReference.data)) { resource[casedRelationName] = relationReference.data.map((relationData) => { - return findJsonApiIncluded(included, includedCache, relationData.type, relationData.id, options) + return findJsonApiIncluded(includedMap, includedCache, relationData.type, relationData.id, options) }) } else if (relationReference && relationReference.data) { const relationResource = findJsonApiIncluded, TExtraOptions>( - included, + includedMap, includedCache, relationReference.data.type, relationReference.data.id, @@ -102,24 +108,24 @@ function parseJsonApiSimpleResourceData( /** * - * @param included + * @param includedMap * @param includedCache * @param type * @param id * @param options */ function findJsonApiIncluded( - included: ExistingResourceObject[], + includedMap: IncludedMap, includedCache: IncludedCache, type: string, id: string, options: Options, ): TEntity { - const foundResource = included.find((item) => item.type === type && item.id === id) + const foundResource = includedMap[type]?.[id] if (!foundResource) { return { id } as unknown as TEntity } - return parseJsonApiSimpleResourceData(foundResource, included, options, true, includedCache) + return parseJsonApiSimpleResourceData(foundResource, includedMap, options, true, includedCache) }