From aa95e0c254bcd719565afac5c1b85f3158f6b1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20Feij=C3=B3=20de=20Almeida=20Pereira=20Lima?= Date: Fri, 29 Sep 2023 19:03:25 -0300 Subject: [PATCH 1/2] docs: commenting complex unique name validation logic --- src/menus/entities/subscribers/menu.subscriber.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/menus/entities/subscribers/menu.subscriber.ts b/src/menus/entities/subscribers/menu.subscriber.ts index 57547a0..4a6d1e4 100644 --- a/src/menus/entities/subscribers/menu.subscriber.ts +++ b/src/menus/entities/subscribers/menu.subscriber.ts @@ -210,8 +210,13 @@ export class MenuSubscriber implements EntitySubscriberInterface { (m2) => m2.name === m.name && m2.id !== m.id, ); return ( + // Filter out meta (m) if NOT updating name !!m.name && + // Filter out meta (m) if name is unique existing && + // Filter out meta (m) if + // existing meta name is NOT being updated, OR + // it is being deleted !metaWithIndex.find( (m2) => m2.id === existing.id && @@ -219,6 +224,8 @@ export class MenuSubscriber implements EntitySubscriberInterface { ) ); }) + // For each meta that was NOT filtered out (i.e. is NOT unique) + // add an error to the errors object .forEach((m) => { errors[`meta[${m.index}]`] = { ...errors[`meta[${m.index}]`], From 688a9832692e63f48fd5e74f108dafa3164a769d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20Feij=C3=B3=20de=20Almeida=20Pereira=20Lima?= Date: Fri, 29 Sep 2023 22:06:40 -0300 Subject: [PATCH 2/2] fix: menu meta validation bug refactor: hydrating the menu meta entity before checks --- .../entities/subscribers/menu.subscriber.ts | 111 ++++-------------- 1 file changed, 22 insertions(+), 89 deletions(-) diff --git a/src/menus/entities/subscribers/menu.subscriber.ts b/src/menus/entities/subscribers/menu.subscriber.ts index 4a6d1e4..4f8fd54 100644 --- a/src/menus/entities/subscribers/menu.subscriber.ts +++ b/src/menus/entities/subscribers/menu.subscriber.ts @@ -121,7 +121,20 @@ export class MenuSubscriber implements EntitySubscriberInterface { meta: WithAction[], dbMeta?: MenuMeta[], ): void { - const metaWithIndex = meta.map((m, index) => ({ ...m, index })); + const hydrateMeta = (meta: WithAction[]) => { + return meta.map((m) => { + if (m.action === InputAction.CREATE) { + return m; + } + const dbMetaItem = dbMeta?.find((m2) => m2.id === m.id) || {}; + if (dbMetaItem) { + return { ...dbMetaItem, ...m }; + } + return m; + }); + }; + const entity = hydrateMeta(meta); + const entityWithIndex = entity.map((m, index) => ({ ...m, index })); const errors = {}; const { IS_UNIQUE, @@ -129,9 +142,9 @@ export class MenuSubscriber implements EntitySubscriberInterface { META_DEFAULT_VALUE_REQUIRED, } = FieldValidationError.constraints; // Check if ids are unique - metaWithIndex + entityWithIndex .filter((m) => { - return metaWithIndex.find( + return entityWithIndex.find( (m2) => m2.id === m.id && m2.index !== m.index, ); }) @@ -147,9 +160,9 @@ export class MenuSubscriber implements EntitySubscriberInterface { }; }); // Check if names are unique - metaWithIndex + entityWithIndex .filter((m) => { - return metaWithIndex.find( + return entityWithIndex.find( (m2) => !!m.name && m2.name === m.name && m2.index !== m.index, ); }) @@ -165,9 +178,9 @@ export class MenuSubscriber implements EntitySubscriberInterface { }; }); // Check if orders are unique - metaWithIndex + entityWithIndex .filter((m) => { - return metaWithIndex.find( + return entityWithIndex.find( (m2) => !!m.order && m2.order === m.order && m2.index !== m.index, ); }) @@ -184,88 +197,8 @@ export class MenuSubscriber implements EntitySubscriberInterface { }); if (dbMeta) { // Is an update - // Check if ids are unique - metaWithIndex - .filter((m) => { - return ( - m.action === InputAction.CREATE && - dbMeta.find((m2) => m2.id === m.id) - ); - }) - .forEach((m) => { - errors[`meta[${m.index}]`] = { - ...errors[`meta[${m.index}]`], - id: { - errors: [ - `Menu meta ids must be unique. Found repeated id: ${m.id}`, - ], - constraints: [IS_UNIQUE], - }, - }; - }); - // Check if names are unique - metaWithIndex - .filter((m) => { - const existing = dbMeta.find( - (m2) => m2.name === m.name && m2.id !== m.id, - ); - return ( - // Filter out meta (m) if NOT updating name - !!m.name && - // Filter out meta (m) if name is unique - existing && - // Filter out meta (m) if - // existing meta name is NOT being updated, OR - // it is being deleted - !metaWithIndex.find( - (m2) => - m2.id === existing.id && - (m2.name !== m.name || m2.action === InputAction.DELETE), - ) - ); - }) - // For each meta that was NOT filtered out (i.e. is NOT unique) - // add an error to the errors object - .forEach((m) => { - errors[`meta[${m.index}]`] = { - ...errors[`meta[${m.index}]`], - name: { - errors: [ - `Menu meta names must be unique. Found repeated name: ${m.name}`, - ], - constraints: [IS_UNIQUE], - }, - }; - }); - // Check if orders are unique - metaWithIndex - .filter((m) => { - const existing = dbMeta.find( - (m2) => m2.order === m.order && m2.id !== m.id, - ); - return ( - !!m.order && - existing && - !metaWithIndex.find( - (m2) => - m2.id === existing.id && - (m2.order !== m.order || m2.action === InputAction.DELETE), - ) - ); - }) - .forEach((m) => { - errors[`meta[${m.index}]`] = { - ...errors[`meta[${m.index}]`], - order: { - errors: [ - `Menu meta orders must be unique. Found repeated order: ${m.order}`, - ], - constraints: [IS_UNIQUE], - }, - }; - }); // Check if types have changed - metaWithIndex + entityWithIndex .filter((m) => { const dbMetaItem = dbMeta.find((m2) => m2.id === m.id); return dbMetaItem && m.type && dbMetaItem.type !== m.type; @@ -282,7 +215,7 @@ export class MenuSubscriber implements EntitySubscriberInterface { }; }); // Check if default value is set when required - metaWithIndex + entityWithIndex .filter((m) => { const dbMetaItem = dbMeta.find((m2) => m2.id === m.id); const required =