├── .github └── workflows │ └── test-node.yml ├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── package.json └── test.js /.github/workflows/test-node.yml: -------------------------------------------------------------------------------- 1 | name: Build Status 2 | on: 3 | push: 4 | branches: 5 | - master 6 | pull_request: 7 | branches: 8 | - master 9 | jobs: 10 | build: 11 | strategy: 12 | matrix: 13 | node-version: [lts/*] 14 | os: [ubuntu-latest, macos-latest, windows-latest] 15 | runs-on: ${{ matrix.os }} 16 | steps: 17 | - uses: actions/checkout@v2 18 | - name: Use Node.js ${{ matrix.node-version }} 19 | uses: actions/setup-node@v2 20 | with: 21 | node-version: ${{ matrix.node-version }} 22 | - run: npm install 23 | - run: npm test 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | sandbox.js 3 | sandbox 4 | coverage 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2022 Mathias Buus 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # same-data 2 | 3 | Deep equal with no deps and only for "data" objects, ie basic objects, arrays, primitives and typed arrays 4 | 5 | ``` 6 | npm install same-data 7 | ``` 8 | 9 | Designed to be simple and for data. Does NOT do anything magic for functions, symbols, recursive objects 10 | 11 | ## Usage 12 | 13 | ``` js 14 | const sameData = require('same-data') 15 | 16 | console.log(sameData(1, 1)) // true 17 | console.log(sameData(1, 2)) // false 18 | console.log(sameData({ foo: 1 }, { foo: 1 })) // true 19 | console.log(sameData({ foo: 1 }, { foo: 1, bar: true })) // false 20 | console.log(sameData({ foo: 1, nested: { a: 1 } }, { foo: 1, nested: { a: 1 } })) // true 21 | console.log(sameData([{ a: 1 }, { b: 1 }], [{ a: 1 }, { b: 1 }])) // true 22 | ``` 23 | 24 | ## License 25 | 26 | MIT 27 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = sameData 2 | 3 | function type (o) { 4 | const t = typeof o 5 | 6 | return t === 'object' 7 | ? Array.isArray(o) 8 | ? 'array' 9 | : isTypedArray(o) 10 | ? (typeof o.equals === 'function') ? 'buffer' : 'array' 11 | : (o === null ? 'null' : 'object') 12 | : t 13 | } 14 | 15 | function isTypedArray (a) { 16 | return !!a && typeof a.length === 'number' && ArrayBuffer.isView(a.array) 17 | } 18 | 19 | function sameData (a, b) { 20 | if (a === b) return true 21 | 22 | const ta = type(a) 23 | const tb = type(b) 24 | 25 | if (ta !== tb) return false 26 | 27 | if (ta === 'buffer') return a.equals(b) 28 | 29 | if (ta === 'array') { 30 | if (a.length !== b.length) return false 31 | 32 | for (let i = 0; i < a.length; i++) { 33 | if (!sameData(a[i], b[i])) return false 34 | } 35 | 36 | return true 37 | } 38 | 39 | if (ta !== 'object') return false 40 | 41 | const ea = Object.entries(a) 42 | const eb = Object.entries(b) 43 | 44 | if (ea.length !== eb.length) return false 45 | 46 | ea.sort(cmp) 47 | eb.sort(cmp) 48 | 49 | for (let i = 0; i < ea.length; i++) { 50 | if (ea[i][0] !== eb[i][0] || !sameData(ea[i][1], eb[i][1])) return false 51 | } 52 | 53 | return true 54 | } 55 | 56 | function cmp (a, b) { 57 | return a[0] === b[0] ? 0 : a[0] < b[0] ? -1 : 1 58 | } 59 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "same-data", 3 | "version": "1.0.0", 4 | "description": "Deep equal with no deps and only for 'data' objects, ie basic objects, arrays, primitives and typed arrays", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "standard && brittle test.js" 8 | }, 9 | "devDependencies": { 10 | "brittle": "^3.1.1", 11 | "standard": "^17.0.0" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "https://github.com/mafintosh/same-data.git" 16 | }, 17 | "author": "Mathias Buus (@mafintosh)", 18 | "license": "MIT", 19 | "bugs": { 20 | "url": "https://github.com/mafintosh/same-data/issues" 21 | }, 22 | "homepage": "https://github.com/mafintosh/same-data" 23 | } 24 | -------------------------------------------------------------------------------- /test.js: -------------------------------------------------------------------------------- 1 | const test = require('brittle') 2 | const sameData = require('./') 3 | 4 | test('basic', function (t) { 5 | t.is(sameData(1, 1), true) 6 | t.is(sameData(1, 2), false) 7 | t.is(sameData(), true) // undef undef 8 | t.is(sameData(true, true), true) 9 | t.is(sameData('true', true), false) 10 | t.is(sameData('true', 'true'), true) 11 | }) 12 | 13 | test('objects', function (t) { 14 | t.is(sameData({ foo: 1 }, { foo: 1 }), true) 15 | t.is(sameData({ foo: 1 }, { foo: 1, bar: true }), false) 16 | t.is(sameData({ foo: 1, nested: { a: 1 } }, { foo: 1, nested: { a: 1 } }), true) 17 | t.is(sameData([{ a: 1 }, { b: 1 }], [{ a: 1 }, { b: 1 }]), true) 18 | }) 19 | 20 | test('typed arrays', function (t) { 21 | t.is(sameData(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3])), true) 22 | t.is(sameData(new Uint8Array([1, 2, 1]), new Uint8Array([1, 2, 3])), false) 23 | }) 24 | 25 | test('buffers', function (t) { 26 | t.is(sameData(Buffer.from([1, 2, 3]), Buffer.from([1, 2, 3])), true) 27 | t.is(sameData(Buffer.from([1, 2, 1]), Buffer.from([1, 2, 3])), false) 28 | }) 29 | --------------------------------------------------------------------------------