{"_id":"@aikotools/datacompare","_rev":"7-3bf57ada7a14c370164f8509808edd3e","name":"@aikotools/datacompare","dist-tags":{"latest":"1.3.1"},"versions":{"1.0.0":{"name":"@aikotools/datacompare","version":"1.0.0","keywords":["comparison","data-compare","e2e-testing","test-automation","matcher","assertion","deep-equal","json-compare"],"author":{"name":"aikotools"},"license":"MIT","_id":"@aikotools/datacompare@1.0.0","maintainers":[{"name":"darlenya","email":"torstenlink@gmx.de"}],"homepage":"https://github.com/aikotools/datacompare#readme","bugs":{"url":"https://github.com/aikotools/datacompare/issues"},"dist":{"shasum":"2772e8595a0ff928d36e2cf6bba19b702f42e5e7","tarball":"https://registry.npmjs.org/@aikotools/datacompare/-/datacompare-1.0.0.tgz","fileCount":48,"integrity":"sha512-rvgIwz2JyQxAJA3OP9wppOsf/SU1Kbl8uDemgLDh8q+CT1tMBHVerzvDRxIBcSaAtQ3zokhCqb0UD93Dw30iHA==","signatures":[{"sig":"MEUCIQDD0s+yLTnDYGExW/zendXRkKEQxoJk0ubqm7vplg7I3QIgBmknMMinWK2bD4/YRNXx1YLiFTmv9oF/3swioaFQZ7Q=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":78312},"main":"./dist/aikotools-datacompare.js","type":"module","types":"./dist/src/index.d.ts","module":"./dist/aikotools-datacompare.js","gitHead":"4a802cd0848274bc1fafb90fd2da96512e0c3fa9","scripts":{"dev":"vite","lint":"eslint \"src/**/*.{js,ts}\"","test":"npm run build && vitest run --coverage","build":"npm run format && npm run lint && npm run depcheck && tsc && vite build","format":"prettier --write \"src/**/*.{js,ts,json}\"","depcheck":"depcheck","test:run":"vitest run","docs:build":"bash scripts/build-readme.sh","test:watch":"vitest"},"_npmUser":{"name":"darlenya","email":"torstenlink@gmx.de"},"repository":{"url":"git+https://github.com/aikotools/datacompare.git","type":"git"},"_npmVersion":"11.6.2","description":"Advanced data comparison engine with directive-based matching for E2E testing","directories":{},"_nodeVersion":"24.10.0","dependencies":{"luxon":"^3.7.2","depcheck":"^1.4.7"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.1.11","eslint":"^9.38.0","vitest":"^3.2.4","prettier":"^3.6.2","typescript":"^5.9.3","@types/node":"^24.9.1","@types/luxon":"^3.7.1","vite-plugin-dts":"^4.5.4","@vitest/coverage-v8":"^3.2.4","@typescript-eslint/parser":"^8.46.2","@typescript-eslint/eslint-plugin":"^8.46.2"},"_npmOperationalInternal":{"tmp":"tmp/datacompare_1.0.0_1761142115890_0.7053961156448652","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@aikotools/datacompare","version":"1.0.1","keywords":["comparison","data-compare","e2e-testing","test-automation","matcher","assertion","deep-equal","json-compare"],"author":{"name":"aikotools"},"license":"MIT","_id":"@aikotools/datacompare@1.0.1","maintainers":[{"name":"darlenya","email":"torstenlink@gmx.de"}],"homepage":"https://github.com/aikotools/datacompare#readme","bugs":{"url":"https://github.com/aikotools/datacompare/issues"},"dist":{"shasum":"a596874d4ad86bcb6dbd97272ff734d2babde719","tarball":"https://registry.npmjs.org/@aikotools/datacompare/-/datacompare-1.0.1.tgz","fileCount":49,"integrity":"sha512-0SPTPvALTDT26v3UGO6xkVzWBTzFREDqoPRL0dKZnvohCIoPQOWlZV6KD5M7KPr0P6Glyoce4T2o+uiwIYxybw==","signatures":[{"sig":"MEUCIQD993EInPQ2ByKD9YndQrIG0yVasE/KGALvcut/WxoF1gIgeBaJIgpIj/ONXdQNJ+sqVU19xCsHKa87teyVC3XuzWQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":95001},"main":"./dist/aikotools-datacompare.cjs","type":"module","types":"./dist/src/index.d.ts","module":"./dist/aikotools-datacompare.mjs","exports":{".":{"import":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.mjs"},"require":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.cjs"}}},"gitHead":"1b9c86e09ee0feb122571dd61f7694da0882b5a5","scripts":{"dev":"vite","lint":"eslint \"src/**/*.{js,ts}\"","test":"npm run build && vitest run --coverage","build":"npm run format && npm run lint && npm run depcheck && tsc && vite build","format":"prettier --write \"src/**/*.{js,ts,json}\"","depcheck":"depcheck","test:run":"vitest run","docs:build":"bash scripts/build-readme.sh","test:watch":"vitest"},"_npmUser":{"name":"darlenya","email":"torstenlink@gmx.de"},"repository":{"url":"git+https://github.com/aikotools/datacompare.git","type":"git"},"_npmVersion":"11.6.2","description":"Advanced data comparison engine with directive-based matching for E2E testing","directories":{},"_nodeVersion":"24.10.0","dependencies":{"luxon":"^3.7.2","depcheck":"^1.4.7"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.1.11","eslint":"^9.38.0","vitest":"^3.2.4","prettier":"^3.6.2","typescript":"^5.9.3","@types/node":"^24.9.1","@types/luxon":"^3.7.1","vite-plugin-dts":"^4.5.4","@vitest/coverage-v8":"^3.2.4","@typescript-eslint/parser":"^8.46.2","@typescript-eslint/eslint-plugin":"^8.46.2"},"_npmOperationalInternal":{"tmp":"tmp/datacompare_1.0.1_1761207470931_0.48709076916133287","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@aikotools/datacompare","version":"1.1.0","keywords":["comparison","data-compare","e2e-testing","test-automation","matcher","assertion","deep-equal","json-compare"],"author":{"name":"aikotools"},"license":"MIT","_id":"@aikotools/datacompare@1.1.0","maintainers":[{"name":"darlenya","email":"torstenlink@gmx.de"}],"homepage":"https://github.com/aikotools/datacompare#readme","bugs":{"url":"https://github.com/aikotools/datacompare/issues"},"dist":{"shasum":"1c9672d29a9eb26ed41fd0e73e76e3e560c047be","tarball":"https://registry.npmjs.org/@aikotools/datacompare/-/datacompare-1.1.0.tgz","fileCount":49,"integrity":"sha512-LqalktFAz4KVPkfeBDK6ThwJNE+sHHoQlk1qXzWKyhUQduxAgYAsPK1r7r73/feOCnKKMPuaFjipM1ld5mHu9w==","signatures":[{"sig":"MEQCIDjw9YXIwLgA5+OCormWf4KSqSsEpmSorN3R7laaWyJVAiBihmwW9N1SjvA4KR/q5z05yNkFZr5Usu/MclDxHHynRw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97416},"main":"./dist/aikotools-datacompare.cjs","type":"module","types":"./dist/src/index.d.ts","module":"./dist/aikotools-datacompare.mjs","exports":{".":{"import":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.mjs"},"require":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.cjs"}}},"gitHead":"f4d44431e4757c76c45e514f28d7225de9069166","scripts":{"dev":"vite","lint":"eslint \"src/**/*.{js,ts}\"","test":"npm run build && vitest run --coverage","build":"npm run format && npm run lint && npm run depcheck && tsc && vite build","format":"prettier --write \"src/**/*.{js,ts,json}\"","depcheck":"depcheck","test:run":"vitest run","docs:build":"bash scripts/build-readme.sh","test:watch":"vitest"},"_npmUser":{"name":"darlenya","email":"torstenlink@gmx.de"},"repository":{"url":"git+https://github.com/aikotools/datacompare.git","type":"git"},"_npmVersion":"11.6.2","description":"Advanced data comparison engine with directive-based matching for E2E testing","directories":{},"_nodeVersion":"24.11.0","dependencies":{"luxon":"^3.7.2","depcheck":"^1.4.7"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.1.11","eslint":"^9.38.0","vitest":"^3.2.4","prettier":"^3.6.2","typescript":"^5.9.3","@types/node":"^24.9.1","@types/luxon":"^3.7.1","vite-plugin-dts":"^4.5.4","@vitest/coverage-v8":"^3.2.4","@typescript-eslint/parser":"^8.46.2","@typescript-eslint/eslint-plugin":"^8.46.2"},"_npmOperationalInternal":{"tmp":"tmp/datacompare_1.1.0_1762430824157_0.5115956575000029","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@aikotools/datacompare","version":"1.1.1","keywords":["comparison","data-compare","e2e-testing","test-automation","matcher","assertion","deep-equal","json-compare"],"author":{"name":"aikotools"},"license":"MIT","_id":"@aikotools/datacompare@1.1.1","maintainers":[{"name":"darlenya","email":"torstenlink@gmx.de"}],"homepage":"https://github.com/aikotools/datacompare#readme","bugs":{"url":"https://github.com/aikotools/datacompare/issues"},"dist":{"shasum":"c6bb172f21c82ce38caa4857352f5894ca6831a4","tarball":"https://registry.npmjs.org/@aikotools/datacompare/-/datacompare-1.1.1.tgz","fileCount":49,"integrity":"sha512-phwOr/OYTxldwo4bCymzLzHxMfDRU+CQahRZgmEGCNR026VbmrEUvZnV8NZ/NA1xmfsZsf+0HM7wD9HBCad1vw==","signatures":[{"sig":"MEYCIQC8G65UichSvnFlTRbv1v3X9+kG0RdEVXOYDBptMW1ubgIhAOf63ZqXvvkYeRbipnNV+lGdv83ubFjmYzxDsoCLipiS","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":97707},"main":"./dist/aikotools-datacompare.cjs","type":"module","types":"./dist/src/index.d.ts","module":"./dist/aikotools-datacompare.mjs","exports":{".":{"import":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.mjs"},"require":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.cjs"}}},"gitHead":"55ee68b84ab23f9b4eb2aa2ff3a35fd3143f39f8","scripts":{"dev":"vite","lint":"eslint \"src/**/*.{js,ts}\"","test":"npm run build && vitest run --coverage","build":"npm run format && npm run lint && npm run depcheck && tsc && vite build","format":"prettier --write \"src/**/*.{js,ts,json}\"","depcheck":"depcheck","test:run":"vitest run","docs:build":"bash scripts/build-readme.sh","test:watch":"vitest"},"_npmUser":{"name":"darlenya","email":"torstenlink@gmx.de"},"repository":{"url":"git+https://github.com/aikotools/datacompare.git","type":"git"},"_npmVersion":"11.6.2","description":"Advanced data comparison engine with directive-based matching for E2E testing","directories":{},"_nodeVersion":"24.11.0","dependencies":{"luxon":"^3.7.2","depcheck":"^1.4.7"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.1.11","eslint":"^9.38.0","vitest":"^3.2.4","prettier":"^3.6.2","typescript":"^5.9.3","@types/node":"^24.9.1","@types/luxon":"^3.7.1","vite-plugin-dts":"^4.5.4","@vitest/coverage-v8":"^3.2.4","@typescript-eslint/parser":"^8.46.2","@typescript-eslint/eslint-plugin":"^8.46.2"},"_npmOperationalInternal":{"tmp":"tmp/datacompare_1.1.1_1762510330158_0.04125314508550226","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@aikotools/datacompare","version":"1.2.0","keywords":["comparison","data-compare","e2e-testing","test-automation","matcher","assertion","deep-equal","json-compare"],"author":{"name":"aikotools"},"license":"MIT","_id":"@aikotools/datacompare@1.2.0","maintainers":[{"name":"darlenya","email":"torstenlink@gmx.de"}],"homepage":"https://github.com/aikotools/datacompare#readme","bugs":{"url":"https://github.com/aikotools/datacompare/issues"},"dist":{"shasum":"3825d3d91581a4a950e17ad98f08a6e73e5cb57d","tarball":"https://registry.npmjs.org/@aikotools/datacompare/-/datacompare-1.2.0.tgz","fileCount":49,"integrity":"sha512-99ROGj0klQawkdJ4uzdVDZmJPjANw6WI8tXnemCGZzXbQSCUl4kquiUx4z4UgEQsBxNMeFXsIYBpQWGXuuejcg==","signatures":[{"sig":"MEUCICPZtVBv7aVU1ej810yLiHn+5kU/0EUk/EZ/ZGzp4D7uAiEA2ICaRF+KJI7f+jzUlsWPIb0pcGvTWb1Vl5HilJB2LrQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aikotools%2fdatacompare@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":97732},"main":"./dist/aikotools-datacompare.cjs","type":"module","types":"./dist/src/index.d.ts","module":"./dist/aikotools-datacompare.mjs","exports":{".":{"import":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.mjs"},"require":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.cjs"}}},"gitHead":"88c5ac51dc3fdf1dd508676581ae9b75c16ba508","scripts":{"dev":"vite","lint":"eslint \"src/**/*.{js,ts}\"","test":"npm run build && vitest run --coverage","build":"npm run format && npm run lint && npm run depcheck && tsc && vite build","format":"prettier --write \"src/**/*.{js,ts,json}\"","depcheck":"depcheck","test:run":"vitest run","docs:build":"bash scripts/build-readme.sh","test:watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:aa163bc3-0072-4686-8395-cf316dc6a609"}},"repository":{"url":"git+https://github.com/aikotools/datacompare.git","type":"git"},"_npmVersion":"11.9.0","description":"Advanced data comparison engine with directive-based matching for E2E testing","directories":{},"_nodeVersion":"24.13.0","dependencies":{"luxon":"^3.7.2","depcheck":"^1.4.7"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","eslint":"^9.38.0","vitest":"^4.0.18","prettier":"^3.8.1","typescript":"^5.9.3","@types/node":"^25.2.2","@types/luxon":"^3.7.1","vite-plugin-dts":"^4.5.4","@vitest/coverage-v8":"^4.0.18","@typescript-eslint/parser":"^8.55.0","@typescript-eslint/eslint-plugin":"^8.55.0"},"_npmOperationalInternal":{"tmp":"tmp/datacompare_1.2.0_1770661465892_0.8219574182620315","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@aikotools/datacompare","version":"1.3.0","keywords":["comparison","data-compare","e2e-testing","test-automation","matcher","assertion","deep-equal","json-compare"],"author":{"name":"aikotools"},"license":"MIT","_id":"@aikotools/datacompare@1.3.0","maintainers":[{"name":"darlenya","email":"torstenlink@gmx.de"}],"homepage":"https://github.com/aikotools/datacompare#readme","bugs":{"url":"https://github.com/aikotools/datacompare/issues"},"dist":{"shasum":"902eaae0d8bb80b3e19cc060f0b14e71a727dc94","tarball":"https://registry.npmjs.org/@aikotools/datacompare/-/datacompare-1.3.0.tgz","fileCount":49,"integrity":"sha512-/EkYklZcWZzXbLvL7msnz7exH0s1egiPwbxXXOFOnWU/kknTs+5P612rE6Nki1ECkJ6ki6+l8WJ/S8flncZ4Qw==","signatures":[{"sig":"MEYCIQDABrLqxjxsXGSaHdKkoXyo0K607tdoeMjL5w44SJ7ffgIhANm0qB4eKvY/mXkpfDa4I7tyz7teK9c3xY3p3vQUk8IL","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aikotools%2fdatacompare@1.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":102900},"main":"./dist/aikotools-datacompare.cjs","type":"module","types":"./dist/src/index.d.ts","module":"./dist/aikotools-datacompare.mjs","exports":{".":{"import":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.mjs"},"require":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.cjs"}}},"gitHead":"b84e80c74effcc7aca3342082b3bc7bd87b28b17","scripts":{"dev":"vite","lint":"eslint \"src/**/*.{js,ts}\"","test":"npm run build && vitest run --coverage","build":"npm run format && npm run lint && npm run depcheck && tsc && vite build","format":"prettier --write \"src/**/*.{js,ts,json}\"","depcheck":"depcheck","test:run":"vitest run","docs:build":"bash scripts/build-readme.sh","test:watch":"vitest"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:aa163bc3-0072-4686-8395-cf316dc6a609"}},"repository":{"url":"git+https://github.com/aikotools/datacompare.git","type":"git"},"_npmVersion":"11.10.0","description":"Advanced data comparison engine with directive-based matching for E2E testing","directories":{},"_nodeVersion":"24.13.0","dependencies":{"luxon":"^3.7.2"},"publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.3.1","eslint":"^10.0.0","vitest":"^4.0.18","depcheck":"^1.4.7","prettier":"^3.8.1","typescript":"^5.9.3","@types/node":"^25.2.3","@types/luxon":"^3.7.1","vite-plugin-dts":"^4.5.4","@vitest/coverage-v8":"^4.0.18","@typescript-eslint/parser":"^8.56.0","@typescript-eslint/eslint-plugin":"^8.56.0"},"_npmOperationalInternal":{"tmp":"tmp/datacompare_1.3.0_1771330601667_0.17161046573610816","host":"s3://npm-registry-packages-npm-production"}},"1.3.1":{"name":"@aikotools/datacompare","version":"1.3.1","description":"Advanced data comparison engine with directive-based matching for E2E testing","main":"./dist/aikotools-datacompare.cjs","module":"./dist/aikotools-datacompare.mjs","types":"./dist/src/index.d.ts","type":"module","exports":{".":{"import":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.mjs"},"require":{"types":"./dist/src/index.d.ts","default":"./dist/aikotools-datacompare.cjs"}}},"scripts":{"dev":"vite","format":"prettier --write \"src/**/*.{js,ts,json}\"","lint":"eslint \"src/**/*.{js,ts}\"","depcheck":"depcheck","build":"npm run format && npm run lint && npm run depcheck && tsc && vite build","test":"npm run build && vitest run --coverage","test:run":"vitest run","test:watch":"vitest","docs:build":"bash scripts/build-readme.sh"},"repository":{"type":"git","url":"git+https://github.com/aikotools/datacompare.git"},"keywords":["comparison","data-compare","e2e-testing","test-automation","matcher","assertion","deep-equal","json-compare"],"author":{"name":"aikotools"},"license":"MIT","publishConfig":{"access":"public","provenance":true},"dependencies":{"luxon":"^3.7.2"},"devDependencies":{"@types/luxon":"^3.7.1","@types/node":"^25.2.3","@typescript-eslint/eslint-plugin":"^8.56.0","@typescript-eslint/parser":"^8.56.0","@vitest/coverage-v8":"^4.0.18","depcheck":"^1.4.7","eslint":"^10.0.0","prettier":"^3.8.1","typescript":"^5.9.3","vite":"^7.3.1","vite-plugin-dts":"^4.5.4","vitest":"^4.0.18"},"gitHead":"1b88b9695e09441ea989a24f0f93c17c1298701b","_id":"@aikotools/datacompare@1.3.1","bugs":{"url":"https://github.com/aikotools/datacompare/issues"},"homepage":"https://github.com/aikotools/datacompare#readme","_nodeVersion":"24.14.0","_npmVersion":"11.11.1","dist":{"integrity":"sha512-ApGjiG58IKaxt8+73BCnAfGISGZOFCnGRbbkFqxTFfNnGIjcw4r2Cgs0V+iFWQSnjixiDo701fWFL+L2YPz3Lg==","shasum":"d56dda3c48088d6674d339f7712961ef5ac3e2c8","tarball":"https://registry.npmjs.org/@aikotools/datacompare/-/datacompare-1.3.1.tgz","fileCount":49,"unpackedSize":102912,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@aikotools%2fdatacompare@1.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIGkJSLE1vIaudQhDvQAN7MxehAA47iTsw7oPql3CsOE+AiBitGm0zrNzpL96SR0yTCJhrdrjMQgogeYO5bJGHiTEuQ=="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:aa163bc3-0072-4686-8395-cf316dc6a609"}},"directories":{},"maintainers":[{"name":"darlenya","email":"torstenlink@gmx.de"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/datacompare_1.3.1_1773396959314_0.26469877281407883"},"_hasShrinkwrap":false}},"time":{"created":"2025-10-22T14:08:35.774Z","modified":"2026-03-13T10:15:59.749Z","1.0.0":"2025-10-22T14:08:36.091Z","1.0.1":"2025-10-23T08:17:51.118Z","1.1.0":"2025-11-06T12:07:04.371Z","1.1.1":"2025-11-07T10:12:10.346Z","1.2.0":"2026-02-09T18:24:26.050Z","1.3.0":"2026-02-17T12:16:41.831Z","1.3.1":"2026-03-13T10:15:59.451Z"},"bugs":{"url":"https://github.com/aikotools/datacompare/issues"},"author":{"name":"aikotools"},"license":"MIT","homepage":"https://github.com/aikotools/datacompare#readme","keywords":["comparison","data-compare","e2e-testing","test-automation","matcher","assertion","deep-equal","json-compare"],"repository":{"type":"git","url":"git+https://github.com/aikotools/datacompare.git"},"description":"Advanced data comparison engine with directive-based matching for E2E testing","maintainers":[{"name":"darlenya","email":"torstenlink@gmx.de"}],"readme":"# @aikotools/datacompare\n\nAdvanced data comparison engine with directive-based matching for E2E testing.\n\n[![npm version](https://badge.fury.io/js/@aikotools%2Fdatacompare.svg)](https://www.npmjs.com/package/@aikotools/datacompare)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n\n## Overview\n\n`@aikotools/datacompare` provides sophisticated recursive object and array comparison with support for:\n\n- **Deep Recursive Comparison**: Navigate nested object and array structures\n- **Directive-Based Matching**: Flexible comparison directives with `{{compare:...}}` syntax\n- **Time Range Comparisons**: Compare timestamps with tolerance ranges (±5 minutes, etc.)\n- **Number Range Comparisons**: Validate numbers within ranges or tolerances\n- **String Pattern Matching**: Regex, startsWith, endsWith, contains patterns\n- **Array Flexibility**: Order-independent, partial matching, wildcards\n- **Type Preservation**: Maintains proper types during comparison\n\n## Installation\n\n```bash\nnpm install @aikotools/datacompare\n```\n\n## Quick Start\n\n```typescript\nimport { compareData } from '@aikotools/datacompare';\n\nconst result = await compareData({\n  expected: {\n    userId: 'user_12345',\n    email: '{{compare:endsWith:@example.com}}',\n    score: '{{compare:number:range:0:100}}',\n    timestamp: '{{compare:time:range:-60:+60:seconds}}',\n  },\n  actual: {\n    userId: 'user_12345',\n    email: 'john.doe@example.com',\n    score: 85,\n    timestamp: '2023-12-01T10:30:00Z',\n    extra: 'ignored by default',\n  },\n  context: {\n    startTimeTest: '2023-12-01T10:30:00Z',\n  },\n});\n\nconsole.log(result.success); // true\nconsole.log(result.stats);   // { totalChecks: 4, passedChecks: 4, ... }\n```\n\n## Features\n\n### 1. Basic Object Comparison\n\n```typescript\nawait compareData({\n  expected: { name: 'John', age: 30 },\n  actual: { name: 'John', age: 30, extra: 'ignored' },\n});\n// ✅ Passes - extra properties ignored by default\n```\n\n### 2. Array Comparison\n\n```typescript\n// Ordered comparison\nawait compareData({\n  expected: [1, 2, 3],\n  actual: [1, 2, 3],\n});\n// ✅ Exact match\n\n// Order-independent\nawait compareData({\n  expected: ['{{compare:ignoreOrder}}', 'apple', 'banana'],\n  actual: ['banana', 'apple'],\n});\n// ✅ Order doesn't matter\n\n// Partial matching\nawait compareData({\n  expected: [1, 2, '{{compare:ignoreRest}}'],\n  actual: [1, 2, 3, 4, 5],\n});\n// ✅ Only validates first 2 elements\n```\n\n### 3. String Pattern Directives\n\n```typescript\nawait compareData({\n  expected: {\n    message: '{{compare:startsWith:Hello}}',\n    email: '{{compare:endsWith:@example.com}}',\n    userId: '{{compare:regex:user_[0-9]{5}}}',\n    log: '{{compare:contains:ERROR}}',\n  },\n  actual: {\n    message: 'Hello World',\n    email: 'john@example.com',\n    userId: 'user_12345',\n    log: '[2023-12-01] ERROR: Failed',\n  },\n});\n// ✅ All patterns match\n```\n\n### 4. Time Range Comparisons (NEW!)\n\n```typescript\nconst now = new Date().toISOString();\n\n// Combined range: past and future (±5 minutes)\nawait compareData({\n  expected: { timestamp: '{{compare:time:range:-300:+300:seconds}}' },\n  actual: { timestamp: now },\n  context: { startTimeTest: now },\n});\n\n// Future only: up to 1 hour in the future\nawait compareData({\n  expected: { timestamp: '{{compare:time:range:+60:minutes}}' },\n  actual: { timestamp: futureTime },\n  context: { startTimeTest: now },\n});\n\n// Past only: up to 1 hour in the past\nawait compareData({\n  expected: { timestamp: '{{compare:time:range:-60:minutes}}' },\n  actual: { timestamp: pastTime },\n  context: { startTimeTest: now },\n});\n\n// Exact time match (no offset = baseTime itself)\nawait compareData({\n  expected: { timestamp: '{{compare:time:exact}}' },\n  actual: { timestamp: now },\n  context: { startTimeTest: now },\n});\n\n// Exact time match with offset (baseTime + offset)\nawait compareData({\n  expected: { abfahrt: '{{compare:time:exact:630:seconds}}' },\n  actual: { abfahrt: departureTime }, // exactly baseTime + 630 seconds\n  context: { startTimeTest: baseTime },\n});\n\n// Exact time match with negative offset (baseTime - offset)\nawait compareData({\n  expected: { arrival: '{{compare:time:exact:-10:minutes}}' },\n  actual: { arrival: arrivalTime }, // exactly baseTime - 10 minutes\n  context: { startTimeTest: baseTime },\n});\n```\n\n### 5. Number Range Comparisons (NEW!)\n\n```typescript\n// Range validation\nawait compareData({\n  expected: { score: '{{compare:number:range:0:100}}' },\n  actual: { score: 85 },\n});\n// ✅ 85 is within [0, 100]\n\n// Tolerance (absolute)\nawait compareData({\n  expected: { value: '{{compare:number:tolerance:42:±5}}' },\n  actual: { value: 44 },\n});\n// ✅ 44 is within 42±5 (37-47)\n\n// Tolerance (percentage)\nawait compareData({\n  expected: { value: '{{compare:number:tolerance:100:±10%}}' },\n  actual: { value: 95 },\n});\n// ✅ 95 is within 100±10% (90-110)\n```\n\n### 6. Ignore Paths\n\nSkip entire subtrees during comparison, regardless of type differences or nested mismatches.\nUseful for fields that are known to differ (e.g. direction fields populated by external systems).\n\n```typescript\n// Ignore a specific field\nawait compareData({\n  expected: { name: 'John', secret: 'expectedValue' },\n  actual: { name: 'John', secret: 'completelyDifferent' },\n  options: {\n    ignorePaths: [\n      { path: ['secret'], doc: ['Secret field ignored for testing'] }\n    ]\n  }\n});\n// ✅ Passes - 'secret' is completely skipped\n\n// Wildcard matching with '*' (matches any segment including array indices)\nawait compareData({\n  expected: {\n    data: {\n      allFahrtereignis: [\n        { name: 'event1', richtung: 'NORD' },\n        { name: 'event2', richtung: 'SUED' }\n      ]\n    }\n  },\n  actual: {\n    data: {\n      allFahrtereignis: [\n        { name: 'event1', richtung: 'WEST' },\n        { name: 'event2', richtung: 'OST' }\n      ]\n    }\n  },\n  options: {\n    ignorePaths: [\n      { path: ['data', 'allFahrtereignis', '*', 'richtung'], doc: ['Richtung wird ignoriert'] }\n    ]\n  }\n});\n// ✅ Passes - 'richtung' in all array elements is skipped\n\n// Subtree ignoring (entire nested structure is skipped)\nawait compareData({\n  expected: { data: { nested: { deep: 'a', another: [1, 2, 3] } } },\n  actual: { data: { nested: { deep: 'b', another: [4, 5] } } },\n  options: {\n    ignorePaths: [\n      { path: ['data', 'nested'], doc: ['Entire subtree ignored'] }\n    ]\n  }\n});\n// ✅ Passes - everything under 'data.nested' is skipped\n```\n\n**IgnorePathConfig:**\n- `path`: Array of path segments. Use `'*'` as wildcard to match any single segment (including array indices like `[0]`).\n- `doc`: Optional array of documentation strings explaining why this path is ignored.\n\n### 7. Special Keywords\n\n```typescript\n// Exact matching (no extra properties allowed)\nawait compareData({\n  expected: {\n    '{{compare:exact}}': true,\n    name: 'John',\n    age: 30,\n  },\n  actual: {\n    name: 'John',\n    age: 30,\n    extra: 'property', // ❌ Will cause error in exact mode\n  },\n});\n\n// Ignore specific values\nawait compareData({\n  expected: {\n    userId: 'user_123',\n    timestamp: '{{compare:ignore}}', // Ignored\n  },\n  actual: {\n    userId: 'user_123',\n    timestamp: '2023-12-01T10:30:00Z', // Any value OK\n  },\n});\n```\n\n## API Reference\n\n### compareData(request: CompareRequest): Promise<CompareResult>\n\nMain comparison function.\n\n**Parameters:**\n- `expected`: Expected object with compare directives\n- `actual`: Actual object to compare against\n- `context`: Optional context (startTimeTest, startTimeScript, etc.)\n- `options`: Optional comparison options\n  - `format`: Data format (`'json'`, `'text'`, `'xml'`)\n  - `strictMode`: Exact matching everywhere (default: `false`)\n  - `ignoreExtraProperties`: Ignore extra properties in actual (default: `true`)\n  - `maxDepth`: Maximum nesting depth\n  - `maxErrors`: Stop after N errors\n  - `ignorePaths`: Array of `IgnorePathConfig` to skip entire subtrees (see section 6)\n\n**Returns:** `CompareResult` with:\n- `success`: boolean - Overall status\n- `errors`: CompareError[] - List of all errors\n- `details`: CompareDetail[] - Detailed check information\n- `stats`: CompareStats - Comparison statistics\n\n### createDefaultEngine(): CompareEngine\n\nCreates a CompareEngine with all built-in directives registered.\n\n### CompareEngine\n\nCore comparison engine. Use for custom directive registration:\n\n```typescript\nimport { createDefaultEngine, MyCustomDirective } from '@aikotools/datacompare';\n\nconst engine = createDefaultEngine();\nengine.getRegistry().registerDirective(new MyCustomDirective());\n\nconst result = await engine.compare({\n  expected: { /* ... */ },\n  actual: { /* ... */ },\n});\n```\n\n## Directive Reference\n\n### String Patterns\n- `{{compare:startsWith:pattern}}` - String must start with pattern\n- `{{compare:endsWith:pattern}}` - String must end with pattern\n- `{{compare:regex:pattern}}` - String must match regex\n- `{{compare:contains:substring}}` - String must contain substring\n\n### Time Ranges\n- `{{compare:time:range:-N:+M:unit}}` - Time within range (N units in past, M units in future)\n- `{{compare:time:range:+N:unit}}` - Time within N units in the future only\n- `{{compare:time:range:-N:unit}}` - Time within N units in the past only\n- `{{compare:time:exact}}` - Exact time match with baseTime (offset = 0)\n- `{{compare:time:exact:N:unit}}` - Exact time match with baseTime + N units (supports negative values)\n\n**Units:** milliseconds, seconds, minutes, hours, days, weeks, months, years\n\n**Base Time Priority:** startTimeTest > startTimeScript > current time (from context)\n\n### Number Ranges\n- `{{compare:number:range:min:max}}` - Number within [min, max]\n- `{{compare:number:tolerance:value:±N}}` - Number within value±N\n- `{{compare:number:tolerance:value:±N%}}` - Number within value±N%\n\n### Special Keywords\n- `{{compare:exact}}` - Enable exact property matching\n- `{{compare:ignore}}` - Ignore this value\n- `{{compare:ignoreRest}}` - Ignore remaining array elements\n- `{{compare:ignoreOrder}}` - Ignore array element order\n\n## Examples\n\nSee the integration tests for comprehensive examples:\n- [BasicComparison.test.ts](tests/integration/BasicComparison.test.ts) - Core comparison features\n- [IgnorePaths.test.ts](tests/integration/IgnorePaths.test.ts) - ignorePaths feature\n\n## Migration from e2e-tool-util-compare-object\n\n```typescript\n// Old syntax\nconst expected = {\n  \"__EXACT__\": true,\n  userId: \"<compare:ref:userId>\",\n  email: \"<CS:ENDS_WITH>@example.com\",\n};\n\n// New syntax\nconst expected = {\n  \"{{compare:exact}}\": true,\n  userId: \"{{compare:ref:userId}}\", // Coming in future release\n  email: \"{{compare:endsWith:@example.com}}\",\n};\n```\n\n## Architecture\n\n```\nCompareEngine\n├── CompareParser (parses {{compare:...}} directives)\n├── CompareRegistry (manages directives, matchers, transforms)\n└── RecursiveComparer (deep object/array comparison)\n    ├── Object comparison (partial/exact matching)\n    ├── Array comparison (ordered/unordered/partial)\n    └── Directive evaluation (startsWith, time, number, etc.)\n```\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build\nnpm run build\n\n# Test\nnpm test\n\n# Lint\nnpm run lint\n\n# Format\nnpm run format\n```\n\n## Test Results\n\n✅ 39/39 tests passing (4 test files)\n- ✅ Basic object/array comparison\n- ✅ String pattern directives (startsWith, endsWith, contains, regex)\n- ✅ Time range directives\n- ✅ Number range directives\n- ✅ Array flexibility (ignoreOrder, ignoreRest)\n- ✅ ignorePaths (exact, wildcard, subtree, nested)\n\n## Roadmap\n\n### Implemented ✅\n- [x] Core comparison engine\n- [x] Recursive deep comparison\n- [x] String pattern directives\n- [x] Time range comparisons\n- [x] Number range comparisons\n- [x] Array flexibility\n- [x] ignorePaths (skip subtrees with wildcard support)\n\n### Coming Soon\n- [ ] Reference directives (`{{compare:ref:anId}}`)\n- [ ] Custom transform pipeline\n- [ ] JSON/Text processors\n- [ ] Performance optimizations\n\n## License\n\nMIT - See [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nThis is part of the @aikotools ecosystem. For issues and contributions, please see the repository.\n\n---\n\n**Built with ❤️ for E2E Testing**\n","readmeFilename":"README.md"}