From aed7347caf5351caf8abee2eff7116dbf8a89528 Mon Sep 17 00:00:00 2001 From: Rafael Date: Wed, 12 Nov 2025 15:11:00 -0600 Subject: [PATCH] feat: add shallow comparison option to ignore nested objects and arrays Add new 'shallow' option to diff function that performs shallow comparison by only comparing primitive values at the first level and ignoring nested objects and arrays. This is useful when you only need to track changes in top-level primitive properties without recursing into complex structures. Changes: - Add 'shallow' boolean option to Options interface - Skip objects/arrays in REMOVE, CHANGE, and CREATE operations when shallow mode is enabled - Update test data with simplified car examples instead of provider data - Add comprehensive tests for shallow vs deep comparison modes --- index.ts | 18 +++++++++++- tests/data/data.js | 66 +++++++++++++++++++++++++++++++++++++++++++ tests/shallow-test.js | 20 +++++++++++++ 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 tests/data/data.js create mode 100644 tests/shallow-test.js diff --git a/index.ts b/index.ts index c2383af..7b39782 100644 --- a/index.ts +++ b/index.ts @@ -21,6 +21,7 @@ export type Difference = DifferenceCreate | DifferenceRemove | DifferenceChange; interface Options { cyclesFix: boolean; + shallow: boolean; } const richTypes = { Date: true, RegExp: true, String: true, Number: true }; @@ -28,7 +29,7 @@ const richTypes = { Date: true, RegExp: true, String: true, Number: true }; export default function diff( obj: Record | any[], newObj: Record | any[], - options: Partial = { cyclesFix: true }, + options: Partial = { cyclesFix: true, shallow: false }, _stack: Record[] = [], ): Difference[] { let diffs: Difference[] = []; @@ -38,6 +39,10 @@ export default function diff( const objKey = obj[key]; const path = isObjArray ? +key : key; if (!(key in newObj)) { + // En modo shallow, ignorar propiedades que son objetos/arrays + if (options.shallow && typeof objKey === "object" && objKey !== null) { + continue; + } diffs.push({ type: "REMOVE", path: [path], @@ -50,6 +55,12 @@ export default function diff( typeof objKey === "object" && typeof newObjKey === "object" && Array.isArray(objKey) === Array.isArray(newObjKey); + + // En modo shallow, ignorar completamente propiedades que son objetos/arrays + if (options.shallow && typeof objKey === "object" && objKey !== null) { + continue; + } + if ( objKey && newObjKey && @@ -92,6 +103,11 @@ export default function diff( const isNewObjArray = Array.isArray(newObj); for (const key in newObj) { if (!(key in obj)) { + const newObjKey = newObj[key]; + // En modo shallow, ignorar propiedades que son objetos/arrays + if (options.shallow && typeof newObjKey === "object" && newObjKey !== null) { + continue; + } diffs.push({ type: "CREATE", path: [isNewObjArray ? +key : key], diff --git a/tests/data/data.js b/tests/data/data.js new file mode 100644 index 0000000..0085480 --- /dev/null +++ b/tests/data/data.js @@ -0,0 +1,66 @@ +export const original = { + IdAuto: 101, + Marca: "Toyota", + Modelo: "Corolla", + Año: 2020, + Color: "Rojo", + Precio: 250000, + EnStock: 1, + DatosAuto: [ + { + IdDatosAuto: 1, + IdAuto: 101, + NumeroSerie: "ABC123XYZ456", + Kilometraje: 15000, + Transmision: "Manual", + Motor: { + Tipo: "Gasolina", + Cilindros: 4, + Potencia: "140 HP", + }, + Equipamiento: [ + { IdEquipamiento: 1, Nombre: "Aire Acondicionado" }, + { IdEquipamiento: 2, Nombre: "Bluetooth" }, + { IdEquipamiento: 3, Nombre: "Rines de Aluminio" }, + ], + Ubicacion: { + Sucursal: "Centro", + Ciudad: "Ciudad de México", + CodigoPostal: "06000", + }, + }, + ], +}; + +export const editado = { + IdAuto: 101, + Marca: "Toyota", + Modelo: "Corolla", + Año: 2020, + Color: "Azul", + Precio: 245000, + EnStock: 1, + DatosAuto: [ + { + IdDatosAuto: 1, + IdAuto: 101, + NumeroSerie: "ABC123XYZ456", + Kilometraje: 18000, + Transmision: "Automática", + Motor: { + Tipo: "Gasolina", + Cilindros: 4, + Potencia: "150 HP", + }, + Equipamiento: [ + { IdEquipamiento: 1, Nombre: "Aire Acondicionado" }, + { IdEquipamiento: 4, Nombre: "Cámara de Reversa" }, + ], + Ubicacion: { + Sucursal: "Norte", + Ciudad: "Guadalajara", + CodigoPostal: "44100", + }, + }, + ], +}; diff --git a/tests/shallow-test.js b/tests/shallow-test.js new file mode 100644 index 0000000..3cba0ce --- /dev/null +++ b/tests/shallow-test.js @@ -0,0 +1,20 @@ +import diff from "../dist/index.js"; +import { original, editado } from "./data/data.js"; + +console.log("=== Comparación SHALLOW del objeto principal (solo primitivos) ==="); +const shallowDiffPrincipal = diff(original, editado, { shallow: true }); +console.log(shallowDiffPrincipal); + +console.log("\n=== Comparación PROFUNDA del objeto principal ==="); +const deepDiffPrincipal = diff(original, editado); +console.log(deepDiffPrincipal); + +console.log("\n\n=== Comparación SHALLOW de DatosAuto[0] (solo primitivos) ==="); +const shallowDiffDatos = diff(original.DatosAuto[0], editado.DatosAuto[0], { + shallow: true, +}); +console.log(shallowDiffDatos); + +console.log("\n=== Comparación PROFUNDA de DatosAuto[0] ==="); +const deepDiffDatos = diff(original.DatosAuto[0], editado.DatosAuto[0]); +console.log(deepDiffDatos);