├── .commitlintrc.js ├── .editorconfig ├── .eslintignore ├── .eslintrc.json ├── .github ├── CODEOWNERS └── workflows │ ├── codeql.yml │ ├── release.yml │ └── verify.yml ├── .gitignore ├── .npmignore ├── .prettierignore ├── .prettierrc.js ├── .releaserc.js ├── .vscode └── launch.json ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── __tests__ ├── __snapshots__ │ └── compatibility.spec.ts.snap ├── compatibility.spec.ts ├── hasher.spec.ts └── objectSorter.spec.ts ├── ci ├── changelog.js ├── commit-analyzer.js ├── git-service-deploy.js ├── git.js ├── gitlab-release.js ├── npm-change-version.js ├── npm-publish.js └── release-notes.js ├── docs ├── CHANGELOG-v2.md ├── CHANGELOG.md └── api │ ├── .nojekyll │ ├── README.md │ ├── interfaces │ ├── hasher.Hashable.md │ ├── hasher.Hasher.md │ ├── hasher.HasherOptions.md │ ├── objectSorter.CoerceOptions.md │ ├── objectSorter.SortOptions.md │ ├── objectSorter.SorterOptions.md │ └── objectSorter.TrimOptions.md │ └── modules │ ├── hasher.md │ └── objectSorter.md ├── jest.config.js ├── logo.svg ├── package.json ├── pnpm-lock.yaml ├── src ├── hasher.ts ├── objectSorter.ts ├── stringifiers.ts └── typeGuess.ts ├── tsconfig.build.json └── tsconfig.json /.commitlintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = {extends: ['@commitlint/config-conventional']}; 2 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # top-most EditorConfig file 2 | root = true 3 | 4 | # Unix-style newlines with a newline ending every file 5 | [*] 6 | end_of_line = lf 7 | insert_final_newline = true 8 | charset = utf-8 9 | indent_style = space 10 | indent_size = 2 11 | tab_width = 2 12 | 13 | # Indentation override for all JS under lib directory 14 | [*.js] 15 | indent_style = space 16 | indent_size = 2 17 | trim_trailing_whitespace = true 18 | insert_final_newline = true 19 | max_line_length = 100 20 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | logs/ 2 | coverage/ 3 | node_modules/ 4 | .idea/ 5 | .vscode/ 6 | benchmark/ 7 | **/*.xxx.* 8 | dist/ 9 | ci/ 10 | jest.config.js 11 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "es6": true, 4 | "node": true 5 | }, 6 | "extends": [ 7 | "eslint:recommended", 8 | // "google", 9 | "plugin:@typescript-eslint/eslint-recommended", 10 | "plugin:@typescript-eslint/recommended", 11 | "plugin:@typescript-eslint/recommended-requiring-type-checking", 12 | "plugin:jest/recommended", 13 | "plugin:jest/style", 14 | "plugin:import/recommended", 15 | "plugin:import/typescript", 16 | "plugin:node/recommended-module", 17 | "plugin:security/recommended", 18 | "plugin:prettier/recommended" 19 | ], 20 | "overrides": [ 21 | { 22 | "files": ["**/__tests__/**/*.spec.ts", "**/__tests__/**/*.mock.ts"], 23 | "env": { 24 | "jest": true 25 | }, 26 | "rules": { 27 | "node/no-unpublished-require": ["off"], 28 | "node/no-unpublished-import": ["off"], 29 | // extends plugin:jest/recommended 30 | "jest/expect-expect": "error", 31 | "jest/no-commented-out-tests": "error", 32 | "jest/no-disabled-tests": "off", 33 | 34 | // extends plugin:jest/style 35 | "jest/no-alias-methods": "error", 36 | "import/no-extraneous-dependencies": ["error", { "devDependencies": true }], 37 | "no-new-wrappers": "off" 38 | } 39 | } 40 | ], 41 | "parser": "@typescript-eslint/parser", 42 | "parserOptions": { 43 | "project": ["tsconfig.json"] 44 | }, 45 | "plugins": ["prettier", "@typescript-eslint"], 46 | "rules": { 47 | "@typescript-eslint/consistent-type-imports": "error", 48 | "@typescript-eslint/require-await": "off", 49 | "@typescript-eslint/return-await": "error", 50 | "@typescript-eslint/await-thenable": "error", 51 | "@typescript-eslint/no-floating-promises": "error", 52 | "@typescript-eslint/explicit-function-return-type": ["error", { "allowExpressions": true }], 53 | 54 | // extends plugin:@typescript-eslint/recommended 55 | "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], // it is warn by default 56 | "@typescript-eslint/no-explicit-any": "error", // it is warn by default 57 | "@typescript-eslint/no-non-null-assertion": "off", 58 | "@typescript-eslint/ban-types": [ 59 | "error", 60 | { 61 | "extendDefaults": true, 62 | "types": { 63 | "Array": "Use [] instead of Array." 64 | } 65 | } 66 | ], 67 | "@typescript-eslint/explicit-module-boundary-types": "off", 68 | "@typescript-eslint/no-non-null-asserted-optional-chain": "off", 69 | "@typescript-eslint/no-namespace": "off", 70 | "@typescript-eslint/no-empty-interface": "off", 71 | 72 | "prettier/prettier": "error", 73 | "node/no-unpublished-import": "off", 74 | "node/no-unpublished-require": "off", 75 | 76 | // extends plugin:security/recommended 77 | "security/detect-object-injection": "off", 78 | "security/detect-possible-timing-attacks": "off", 79 | "security/detect-non-literal-fs-filename": "off", 80 | 81 | // extends plugin:import/recommended 82 | "import/no-duplicates": "error", 83 | "import/no-named-as-default": "error", 84 | "import/no-named-as-default-member": "error", 85 | "import/export": "off", 86 | "new-cap": "off", 87 | // extends plugin:node/recommended-module 88 | "node/no-missing-import": "off", 89 | "no-invalid-this": "off" 90 | }, 91 | "settings": { 92 | "import/resolver": { 93 | "typescript": {} 94 | }, 95 | "jest": { "version": 29 } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @SkeLLLa 2 | -------------------------------------------------------------------------------- /.github/workflows/codeql.yml: -------------------------------------------------------------------------------- 1 | name: 'CodeQL' 2 | 3 | on: 4 | push: 5 | branches: ['master'] 6 | pull_request: 7 | branches: ['master'] 8 | schedule: 9 | - cron: '30 22 * * 5' 10 | 11 | jobs: 12 | analyze: 13 | name: Analyze 14 | runs-on: ubuntu-latest 15 | permissions: 16 | actions: read 17 | contents: read 18 | security-events: write 19 | 20 | strategy: 21 | fail-fast: false 22 | matrix: 23 | language: [javascript] 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v4 28 | 29 | - name: Initialize CodeQL 30 | uses: github/codeql-action/init@v2 31 | with: 32 | languages: ${{ matrix.language }} 33 | queries: +security-and-quality 34 | 35 | - name: Autobuild 36 | uses: github/codeql-action/autobuild@v2 37 | 38 | - name: Perform CodeQL Analysis 39 | uses: github/codeql-action/analyze@v2 40 | with: 41 | category: '/language:${{ matrix.language }}' 42 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: release 2 | 3 | env: 4 | REGISTRY: ghcr.io 5 | IMAGE_NAME: ${{ github.repository }} 6 | 7 | on: 8 | push: 9 | branches: 10 | - master 11 | - next 12 | 13 | jobs: 14 | verify: 15 | name: Verify 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Use Node.js 22 20 | uses: actions/setup-node@v4 21 | with: 22 | node-version: 22 23 | - uses: pnpm/action-setup@v4 24 | name: Install pnpm 25 | id: pnpm-install 26 | with: 27 | # version: 9 28 | run_install: false 29 | - name: Get pnpm store directory 30 | id: pnpm-cache 31 | run: | 32 | echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" 33 | - uses: actions/cache@v4 34 | name: Setup pnpm cache 35 | with: 36 | path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} 37 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 38 | restore-keys: | 39 | ${{ runner.os }}-pnpm-store- 40 | - name: Install dependencies 41 | run: pnpm install 42 | - name: Build 43 | run: pnpm build 44 | - name: Lint 45 | uses: reviewdog/action-eslint@v1 46 | with: 47 | github_token: ${{ secrets.GITHUB_TOKEN }} 48 | reporter: github-pr-review 49 | eslint_flags: '. --ext js,jsx,ts,tsx' 50 | - name: Test 51 | run: pnpm test 52 | - name: Upload coverage to Codecov 53 | uses: codecov/codecov-action@v1 54 | with: 55 | token: ${{ secrets.CODECOV_TOKEN }} 56 | name: codecov-umbrella 57 | fail_ci_if_error: false 58 | verbose: true 59 | release: 60 | name: Release 61 | runs-on: ubuntu-latest 62 | needs: verify 63 | permissions: 64 | contents: write # to be able to publish a GitHub release 65 | issues: write # to be able to comment on released issues 66 | pull-requests: write # to be able to comment on released pull requests 67 | id-token: write # to enable use of OIDC for npm provenance 68 | packages: write 69 | checks: write 70 | steps: 71 | - name: Checkout 72 | uses: actions/checkout@v4 73 | - name: Use Node.js 74 | uses: actions/setup-node@v4 75 | with: 76 | node-version: 22 77 | - uses: pnpm/action-setup@v4 78 | name: Install pnpm 79 | id: pnpm-install 80 | with: 81 | run_install: false 82 | - name: Get pnpm store directory 83 | id: pnpm-cache 84 | run: | 85 | echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" 86 | - uses: actions/cache@v4 87 | name: Setup pnpm cache 88 | with: 89 | path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} 90 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 91 | restore-keys: | 92 | ${{ runner.os }}-pnpm-store- 93 | - name: Install dependencies 94 | run: pnpm install 95 | - name: Build 96 | run: pnpm build 97 | - name: Semantic Release 98 | run: pnpm run release 99 | env: 100 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 101 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }} 102 | -------------------------------------------------------------------------------- /.github/workflows/verify.yml: -------------------------------------------------------------------------------- 1 | name: verify 2 | 3 | on: 4 | pull_request: 5 | branches: [master, next] 6 | 7 | jobs: 8 | build: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | node-version: [20.x, 22.x] 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: Use Node.js ${{ matrix.node-version }} 16 | uses: actions/setup-node@v4 17 | with: 18 | node-version: ${{ matrix.node-version }} 19 | - uses: pnpm/action-setup@v4 20 | name: Install pnpm 21 | id: pnpm-install 22 | with: 23 | # version: 9 24 | run_install: false 25 | - name: Get pnpm store directory 26 | id: pnpm-cache 27 | run: | 28 | echo "::set-output name=pnpm_cache_dir::$(pnpm store path)" 29 | - uses: actions/cache@v4 30 | name: Setup pnpm cache 31 | with: 32 | path: ${{ steps.pnpm-cache.outputs.pnpm_cache_dir }} 33 | key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }} 34 | restore-keys: | 35 | ${{ runner.os }}-pnpm-store- 36 | - name: Install dependencies 37 | run: pnpm install 38 | - name: Build 39 | run: pnpm build 40 | - name: Lint 41 | uses: reviewdog/action-eslint@v1 42 | with: 43 | github_token: ${{ secrets.GITHUB_TOKEN }} 44 | reporter: github-pr-review 45 | eslint_flags: '. --ext js,jsx,ts,tsx' 46 | - name: Test 47 | run: pnpm test 48 | - name: Upload coverage to Codecov 49 | uses: codecov/codecov-action@v1 50 | with: 51 | token: ${{ secrets.CODECOV_TOKEN }} 52 | name: codecov-umbrella 53 | fail_ci_if_error: false 54 | verbose: true 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules 3 | deploy 4 | build 5 | coverage 6 | config/local.* 7 | **/*.xxx.js 8 | **/*.xxx.ts 9 | dist 10 | browser 11 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | test 3 | tsconfig*.json 4 | coverage 5 | .* 6 | *.config.js 7 | docs/ 8 | src/ 9 | example/ 10 | benchmark/ 11 | test/ 12 | jest.config.js 13 | ci/ 14 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | build/ 2 | coverage/ 3 | static/ 4 | node_modules/ 5 | **/*.conf 6 | **/*.min.* -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | $schema: 'http://json.schemastore.org/prettierrc', 3 | trailingComma: 'all', 4 | useTabs: false, 5 | tabWidth: 2, 6 | semi: true, 7 | singleQuote: true, 8 | quoteProps: 'consistent', 9 | arrowParens: 'always', 10 | bracketSpacing: true, 11 | endOfLine: 'lf', 12 | printWidth: 120, 13 | plugins: [ 14 | require.resolve('prettier-plugin-sh'), 15 | require.resolve('prettier-plugin-sort-json'), 16 | require.resolve('prettier-plugin-packagejson'), 17 | require.resolve('@trivago/prettier-plugin-sort-imports'), 18 | ], 19 | importOrder: ['', '^\\.\\..*$', '^\\..*$'], 20 | importOrderSeparation: true, 21 | importOrderSortSpecifiers: true, 22 | }; 23 | -------------------------------------------------------------------------------- /.releaserc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | branches: ['master', 'next'], 3 | plugins: [ 4 | require('./ci/commit-analyzer'), 5 | require('./ci/release-notes'), 6 | require('./ci/changelog'), 7 | require('./ci/npm-publish'), 8 | require('./ci/git'), 9 | require('./ci/gitlab-release'), 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "name": "vscode-jest-tests", 10 | "request": "launch", 11 | "args": ["--runInBand"], 12 | "cwd": "${workspaceFolder}", 13 | "console": "integratedTerminal", 14 | "internalConsoleOptions": "neverOpen", 15 | "disableOptimisticBPs": true, 16 | "program": "${workspaceFolder}/node_modules/jest/bin/jest" 17 | }, 18 | { 19 | "name": "Debug Jest Tests", 20 | "type": "node", 21 | "request": "launch", 22 | "runtimeArgs": [ 23 | "--inspect-brk", 24 | "${workspaceRoot}/node_modules/.bin/jest", 25 | "--runInBand", 26 | "--coverage", 27 | "false" 28 | ], 29 | "console": "integratedTerminal", 30 | "internalConsoleOptions": "neverOpen" 31 | }, 32 | { 33 | "name": "Node Inspector", 34 | "type": "node", 35 | "request": "launch", 36 | "args": ["${workspaceRoot}/test.xxx.ts"], 37 | "runtimeArgs": ["-r", "ts-node/register"], 38 | "cwd": "${workspaceRoot}", 39 | "protocol": "inspector", 40 | "internalConsoleOptions": "openOnSessionStart", 41 | "env": { 42 | "TS_NODE_IGNORE": "false" 43 | } 44 | } 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Basic contribution rules 4 | 5 | * If you have improvements - you're welcome. 6 | * If you don't you're also welcome. 7 | * If you wanna add some sarcasm into your messages - you're welcome, but be ready to it in answers. 8 | 9 | ## Purpose of this doc 10 | 11 | This doc was created just to get rid of github notification about CoC. 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Feel free to contribute to this repo. Changes that improve overall performance, code quality, tests, etc. are highly appreciated. 4 | 5 | ## Pull Request Process 6 | 7 | 1. Ensure that all deps are installed and up to date. 8 | 2. Ensure that all tests are OK. 9 | 3. Add tests if necessary. 10 | 4. Update the README.md if necessary and regenerate docs via provided script (`pnpm run typedoc`). 11 | 5. Optionally run benchmarks to ensure that your update does no harm to performance. 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 m03geek 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 all 13 | 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 THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-object-hash 2 | 3 |
4 | logo 5 | 6 | Tiny and fast node.js object hash library with properties/arrays sorting to provide constant hashes. 7 | It also provides a method that returns sorted object strings that can be used for object comparison without hashes. 8 | One of the fastest among other analogues (see [benchmarks](#benchmarks)). 9 | 10 | Hashes are built on top of node's crypto module. If you want to use it in browser it's recommented to use `objectSorter` only. It will provide you with unique string representation of your object. Afterwards you may use some hash library to reduce string size. Also you may use something like [browserify-crypto](https://github.com/crypto-browserify/crypto-browserify) or some kind of crypto functions polyfills. 11 | 12 | [![Node](https://img.shields.io/node/v/node-object-hash.svg)](https://nodejs.org/download/release/latest) 13 | [![NPM Version](https://img.shields.io/npm/v/node-object-hash.svg)](https://www.npmjs.com/package/node-object-hash) 14 | [![Downloads Count](https://img.shields.io/npm/dm/node-object-hash.svg)](https://www.npmjs.com/package/node-object-hash) 15 | [![Vunerabilities Count](https://snyk.io/test/npm/node-object-hash/badge.svg)](https://www.npmjs.com/package/node-object-hash) 16 | [![Npms.io Score](https://badges.npms.io/node-object-hash.svg)](https://npms.io/search?q=node-object-hash) 17 | [![Build Status](https://github.com/SkeLLLa/node-object-hash/workflows/build/badge.svg)](https://github.com/SkeLLLa/node-object-hash/commits/master) 18 | [![License](https://img.shields.io/npm/l/node-object-hash.svg)](https://gitlab.com/m03geek/node-object-hash/blob/master/LICENSE) 19 | [![Codecov Coverage](https://codecov.io/gh/SkeLLLa/node-object-hash/branch/master/graph/badge.svg?token=wLjMou8TT7)](https://codecov.io/gh/SkeLLLa/node-object-hash) 20 | 21 |
22 | 23 |
24 | 25 | ## ToC 26 | 27 | - [node-object-hash](#node-object-hash) 28 | - [ToC](#toc) 29 | - [What's new in v3.0.0](#whats-new-in-v300) 30 | - [What's new in v2.0.0](#whats-new-in-v200) 31 | - [Breaking changes](#breaking-changes) 32 | - [New features](#new-features) 33 | - [Installation](#installation) 34 | - [Features](#features) 35 | - [Type map](#type-map) 36 | - [Coercion map](#coercion-map) 37 | - [Changes](#changes) 38 | - [Docs](#docs) 39 | - [API overview](#api-overview) 40 | - [Constructor](#constructor) 41 | - [API methods](#api-methods) 42 | - [`hash(object[, options])`](#hashobject-options) 43 | - [`sort(object)`](#sortobject) 44 | - [Hashing custom objects](#hashing-custom-objects) 45 | - [Requirements](#requirements) 46 | - [version \>=1.0.0](#version-100) 47 | - [version \>=0.1.0 \&\& \<1.0.0](#version-010--100) 48 | - [Examples](#examples) 49 | - [Benchmarks](#benchmarks) 50 | - [Usage](#usage) 51 | - [Results](#results) 52 | - [Custom benchmark (code)](#custom-benchmark-code) 53 | - [Benchmark suite module (code)](#benchmark-suite-module-code) 54 | - [Links](#links) 55 | - [License](#license) 56 | 57 | ## What's new in v3.0.0 58 | 59 | **Disclaimer**: No new features or changes that may break hashes from previous versions. There's no need to update unless you're starting project from scratch. 60 | 61 | - Refactor and migration to typescript 5. 62 | - Drop old node support. 63 | - Removed typescript namespaces. 64 | - Updated exported functions and object structure. 65 | - Removed faker and old benchmarks. 66 | - New CI and release automation. 67 | 68 | ## What's new in v2.0.0 69 | 70 | ### Breaking changes 71 | 72 | - Library rewritten in typescript that could cause some side-effects, but it should not. 73 | - With `coerce=false` `Set`s will no longer generate the same hashes as `Array`s. In order to restore previous behavior set `coerce.set=true`. 74 | - With `coerce=false` `Symbol`s will generate hash based on symbol `.toString` value. That's useful for `Symbol.for('smth')`. If `coerce.symbol=true` all `Symbols`s will have equal hashes. 75 | TLDR; If you use library with `Set`s or `Symbol`s with `coerce=false` in order to keep hashes the same as in `v1.X.X` you should use following constructor: 76 | 77 | ``` 78 | const hasher = require('node-object-hash')({coerce: {set: true, symbol: true}}) 79 | ``` 80 | 81 | - Object sorter sources moved to `dist` directory. If you required it directly via `require('node-object-hash/objectSorter')` you should change it to require('node-object-hash/dist/objectSorter'). 82 | - Removed old `v0` version from code. 83 | - Changed license to MIT. 84 | 85 | ### New features 86 | 87 | - New granular options. Now you can specify what types need to be sorted or coerced. 88 | - Add new `trim` option. It can be used to remove unncecessary spaces in `string`s or `function` bodies. 89 | - Library rewritten to typescript, so it may have better ts compatibility. 90 | 91 | ## Installation 92 | 93 | `npm i node-object-hash -S` 94 | 95 | ## Features 96 | 97 | - Supports object property sorting for constant hashes for objects with same properties, but different order. 98 | - Supports ES6 Maps and Sets. 99 | - Supports type coercion (see table below). 100 | - Supports all hashes and encodings of crypto library. 101 | - Supports large objects and arrays. 102 | - Has granular options that allows to control what should be sorted or coerced. 103 | - Very fast comparing to other libs (see [Benchmarks](#benchmarks) section). 104 | 105 | ### Type map 106 | 107 | This map displays what types will have identical string representation (e.g. new Set([1, 2, 3]) and [1, 2, 3] will have 108 | equal string representations and hashes. 109 | 110 | | Initial type | Mapped type | 111 | | ------------------------- | ------------ | 112 | | Array ([]) | array | 113 | | ArrayObject (new Array()) | | 114 | | Int8Array | | 115 | | Uint8Array | | 116 | | Uint8ClampedArray | | 117 | | Int16Array | | 118 | | Uint16Array | | 119 | | Int32Array | | 120 | | Uint32Array | | 121 | | Float32Array | | 122 | | Float64Array | | 123 | | Buffer | | 124 | | Set | | 125 | | | | 126 | | Map | array[array] | 127 | | | | 128 | | string ('') | string | 129 | | String (new String()) | | 130 | | | | 131 | | boolean (true) | boolean | 132 | | Boolean (new Boolean()) | | 133 | | | | 134 | | number (true) | number | 135 | | Number (new Number()) | | 136 | | | | 137 | | Date | date | 138 | | | | 139 | | Symbol | symbol | 140 | | | | 141 | | undefined | undefined | 142 | | | | 143 | | null | null | 144 | | | | 145 | | function | function | 146 | | | | 147 | | Object ({}) | object | 148 | | Object (new Object()) | | 149 | | | | 150 | | other | unknown | 151 | 152 | ### Coercion map 153 | 154 | | Initial "type" | Coerced type | Example | 155 | | -------------- | -------------- | ------------ | 156 | | boolean | string | true -> 1 | 157 | | number | string | '1' -> 1 | 158 | | string | string | 'a' -> a | 159 | | null | string (empty) | null -> | 160 | | undefined | string (empty) | undefined -> | 161 | 162 | ## Changes 163 | 164 | See [changelog](docs/CHANGELOG.md) 165 | For v2 changes see [changelog-v2](docs/CHANGELOG-v2.md) 166 | 167 | ## Docs 168 | 169 | Full API docs could be found in [docs](./docs/api/README.md). 170 | 171 | ### API overview 172 | 173 | #### Constructor 174 | 175 | ```js 176 | require('node-object-hash').hasher([options]); 177 | ``` 178 | 179 | Returns preconfigured object with API 180 | 181 | Parameters: 182 | 183 | - `options`:`object` - object with hasher config options 184 | - `options.coerce`:`boolean|object` - if true performs type coercion (default: `true`); 185 | e.g. `hash(true) == hash('1') == hash(1)`, `hash(false) == hash('0') == hash(0)` 186 | - `options.sort`:`boolean|object` - if true performs sorting on objects, arrays, etc. (default: `true`); in order to 187 | perform sorting on `TypedArray` (`Buffer`, `Int8Array`, etc.), specify it explicitly: `typedArray: true` 188 | - `options.trim`:`boolean|object` - if true performs trim of spaces and replaces space-like characters with single space (default: `false`); 189 | - `options.alg`:`string` - sets default hash algorithm (default: `'sha256'`); can be overridden in `hash` method; 190 | - `options.enc`:`string` - sets default hash encoding (default: `'hex'`); can be overridden in `hash` method; 191 | 192 | ### API methods 193 | 194 | #### `hash(object[, options])` 195 | 196 | Returns hash string. 197 | 198 | - `object`:`*` object for calculating hash; 199 | - `options`:`object` object with options; 200 | - `options.alg`:`string` - hash algorithm (default: `'sha256'`); 201 | - `options.enc`:`string` - hash encoding (default: `'hex'`); 202 | 203 | #### `sort(object)` 204 | 205 | Returns sorted string generated from object (can be used for object comparison) 206 | 207 | - `object`:`*` - object for sorting; 208 | 209 | ### Hashing custom objects 210 | 211 | In order to serialize and hash your custom objects you may provide `.toHashableString()` method for your object. It should return `string` that will be hashed. You may use `objectSorter` and pass notable fields to it in your `.toHashableString` method. 212 | 213 | For typescript users you may add to your classes `implements Hashable`. 214 | 215 | ## Requirements 216 | 217 | ### version \>=1.0.0 218 | 219 | - `>=nodejs-0.10.0` 220 | 221 | ### version \>=0.1.0 && <1.0.0 222 | 223 | - `>=nodejs-6.0.0` 224 | - `>=nodejs-4.0.0` (requires to run node with `--harmony` flag) 225 | 226 | ## Examples 227 | 228 | ```js 229 | var { hasher } = require('node-object-hash'); 230 | 231 | var hashSortCoerce = hasher({ sort: true, coerce: true }); 232 | // or 233 | // var hashSortCoerce = hasher(); 234 | // or 235 | // var hashSort = hasher({sort:true, coerce:false}); 236 | // or 237 | // var hashCoerce = hasher({sort:false, coerce:true}); 238 | 239 | var objects = { 240 | a: { 241 | a: [{ c: 2, a: 1, b: { a: 3, c: 2, b: 0 } }], 242 | b: [1, 'a', {}, null], 243 | }, 244 | b: { 245 | b: ['a', 1, {}, undefined], 246 | a: [{ c: '2', b: { b: false, c: 2, a: '3' }, a: true }], 247 | }, 248 | c: ['4', true, 0, 2, 3], 249 | }; 250 | 251 | hashSortCoerce.hash(objects.a) === hashSortCoerce.hash(objects.b); 252 | // returns true 253 | 254 | hashSortCoerce.sort(object.c); 255 | // returns '[0,1,2,3,4]' 256 | ``` 257 | 258 | For more examples you can see [tests](./test) or try it out online at [runkit](https://runkit.com/skellla/node-object-hash-example) 259 | 260 | ## Benchmarks 261 | 262 | Bench data - array of 100000 complex objects 263 | 264 | ### Usage 265 | 266 | - `npm run bench` to run custom benchmark 267 | - `npm run benchmark` to run benchmark suite 268 | - `npm run benchmark:hash` to run hash benchmark suite 269 | 270 | ### Results 271 | 272 | | Hashing algorithm | Result hash bytes length | Performance (ops/sec) | 273 | | ------------------ | ------------------------ | --------------------- | 274 | | `sha256` (default) | 64 | 1,599 +- 5.77% | 275 | | `sha1` | 40 | 1,983 +- 1.50% | 276 | | `sha224` | 56 | 1,701 +- 2.81% | 277 | | `sha384` | 96 | 1,800 +- 0.81% | 278 | | `sha512` | 128 | 1,847 +- 1.75% | 279 | | `md4` | 32 | 1,971 +- 0.98% | 280 | | `md5` | 32 | 1,691 +- 3.18% | 281 | | `whirlpool` | 128 | 1,487 +- 2.33% | 282 | | | | | 283 | 284 | #### Custom benchmark ([code](bench/index.js)) 285 | 286 | | Library | Time (ms) | Memory (Mb) | 287 | | --------------------------------- | ---------- | ------------------ | 288 | | node-object-hash-0.2.1 | 5813.575 | 34 | 289 | | node-object-hash-1.0.X | 2805.581 | 27 | 290 | | node-object-hash-1.1.X (node v7) | 2555.583 | 27 | 291 | | node-object-hash-1.2.X (node v7) | 2390.752 | 28 | 292 | | node-object-hash-2.X.X (node v12) | 1990.622 | 24 | 293 | | object-hash-1.1.5 (node v7) | 28115.553 | 39 | 294 | | object-hash-1.1.4 | 534528.254 | 41 | 295 | | object-hash-1.1.3 | ERROR | Out of heap memory | 296 | | hash-object-0.1.7 | 9219.826 | 42 | 297 | 298 | #### Benchmark suite module ([code](bench/bench.js)) 299 | 300 | | Library (node v12) | Perf (ops/s) | 301 | | ---------------------- | ------------ | 302 | | node-object-hash-2.0.0 | 2087 ±0.59% | 303 | | object-hash-1.3.1 | 239 ±0.39% | 304 | | hash-object-0.1.7 | 711 ±0.18% | 305 | 306 | ### Links 307 | 308 | - [object-hash](https://www.npmjs.com/package/object-hash) - Slow, useful for browsers because it not uses node's crypto library 309 | - [hash-object](https://www.npmjs.com/package/hash-object) - no ES6 types support 310 | 311 | ## License 312 | 313 | MIT 314 | -------------------------------------------------------------------------------- /__tests__/__snapshots__/compatibility.spec.ts.snap: -------------------------------------------------------------------------------- 1 | // Jest Snapshot v1, https://goo.gl/fbAQLP 2 | 3 | exports[`Backward compatibility possible options type: Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:-1,<:n>:21,<:n>:3]"`; 4 | 5 | exports[`Backward compatibility possible options type: Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"fda0717f859a28a65f497260e076336cea9e02bcb90364bea8c8af4257d1c30f"`; 6 | 7 | exports[`Backward compatibility possible options type: Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:-1,<:n>:21,<:n>:3]"`; 8 | 9 | exports[`Backward compatibility possible options type: Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"fda0717f859a28a65f497260e076336cea9e02bcb90364bea8c8af4257d1c30f"`; 10 | 11 | exports[`Backward compatibility possible options type: Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:-1,<:n>:21,<:n>:3]"`; 12 | 13 | exports[`Backward compatibility possible options type: Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"fda0717f859a28a65f497260e076336cea9e02bcb90364bea8c8af4257d1c30f"`; 14 | 15 | exports[`Backward compatibility possible options type: Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:-1,<:n>:21,<:n>:3]"`; 16 | 17 | exports[`Backward compatibility possible options type: Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"fda0717f859a28a65f497260e076336cea9e02bcb90364bea8c8af4257d1c30f"`; 18 | 19 | exports[`Backward compatibility possible options type: Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:-1,<:n>:21,<:n>:3]"`; 20 | 21 | exports[`Backward compatibility possible options type: Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"fda0717f859a28a65f497260e076336cea9e02bcb90364bea8c8af4257d1c30f"`; 22 | 23 | exports[`Backward compatibility possible options type: Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:-1,<:n>:21,<:n>:3]"`; 24 | 25 | exports[`Backward compatibility possible options type: Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"fda0717f859a28a65f497260e076336cea9e02bcb90364bea8c8af4257d1c30f"`; 26 | 27 | exports[`Backward compatibility possible options type: Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[-1,21,3]"`; 28 | 29 | exports[`Backward compatibility possible options type: Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"f77ac6eb57940a92cee22e24660b5699f30e4194aa2e90035812023690e9547b"`; 30 | 31 | exports[`Backward compatibility possible options type: Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[-1,21,3]"`; 32 | 33 | exports[`Backward compatibility possible options type: Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"f77ac6eb57940a92cee22e24660b5699f30e4194aa2e90035812023690e9547b"`; 34 | 35 | exports[`Backward compatibility possible options type: Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[-1,21,3]"`; 36 | 37 | exports[`Backward compatibility possible options type: Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"f77ac6eb57940a92cee22e24660b5699f30e4194aa2e90035812023690e9547b"`; 38 | 39 | exports[`Backward compatibility possible options type: Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[-1,21,3]"`; 40 | 41 | exports[`Backward compatibility possible options type: Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"f77ac6eb57940a92cee22e24660b5699f30e4194aa2e90035812023690e9547b"`; 42 | 43 | exports[`Backward compatibility possible options type: Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[-1,21,3]"`; 44 | 45 | exports[`Backward compatibility possible options type: Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"f77ac6eb57940a92cee22e24660b5699f30e4194aa2e90035812023690e9547b"`; 46 | 47 | exports[`Backward compatibility possible options type: Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[-1,21,3]"`; 48 | 49 | exports[`Backward compatibility possible options type: Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"f77ac6eb57940a92cee22e24660b5699f30e4194aa2e90035812023690e9547b"`; 50 | 51 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:bi>:18446744073709551615,<:bi>:23,<:bi>:123]"`; 52 | 53 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"c17a1404e9fcde51ae8efb353de8a2ad56bc4fa65447e89d1666da07e63a8fd5"`; 54 | 55 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:bi>:18446744073709551615,<:bi>:23,<:bi>:123]"`; 56 | 57 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"c17a1404e9fcde51ae8efb353de8a2ad56bc4fa65447e89d1666da07e63a8fd5"`; 58 | 59 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:bi>:18446744073709551615,<:bi>:23,<:bi>:123]"`; 60 | 61 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"c17a1404e9fcde51ae8efb353de8a2ad56bc4fa65447e89d1666da07e63a8fd5"`; 62 | 63 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:bi>:18446744073709551615,<:bi>:23,<:bi>:123]"`; 64 | 65 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"c17a1404e9fcde51ae8efb353de8a2ad56bc4fa65447e89d1666da07e63a8fd5"`; 66 | 67 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:bi>:123,<:bi>:18446744073709551615,<:bi>:23]"`; 68 | 69 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"58e802b18ce684309a3d3580b06321894791c56879d0c0c76c4eec64d99867ec"`; 70 | 71 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:bi>:123,<:bi>:18446744073709551615,<:bi>:23]"`; 72 | 73 | exports[`Backward compatibility possible options type: BigUint64Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"58e802b18ce684309a3d3580b06321894791c56879d0c0c76c4eec64d99867ec"`; 74 | 75 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[18446744073709551615,23,123]"`; 76 | 77 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"175741df390194e4049a0f89c830ad17cae1d28bcb88e33e7f5f8ed21f242ba6"`; 78 | 79 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[18446744073709551615,23,123]"`; 80 | 81 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"175741df390194e4049a0f89c830ad17cae1d28bcb88e33e7f5f8ed21f242ba6"`; 82 | 83 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[18446744073709551615,23,123]"`; 84 | 85 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"175741df390194e4049a0f89c830ad17cae1d28bcb88e33e7f5f8ed21f242ba6"`; 86 | 87 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[18446744073709551615,23,123]"`; 88 | 89 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"175741df390194e4049a0f89c830ad17cae1d28bcb88e33e7f5f8ed21f242ba6"`; 90 | 91 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[123,18446744073709551615,23]"`; 92 | 93 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"986f4840c2d333b01de76a1f4235e8a02d517e4005c0e99bfc77b3d77155388b"`; 94 | 95 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[123,18446744073709551615,23]"`; 96 | 97 | exports[`Backward compatibility possible options type: BigUint64Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"986f4840c2d333b01de76a1f4235e8a02d517e4005c0e99bfc77b3d77155388b"`; 98 | 99 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 100 | 101 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: False trim option: False produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 102 | 103 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 104 | 105 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: False trim option: True produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 106 | 107 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 108 | 109 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: True trim option: False produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 110 | 111 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 112 | 113 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: True trim option: True produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 114 | 115 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 116 | 117 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 118 | 119 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 120 | 121 | exports[`Backward compatibility possible options type: Buffer coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 122 | 123 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: False trim option: False produces sorted string 1`] = `"[1,2,3]"`; 124 | 125 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: False trim option: False produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 126 | 127 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: False trim option: True produces sorted string 1`] = `"[1,2,3]"`; 128 | 129 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: False trim option: True produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 130 | 131 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: True trim option: False produces sorted string 1`] = `"[1,2,3]"`; 132 | 133 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: True trim option: False produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 134 | 135 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: True trim option: True produces sorted string 1`] = `"[1,2,3]"`; 136 | 137 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: True trim option: True produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 138 | 139 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[1,2,3]"`; 140 | 141 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 142 | 143 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[1,2,3]"`; 144 | 145 | exports[`Backward compatibility possible options type: Buffer coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 146 | 147 | exports[`Backward compatibility possible options type: Date coerce option False sort option: False trim option: False produces sorted string 1`] = `"<:date>:1970-01-01T00:00:00.000Z"`; 148 | 149 | exports[`Backward compatibility possible options type: Date coerce option False sort option: False trim option: False produces valid hash 1`] = `"1da2cee5350f17f14248577667954320bb95589411c1a838ddb49b944a183b2d"`; 150 | 151 | exports[`Backward compatibility possible options type: Date coerce option False sort option: False trim option: True produces sorted string 1`] = `"<:date>:1970-01-01T00:00:00.000Z"`; 152 | 153 | exports[`Backward compatibility possible options type: Date coerce option False sort option: False trim option: True produces valid hash 1`] = `"1da2cee5350f17f14248577667954320bb95589411c1a838ddb49b944a183b2d"`; 154 | 155 | exports[`Backward compatibility possible options type: Date coerce option False sort option: True trim option: False produces sorted string 1`] = `"<:date>:1970-01-01T00:00:00.000Z"`; 156 | 157 | exports[`Backward compatibility possible options type: Date coerce option False sort option: True trim option: False produces valid hash 1`] = `"1da2cee5350f17f14248577667954320bb95589411c1a838ddb49b944a183b2d"`; 158 | 159 | exports[`Backward compatibility possible options type: Date coerce option False sort option: True trim option: True produces sorted string 1`] = `"<:date>:1970-01-01T00:00:00.000Z"`; 160 | 161 | exports[`Backward compatibility possible options type: Date coerce option False sort option: True trim option: True produces valid hash 1`] = `"1da2cee5350f17f14248577667954320bb95589411c1a838ddb49b944a183b2d"`; 162 | 163 | exports[`Backward compatibility possible options type: Date coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"<:date>:1970-01-01T00:00:00.000Z"`; 164 | 165 | exports[`Backward compatibility possible options type: Date coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"1da2cee5350f17f14248577667954320bb95589411c1a838ddb49b944a183b2d"`; 166 | 167 | exports[`Backward compatibility possible options type: Date coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"<:date>:1970-01-01T00:00:00.000Z"`; 168 | 169 | exports[`Backward compatibility possible options type: Date coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"1da2cee5350f17f14248577667954320bb95589411c1a838ddb49b944a183b2d"`; 170 | 171 | exports[`Backward compatibility possible options type: Date coerce option True sort option: False trim option: False produces sorted string 1`] = `"1970-01-01T00:00:00.000Z"`; 172 | 173 | exports[`Backward compatibility possible options type: Date coerce option True sort option: False trim option: False produces valid hash 1`] = `"7d5ee5d890d67326d685789ea030e6571284171792ef48328db6894643dedd8d"`; 174 | 175 | exports[`Backward compatibility possible options type: Date coerce option True sort option: False trim option: True produces sorted string 1`] = `"1970-01-01T00:00:00.000Z"`; 176 | 177 | exports[`Backward compatibility possible options type: Date coerce option True sort option: False trim option: True produces valid hash 1`] = `"7d5ee5d890d67326d685789ea030e6571284171792ef48328db6894643dedd8d"`; 178 | 179 | exports[`Backward compatibility possible options type: Date coerce option True sort option: True trim option: False produces sorted string 1`] = `"1970-01-01T00:00:00.000Z"`; 180 | 181 | exports[`Backward compatibility possible options type: Date coerce option True sort option: True trim option: False produces valid hash 1`] = `"7d5ee5d890d67326d685789ea030e6571284171792ef48328db6894643dedd8d"`; 182 | 183 | exports[`Backward compatibility possible options type: Date coerce option True sort option: True trim option: True produces sorted string 1`] = `"1970-01-01T00:00:00.000Z"`; 184 | 185 | exports[`Backward compatibility possible options type: Date coerce option True sort option: True trim option: True produces valid hash 1`] = `"7d5ee5d890d67326d685789ea030e6571284171792ef48328db6894643dedd8d"`; 186 | 187 | exports[`Backward compatibility possible options type: Date coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"1970-01-01T00:00:00.000Z"`; 188 | 189 | exports[`Backward compatibility possible options type: Date coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"7d5ee5d890d67326d685789ea030e6571284171792ef48328db6894643dedd8d"`; 190 | 191 | exports[`Backward compatibility possible options type: Date coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"1970-01-01T00:00:00.000Z"`; 192 | 193 | exports[`Backward compatibility possible options type: Date coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"7d5ee5d890d67326d685789ea030e6571284171792ef48328db6894643dedd8d"`; 194 | 195 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:8,<:n>:3,<:n>:4]"`; 196 | 197 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"ce57ef0890fa3f6a9cd1a4087d1253cbd64860fe8c54de91152ed2b503abe425"`; 198 | 199 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:8,<:n>:3,<:n>:4]"`; 200 | 201 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"ce57ef0890fa3f6a9cd1a4087d1253cbd64860fe8c54de91152ed2b503abe425"`; 202 | 203 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:8,<:n>:3,<:n>:4]"`; 204 | 205 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"ce57ef0890fa3f6a9cd1a4087d1253cbd64860fe8c54de91152ed2b503abe425"`; 206 | 207 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:8,<:n>:3,<:n>:4]"`; 208 | 209 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"ce57ef0890fa3f6a9cd1a4087d1253cbd64860fe8c54de91152ed2b503abe425"`; 210 | 211 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:3,<:n>:4,<:n>:8]"`; 212 | 213 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"7fa85d16c6e25de279bd38bcfc9a0b6c022021674efa50822fe66c69840323cc"`; 214 | 215 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:3,<:n>:4,<:n>:8]"`; 216 | 217 | exports[`Backward compatibility possible options type: Float32Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"7fa85d16c6e25de279bd38bcfc9a0b6c022021674efa50822fe66c69840323cc"`; 218 | 219 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[1,8,3,4]"`; 220 | 221 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"1eed22003ad1bc0e099f0ce85192a2a6f7a08e04bf985f1ec0fa8523c5798d99"`; 222 | 223 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[1,8,3,4]"`; 224 | 225 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"1eed22003ad1bc0e099f0ce85192a2a6f7a08e04bf985f1ec0fa8523c5798d99"`; 226 | 227 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[1,8,3,4]"`; 228 | 229 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"1eed22003ad1bc0e099f0ce85192a2a6f7a08e04bf985f1ec0fa8523c5798d99"`; 230 | 231 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[1,8,3,4]"`; 232 | 233 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"1eed22003ad1bc0e099f0ce85192a2a6f7a08e04bf985f1ec0fa8523c5798d99"`; 234 | 235 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[1,3,4,8]"`; 236 | 237 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"ebd37e510c8cdaf6904c311ccd829f1a4632a911e6e6d0de355b59c73135a984"`; 238 | 239 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[1,3,4,8]"`; 240 | 241 | exports[`Backward compatibility possible options type: Float32Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"ebd37e510c8cdaf6904c311ccd829f1a4632a911e6e6d0de355b59c73135a984"`; 242 | 243 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:7,<:n>:3,<:n>:3,<:n>:1]"`; 244 | 245 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"618a3ab0c7fcf12d07af2b3e838a4dedb1488c9406cdf63977070c5bfab30658"`; 246 | 247 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:7,<:n>:3,<:n>:3,<:n>:1]"`; 248 | 249 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"618a3ab0c7fcf12d07af2b3e838a4dedb1488c9406cdf63977070c5bfab30658"`; 250 | 251 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:7,<:n>:3,<:n>:3,<:n>:1]"`; 252 | 253 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"618a3ab0c7fcf12d07af2b3e838a4dedb1488c9406cdf63977070c5bfab30658"`; 254 | 255 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:7,<:n>:3,<:n>:3,<:n>:1]"`; 256 | 257 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"618a3ab0c7fcf12d07af2b3e838a4dedb1488c9406cdf63977070c5bfab30658"`; 258 | 259 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:3,<:n>:3,<:n>:7]"`; 260 | 261 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"4bd2f29a233934f95d681bb1a246a17dc1cd6cc222e1381bd6f09b289822a302"`; 262 | 263 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:3,<:n>:3,<:n>:7]"`; 264 | 265 | exports[`Backward compatibility possible options type: Float64Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"4bd2f29a233934f95d681bb1a246a17dc1cd6cc222e1381bd6f09b289822a302"`; 266 | 267 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[7,3,3,1]"`; 268 | 269 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"7900be525e0265af2f95ba54458c7e69c991be61d6d08b0edc648c5ba6fa1e45"`; 270 | 271 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[7,3,3,1]"`; 272 | 273 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"7900be525e0265af2f95ba54458c7e69c991be61d6d08b0edc648c5ba6fa1e45"`; 274 | 275 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[7,3,3,1]"`; 276 | 277 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"7900be525e0265af2f95ba54458c7e69c991be61d6d08b0edc648c5ba6fa1e45"`; 278 | 279 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[7,3,3,1]"`; 280 | 281 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"7900be525e0265af2f95ba54458c7e69c991be61d6d08b0edc648c5ba6fa1e45"`; 282 | 283 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[1,3,3,7]"`; 284 | 285 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"98a1516c2e298868fcb1b4b21504bbcf720d7333d76fe50d0d92b4dad35990a9"`; 286 | 287 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[1,3,3,7]"`; 288 | 289 | exports[`Backward compatibility possible options type: Float64Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"98a1516c2e298868fcb1b4b21504bbcf720d7333d76fe50d0d92b4dad35990a9"`; 290 | 291 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:11,<:n>:-22,<:n>:3]"`; 292 | 293 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"eab9c2e10e57a8828c031640653b8e815463f806179e7edeccdca4e5889813ee"`; 294 | 295 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:11,<:n>:-22,<:n>:3]"`; 296 | 297 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"eab9c2e10e57a8828c031640653b8e815463f806179e7edeccdca4e5889813ee"`; 298 | 299 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:11,<:n>:-22,<:n>:3]"`; 300 | 301 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"eab9c2e10e57a8828c031640653b8e815463f806179e7edeccdca4e5889813ee"`; 302 | 303 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:11,<:n>:-22,<:n>:3]"`; 304 | 305 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"eab9c2e10e57a8828c031640653b8e815463f806179e7edeccdca4e5889813ee"`; 306 | 307 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:-22,<:n>:11,<:n>:3]"`; 308 | 309 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"2386b66009ed2de52189a7a51eb41809570029e5304631618d7fdad68d56b981"`; 310 | 311 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:-22,<:n>:11,<:n>:3]"`; 312 | 313 | exports[`Backward compatibility possible options type: Int8Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"2386b66009ed2de52189a7a51eb41809570029e5304631618d7fdad68d56b981"`; 314 | 315 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[11,-22,3]"`; 316 | 317 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"6982e8ebc3fb65a75cd0b1014a3bc8fad41390b650a6ab7af3aae450434fef3e"`; 318 | 319 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[11,-22,3]"`; 320 | 321 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"6982e8ebc3fb65a75cd0b1014a3bc8fad41390b650a6ab7af3aae450434fef3e"`; 322 | 323 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[11,-22,3]"`; 324 | 325 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"6982e8ebc3fb65a75cd0b1014a3bc8fad41390b650a6ab7af3aae450434fef3e"`; 326 | 327 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[11,-22,3]"`; 328 | 329 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"6982e8ebc3fb65a75cd0b1014a3bc8fad41390b650a6ab7af3aae450434fef3e"`; 330 | 331 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[-22,11,3]"`; 332 | 333 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"148bdab2b7c7ed18a0b7530c629cc7fdcd9e581dedd1bff1f3c04881dc013091"`; 334 | 335 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[-22,11,3]"`; 336 | 337 | exports[`Backward compatibility possible options type: Int8Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"148bdab2b7c7ed18a0b7530c629cc7fdcd9e581dedd1bff1f3c04881dc013091"`; 338 | 339 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:0,<:n>:5,<:n>:3]"`; 340 | 341 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"eaaf9283362997097212288934ebb5e3adda3fd5a75ab383337d3c4f45530790"`; 342 | 343 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:0,<:n>:5,<:n>:3]"`; 344 | 345 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"eaaf9283362997097212288934ebb5e3adda3fd5a75ab383337d3c4f45530790"`; 346 | 347 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:0,<:n>:5,<:n>:3]"`; 348 | 349 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"eaaf9283362997097212288934ebb5e3adda3fd5a75ab383337d3c4f45530790"`; 350 | 351 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:0,<:n>:5,<:n>:3]"`; 352 | 353 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"eaaf9283362997097212288934ebb5e3adda3fd5a75ab383337d3c4f45530790"`; 354 | 355 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:0,<:n>:3,<:n>:5]"`; 356 | 357 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"b411a4b2ad067bede38cfc517406de4981e1982c3a93ffe4919d02d522644533"`; 358 | 359 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:0,<:n>:3,<:n>:5]"`; 360 | 361 | exports[`Backward compatibility possible options type: Int16Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"b411a4b2ad067bede38cfc517406de4981e1982c3a93ffe4919d02d522644533"`; 362 | 363 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[0,5,3]"`; 364 | 365 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"849b8b150cf7af7573d8c869c2de0474f96696357a7a9e6a43cc53e48f69b912"`; 366 | 367 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[0,5,3]"`; 368 | 369 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"849b8b150cf7af7573d8c869c2de0474f96696357a7a9e6a43cc53e48f69b912"`; 370 | 371 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[0,5,3]"`; 372 | 373 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"849b8b150cf7af7573d8c869c2de0474f96696357a7a9e6a43cc53e48f69b912"`; 374 | 375 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[0,5,3]"`; 376 | 377 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"849b8b150cf7af7573d8c869c2de0474f96696357a7a9e6a43cc53e48f69b912"`; 378 | 379 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[0,3,5]"`; 380 | 381 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"acca29b897e885e2b08c3eda2c57262d3339c559072001f13a24b9a37c44129f"`; 382 | 383 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[0,3,5]"`; 384 | 385 | exports[`Backward compatibility possible options type: Int16Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"acca29b897e885e2b08c3eda2c57262d3339c559072001f13a24b9a37c44129f"`; 386 | 387 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:3,<:n>:12]"`; 388 | 389 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"1d6156a47c7b5d0a32896d764f0079b9596eb2dc4ea402edbdc0c147d7022419"`; 390 | 391 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:3,<:n>:12]"`; 392 | 393 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"1d6156a47c7b5d0a32896d764f0079b9596eb2dc4ea402edbdc0c147d7022419"`; 394 | 395 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:3,<:n>:12]"`; 396 | 397 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"1d6156a47c7b5d0a32896d764f0079b9596eb2dc4ea402edbdc0c147d7022419"`; 398 | 399 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:3,<:n>:12]"`; 400 | 401 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"1d6156a47c7b5d0a32896d764f0079b9596eb2dc4ea402edbdc0c147d7022419"`; 402 | 403 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:12,<:n>:3]"`; 404 | 405 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"72fdd1d9c4e0aea96f9aa1e1f3128d6662ae819e86dbe31e1493f3a3e20f4e00"`; 406 | 407 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:12,<:n>:3]"`; 408 | 409 | exports[`Backward compatibility possible options type: Int32Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"72fdd1d9c4e0aea96f9aa1e1f3128d6662ae819e86dbe31e1493f3a3e20f4e00"`; 410 | 411 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[1,3,12]"`; 412 | 413 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"af44a93b2e5f26ec2990e7bc7a4014c774980838ad0b2feab7b40c0eedb23d5c"`; 414 | 415 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[1,3,12]"`; 416 | 417 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"af44a93b2e5f26ec2990e7bc7a4014c774980838ad0b2feab7b40c0eedb23d5c"`; 418 | 419 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[1,3,12]"`; 420 | 421 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"af44a93b2e5f26ec2990e7bc7a4014c774980838ad0b2feab7b40c0eedb23d5c"`; 422 | 423 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[1,3,12]"`; 424 | 425 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"af44a93b2e5f26ec2990e7bc7a4014c774980838ad0b2feab7b40c0eedb23d5c"`; 426 | 427 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[1,12,3]"`; 428 | 429 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"1a77f013ef325e7a095f32906556bf3c06f597429e43e4d19d1168b3c2af04a7"`; 430 | 431 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[1,12,3]"`; 432 | 433 | exports[`Backward compatibility possible options type: Int32Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"1a77f013ef325e7a095f32906556bf3c06f597429e43e4d19d1168b3c2af04a7"`; 434 | 435 | exports[`Backward compatibility possible options type: Map coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:2;<:n>:2,<:n>:3;<:n>:3,<:n>:4]"`; 436 | 437 | exports[`Backward compatibility possible options type: Map coerce option False sort option: False trim option: False produces valid hash 1`] = `"9abc27af45f70fee16a68f4b60db840882d1f9ab9e75474ac85d043468d0786c"`; 438 | 439 | exports[`Backward compatibility possible options type: Map coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:2;<:n>:2,<:n>:3;<:n>:3,<:n>:4]"`; 440 | 441 | exports[`Backward compatibility possible options type: Map coerce option False sort option: False trim option: True produces valid hash 1`] = `"9abc27af45f70fee16a68f4b60db840882d1f9ab9e75474ac85d043468d0786c"`; 442 | 443 | exports[`Backward compatibility possible options type: Map coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:2;<:n>:2,<:n>:3;<:n>:3,<:n>:4]"`; 444 | 445 | exports[`Backward compatibility possible options type: Map coerce option False sort option: True trim option: False produces valid hash 1`] = `"9abc27af45f70fee16a68f4b60db840882d1f9ab9e75474ac85d043468d0786c"`; 446 | 447 | exports[`Backward compatibility possible options type: Map coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:2;<:n>:2,<:n>:3;<:n>:3,<:n>:4]"`; 448 | 449 | exports[`Backward compatibility possible options type: Map coerce option False sort option: True trim option: True produces valid hash 1`] = `"9abc27af45f70fee16a68f4b60db840882d1f9ab9e75474ac85d043468d0786c"`; 450 | 451 | exports[`Backward compatibility possible options type: Map coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:2;<:n>:2,<:n>:3;<:n>:3,<:n>:4]"`; 452 | 453 | exports[`Backward compatibility possible options type: Map coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"9abc27af45f70fee16a68f4b60db840882d1f9ab9e75474ac85d043468d0786c"`; 454 | 455 | exports[`Backward compatibility possible options type: Map coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:2;<:n>:2,<:n>:3;<:n>:3,<:n>:4]"`; 456 | 457 | exports[`Backward compatibility possible options type: Map coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"9abc27af45f70fee16a68f4b60db840882d1f9ab9e75474ac85d043468d0786c"`; 458 | 459 | exports[`Backward compatibility possible options type: Map coerce option True sort option: False trim option: False produces sorted string 1`] = `"[1,2;2,3;3,4]"`; 460 | 461 | exports[`Backward compatibility possible options type: Map coerce option True sort option: False trim option: False produces valid hash 1`] = `"c2b55813b1024be1f6ad7d25b3d7b0bcdcef5c0d7a6a7841c92b06327e9e7b18"`; 462 | 463 | exports[`Backward compatibility possible options type: Map coerce option True sort option: False trim option: True produces sorted string 1`] = `"[1,2;2,3;3,4]"`; 464 | 465 | exports[`Backward compatibility possible options type: Map coerce option True sort option: False trim option: True produces valid hash 1`] = `"c2b55813b1024be1f6ad7d25b3d7b0bcdcef5c0d7a6a7841c92b06327e9e7b18"`; 466 | 467 | exports[`Backward compatibility possible options type: Map coerce option True sort option: True trim option: False produces sorted string 1`] = `"[1,2;2,3;3,4]"`; 468 | 469 | exports[`Backward compatibility possible options type: Map coerce option True sort option: True trim option: False produces valid hash 1`] = `"c2b55813b1024be1f6ad7d25b3d7b0bcdcef5c0d7a6a7841c92b06327e9e7b18"`; 470 | 471 | exports[`Backward compatibility possible options type: Map coerce option True sort option: True trim option: True produces sorted string 1`] = `"[1,2;2,3;3,4]"`; 472 | 473 | exports[`Backward compatibility possible options type: Map coerce option True sort option: True trim option: True produces valid hash 1`] = `"c2b55813b1024be1f6ad7d25b3d7b0bcdcef5c0d7a6a7841c92b06327e9e7b18"`; 474 | 475 | exports[`Backward compatibility possible options type: Map coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[1,2;2,3;3,4]"`; 476 | 477 | exports[`Backward compatibility possible options type: Map coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"c2b55813b1024be1f6ad7d25b3d7b0bcdcef5c0d7a6a7841c92b06327e9e7b18"`; 478 | 479 | exports[`Backward compatibility possible options type: Map coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[1,2;2,3;3,4]"`; 480 | 481 | exports[`Backward compatibility possible options type: Map coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"c2b55813b1024be1f6ad7d25b3d7b0bcdcef5c0d7a6a7841c92b06327e9e7b18"`; 482 | 483 | exports[`Backward compatibility possible options type: Set coerce option False sort option: False trim option: False produces sorted string 1`] = `"<:set>:[<:n>:1,<:n>:2,<:n>:3]"`; 484 | 485 | exports[`Backward compatibility possible options type: Set coerce option False sort option: False trim option: False produces valid hash 1`] = `"ed7ecce9ea26c0cdfbc0168af81ef33b4967168368cc41d495d021ba6629eac3"`; 486 | 487 | exports[`Backward compatibility possible options type: Set coerce option False sort option: False trim option: True produces sorted string 1`] = `"<:set>:[<:n>:1,<:n>:2,<:n>:3]"`; 488 | 489 | exports[`Backward compatibility possible options type: Set coerce option False sort option: False trim option: True produces valid hash 1`] = `"ed7ecce9ea26c0cdfbc0168af81ef33b4967168368cc41d495d021ba6629eac3"`; 490 | 491 | exports[`Backward compatibility possible options type: Set coerce option False sort option: True trim option: False produces sorted string 1`] = `"<:set>:[<:n>:1,<:n>:2,<:n>:3]"`; 492 | 493 | exports[`Backward compatibility possible options type: Set coerce option False sort option: True trim option: False produces valid hash 1`] = `"ed7ecce9ea26c0cdfbc0168af81ef33b4967168368cc41d495d021ba6629eac3"`; 494 | 495 | exports[`Backward compatibility possible options type: Set coerce option False sort option: True trim option: True produces sorted string 1`] = `"<:set>:[<:n>:1,<:n>:2,<:n>:3]"`; 496 | 497 | exports[`Backward compatibility possible options type: Set coerce option False sort option: True trim option: True produces valid hash 1`] = `"ed7ecce9ea26c0cdfbc0168af81ef33b4967168368cc41d495d021ba6629eac3"`; 498 | 499 | exports[`Backward compatibility possible options type: Set coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"<:set>:[<:n>:1,<:n>:2,<:n>:3]"`; 500 | 501 | exports[`Backward compatibility possible options type: Set coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"ed7ecce9ea26c0cdfbc0168af81ef33b4967168368cc41d495d021ba6629eac3"`; 502 | 503 | exports[`Backward compatibility possible options type: Set coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"<:set>:[<:n>:1,<:n>:2,<:n>:3]"`; 504 | 505 | exports[`Backward compatibility possible options type: Set coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"ed7ecce9ea26c0cdfbc0168af81ef33b4967168368cc41d495d021ba6629eac3"`; 506 | 507 | exports[`Backward compatibility possible options type: Set coerce option True sort option: False trim option: False produces sorted string 1`] = `"[1,2,3]"`; 508 | 509 | exports[`Backward compatibility possible options type: Set coerce option True sort option: False trim option: False produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 510 | 511 | exports[`Backward compatibility possible options type: Set coerce option True sort option: False trim option: True produces sorted string 1`] = `"[1,2,3]"`; 512 | 513 | exports[`Backward compatibility possible options type: Set coerce option True sort option: False trim option: True produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 514 | 515 | exports[`Backward compatibility possible options type: Set coerce option True sort option: True trim option: False produces sorted string 1`] = `"[1,2,3]"`; 516 | 517 | exports[`Backward compatibility possible options type: Set coerce option True sort option: True trim option: False produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 518 | 519 | exports[`Backward compatibility possible options type: Set coerce option True sort option: True trim option: True produces sorted string 1`] = `"[1,2,3]"`; 520 | 521 | exports[`Backward compatibility possible options type: Set coerce option True sort option: True trim option: True produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 522 | 523 | exports[`Backward compatibility possible options type: Set coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[1,2,3]"`; 524 | 525 | exports[`Backward compatibility possible options type: Set coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 526 | 527 | exports[`Backward compatibility possible options type: Set coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[1,2,3]"`; 528 | 529 | exports[`Backward compatibility possible options type: Set coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 530 | 531 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:13,<:n>:254,<:n>:253]"`; 532 | 533 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"9fc7dbb54b68ab4a64bd6450e2022ede2383d9fc58b5f4a9bc2e52d4c568a007"`; 534 | 535 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:13,<:n>:254,<:n>:253]"`; 536 | 537 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"9fc7dbb54b68ab4a64bd6450e2022ede2383d9fc58b5f4a9bc2e52d4c568a007"`; 538 | 539 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:13,<:n>:254,<:n>:253]"`; 540 | 541 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"9fc7dbb54b68ab4a64bd6450e2022ede2383d9fc58b5f4a9bc2e52d4c568a007"`; 542 | 543 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:13,<:n>:254,<:n>:253]"`; 544 | 545 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"9fc7dbb54b68ab4a64bd6450e2022ede2383d9fc58b5f4a9bc2e52d4c568a007"`; 546 | 547 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:13,<:n>:253,<:n>:254]"`; 548 | 549 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"8c00927792ac474e4ef34abfe859e2c88ffdbdd64f56d08069d3e383968ca668"`; 550 | 551 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:13,<:n>:253,<:n>:254]"`; 552 | 553 | exports[`Backward compatibility possible options type: Uint8Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"8c00927792ac474e4ef34abfe859e2c88ffdbdd64f56d08069d3e383968ca668"`; 554 | 555 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[13,254,253]"`; 556 | 557 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"3241abff1bd917d5aaa71b87f0739452fde8c104e7f49a9c2be564a4ecb16595"`; 558 | 559 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[13,254,253]"`; 560 | 561 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"3241abff1bd917d5aaa71b87f0739452fde8c104e7f49a9c2be564a4ecb16595"`; 562 | 563 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[13,254,253]"`; 564 | 565 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"3241abff1bd917d5aaa71b87f0739452fde8c104e7f49a9c2be564a4ecb16595"`; 566 | 567 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[13,254,253]"`; 568 | 569 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"3241abff1bd917d5aaa71b87f0739452fde8c104e7f49a9c2be564a4ecb16595"`; 570 | 571 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[13,253,254]"`; 572 | 573 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"69131d32e7ec1a5e817d572bcc37dc42494ba931003ae81e18762f0301cf6545"`; 574 | 575 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[13,253,254]"`; 576 | 577 | exports[`Backward compatibility possible options type: Uint8Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"69131d32e7ec1a5e817d572bcc37dc42494ba931003ae81e18762f0301cf6545"`; 578 | 579 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 580 | 581 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 582 | 583 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 584 | 585 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 586 | 587 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 588 | 589 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 590 | 591 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 592 | 593 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 594 | 595 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 596 | 597 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 598 | 599 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:1,<:n>:2,<:n>:3]"`; 600 | 601 | exports[`Backward compatibility possible options type: Uint16Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"8725c0fa43aed2afad780f6bbee6033cad07b504ccdcb4503ec1072b28821c93"`; 602 | 603 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[1,2,3]"`; 604 | 605 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 606 | 607 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[1,2,3]"`; 608 | 609 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 610 | 611 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[1,2,3]"`; 612 | 613 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 614 | 615 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[1,2,3]"`; 616 | 617 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 618 | 619 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[1,2,3]"`; 620 | 621 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 622 | 623 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[1,2,3]"`; 624 | 625 | exports[`Backward compatibility possible options type: Uint16Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4"`; 626 | 627 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: False trim option: False produces sorted string 1`] = `"[<:n>:123,<:n>:4]"`; 628 | 629 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: False trim option: False produces valid hash 1`] = `"eb055807e9f45f440fe5f441802a5dfdeaceef937cfb39f0129a1c8e8c1b5c83"`; 630 | 631 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: False trim option: True produces sorted string 1`] = `"[<:n>:123,<:n>:4]"`; 632 | 633 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: False trim option: True produces valid hash 1`] = `"eb055807e9f45f440fe5f441802a5dfdeaceef937cfb39f0129a1c8e8c1b5c83"`; 634 | 635 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: True trim option: False produces sorted string 1`] = `"[<:n>:123,<:n>:4]"`; 636 | 637 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: True trim option: False produces valid hash 1`] = `"eb055807e9f45f440fe5f441802a5dfdeaceef937cfb39f0129a1c8e8c1b5c83"`; 638 | 639 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: True trim option: True produces sorted string 1`] = `"[<:n>:123,<:n>:4]"`; 640 | 641 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: True trim option: True produces valid hash 1`] = `"eb055807e9f45f440fe5f441802a5dfdeaceef937cfb39f0129a1c8e8c1b5c83"`; 642 | 643 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[<:n>:123,<:n>:4]"`; 644 | 645 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"eb055807e9f45f440fe5f441802a5dfdeaceef937cfb39f0129a1c8e8c1b5c83"`; 646 | 647 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[<:n>:123,<:n>:4]"`; 648 | 649 | exports[`Backward compatibility possible options type: Uint32Array coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"eb055807e9f45f440fe5f441802a5dfdeaceef937cfb39f0129a1c8e8c1b5c83"`; 650 | 651 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: False trim option: False produces sorted string 1`] = `"[123,4]"`; 652 | 653 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: False trim option: False produces valid hash 1`] = `"7f8aba9ee43f78717314ca8e3e6e3148cbd8db85c31b749452ca8bef14ec2fa6"`; 654 | 655 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: False trim option: True produces sorted string 1`] = `"[123,4]"`; 656 | 657 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: False trim option: True produces valid hash 1`] = `"7f8aba9ee43f78717314ca8e3e6e3148cbd8db85c31b749452ca8bef14ec2fa6"`; 658 | 659 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: True trim option: False produces sorted string 1`] = `"[123,4]"`; 660 | 661 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: True trim option: False produces valid hash 1`] = `"7f8aba9ee43f78717314ca8e3e6e3148cbd8db85c31b749452ca8bef14ec2fa6"`; 662 | 663 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: True trim option: True produces sorted string 1`] = `"[123,4]"`; 664 | 665 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: True trim option: True produces valid hash 1`] = `"7f8aba9ee43f78717314ca8e3e6e3148cbd8db85c31b749452ca8bef14ec2fa6"`; 666 | 667 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"[123,4]"`; 668 | 669 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"7f8aba9ee43f78717314ca8e3e6e3148cbd8db85c31b749452ca8bef14ec2fa6"`; 670 | 671 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"[123,4]"`; 672 | 673 | exports[`Backward compatibility possible options type: Uint32Array coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"7f8aba9ee43f78717314ca8e3e6e3148cbd8db85c31b749452ca8bef14ec2fa6"`; 674 | 675 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: False trim option: False produces sorted string 1`] = `"<:bi>:1238573921"`; 676 | 677 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: False trim option: False produces valid hash 1`] = `"afe682f65445dd62cb34d3d162d7d3160ddc152657a30d6fa3bb7ddbfe1e95c8"`; 678 | 679 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: False trim option: True produces sorted string 1`] = `"<:bi>:1238573921"`; 680 | 681 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: False trim option: True produces valid hash 1`] = `"afe682f65445dd62cb34d3d162d7d3160ddc152657a30d6fa3bb7ddbfe1e95c8"`; 682 | 683 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: True trim option: False produces sorted string 1`] = `"<:bi>:1238573921"`; 684 | 685 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: True trim option: False produces valid hash 1`] = `"afe682f65445dd62cb34d3d162d7d3160ddc152657a30d6fa3bb7ddbfe1e95c8"`; 686 | 687 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: True trim option: True produces sorted string 1`] = `"<:bi>:1238573921"`; 688 | 689 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: True trim option: True produces valid hash 1`] = `"afe682f65445dd62cb34d3d162d7d3160ddc152657a30d6fa3bb7ddbfe1e95c8"`; 690 | 691 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"<:bi>:1238573921"`; 692 | 693 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"afe682f65445dd62cb34d3d162d7d3160ddc152657a30d6fa3bb7ddbfe1e95c8"`; 694 | 695 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"<:bi>:1238573921"`; 696 | 697 | exports[`Backward compatibility possible options type: bigint coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"afe682f65445dd62cb34d3d162d7d3160ddc152657a30d6fa3bb7ddbfe1e95c8"`; 698 | 699 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: False trim option: False produces sorted string 1`] = `"1238573921"`; 700 | 701 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: False trim option: False produces valid hash 1`] = `"25e2e8455dc0f02562ec2c86360dcaad5bf05d3b58aaf9f5682f2ab8368cccb6"`; 702 | 703 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: False trim option: True produces sorted string 1`] = `"1238573921"`; 704 | 705 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: False trim option: True produces valid hash 1`] = `"25e2e8455dc0f02562ec2c86360dcaad5bf05d3b58aaf9f5682f2ab8368cccb6"`; 706 | 707 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: True trim option: False produces sorted string 1`] = `"1238573921"`; 708 | 709 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: True trim option: False produces valid hash 1`] = `"25e2e8455dc0f02562ec2c86360dcaad5bf05d3b58aaf9f5682f2ab8368cccb6"`; 710 | 711 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: True trim option: True produces sorted string 1`] = `"1238573921"`; 712 | 713 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: True trim option: True produces valid hash 1`] = `"25e2e8455dc0f02562ec2c86360dcaad5bf05d3b58aaf9f5682f2ab8368cccb6"`; 714 | 715 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"1238573921"`; 716 | 717 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"25e2e8455dc0f02562ec2c86360dcaad5bf05d3b58aaf9f5682f2ab8368cccb6"`; 718 | 719 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"1238573921"`; 720 | 721 | exports[`Backward compatibility possible options type: bigint coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"25e2e8455dc0f02562ec2c86360dcaad5bf05d3b58aaf9f5682f2ab8368cccb6"`; 722 | 723 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: False trim option: False produces sorted string 1`] = `"<:b>:true"`; 724 | 725 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: False trim option: False produces valid hash 1`] = `"176764f03246b65b3eaa82bce207f1543c083cbf7039218e23b3867007eabb92"`; 726 | 727 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: False trim option: True produces sorted string 1`] = `"<:b>:true"`; 728 | 729 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: False trim option: True produces valid hash 1`] = `"176764f03246b65b3eaa82bce207f1543c083cbf7039218e23b3867007eabb92"`; 730 | 731 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: True trim option: False produces sorted string 1`] = `"<:b>:true"`; 732 | 733 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: True trim option: False produces valid hash 1`] = `"176764f03246b65b3eaa82bce207f1543c083cbf7039218e23b3867007eabb92"`; 734 | 735 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: True trim option: True produces sorted string 1`] = `"<:b>:true"`; 736 | 737 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: True trim option: True produces valid hash 1`] = `"176764f03246b65b3eaa82bce207f1543c083cbf7039218e23b3867007eabb92"`; 738 | 739 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"<:b>:true"`; 740 | 741 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"176764f03246b65b3eaa82bce207f1543c083cbf7039218e23b3867007eabb92"`; 742 | 743 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"<:b>:true"`; 744 | 745 | exports[`Backward compatibility possible options type: boolean coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"176764f03246b65b3eaa82bce207f1543c083cbf7039218e23b3867007eabb92"`; 746 | 747 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: False trim option: False produces sorted string 1`] = `"1"`; 748 | 749 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: False trim option: False produces valid hash 1`] = `"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"`; 750 | 751 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: False trim option: True produces sorted string 1`] = `"1"`; 752 | 753 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: False trim option: True produces valid hash 1`] = `"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"`; 754 | 755 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: True trim option: False produces sorted string 1`] = `"1"`; 756 | 757 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: True trim option: False produces valid hash 1`] = `"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"`; 758 | 759 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: True trim option: True produces sorted string 1`] = `"1"`; 760 | 761 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: True trim option: True produces valid hash 1`] = `"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"`; 762 | 763 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"1"`; 764 | 765 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"`; 766 | 767 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"1"`; 768 | 769 | exports[`Backward compatibility possible options type: boolean coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b"`; 770 | 771 | exports[`Backward compatibility possible options type: number coerce option False sort option: False trim option: False produces sorted string 1`] = `"<:n>:19284"`; 772 | 773 | exports[`Backward compatibility possible options type: number coerce option False sort option: False trim option: False produces valid hash 1`] = `"60d59fdc8f59f9a9e1ceddaa8606db45c9aa5ee49b80f62b04a2cfd94731f40d"`; 774 | 775 | exports[`Backward compatibility possible options type: number coerce option False sort option: False trim option: True produces sorted string 1`] = `"<:n>:19284"`; 776 | 777 | exports[`Backward compatibility possible options type: number coerce option False sort option: False trim option: True produces valid hash 1`] = `"60d59fdc8f59f9a9e1ceddaa8606db45c9aa5ee49b80f62b04a2cfd94731f40d"`; 778 | 779 | exports[`Backward compatibility possible options type: number coerce option False sort option: True trim option: False produces sorted string 1`] = `"<:n>:19284"`; 780 | 781 | exports[`Backward compatibility possible options type: number coerce option False sort option: True trim option: False produces valid hash 1`] = `"60d59fdc8f59f9a9e1ceddaa8606db45c9aa5ee49b80f62b04a2cfd94731f40d"`; 782 | 783 | exports[`Backward compatibility possible options type: number coerce option False sort option: True trim option: True produces sorted string 1`] = `"<:n>:19284"`; 784 | 785 | exports[`Backward compatibility possible options type: number coerce option False sort option: True trim option: True produces valid hash 1`] = `"60d59fdc8f59f9a9e1ceddaa8606db45c9aa5ee49b80f62b04a2cfd94731f40d"`; 786 | 787 | exports[`Backward compatibility possible options type: number coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"<:n>:19284"`; 788 | 789 | exports[`Backward compatibility possible options type: number coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"60d59fdc8f59f9a9e1ceddaa8606db45c9aa5ee49b80f62b04a2cfd94731f40d"`; 790 | 791 | exports[`Backward compatibility possible options type: number coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"<:n>:19284"`; 792 | 793 | exports[`Backward compatibility possible options type: number coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"60d59fdc8f59f9a9e1ceddaa8606db45c9aa5ee49b80f62b04a2cfd94731f40d"`; 794 | 795 | exports[`Backward compatibility possible options type: number coerce option True sort option: False trim option: False produces sorted string 1`] = `"19284"`; 796 | 797 | exports[`Backward compatibility possible options type: number coerce option True sort option: False trim option: False produces valid hash 1`] = `"e31ea9e1c738c14e61b644cb2e78c703bd2b1614134a8fd569641467a9ffea04"`; 798 | 799 | exports[`Backward compatibility possible options type: number coerce option True sort option: False trim option: True produces sorted string 1`] = `"19284"`; 800 | 801 | exports[`Backward compatibility possible options type: number coerce option True sort option: False trim option: True produces valid hash 1`] = `"e31ea9e1c738c14e61b644cb2e78c703bd2b1614134a8fd569641467a9ffea04"`; 802 | 803 | exports[`Backward compatibility possible options type: number coerce option True sort option: True trim option: False produces sorted string 1`] = `"19284"`; 804 | 805 | exports[`Backward compatibility possible options type: number coerce option True sort option: True trim option: False produces valid hash 1`] = `"e31ea9e1c738c14e61b644cb2e78c703bd2b1614134a8fd569641467a9ffea04"`; 806 | 807 | exports[`Backward compatibility possible options type: number coerce option True sort option: True trim option: True produces sorted string 1`] = `"19284"`; 808 | 809 | exports[`Backward compatibility possible options type: number coerce option True sort option: True trim option: True produces valid hash 1`] = `"e31ea9e1c738c14e61b644cb2e78c703bd2b1614134a8fd569641467a9ffea04"`; 810 | 811 | exports[`Backward compatibility possible options type: number coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"19284"`; 812 | 813 | exports[`Backward compatibility possible options type: number coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"e31ea9e1c738c14e61b644cb2e78c703bd2b1614134a8fd569641467a9ffea04"`; 814 | 815 | exports[`Backward compatibility possible options type: number coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"19284"`; 816 | 817 | exports[`Backward compatibility possible options type: number coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"e31ea9e1c738c14e61b644cb2e78c703bd2b1614134a8fd569641467a9ffea04"`; 818 | 819 | exports[`Backward compatibility possible options type: object coerce option False sort option: False trim option: False produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 820 | 821 | exports[`Backward compatibility possible options type: object coerce option False sort option: False trim option: False produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 822 | 823 | exports[`Backward compatibility possible options type: object coerce option False sort option: False trim option: True produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 824 | 825 | exports[`Backward compatibility possible options type: object coerce option False sort option: False trim option: True produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 826 | 827 | exports[`Backward compatibility possible options type: object coerce option False sort option: True trim option: False produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 828 | 829 | exports[`Backward compatibility possible options type: object coerce option False sort option: True trim option: False produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 830 | 831 | exports[`Backward compatibility possible options type: object coerce option False sort option: True trim option: True produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 832 | 833 | exports[`Backward compatibility possible options type: object coerce option False sort option: True trim option: True produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 834 | 835 | exports[`Backward compatibility possible options type: object coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 836 | 837 | exports[`Backward compatibility possible options type: object coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 838 | 839 | exports[`Backward compatibility possible options type: object coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 840 | 841 | exports[`Backward compatibility possible options type: object coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 842 | 843 | exports[`Backward compatibility possible options type: object coerce option True sort option: False trim option: False produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 844 | 845 | exports[`Backward compatibility possible options type: object coerce option True sort option: False trim option: False produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 846 | 847 | exports[`Backward compatibility possible options type: object coerce option True sort option: False trim option: True produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 848 | 849 | exports[`Backward compatibility possible options type: object coerce option True sort option: False trim option: True produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 850 | 851 | exports[`Backward compatibility possible options type: object coerce option True sort option: True trim option: False produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 852 | 853 | exports[`Backward compatibility possible options type: object coerce option True sort option: True trim option: False produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 854 | 855 | exports[`Backward compatibility possible options type: object coerce option True sort option: True trim option: True produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 856 | 857 | exports[`Backward compatibility possible options type: object coerce option True sort option: True trim option: True produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 858 | 859 | exports[`Backward compatibility possible options type: object coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 860 | 861 | exports[`Backward compatibility possible options type: object coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 862 | 863 | exports[`Backward compatibility possible options type: object coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"<:UnknownClass>:{"name":"unknown"}"`; 864 | 865 | exports[`Backward compatibility possible options type: object coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"32363a23a5c195e6659c3cb51f428ec9775d519780eacbfddb8d26bc10d9849d"`; 866 | 867 | exports[`Backward compatibility possible options type: string coerce option False sort option: False trim option: False produces sorted string 1`] = `"<:s>:some string"`; 868 | 869 | exports[`Backward compatibility possible options type: string coerce option False sort option: False trim option: False produces valid hash 1`] = `"1c8a48f4dc5a01175cdf8863672913240869a2a72a61b3683f151e4151b34079"`; 870 | 871 | exports[`Backward compatibility possible options type: string coerce option False sort option: False trim option: True produces sorted string 1`] = `"<:s>:some string"`; 872 | 873 | exports[`Backward compatibility possible options type: string coerce option False sort option: False trim option: True produces valid hash 1`] = `"1c8a48f4dc5a01175cdf8863672913240869a2a72a61b3683f151e4151b34079"`; 874 | 875 | exports[`Backward compatibility possible options type: string coerce option False sort option: True trim option: False produces sorted string 1`] = `"<:s>:some string"`; 876 | 877 | exports[`Backward compatibility possible options type: string coerce option False sort option: True trim option: False produces valid hash 1`] = `"1c8a48f4dc5a01175cdf8863672913240869a2a72a61b3683f151e4151b34079"`; 878 | 879 | exports[`Backward compatibility possible options type: string coerce option False sort option: True trim option: True produces sorted string 1`] = `"<:s>:some string"`; 880 | 881 | exports[`Backward compatibility possible options type: string coerce option False sort option: True trim option: True produces valid hash 1`] = `"1c8a48f4dc5a01175cdf8863672913240869a2a72a61b3683f151e4151b34079"`; 882 | 883 | exports[`Backward compatibility possible options type: string coerce option False sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"<:s>:some string"`; 884 | 885 | exports[`Backward compatibility possible options type: string coerce option False sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"1c8a48f4dc5a01175cdf8863672913240869a2a72a61b3683f151e4151b34079"`; 886 | 887 | exports[`Backward compatibility possible options type: string coerce option False sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"<:s>:some string"`; 888 | 889 | exports[`Backward compatibility possible options type: string coerce option False sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"1c8a48f4dc5a01175cdf8863672913240869a2a72a61b3683f151e4151b34079"`; 890 | 891 | exports[`Backward compatibility possible options type: string coerce option True sort option: False trim option: False produces sorted string 1`] = `"some string"`; 892 | 893 | exports[`Backward compatibility possible options type: string coerce option True sort option: False trim option: False produces valid hash 1`] = `"61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc"`; 894 | 895 | exports[`Backward compatibility possible options type: string coerce option True sort option: False trim option: True produces sorted string 1`] = `"some string"`; 896 | 897 | exports[`Backward compatibility possible options type: string coerce option True sort option: False trim option: True produces valid hash 1`] = `"61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc"`; 898 | 899 | exports[`Backward compatibility possible options type: string coerce option True sort option: True trim option: False produces sorted string 1`] = `"some string"`; 900 | 901 | exports[`Backward compatibility possible options type: string coerce option True sort option: True trim option: False produces valid hash 1`] = `"61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc"`; 902 | 903 | exports[`Backward compatibility possible options type: string coerce option True sort option: True trim option: True produces sorted string 1`] = `"some string"`; 904 | 905 | exports[`Backward compatibility possible options type: string coerce option True sort option: True trim option: True produces valid hash 1`] = `"61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc"`; 906 | 907 | exports[`Backward compatibility possible options type: string coerce option True sort option: TypedArrayTrue trim option: False produces sorted string 1`] = `"some string"`; 908 | 909 | exports[`Backward compatibility possible options type: string coerce option True sort option: TypedArrayTrue trim option: False produces valid hash 1`] = `"61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc"`; 910 | 911 | exports[`Backward compatibility possible options type: string coerce option True sort option: TypedArrayTrue trim option: True produces sorted string 1`] = `"some string"`; 912 | 913 | exports[`Backward compatibility possible options type: string coerce option True sort option: TypedArrayTrue trim option: True produces valid hash 1`] = `"61d034473102d7dac305902770471fd50f4c5b26f6831a56dd90b5184b3c30fc"`; 914 | -------------------------------------------------------------------------------- /__tests__/compatibility.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from '@jest/globals'; 2 | 3 | import { hasher } from '../src/hasher'; 4 | import type { SortOptions } from '../src/objectSorter'; 5 | 6 | describe('Backward compatibility', () => { 7 | class UnknownClass { 8 | protected name: string; 9 | constructor() { 10 | this.name = 'unknown'; 11 | } 12 | toString(): string { 13 | return JSON.stringify(this); 14 | } 15 | } 16 | 17 | const testData = { 18 | objects: { 19 | noSort: { 20 | a: 1, 21 | b: 2, 22 | c: 3, 23 | d: { 24 | e: 4, 25 | f: 5, 26 | }, 27 | g: 0, 28 | h: undefined, 29 | i: null, 30 | j: new Set([1, 2, 3, 4, 5]), 31 | k: new Map([ 32 | [1, 1], 33 | [2, 2], 34 | [3, 3], 35 | ]), 36 | l: new Date(0), 37 | m: Symbol(), 38 | n: function n() { 39 | return 'n'; 40 | }, 41 | o: [5, 4, 3, 2, 1, 0], 42 | p: BigInt(123450), 43 | x: new UnknownClass(), 44 | y: true, 45 | }, 46 | noCoerce: { 47 | a: 1, 48 | b: 2, 49 | c: 3, 50 | d: { 51 | e: 4, 52 | f: 5, 53 | }, 54 | g: 0, 55 | h: undefined, 56 | i: null, 57 | j: new Set([1, 2, 3, 4, 5]), 58 | k: new Map([ 59 | [1, 1], 60 | [2, 2], 61 | [3, 3], 62 | ]), 63 | l: new Date(0), 64 | m: Symbol(), 65 | n: function n() { 66 | return 'n'; 67 | }, 68 | o: [5, 4, 3, 2, 1, 0], 69 | p: BigInt(123450), 70 | x: new UnknownClass(), 71 | y: true, 72 | }, 73 | sort: { 74 | d: { 75 | e: 4, 76 | f: 5, 77 | }, 78 | b: 2, 79 | a: 1, 80 | c: 3, 81 | k: new Map([ 82 | [3, 3], 83 | [2, 2], 84 | [1, 1], 85 | ]), 86 | g: 0, 87 | o: [4, 2, 1, 3, 5, 0], 88 | p: BigInt(123450), 89 | h: undefined, 90 | n: function n() { 91 | return 'n'; 92 | }, 93 | j: new Set([2, 4, 3, 5, 1]), 94 | l: new Date(0), 95 | i: null, 96 | m: Symbol(), 97 | x: new UnknownClass(), 98 | y: new Boolean(true), 99 | }, 100 | coerce: { 101 | a: true, 102 | b: '2', 103 | c: new String('3'), 104 | d: { 105 | e: new Number(4), 106 | f: '5', 107 | }, 108 | g: false, 109 | h: null, 110 | i: undefined, 111 | j: new Set(['1', 2, '3', 4, 5]), 112 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 113 | k: new Map([ 114 | ['1', 1], 115 | [2, '2'], 116 | [3, 3], 117 | ]), 118 | l: new Date(0), 119 | m: Symbol(), 120 | n: function n() { 121 | return 'n'; 122 | }, 123 | o: ['5', 4, '3', 2, true, false], 124 | p: BigInt(123450), 125 | x: new UnknownClass(), 126 | y: true, 127 | }, 128 | sortCoerce: { 129 | b: 2, 130 | n: function n() { 131 | return 'n'; 132 | }, 133 | g: false, 134 | j: new Set([4, 2, 1, 3, 5]), 135 | a: true, 136 | i: undefined, 137 | d: { 138 | f: 5, 139 | e: '4', 140 | }, 141 | x: new UnknownClass(), 142 | o: ['5', 4, '3', 2, true, false], 143 | p: BigInt(123450), 144 | c: '3', 145 | l: new Date(0), 146 | k: new Map([ 147 | [2, 2], 148 | [3, 3], 149 | [1, 1], 150 | ]), 151 | h: null, 152 | m: Symbol(), 153 | y: new Number(1), 154 | }, 155 | }, 156 | }; 157 | 158 | describe('trim=true', () => { 159 | describe('sort=true coerce=true', () => { 160 | const hash = hasher({ sort: true, coerce: true, trim: true }); 161 | test('coerce', () => { 162 | expect(hash.hash(testData.objects.coerce)).toBe( 163 | 'fce5fc0483350eadaf1e506a30801e4744984a192f7117fd17b47c59d966aaf2', 164 | ); 165 | }); 166 | test('no coerce', () => { 167 | expect(hash.hash(testData.objects.noCoerce)).toBe( 168 | 'fce5fc0483350eadaf1e506a30801e4744984a192f7117fd17b47c59d966aaf2', 169 | ); 170 | }); 171 | test('sort', () => { 172 | expect(hash.hash(testData.objects.sort)).toBe( 173 | 'fce5fc0483350eadaf1e506a30801e4744984a192f7117fd17b47c59d966aaf2', 174 | ); 175 | }); 176 | test('no sort', () => { 177 | expect(hash.hash(testData.objects.noSort)).toBe( 178 | 'fce5fc0483350eadaf1e506a30801e4744984a192f7117fd17b47c59d966aaf2', 179 | ); 180 | }); 181 | test('sort and coerce', () => { 182 | expect(hash.hash(testData.objects.sortCoerce)).toBe( 183 | 'fce5fc0483350eadaf1e506a30801e4744984a192f7117fd17b47c59d966aaf2', 184 | ); 185 | }); 186 | }); 187 | 188 | describe('sort=true coerce=false', () => { 189 | const hash = hasher({ 190 | sort: true, 191 | coerce: { set: true, symbol: true }, 192 | trim: true, 193 | }); 194 | 195 | test('coerce', () => { 196 | expect(hash.hash(testData.objects.coerce)).toBe( 197 | '4930c339209f05627234b5bdff0577abd99c5ba9c7f7998731183c5123d0057c', 198 | ); 199 | }); 200 | test('no coerce', () => { 201 | expect(hash.hash(testData.objects.noCoerce)).toBe( 202 | '5394d25e67809bacb64ba04dc2daa4763c56918efb1c689438b86373a98e826e', 203 | ); 204 | }); 205 | test('sort', () => { 206 | expect(hash.hash(testData.objects.sort)).toBe( 207 | '5394d25e67809bacb64ba04dc2daa4763c56918efb1c689438b86373a98e826e', 208 | ); 209 | }); 210 | test('no sort', () => { 211 | expect(hash.hash(testData.objects.noSort)).toBe( 212 | '5394d25e67809bacb64ba04dc2daa4763c56918efb1c689438b86373a98e826e', 213 | ); 214 | }); 215 | test('sort and coerce', () => { 216 | expect(hash.hash(testData.objects.sortCoerce)).toBe( 217 | '510f7a95d1d95671c35f912309450bdbd418d32188d34d3980171c4fbb36fbe7', 218 | ); 219 | }); 220 | }); 221 | describe('sort=false coerce=true', () => { 222 | const hash = hasher({ sort: false, coerce: true, trim: true }); 223 | 224 | test('coerce', () => { 225 | expect(hash.hash(testData.objects.coerce)).toBe( 226 | '10791fd23c784c064cce27998a4f7e3bb49a7d45ab0069281008adab3e8a4675', 227 | ); 228 | }); 229 | test('no coerce', () => { 230 | expect(hash.hash(testData.objects.noCoerce)).toBe( 231 | '10791fd23c784c064cce27998a4f7e3bb49a7d45ab0069281008adab3e8a4675', 232 | ); 233 | }); 234 | test('sort', () => { 235 | expect(hash.hash(testData.objects.sort)).toBe( 236 | '61555f24544d9d6154962051a62bebc84327f1f4bcef2c289df053c12a0a4f5c', 237 | ); 238 | }); 239 | test('no sort', () => { 240 | expect(hash.hash(testData.objects.noSort)).toBe( 241 | '10791fd23c784c064cce27998a4f7e3bb49a7d45ab0069281008adab3e8a4675', 242 | ); 243 | }); 244 | test('sort and coerce', () => { 245 | expect(hash.hash(testData.objects.sortCoerce)).toBe( 246 | '38a3b4bf344dd11229ae1ab05e1348414fe42edb98f4a32279b8270071bbb4dc', 247 | ); 248 | }); 249 | }); 250 | describe('sort=false coerce=false', () => { 251 | const hash = hasher({ 252 | sort: false, 253 | coerce: { set: true, symbol: true }, 254 | trim: true, 255 | }); 256 | test('coerce', () => { 257 | expect(hash.hash(testData.objects.coerce)).toBe( 258 | '85989bfe8c8a5aa29d3cd052bb50cf0b3cb5d2177f788bfa0b0b13756b5f9041', 259 | ); 260 | }); 261 | test('no coerce', () => { 262 | expect(hash.hash(testData.objects.noCoerce)).toBe( 263 | 'e302b813a63216fc4a2ccfe5d7412744438768f201116269fa185d60e805cd0c', 264 | ); 265 | }); 266 | test('sort', () => { 267 | expect(hash.hash(testData.objects.sort)).toBe( 268 | '74e1458df6bd97860fd8cdf6db79408ee30dbcc4265371057cbb0733061debaf', 269 | ); 270 | }); 271 | test('no sort', () => { 272 | expect(hash.hash(testData.objects.noSort)).toBe( 273 | 'e302b813a63216fc4a2ccfe5d7412744438768f201116269fa185d60e805cd0c', 274 | ); 275 | }); 276 | test('sort and coerce', () => { 277 | expect(hash.hash(testData.objects.sortCoerce)).toBe( 278 | 'ba5efaa940a6eb779cc1d739ad4d9f423cf1a76d75cc1a0475d992a627586889', 279 | ); 280 | }); 281 | }); 282 | }); 283 | 284 | describe('trim=false', () => { 285 | describe('sort=true coerce=true', () => { 286 | const hash = hasher(); 287 | describe('compatibility', function () { 288 | test('sort strings', () => { 289 | expect(hash.sort(testData.objects.coerce)).toBe( 290 | `{a:1,b:2,c:3,d:{e:4,f:5},g:0,h:,i:,j:[1,2,3,4,5],k:[1,1;2,2;3,3],l:1970-01-01T00:00:00.000Z,m:<:smbl>,n:n=>function n() {\n return 'n';\n },o:[0,1,2,3,4,5],p:123450,x:<:UnknownClass>:{"name":"unknown"},y:1}`, 291 | ); 292 | expect(hash.sort(testData.objects.noCoerce)).toBe( 293 | `{a:1,b:2,c:3,d:{e:4,f:5},g:0,h:,i:,j:[1,2,3,4,5],k:[1,1;2,2;3,3],l:1970-01-01T00:00:00.000Z,m:<:smbl>,n:n=>function n() {\n return 'n';\n },o:[0,1,2,3,4,5],p:123450,x:<:UnknownClass>:{"name":"unknown"},y:1}`, 294 | ); 295 | expect(hash.sort(testData.objects.sort)).toBe( 296 | `{a:1,b:2,c:3,d:{e:4,f:5},g:0,h:,i:,j:[1,2,3,4,5],k:[1,1;2,2;3,3],l:1970-01-01T00:00:00.000Z,m:<:smbl>,n:n=>function n() {\n return 'n';\n },o:[0,1,2,3,4,5],p:123450,x:<:UnknownClass>:{"name":"unknown"},y:1}`, 297 | ); 298 | expect(hash.sort(testData.objects.noSort)).toBe( 299 | `{a:1,b:2,c:3,d:{e:4,f:5},g:0,h:,i:,j:[1,2,3,4,5],k:[1,1;2,2;3,3],l:1970-01-01T00:00:00.000Z,m:<:smbl>,n:n=>function n() {\n return 'n';\n },o:[0,1,2,3,4,5],p:123450,x:<:UnknownClass>:{"name":"unknown"},y:1}`, 300 | ); 301 | expect(hash.sort(testData.objects.sortCoerce)).toBe( 302 | `{a:1,b:2,c:3,d:{e:4,f:5},g:0,h:,i:,j:[1,2,3,4,5],k:[1,1;2,2;3,3],l:1970-01-01T00:00:00.000Z,m:<:smbl>,n:n=>function n() {\n return 'n';\n },o:[0,1,2,3,4,5],p:123450,x:<:UnknownClass>:{"name":"unknown"},y:1}`, 303 | ); 304 | }); 305 | test('hash strings', () => { 306 | expect(hash.hash(testData.objects.coerce)).toBe( 307 | '8f627f585503e6400e79fab0ad4a7e4bf2aa10952f30844207b2f903044a3bbe', 308 | ); 309 | expect(hash.hash(testData.objects.noCoerce)).toBe( 310 | '8f627f585503e6400e79fab0ad4a7e4bf2aa10952f30844207b2f903044a3bbe', 311 | ); 312 | expect(hash.hash(testData.objects.sort)).toBe( 313 | '8f627f585503e6400e79fab0ad4a7e4bf2aa10952f30844207b2f903044a3bbe', 314 | ); 315 | expect(hash.hash(testData.objects.noSort)).toBe( 316 | '8f627f585503e6400e79fab0ad4a7e4bf2aa10952f30844207b2f903044a3bbe', 317 | ); 318 | expect(hash.hash(testData.objects.sortCoerce)).toBe( 319 | '8f627f585503e6400e79fab0ad4a7e4bf2aa10952f30844207b2f903044a3bbe', 320 | ); 321 | }); 322 | }); 323 | describe('sort', () => { 324 | test('should return equal strings', function () { 325 | expect(hash.sort(testData.objects.noSort)).toBe(hash.sort(testData.objects.sort)); 326 | expect(hash.sort(testData.objects.noCoerce)).toBe(hash.sort(testData.objects.coerce)); 327 | expect(hash.sort(testData.objects.sort)).toBe(hash.sort(testData.objects.sortCoerce)); 328 | expect(hash.sort(testData.objects.coerce)).toBe(hash.sort(testData.objects.sortCoerce)); 329 | expect(hash.sort(testData.objects.coerce)).toBe(hash.sort(testData.objects.sortCoerce)); 330 | }); 331 | }); 332 | 333 | describe('hash', () => { 334 | test('should return equal hashes', function () { 335 | expect(hash.hash(testData.objects.noSort)).toBe(hash.hash(testData.objects.sort)); 336 | expect(hash.hash(testData.objects.noCoerce)).toBe(hash.hash(testData.objects.coerce)); 337 | expect(hash.hash(testData.objects.sort)).toBe(hash.hash(testData.objects.sortCoerce)); 338 | expect(hash.hash(testData.objects.coerce)).toBe(hash.hash(testData.objects.sortCoerce)); 339 | expect(hash.hash(testData.objects.coerce)).toBe(hash.hash(testData.objects.sortCoerce)); 340 | }); 341 | }); 342 | }); 343 | 344 | describe('sort=false coerce=true', () => { 345 | const hash = hasher({ sort: false }); 346 | 347 | test('should return different strings', function () { 348 | expect(hash.sort(testData.objects.noSort)).not.toBe(hash.sort(testData.objects.sort)); 349 | expect(hash.sort(testData.objects.noCoerce)).not.toBe(hash.sort(testData.objects.sortCoerce)); 350 | }); 351 | test('should return equal strings', function () { 352 | expect(hash.sort(testData.objects.noCoerce)).toBe(hash.sort(testData.objects.coerce)); 353 | expect(hash.sort(testData.objects.noCoerce)).toBe(hash.sort(testData.objects.noSort)); 354 | }); 355 | }); 356 | 357 | describe('sort=true coerce=false', () => { 358 | const hash = hasher({ coerce: false }); 359 | 360 | test('should return different strings', function () { 361 | expect(hash.sort(testData.objects.noCoerce)).not.toBe(hash.sort(testData.objects.coerce)); 362 | expect(hash.sort(testData.objects.noSort)).not.toBe(hash.sort(testData.objects.sortCoerce)); 363 | }); 364 | test('should return equal strings', function () { 365 | expect(hash.sort(testData.objects.noSort)).toBe(hash.sort(testData.objects.sort)); 366 | expect(hash.sort(testData.objects.noCoerce)).toBe(hash.sort(testData.objects.noSort)); 367 | }); 368 | }); 369 | 370 | describe('sort=false coerce=false', () => { 371 | const hash = hasher({ sort: false, coerce: false }); 372 | 373 | test('should return different strings', function () { 374 | expect(hash.sort(testData.objects.noSort)).not.toBe(hash.sort(testData.objects.sort)); 375 | expect(hash.sort(testData.objects.noCoerce)).not.toBe(hash.sort(testData.objects.coerce)); 376 | }); 377 | test('should return equal strings', function () { 378 | expect(hash.sort(testData.objects.noCoerce)).toBe(hash.sort(testData.objects.noSort)); 379 | }); 380 | }); 381 | }); 382 | 383 | describe('possible options', () => { 384 | const coerceOptions: { [key: string]: boolean } = { 385 | True: true, 386 | False: false, 387 | }; 388 | const sortOptions: { [key: string]: boolean | SortOptions } = { 389 | True: true, 390 | False: false, 391 | TypedArrayTrue: { typedArray: true }, 392 | }; 393 | const trimOptions: { [key: string]: boolean } = { 394 | True: true, 395 | False: false, 396 | }; 397 | const types: { 398 | [key: string]: object | number | string | bigint | boolean; 399 | } = { 400 | Array: Array.from([-1, 21, 3]), 401 | Int8Array: Int8Array.from([11, -22, 3]), 402 | Uint8Array: Uint8Array.from([13, -2, -3]), 403 | Int16Array: Int16Array.from([0, 5, 3]), 404 | Uint16Array: Uint16Array.from([1, 2, 3]), 405 | Int32Array: Int32Array.from([1, 3, 12]), 406 | Uint32Array: Uint32Array.from([123, 4]), 407 | Float32Array: Float32Array.from([1, 8, 3, 4]), 408 | Float64Array: Float64Array.from([7, 3, 3, 1]), 409 | BigUint64Array: BigUint64Array.from([BigInt(-1), BigInt(23), BigInt(123)]), 410 | Buffer: Buffer.from([1, 2, 3]), 411 | Map: new Map([ 412 | [1, 2], 413 | [2, 3], 414 | [3, 4], 415 | ]), 416 | Set: new Set([1, 2, 3]), 417 | Date: new Date(0), 418 | string: 'some string', 419 | number: 19284, 420 | bigint: BigInt(1238573921), 421 | boolean: true, 422 | object: new UnknownClass(), 423 | }; 424 | 425 | describe.each(Object.keys(types))('type: %s', (typeKey: string) => { 426 | describe.each(Object.keys(coerceOptions))('coerce option %s', (coerceKey: string) => { 427 | describe.each(Object.keys(sortOptions))('sort option: %s', (sortKey: string) => { 428 | describe.each(Object.keys(trimOptions))('trim option: %s', (trimKey: string) => { 429 | const type = types[typeKey]; 430 | const coerce = coerceOptions[coerceKey]; 431 | const sort = sortOptions[sortKey]; 432 | const trim = trimOptions[trimKey]; 433 | const hash = hasher({ 434 | coerce: coerce, 435 | sort: sort, 436 | trim: trim, 437 | }); 438 | test('produces sorted string', () => { 439 | expect(hash.sort(type)).toMatchSnapshot(); 440 | }); 441 | test('produces valid hash', () => { 442 | expect(hash.hash(type)).toMatchSnapshot(); 443 | }); 444 | }); 445 | }); 446 | }); 447 | }); 448 | }); 449 | }); 450 | -------------------------------------------------------------------------------- /__tests__/hasher.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from '@jest/globals'; 2 | 3 | import type { Hashable } from '../src/hasher'; 4 | import { hasher } from '../src/hasher'; 5 | 6 | interface MyHashable extends Hashable { 7 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 8 | [key: string]: any; 9 | } 10 | 11 | describe('Hasher', () => { 12 | describe('constructor', () => { 13 | const hash = hasher(); 14 | test('defaults', () => { 15 | expect(hash.sort(['2', true, 3])).toBe('[1,2,3]'); 16 | expect(hash.hash(['2', true, 3])).toBe('a615eeaee21de5179de080de8c3052c8da901138406ba71c38c032845f7d54f4'); 17 | }); 18 | 19 | test('overrides', () => { 20 | expect(hash.sort(['2', true, 3])).toBe('[1,2,3]'); 21 | expect(hash.hash(['2', true, 3], { alg: 'sha512' })).toBe( 22 | '60f7b5dc86ded48785436192a08dbfd04894d7f1b417c4f8d3714679a7f78cb3c833f16a8559a1cf1f32968747dc1d95ef34826263dacf125ded8f5c374be4c0', 23 | ); 24 | expect(hash.hash(['2', true, 3], { enc: 'base64' })).toBe('phXuruId5Red4IDejDBSyNqQEThAa6ccOMAyhF99VPQ='); 25 | }); 26 | 27 | test('hashable', () => { 28 | const hashable: MyHashable = { 29 | value: 'value', 30 | number: 1, 31 | bool: true, 32 | toHashableString: () => 'some_value_to_hash', 33 | }; 34 | expect(hash.sort(hashable)).toBe('some_value_to_hash'); 35 | expect(hash.hash(hashable)).toBe('64204ff2ce2d6bfd2d1f576b58b71d98a08aaa39c8d726fd220b858bfb571039'); 36 | 37 | const anotherHashableWithSameHash: MyHashable = { 38 | value: 'value_another', 39 | number: 5, 40 | toHashableString: () => 'some_value_to_hash', 41 | }; 42 | expect(hash.hash(hashable)).toBe(hash.hash(anotherHashableWithSameHash)); 43 | }); 44 | 45 | test('hashable array', () => { 46 | const arrayHashable = [ 47 | { 48 | value: 'value', 49 | number: 1, 50 | bool: true, 51 | toHashableString: () => 'some_value_to_hash', 52 | }, 53 | { 54 | value: 'value_another', 55 | number: 5, 56 | toHashableString: () => 'another_value_to_hash', 57 | }, 58 | ]; 59 | expect(hash.sort(arrayHashable)).toBe('[another_value_to_hash,some_value_to_hash]'); 60 | 61 | expect(hash.hash(arrayHashable)).toBe('c0705a3e2b55b54d55a6fe675b7dfb48572bd3adf0c54aab621da2b3663a0796'); 62 | 63 | const anotherHashableArrayWithObjectWithTheSameHash = [ 64 | { 65 | someValue: 'somevalue', 66 | toHashableString: () => 'another_value_to_hash', 67 | }, 68 | { 69 | numberValue: 5, 70 | toHashableString: () => 'some_value_to_hash', 71 | }, 72 | ]; 73 | expect(hash.hash(arrayHashable)).toBe(hash.hash(anotherHashableArrayWithObjectWithTheSameHash)); 74 | }); 75 | }); 76 | }); 77 | -------------------------------------------------------------------------------- /__tests__/objectSorter.spec.ts: -------------------------------------------------------------------------------- 1 | import { describe, expect, test } from '@jest/globals'; 2 | 3 | import { hasher } from '../src/hasher'; 4 | import { objectSorter } from '../src/objectSorter'; 5 | 6 | describe('Sorter', () => { 7 | const dataA = { 8 | a: 1, 9 | b: 2, 10 | c: 3, 11 | }; 12 | 13 | const dataB = { 14 | b: 2, 15 | c: 3, 16 | a: 1, 17 | }; 18 | 19 | describe('sort=true coerce=false', () => { 20 | const hash = hasher({ coerce: false }); 21 | test('equal strings', () => { 22 | expect(hash.sort(dataA)).toBe(hash.sort(dataB)); 23 | }); 24 | }); 25 | 26 | describe('sort=false coerce=false', () => { 27 | const hash = hasher({ sort: false, coerce: false }); 28 | test('equal strings', () => { 29 | expect(hash.sort(dataA)).not.toBe(hash.sort(dataB)); 30 | }); 31 | }); 32 | 33 | describe('constructor', () => { 34 | const sort = objectSorter(); 35 | test('defaults', () => { 36 | expect(sort(['2', true, 3])).toBe('[1,2,3]'); 37 | }); 38 | }); 39 | 40 | describe('sort', () => { 41 | test('array', () => { 42 | const hash = hasher({ sort: { array: true } }); 43 | expect(hash.sort([3, 2, 1])).toBe('[1,2,3]'); 44 | }); 45 | test('set', () => { 46 | const hash = hasher({ sort: { set: true } }); 47 | expect(hash.sort(new Set([3, 2, 1]))).toBe('[1,2,3]'); 48 | }); 49 | test('map', () => { 50 | const hash = hasher({ sort: { map: true } }); 51 | expect( 52 | hash.sort( 53 | new Map([ 54 | [3, 3], 55 | [2, 2], 56 | [1, 1], 57 | ]), 58 | ), 59 | ).toBe('[1,1;2,2;3,3]'); 60 | }); 61 | test('dictionary', () => { 62 | const hash = hasher({ sort: { object: true } }); 63 | expect(hash.sort({ c: 3, a: 1, b: 2 })).toBe('{a:1,b:2,c:3}'); 64 | }); 65 | test('buffer', () => { 66 | const hash = hasher({ sort: true, coerce: false }); 67 | expect(hash.sort(Buffer.from([3, 2, 1]))).toBe('[<:n>:3,<:n>:2,<:n>:1]'); 68 | }); 69 | test('Uint8Array', () => { 70 | const hash = hasher({ sort: { typedArray: true }, coerce: false }); 71 | expect(hash.sort(Uint8Array.from([2, 3, 1]))).toBe('[<:n>:1,<:n>:2,<:n>:3]'); 72 | }); 73 | }); 74 | 75 | describe('trim', () => { 76 | test('function', () => { 77 | const hash = hasher({ trim: { function: true } }); 78 | const fn = function fn(): string { 79 | return 'hello world'; 80 | }; 81 | expect(hash.sort(fn)).toBe(`fn=>function fn() { return 'hello world'; }`); 82 | }); 83 | test('string', () => { 84 | const hash = hasher({ trim: { string: true } }); 85 | const str = ` foo bar 86 | baz`; 87 | expect(hash.sort(str)).toBe(`foo bar baz`); 88 | }); 89 | }); 90 | 91 | describe('stringifiers', () => { 92 | test('unknown', () => { 93 | const hash = hasher(); 94 | expect(hash.sort(Object.create(null))).toBe('<:unknonw>:unknown'); 95 | }); 96 | test('unknown with data', () => { 97 | const hash = hasher(); 98 | 99 | const obj = Object.create(null) as Record; 100 | obj['a'] = 1; 101 | 102 | expect(hash.sort(obj)).toBe('<:unknonw>:{"a":1}'); 103 | }); 104 | }); 105 | }); 106 | -------------------------------------------------------------------------------- /ci/changelog.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | '@semantic-release/changelog', 3 | { 4 | changelogFile: 'docs/CHANGELOG.md', 5 | }, 6 | ]; 7 | -------------------------------------------------------------------------------- /ci/commit-analyzer.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | '@semantic-release/commit-analyzer', 3 | { 4 | preset: 'conventionalcommits', 5 | releaseRules: [ 6 | { breaking: true, release: 'major' }, 7 | { scope: 'release-skip', release: false }, 8 | { type: 'chore', scope: 'release', release: false }, 9 | { scope: 'deps', release: 'patch' }, 10 | { type: 'feat', release: 'minor' }, 11 | { type: 'build', release: 'patch' }, 12 | { type: 'refactor', release: 'patch' }, 13 | { type: 'fix', release: 'patch' }, 14 | { type: 'pref', release: 'patch' }, 15 | { type: 'revert', release: 'patch' }, 16 | { type: 'chore', release: false }, 17 | { type: 'docs', release: false }, 18 | { type: 'style', release: false }, 19 | { type: 'test', release: false }, 20 | ], 21 | }, 22 | ]; 23 | -------------------------------------------------------------------------------- /ci/git-service-deploy.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | '@semantic-release/git', 3 | { 4 | assets: ['ci', 'docs', 'package.json'], 5 | message: 'chore(release): ${nextRelease.version} \n\n${nextRelease.notes}', 6 | }, 7 | ]; 8 | -------------------------------------------------------------------------------- /ci/git.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | '@semantic-release/git', 3 | { 4 | assets: ['ci', 'docs', 'package.json'], 5 | }, 6 | ]; 7 | -------------------------------------------------------------------------------- /ci/gitlab-release.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | '@semantic-release/github', 3 | { 4 | message: 'chore(release): ${nextRelease.version} \n\n${nextRelease.notes}', 5 | }, 6 | ]; 7 | -------------------------------------------------------------------------------- /ci/npm-change-version.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | '@semantic-release/npm', 3 | { 4 | npmPublish: false, 5 | }, 6 | ]; 7 | -------------------------------------------------------------------------------- /ci/npm-publish.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | '@semantic-release/npm', 3 | { 4 | npmPublish: true, 5 | }, 6 | ]; 7 | -------------------------------------------------------------------------------- /ci/release-notes.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | '@semantic-release/release-notes-generator', 3 | { 4 | preset: 'conventionalcommits', 5 | writerOpts: { 6 | groupBy: 'type', 7 | commitGroupsSort: ['feat', 'fix', 'perf', 'docs', 'revert', 'refactor', 'chore'], 8 | commitsSort: 'header', 9 | }, 10 | presetConfig: { 11 | types: [ 12 | { type: 'build', section: '🦊 CI/CD', hidden: true }, 13 | { type: 'chore', section: '🧾 Other', hidden: false }, 14 | { type: 'ci', section: '🦊 CI/CD', hidden: true }, 15 | { type: 'docs', section: '📔 Docs', hidden: false }, 16 | { type: 'example', section: '📝 Examples', hidden: false }, 17 | { type: 'feat', section: '🚀 Features', hidden: false }, 18 | { type: 'fix', section: '🛠 Fixes', hidden: false }, 19 | { type: 'perf', section: '⏩ Performance', hidden: false }, 20 | { type: 'refactor', section: '✂️ Refactor', hidden: false }, 21 | { type: 'revert', section: '🙅‍️ Reverts', hidden: false }, 22 | { type: 'style', section: '💈 Style', hidden: true }, 23 | { type: 'test', section: '🧪 Tests', hidden: true }, 24 | ], 25 | }, 26 | }, 27 | ]; 28 | -------------------------------------------------------------------------------- /docs/CHANGELOG-v2.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [2.3.10](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.9...v2.3.10) (2021-09-14) 6 | 7 | 8 | ### Misc 9 | 10 | * **deps:** update ([996e344](https://github.com/SkeLLLa/node-object-hash/commit/996e3441a4560c2f909f8e9e0ef674201a0275c2)) 11 | 12 | ### [2.3.9](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.8...v2.3.9) (2021-08-18) 13 | 14 | ### [2.3.8](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.7...v2.3.8) (2021-07-31) 15 | 16 | ### [2.3.7](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.6...v2.3.7) (2021-06-17) 17 | 18 | 19 | ### Misc 20 | 21 | * update links ([f48c0c9](https://github.com/SkeLLLa/node-object-hash/commit/f48c0c99c7d9f60b7a75109e72a7d373d3913d1b)) 22 | 23 | ### [2.3.6](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.5...v2.3.6) (2021-06-17) 24 | 25 | 26 | ### Tests 27 | 28 | * update jest types ([b1a7774](https://github.com/SkeLLLa/node-object-hash/commit/b1a7774e96d640e9cbce95527c629bdb9ba2d07e)) 29 | 30 | ### [2.3.5](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.4...v2.3.5) (2021-06-17) 31 | 32 | 33 | ### Misc 34 | 35 | * **deps:** update ([d16d2b2](https://github.com/SkeLLLa/node-object-hash/commit/d16d2b2ecaa36bdbb3a4c0d238be4dae4bf18222)) 36 | 37 | 38 | ### Bug fixes 39 | 40 | * revert ts to 4.2 ([6423ea7](https://github.com/SkeLLLa/node-object-hash/commit/6423ea701113f92f9570169c63138dde012f20ed)) 41 | 42 | ### [2.3.4](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.3...v2.3.4) (2021-06-14) 43 | 44 | ### [2.3.3](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.2...v2.3.3) (2021-05-29) 45 | 46 | ### [2.3.2](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.1...v2.3.2) (2021-05-28) 47 | 48 | ### [2.3.1](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.0...v2.3.1) (2021-02-28) 49 | 50 | 51 | ### Tests 52 | 53 | * add tests for every possible option ([0fc56f0](https://github.com/SkeLLLa/node-object-hash/commit/0fc56f08bb8d7cadcfed1d136eb3b2f5b89fa8ba)) 54 | 55 | ## [2.3.0](https://github.com/SkeLLLa/node-object-hash/compare/v2.2.0...v2.3.0) (2021-02-24) 56 | 57 | 58 | ### Features 59 | 60 | * add sorting option for typed arrays ([28d5344](https://github.com/SkeLLLa/node-object-hash/commit/28d53445d1f59213ac32de77890b0311a0dffe7f)) 61 | 62 | 63 | ### Bug fixes 64 | 65 | * stringification of typed arrays ([bc1e1a6](https://github.com/SkeLLLa/node-object-hash/commit/bc1e1a6654036935769006df4823cd16a67c0a62)) 66 | 67 | ## [2.2.0](https://github.com/SkeLLLa/node-object-hash/compare/v2.1.2...v2.2.0) (2021-02-22) 68 | 69 | 70 | ### Features 71 | 72 | * add bigint support ([544d97e](https://github.com/SkeLLLa/node-object-hash/commit/544d97e9712961effae0a6940357bb1f8b9adcc6)) 73 | 74 | 75 | ### Bug fixes 76 | 77 | * coerce option for bigint ([ca2f87c](https://github.com/SkeLLLa/node-object-hash/commit/ca2f87c7af8270ec5ce89de1bb166257000ffca1)) 78 | * typo in doc ([d9d7e24](https://github.com/SkeLLLa/node-object-hash/commit/d9d7e24f2b45e5b14c92a01da648f6ad9daf8427)) 79 | * **typos:** fix typos in test and contributing.md ([2ee3ddd](https://github.com/SkeLLLa/node-object-hash/commit/2ee3ddde2cd062844b2d3829f13647bf78b88eb7)) 80 | 81 | ### [2.1.2](https://github.com/SkeLLLa/node-object-hash/compare/v2.1.1...v2.1.2) (2021-01-29) 82 | 83 | ### [2.1.1](https://github.com/SkeLLLa/node-object-hash/compare/v2.1.0...v2.1.1) (2021-01-29) 84 | 85 | ## 2.1.0 (2021-01-27) 86 | 87 | ### Features 88 | 89 | - added warnings to eslint errors ([422c893](https://github.com/SkeLLLa/node-object-hash/commit/422c8932e8ad140553259e9e49555f7ddfef4db1)) 90 | - fixed eslint errors ([e9245f7](https://github.com/SkeLLLa/node-object-hash/commit/e9245f7aa3aa14238fbb62d97dacdcc414ec0f40)) 91 | - fixed npm script issue ([0bf8c17](https://github.com/SkeLLLa/node-object-hash/commit/0bf8c175ae058bbc442628e953ff577be500d865)) 92 | - updated typescript, migrated to tslint ([3a40fcc](https://github.com/SkeLLLa/node-object-hash/commit/3a40fccbe03f265b8452b59ac1434cb1b0ceb6a3)) 93 | 94 | ### Bug fixes 95 | 96 | - remove unnecessary checks ([1bbad3a](https://github.com/SkeLLLa/node-object-hash/commit/1bbad3a2f6dc1dd28ed48ab2ca065b878b450f53)) 97 | - **lint:** fix eslint ([caeac70](https://github.com/SkeLLLa/node-object-hash/commit/caeac700031c7637448e4d76f2d2fe9276df2b01)) 98 | - **types:** fix encoding type ([cdc6958](https://github.com/SkeLLLa/node-object-hash/commit/cdc69588b781095764d574b6f14e00b2609ff4e5)) 99 | - improve checking of Hashable applicant ([3856207](https://github.com/SkeLLLa/node-object-hash/commit/38562077f9465e1aa871e607fd13de861f10582d)) 100 | 101 | ### Misc 102 | 103 | - **deps:** bump deps ([a370ea2](https://github.com/SkeLLLa/node-object-hash/commit/a370ea2bf9b89b94063d5fb3e584da20dd0eb855)) 104 | - **pj:** add prettier to docs ([77b6001](https://github.com/SkeLLLa/node-object-hash/commit/77b6001674284fc613e95fd44cddb9aec143aeb5)) 105 | - **pj:** update scripts ([dd8c778](https://github.com/SkeLLLa/node-object-hash/commit/dd8c778301899e41dacb73f83426a733bb327dda)) 106 | 107 | ## [2.0.0](https://gitlab.com/m03geek/node-object-hash/compare/v2.0.0-rc.1...v2.0.0) (2019-09-07) 108 | 109 | ## [2.0.0-rc.1](https://gitlab.com/m03geek/node-object-hash/compare/v2.0.0-rc.0...v2.0.0-rc.1) (2019-09-03) 110 | 111 | ## [2.0.0-rc.0](https://gitlab.com/m03geek/node-object-hash/compare/v1.4.2...v2.0.0-rc.0) (2019-09-03) 112 | 113 | ### ⚠ BREAKING CHANGES 114 | 115 | - Library rewritten in typescript that could cause some side-effects, but it should not. 116 | - With `coerce=false` `Set`s will no longer generate the same hashes as `Array`s. In order to restore previous behavior set `coerce.set=true`. 117 | - With `coerce=false` `Symbol`s will generate hash based on symbol `.toString` value. That's useful for `Symbol.for('smth')`. If `coerce.symbol=true` all `Symbols`s will have equal hashes. 118 | TLDR; If you use library with `Set`s or `Symbol`s with `coerce=false` in order to keep hashes the same as in `v1.X.X` you should use following constructor: 119 | 120 | ``` 121 | const hasher = require('node-object-hash')({coerce: {set: true, symbol: true}}) 122 | ``` 123 | 124 | - Object sorter sources moved to `dist` directory. If you required it directly via `require('node-object-hash/objectSorter')` you should change it to require('node-object-hash/dist/objectSorter'). 125 | - Removed old `v0` version from code. 126 | - Changed license to MIT. 127 | 128 | ### Bug Fixes 129 | 130 | - **hasher:** fix options ([05241ca](https://gitlab.com/m03geek/node-object-hash/commit/05241ca)) 131 | 132 | ### Features 133 | 134 | - major refactor ([450471e](https://gitlab.com/m03geek/node-object-hash/commit/450471e)) 135 | - New granular options. Now you can specify what types need to be sorted or coerced. 136 | - Add new `trim` option. It can be used to remove unncecessary spaces in `string`s or `function` bodies. 137 | - Library rewritten to typescript, so it may have better ts compatibility. 138 | 139 | ## [1.4.X](https://gitlab.com/m03geek/node-object-hash/compare/v1.3.0...v1.4.2) 140 | 141 | ### Features 142 | 143 | - Add support for objects without constructor #11 [PR @futpib](https://gitlab.com/m03geek/node-object-hash/pull/12) 144 | - Simplify eslint rules, update codestyle 145 | 146 | ### Fixes 147 | 148 | - Fix npm links issues in readme 149 | - Update dev dependencies 150 | 151 | ## [1.3.X](https://gitlab.com/m03geek/node-object-hash/compare/v1.2.0...v1.3.0) 152 | 153 | ### Features 154 | 155 | - Add definition types to support typescript 156 | - Add >=node-8.0.0 support in tests. 157 | 158 | ## [1.2.X](https://gitlab.com/m03geek/node-object-hash/compare/v1.1.6...v1.2.0) 159 | 160 | ### Features 161 | 162 | - Added typed arrays support 163 | - Added primitive type constructors support 164 | - Add more docs about type mapping and type coercion 165 | 166 | ## [1.1.X](https://gitlab.com/m03geek/node-object-hash/compare/v1.0.3..v1.1.6) 167 | 168 | ### Features 169 | 170 | Mainly all changes affected codestyle and documentation to provide better 171 | experience using this library. There are no changes that should affect 172 | functionality. 173 | 174 | - Renamed `sortObject` function to `sort` (old one is still present in code 175 | for backward compatibility). 176 | - Performed some refactoring for better codestyle and documentation. 177 | - Old version (`0.X.X`) moved to subfolder (`./v0`). 178 | - Advanced API reference added: [link](API.md). 179 | 180 | ## [1.0.0](https://gitlab.com/m03geek/node-object-hash/compare/v0.1.0...v1.0.3) 181 | 182 | - Sorting mechanism rewritten form ES6 Maps to simple arrays 183 | (add <=node-4.0.0 support) 184 | - Performance optimization (~2 times faster than 0.x.x) 185 | - API changes: 186 | - Now module returns 'constructor' function, where you can set 187 | default parameters: `var objectHash = require('node-object-hash')(options);` 188 | 189 | In case if you still need an old 0.x.x version it's available in `hash.js` 190 | file. 191 | -------------------------------------------------------------------------------- /docs/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## [3.1.1](https://github.com/SkeLLLa/node-object-hash/compare/v3.1.0...v3.1.1) (2024-12-17) 2 | 3 | 4 | ### 🛠 Fixes 5 | 6 | * Objects without prototype are now properly stringified ([a6d1c08](https://github.com/SkeLLLa/node-object-hash/commit/a6d1c0810ef14642bba6254708820cab795f6829)) 7 | 8 | ## [3.1.0](https://github.com/SkeLLLa/node-object-hash/compare/v3.0.0...v3.1.0) (2024-12-17) 9 | 10 | 11 | ### 🛠 Fixes 12 | 13 | * add packageManager ([1a64254](https://github.com/SkeLLLa/node-object-hash/commit/1a64254e12b84cf55b5d500af9f08f41837f2c60)) 14 | * ci versions ([c892993](https://github.com/SkeLLLa/node-object-hash/commit/c892993c1aaa1501caf5c227754814167db67479)) 15 | * pm ([91a1ec1](https://github.com/SkeLLLa/node-object-hash/commit/91a1ec116e736c6455485c82e1ba13b78c56bf97)) 16 | * revert version from actions ([89ac590](https://github.com/SkeLLLa/node-object-hash/commit/89ac5907fd2f0dba130a31b570d55ad052b3a308)) 17 | 18 | 19 | ### 🚀 Features 20 | 21 | * update ci, node 22 ([0abf80e](https://github.com/SkeLLLa/node-object-hash/commit/0abf80e3f9f2195391c1a4df2c370966b31f6064)) 22 | 23 | ## [3.0.0](https://github.com/SkeLLLa/node-object-hash/compare/v2.3.10...v3.0.0) (2023-04-14) 24 | 25 | 26 | ### ⚠ BREAKING CHANGES 27 | 28 | * removed namespaces and refactored import format 29 | 30 | ### 🛠 Fixes 31 | 32 | * remove npm package lock ([a082cb9](https://github.com/SkeLLLa/node-object-hash/commit/a082cb973171e0813216365d51df148fc2791807)) 33 | * update lockfile ([e44e27b](https://github.com/SkeLLLa/node-object-hash/commit/e44e27bd25cbb1b1476b76e7b732c20681acf910)) 34 | * **ci:** update release action ([22b763e](https://github.com/SkeLLLa/node-object-hash/commit/22b763e107ce3039b5a458bc2131c23e8a618b9e)) 35 | 36 | 37 | ### 🚀 Features 38 | 39 | * typescript 5 migration ([debf48f](https://github.com/SkeLLLa/node-object-hash/commit/debf48fc0e8d3f2746455925e0d975b39873c4e1)) 40 | -------------------------------------------------------------------------------- /docs/api/.nojekyll: -------------------------------------------------------------------------------- 1 | TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. -------------------------------------------------------------------------------- /docs/api/README.md: -------------------------------------------------------------------------------- 1 | # Node object hash 2 | 3 | # # Node object hash 4 | 5 | ## Table of contents 6 | 7 | ### Modules 8 | 9 | - [hasher](modules/hasher.md) 10 | - [objectSorter](modules/objectSorter.md) 11 | -------------------------------------------------------------------------------- /docs/api/interfaces/hasher.Hashable.md: -------------------------------------------------------------------------------- 1 | [# Node object hash](../README.md) / [hasher](../modules/hasher.md) / Hashable 2 | 3 | # Interface: Hashable 4 | 5 | [hasher](../modules/hasher.md).Hashable 6 | 7 | If object implements Hashable interface then value from toHash 8 | will be used for hash function. It means that the different objects 9 | with the function toHash that return the same value will have the same hash 10 | 11 | ## Table of contents 12 | 13 | ### Properties 14 | 15 | - [toHashableString](hasher.Hashable.md#tohashablestring) 16 | 17 | ## Properties 18 | 19 | ### toHashableString 20 | 21 | • **toHashableString**: () => `string` 22 | 23 | #### Type declaration 24 | 25 | ▸ (): `string` 26 | 27 | ##### Returns 28 | 29 | `string` 30 | 31 | #### Defined in 32 | 33 | [hasher.ts:38](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/hasher.ts#L38) 34 | -------------------------------------------------------------------------------- /docs/api/interfaces/hasher.Hasher.md: -------------------------------------------------------------------------------- 1 | [# Node object hash](../README.md) / [hasher](../modules/hasher.md) / Hasher 2 | 3 | # Interface: Hasher 4 | 5 | [hasher](../modules/hasher.md).Hasher 6 | 7 | ## Type parameters 8 | 9 | | Name | Type | 10 | | :--- | :-------- | 11 | | `T` | `unknown` | 12 | 13 | ## Table of contents 14 | 15 | ### Methods 16 | 17 | - [hash](hasher.Hasher.md#hash) 18 | - [sort](hasher.Hasher.md#sort) 19 | - [sortObject](hasher.Hasher.md#sortobject) 20 | 21 | ## Methods 22 | 23 | ### hash 24 | 25 | ▸ **hash**(`object`, `opts?`): `string` 26 | 27 | Create hash of an object 28 | 29 | #### Parameters 30 | 31 | | Name | Type | Description | 32 | | :------- | :----------------------------------------- | :------------ | 33 | | `object` | [`Hashable`](hasher.Hashable.md) \| `T` | source object | 34 | | `opts?` | [`HasherOptions`](hasher.HasherOptions.md) | - | 35 | 36 | #### Returns 37 | 38 | `string` 39 | 40 | hash string of an object 41 | 42 | #### Defined in 43 | 44 | [hasher.ts:47](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/hasher.ts#L47) 45 | 46 | --- 47 | 48 | ### sort 49 | 50 | ▸ **sort**(`object`): `string` 51 | 52 | Create sorted string from an object 53 | 54 | #### Parameters 55 | 56 | | Name | Type | Description | 57 | | :------- | :--- | :------------ | 58 | | `object` | `T` | source object | 59 | 60 | #### Returns 61 | 62 | `string` 63 | 64 | sorted string from an object 65 | 66 | #### Defined in 67 | 68 | [hasher.ts:53](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/hasher.ts#L53) 69 | 70 | --- 71 | 72 | ### sortObject 73 | 74 | ▸ **sortObject**(`object`): `string` 75 | 76 | Create sorted string from an object 77 | 78 | **`Alias`** 79 | 80 | sort 81 | 82 | #### Parameters 83 | 84 | | Name | Type | Description | 85 | | :------- | :--- | :------------ | 86 | | `object` | `T` | source object | 87 | 88 | #### Returns 89 | 90 | `string` 91 | 92 | sorted string from an object 93 | 94 | #### Defined in 95 | 96 | [hasher.ts:60](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/hasher.ts#L60) 97 | -------------------------------------------------------------------------------- /docs/api/interfaces/hasher.HasherOptions.md: -------------------------------------------------------------------------------- 1 | [# Node object hash](../README.md) / [hasher](../modules/hasher.md) / HasherOptions 2 | 3 | # Interface: HasherOptions 4 | 5 | [hasher](../modules/hasher.md).HasherOptions 6 | 7 | Object hasher options 8 | 9 | ## Hierarchy 10 | 11 | - [`SorterOptions`](objectSorter.SorterOptions.md) 12 | 13 | ↳ **`HasherOptions`** 14 | 15 | ## Table of contents 16 | 17 | ### Properties 18 | 19 | - [alg](hasher.HasherOptions.md#alg) 20 | - [coerce](hasher.HasherOptions.md#coerce) 21 | - [enc](hasher.HasherOptions.md#enc) 22 | - [sort](hasher.HasherOptions.md#sort) 23 | - [trim](hasher.HasherOptions.md#trim) 24 | 25 | ## Properties 26 | 27 | ### alg 28 | 29 | • `Optional` **alg**: `string` 30 | 31 | Hash algorithm to use 32 | 33 | **`Default`** 34 | 35 | ```ts 36 | 'sha256'; 37 | ``` 38 | 39 | #### Defined in 40 | 41 | [hasher.ts:24](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/hasher.ts#L24) 42 | 43 | --- 44 | 45 | ### coerce 46 | 47 | • `Optional` **coerce**: `boolean` \| [`CoerceOptions`](objectSorter.CoerceOptions.md) 48 | 49 | If `true` enables type coercion. 50 | Advanced coerce options could be provided as object 51 | 52 | **`Default`** 53 | 54 | ```ts 55 | true; 56 | ``` 57 | 58 | #### Inherited from 59 | 60 | [SorterOptions](objectSorter.SorterOptions.md).[coerce](objectSorter.SorterOptions.md#coerce) 61 | 62 | #### Defined in 63 | 64 | [objectSorter.ts:170](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L170) 65 | 66 | --- 67 | 68 | ### enc 69 | 70 | • `Optional` **enc**: `BinaryToTextEncoding` 71 | 72 | String encoding for hash 73 | 74 | **`Default`** 75 | 76 | ```ts 77 | 'hex'; 78 | ``` 79 | 80 | #### Defined in 81 | 82 | [hasher.ts:29](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/hasher.ts#L29) 83 | 84 | --- 85 | 86 | ### sort 87 | 88 | • `Optional` **sort**: `boolean` \| [`SortOptions`](objectSorter.SortOptions.md) 89 | 90 | If `true` enables sorting. 91 | Advanced sorting options could be provided as object 92 | 93 | **`Default`** 94 | 95 | ```ts 96 | true; 97 | ``` 98 | 99 | #### Inherited from 100 | 101 | [SorterOptions](objectSorter.SorterOptions.md).[sort](objectSorter.SorterOptions.md#sort) 102 | 103 | #### Defined in 104 | 105 | [objectSorter.ts:176](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L176) 106 | 107 | --- 108 | 109 | ### trim 110 | 111 | • `Optional` **trim**: `boolean` \| [`TrimOptions`](objectSorter.TrimOptions.md) 112 | 113 | If `true` enables trimming and multiple whitespace replacement. 114 | Advanced sorting options could be provided as object. 115 | 116 | **`Default`** 117 | 118 | ```ts 119 | false; 120 | ``` 121 | 122 | #### Inherited from 123 | 124 | [SorterOptions](objectSorter.SorterOptions.md).[trim](objectSorter.SorterOptions.md#trim) 125 | 126 | #### Defined in 127 | 128 | [objectSorter.ts:182](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L182) 129 | -------------------------------------------------------------------------------- /docs/api/interfaces/objectSorter.CoerceOptions.md: -------------------------------------------------------------------------------- 1 | [# Node object hash](../README.md) / [objectSorter](../modules/objectSorter.md) / CoerceOptions 2 | 3 | # Interface: CoerceOptions 4 | 5 | [objectSorter](../modules/objectSorter.md).CoerceOptions 6 | 7 | Advanced coerce options 8 | 9 | ## Table of contents 10 | 11 | ### Properties 12 | 13 | - [bigint](objectSorter.CoerceOptions.md#bigint) 14 | - [boolean](objectSorter.CoerceOptions.md#boolean) 15 | - [date](objectSorter.CoerceOptions.md#date) 16 | - [function](objectSorter.CoerceOptions.md#function) 17 | - [null](objectSorter.CoerceOptions.md#null) 18 | - [number](objectSorter.CoerceOptions.md#number) 19 | - [set](objectSorter.CoerceOptions.md#set) 20 | - [string](objectSorter.CoerceOptions.md#string) 21 | - [symbol](objectSorter.CoerceOptions.md#symbol) 22 | - [undefined](objectSorter.CoerceOptions.md#undefined) 23 | 24 | ## Properties 25 | 26 | ### bigint 27 | 28 | • `Optional` **bigint**: `boolean` 29 | 30 | If `true` converts BigInt to string 31 | 32 | **`Example`** 33 | 34 | ```ts 35 | // coerce.bigint = true 36 | 1n === '1'; 37 | ``` 38 | 39 | **`Example`** 40 | 41 | ```ts 42 | // coerce.bigint = false 43 | 1n !== '1'; 44 | ``` 45 | 46 | **`Default`** 47 | 48 | ```ts 49 | true; 50 | ``` 51 | 52 | #### Defined in 53 | 54 | [objectSorter.ts:43](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L43) 55 | 56 | --- 57 | 58 | ### boolean 59 | 60 | • `Optional` **boolean**: `boolean` 61 | 62 | If `true` converts booleans to string `1` and `0` 63 | 64 | **`Example`** 65 | 66 | ```ts 67 | // coerce.boolean = true 68 | true === 1; 69 | false === '0'; 70 | ``` 71 | 72 | **`Example`** 73 | 74 | ```ts 75 | // coerce.boolean = true 76 | true !== 1; 77 | false !== '0'; 78 | ``` 79 | 80 | **`Default`** 81 | 82 | ```ts 83 | true; 84 | ``` 85 | 86 | #### Defined in 87 | 88 | [objectSorter.ts:21](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L21) 89 | 90 | --- 91 | 92 | ### date 93 | 94 | • `Optional` **date**: `boolean` 95 | 96 | If `true` dates may equal the same formatted strings 97 | 98 | **`Example`** 99 | 100 | ```ts 101 | // coerce.date = true 102 | ``` 103 | 104 | **`Example`** 105 | 106 | ```ts 107 | // coerce.date = false 108 | ``` 109 | 110 | **`Default`** 111 | 112 | ```ts 113 | true; 114 | ``` 115 | 116 | #### Defined in 117 | 118 | [objectSorter.ts:105](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L105) 119 | 120 | --- 121 | 122 | ### function 123 | 124 | • `Optional` **function**: `boolean` 125 | 126 | If `true` functions may equal the same formatted strings 127 | 128 | **`Example`** 129 | 130 | ```ts 131 | // coerce.function = true 132 | ``` 133 | 134 | **`Example`** 135 | 136 | ```ts 137 | // coerce.function = false 138 | ``` 139 | 140 | **`Default`** 141 | 142 | ```ts 143 | true; 144 | ``` 145 | 146 | #### Defined in 147 | 148 | [objectSorter.ts:96](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L96) 149 | 150 | --- 151 | 152 | ### null 153 | 154 | • `Optional` **null**: `boolean` 155 | 156 | If `true` null will be equal to empty string 157 | 158 | **`Example`** 159 | 160 | ```ts 161 | // coerce.null = true 162 | null === ''; 163 | ``` 164 | 165 | **`Example`** 166 | 167 | ```ts 168 | // coerce.null = false 169 | null !== ''; 170 | ``` 171 | 172 | **`Default`** 173 | 174 | ```ts 175 | true; 176 | ``` 177 | 178 | #### Defined in 179 | 180 | [objectSorter.ts:76](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L76) 181 | 182 | --- 183 | 184 | ### number 185 | 186 | • `Optional` **number**: `boolean` 187 | 188 | If `true` converts numbers to strings 189 | 190 | **`Example`** 191 | 192 | ```ts 193 | // coerce.number = true 194 | 1 === '1'; 195 | ``` 196 | 197 | **`Example`** 198 | 199 | ```ts 200 | // coerce.number = false 201 | 1 !== '1'; 202 | ``` 203 | 204 | **`Default`** 205 | 206 | ```ts 207 | true; 208 | ``` 209 | 210 | #### Defined in 211 | 212 | [objectSorter.ts:32](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L32) 213 | 214 | --- 215 | 216 | ### set 217 | 218 | • `Optional` **set**: `boolean` 219 | 220 | If `true` set will be coerced to array 221 | 222 | **`Example`** 223 | 224 | ```ts 225 | // coerce.set = true 226 | ``` 227 | 228 | **`Example`** 229 | 230 | ```ts 231 | // coerce.set = false 232 | ``` 233 | 234 | **`Default`** 235 | 236 | ```ts 237 | true; 238 | ``` 239 | 240 | #### Defined in 241 | 242 | [objectSorter.ts:114](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L114) 243 | 244 | --- 245 | 246 | ### string 247 | 248 | • `Optional` **string**: `boolean` 249 | 250 | If `true` strings and coerced string will be equal to coerced numbers, booleans, etc 251 | 252 | **`Example`** 253 | 254 | ```ts 255 | // coerce.string = true 256 | '1' === true; 257 | ``` 258 | 259 | **`Example`** 260 | 261 | ```ts 262 | // coerce.string = false 263 | '1' !== 1; 264 | ``` 265 | 266 | **`Default`** 267 | 268 | ```ts 269 | true; 270 | ``` 271 | 272 | #### Defined in 273 | 274 | [objectSorter.ts:54](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L54) 275 | 276 | --- 277 | 278 | ### symbol 279 | 280 | • `Optional` **symbol**: `boolean` 281 | 282 | If `true` all symbols will have eual representation 283 | 284 | **`Example`** 285 | 286 | ```ts 287 | // coerce.symbol = true 288 | Symbol.for('a') === Symbol.for('b'); 289 | ``` 290 | 291 | **`Example`** 292 | 293 | ```ts 294 | // coerce.symbol = false 295 | Symbol.for('a') !== Symbol.for('b'); 296 | ``` 297 | 298 | **`Default`** 299 | 300 | ```ts 301 | true; 302 | ``` 303 | 304 | #### Defined in 305 | 306 | [objectSorter.ts:87](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L87) 307 | 308 | --- 309 | 310 | ### undefined 311 | 312 | • `Optional` **undefined**: `boolean` 313 | 314 | If `true` undefined will be equal to empty string 315 | 316 | **`Example`** 317 | 318 | ```ts 319 | // coerce.undefined = true 320 | undefined === ''; 321 | ``` 322 | 323 | **`Example`** 324 | 325 | ```ts 326 | // coerce.undefined = false 327 | undefined !== ''; 328 | ``` 329 | 330 | **`Default`** 331 | 332 | ```ts 333 | true; 334 | ``` 335 | 336 | #### Defined in 337 | 338 | [objectSorter.ts:65](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L65) 339 | -------------------------------------------------------------------------------- /docs/api/interfaces/objectSorter.SortOptions.md: -------------------------------------------------------------------------------- 1 | [# Node object hash](../README.md) / [objectSorter](../modules/objectSorter.md) / SortOptions 2 | 3 | # Interface: SortOptions 4 | 5 | [objectSorter](../modules/objectSorter.md).SortOptions 6 | 7 | Advanced sort options 8 | 9 | ## Table of contents 10 | 11 | ### Properties 12 | 13 | - [array](objectSorter.SortOptions.md#array) 14 | - [bigint](objectSorter.SortOptions.md#bigint) 15 | - [map](objectSorter.SortOptions.md#map) 16 | - [object](objectSorter.SortOptions.md#object) 17 | - [set](objectSorter.SortOptions.md#set) 18 | - [typedArray](objectSorter.SortOptions.md#typedarray) 19 | 20 | ## Properties 21 | 22 | ### array 23 | 24 | • `Optional` **array**: `boolean` 25 | 26 | If `true` sort array entries before hash 27 | 28 | #### Defined in 29 | 30 | [objectSorter.ts:124](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L124) 31 | 32 | --- 33 | 34 | ### bigint 35 | 36 | • `Optional` **bigint**: `boolean` 37 | 38 | If `true` sort BigInt entries before hash 39 | 40 | #### Defined in 41 | 42 | [objectSorter.ts:144](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L144) 43 | 44 | --- 45 | 46 | ### map 47 | 48 | • `Optional` **map**: `boolean` 49 | 50 | If `true` sort map entries before hash 51 | 52 | #### Defined in 53 | 54 | [objectSorter.ts:140](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L140) 55 | 56 | --- 57 | 58 | ### object 59 | 60 | • `Optional` **object**: `boolean` 61 | 62 | If `true` sort object entries before hash 63 | 64 | #### Defined in 65 | 66 | [objectSorter.ts:132](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L132) 67 | 68 | --- 69 | 70 | ### set 71 | 72 | • `Optional` **set**: `boolean` 73 | 74 | If `true` sort set entries before hash 75 | 76 | #### Defined in 77 | 78 | [objectSorter.ts:136](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L136) 79 | 80 | --- 81 | 82 | ### typedArray 83 | 84 | • `Optional` **typedArray**: `boolean` 85 | 86 | If `true` sort TypedArray entries before hash 87 | 88 | #### Defined in 89 | 90 | [objectSorter.ts:128](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L128) 91 | -------------------------------------------------------------------------------- /docs/api/interfaces/objectSorter.SorterOptions.md: -------------------------------------------------------------------------------- 1 | [# Node object hash](../README.md) / [objectSorter](../modules/objectSorter.md) / SorterOptions 2 | 3 | # Interface: SorterOptions 4 | 5 | [objectSorter](../modules/objectSorter.md).SorterOptions 6 | 7 | Object sorter options 8 | 9 | ## Hierarchy 10 | 11 | - **`SorterOptions`** 12 | 13 | ↳ [`HasherOptions`](hasher.HasherOptions.md) 14 | 15 | ## Table of contents 16 | 17 | ### Properties 18 | 19 | - [coerce](objectSorter.SorterOptions.md#coerce) 20 | - [sort](objectSorter.SorterOptions.md#sort) 21 | - [trim](objectSorter.SorterOptions.md#trim) 22 | 23 | ## Properties 24 | 25 | ### coerce 26 | 27 | • `Optional` **coerce**: `boolean` \| [`CoerceOptions`](objectSorter.CoerceOptions.md) 28 | 29 | If `true` enables type coercion. 30 | Advanced coerce options could be provided as object 31 | 32 | **`Default`** 33 | 34 | ```ts 35 | true; 36 | ``` 37 | 38 | #### Defined in 39 | 40 | [objectSorter.ts:170](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L170) 41 | 42 | --- 43 | 44 | ### sort 45 | 46 | • `Optional` **sort**: `boolean` \| [`SortOptions`](objectSorter.SortOptions.md) 47 | 48 | If `true` enables sorting. 49 | Advanced sorting options could be provided as object 50 | 51 | **`Default`** 52 | 53 | ```ts 54 | true; 55 | ``` 56 | 57 | #### Defined in 58 | 59 | [objectSorter.ts:176](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L176) 60 | 61 | --- 62 | 63 | ### trim 64 | 65 | • `Optional` **trim**: `boolean` \| [`TrimOptions`](objectSorter.TrimOptions.md) 66 | 67 | If `true` enables trimming and multiple whitespace replacement. 68 | Advanced sorting options could be provided as object. 69 | 70 | **`Default`** 71 | 72 | ```ts 73 | false; 74 | ``` 75 | 76 | #### Defined in 77 | 78 | [objectSorter.ts:182](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L182) 79 | -------------------------------------------------------------------------------- /docs/api/interfaces/objectSorter.TrimOptions.md: -------------------------------------------------------------------------------- 1 | [# Node object hash](../README.md) / [objectSorter](../modules/objectSorter.md) / TrimOptions 2 | 3 | # Interface: TrimOptions 4 | 5 | [objectSorter](../modules/objectSorter.md).TrimOptions 6 | 7 | Advanced trim options 8 | 9 | ## Table of contents 10 | 11 | ### Properties 12 | 13 | - [function](objectSorter.TrimOptions.md#function) 14 | - [string](objectSorter.TrimOptions.md#string) 15 | 16 | ## Properties 17 | 18 | ### function 19 | 20 | • `Optional` **function**: `boolean` 21 | 22 | If `true` replaces multiple space with one and trims whitespaces in function body 23 | 24 | #### Defined in 25 | 26 | [objectSorter.ts:158](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L158) 27 | 28 | --- 29 | 30 | ### string 31 | 32 | • `Optional` **string**: `boolean` 33 | 34 | If `true` replaces multiple space with one and trims whitespaces in strings 35 | 36 | #### Defined in 37 | 38 | [objectSorter.ts:154](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L154) 39 | -------------------------------------------------------------------------------- /docs/api/modules/hasher.md: -------------------------------------------------------------------------------- 1 | [# Node object hash](../README.md) / hasher 2 | 3 | # Module: hasher 4 | 5 | ## Table of contents 6 | 7 | ### Interfaces 8 | 9 | - [Hashable](../interfaces/hasher.Hashable.md) 10 | - [Hasher](../interfaces/hasher.Hasher.md) 11 | - [HasherOptions](../interfaces/hasher.HasherOptions.md) 12 | 13 | ### Functions 14 | 15 | - [hasher](hasher.md#hasher) 16 | 17 | ## Functions 18 | 19 | ### hasher 20 | 21 | ▸ **hasher**(`options?`): [`Hasher`](../interfaces/hasher.Hasher.md)<`unknown`\> 22 | 23 | Hasher constructor 24 | 25 | #### Parameters 26 | 27 | | Name | Type | Description | 28 | | :--------- | :------------------------------------------------------- | :------------- | 29 | | `options?` | [`HasherOptions`](../interfaces/hasher.HasherOptions.md) | hasher options | 30 | 31 | #### Returns 32 | 33 | [`Hasher`](../interfaces/hasher.Hasher.md)<`unknown`\> 34 | 35 | hasher instance 36 | 37 | #### Defined in 38 | 39 | [hasher.ts:68](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/hasher.ts#L68) 40 | -------------------------------------------------------------------------------- /docs/api/modules/objectSorter.md: -------------------------------------------------------------------------------- 1 | [# Node object hash](../README.md) / objectSorter 2 | 3 | # Module: objectSorter 4 | 5 | ## Table of contents 6 | 7 | ### Interfaces 8 | 9 | - [CoerceOptions](../interfaces/objectSorter.CoerceOptions.md) 10 | - [SortOptions](../interfaces/objectSorter.SortOptions.md) 11 | - [SorterOptions](../interfaces/objectSorter.SorterOptions.md) 12 | - [TrimOptions](../interfaces/objectSorter.TrimOptions.md) 13 | 14 | ### Type Aliases 15 | 16 | - [StringifyFn](objectSorter.md#stringifyfn) 17 | 18 | ### Functions 19 | 20 | - [objectSorter](objectSorter.md#objectsorter) 21 | 22 | ## Type Aliases 23 | 24 | ### StringifyFn 25 | 26 | Ƭ **StringifyFn**: (`obj`: [`Hashable`](../interfaces/hasher.Hashable.md) \| `T`) => `string` 27 | 28 | #### Type declaration 29 | 30 | ▸ <`T`\>(`obj`): `string` 31 | 32 | ##### Type parameters 33 | 34 | | Name | 35 | | :--- | 36 | | `T` | 37 | 38 | ##### Parameters 39 | 40 | | Name | Type | 41 | | :---- | :---------------------------------------------------- | 42 | | `obj` | [`Hashable`](../interfaces/hasher.Hashable.md) \| `T` | 43 | 44 | ##### Returns 45 | 46 | `string` 47 | 48 | #### Defined in 49 | 50 | [objectSorter.ts:185](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L185) 51 | 52 | ## Functions 53 | 54 | ### objectSorter 55 | 56 | ▸ **objectSorter**(`options?`): [`StringifyFn`](objectSorter.md#stringifyfn) 57 | 58 | Object sorter consturctor 59 | 60 | #### Parameters 61 | 62 | | Name | Type | Description | 63 | | :--------- | :------------------------------------------------------------- | :---------------------------- | 64 | | `options?` | [`SorterOptions`](../interfaces/objectSorter.SorterOptions.md) | object transformation options | 65 | 66 | #### Returns 67 | 68 | [`StringifyFn`](objectSorter.md#stringifyfn) 69 | 70 | function that transforms object to strings 71 | 72 | #### Defined in 73 | 74 | [objectSorter.ts:192](https://github.com/SkeLLLa/node-object-hash/blob/a6d1c08/src/objectSorter.ts#L192) 75 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | cache: false, 3 | // collectCoverage: true, // prevents ts-jest bug 4 | collectCoverageFrom: ['src/**/*.(ts|js)'], 5 | coverageReporters: ['lcov', 'text'], 6 | globals: { 7 | 'ts-jest': { 8 | tsconfig: 'tsconfig.json', 9 | disableSourceMapSupport: true, 10 | }, 11 | }, 12 | moduleFileExtensions: ['ts', 'js', 'json'], 13 | testEnvironment: 'node', 14 | testMatch: ['**/__tests__/**/*.spec.(ts|js)'], 15 | testPathIgnorePatterns: ['/node_modules/', '/dist/'], 16 | transform: { 17 | '^.+\\.(ts|tsx)$': 'ts-jest', 18 | }, 19 | verbose: true, 20 | preset: 'ts-jest', 21 | }; 22 | -------------------------------------------------------------------------------- /logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-object-hash", 3 | "version": "3.1.1", 4 | "description": "Node.js object hash library with properties/arrays sorting to provide constant hashes", 5 | "keywords": [ 6 | "hash", 7 | "object", 8 | "hash-object", 9 | "object-hash", 10 | "es6", 11 | "crypto" 12 | ], 13 | "homepage": "https://github.com/SkeLLLa/node-object-hash#readme", 14 | "bugs": { 15 | "url": "https://github.com/SkeLLLa/node-object-hash/issues" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git@github.com:SkeLLLa/node-object-hash.git" 20 | }, 21 | "license": "MIT", 22 | "author": "m03geek", 23 | "main": "dist/hasher.js", 24 | "types": "dist/hasher.d.ts", 25 | "directories": { 26 | "lib": "dist", 27 | "doc": "docs", 28 | "test": "test" 29 | }, 30 | "files": [ 31 | "dist/**/*.js", 32 | "dist/**/*.ts", 33 | "dist/**/*.map" 34 | ], 35 | "scripts": { 36 | "audit": "pnpm audit --prod --audit-level=high", 37 | "benchmark": "pnpm run build && pnpm run benchmark:regular && pnpm run benchmark:custom", 38 | "benchmark:custom": "node --expose-gc benchmark/custom.js", 39 | "benchmark:regular": "node benchmark/bench.js", 40 | "build": "pnpm run build:node && pnpm run build:docs", 41 | "build:docs": "typedoc --plugin typedoc-plugin-markdown --plugin typedoc-plugin-mdn-links && pretty-quick", 42 | "build:node": "tsc -p tsconfig.build.json", 43 | "lint": "pnpm run lint:eslint", 44 | "lint:eslint": "eslint . --ext js,jsx,ts,tsx", 45 | "lint:typescript": "tsc", 46 | "release": "semantic-release", 47 | "test": "pnpm run audit && pnpm run lint && pnpm run test:unit", 48 | "test:unit": "jest --coverage" 49 | }, 50 | "devDependencies": { 51 | "@jest/globals": "^29.5.0", 52 | "@semantic-release/changelog": "^6.0.3", 53 | "@semantic-release/commit-analyzer": "^9.0.2", 54 | "@semantic-release/exec": "^6.0.3", 55 | "@semantic-release/git": "^10.0.1", 56 | "@semantic-release/github": "^8.0.7", 57 | "@semantic-release/npm": "^10.0.3", 58 | "@semantic-release/release-notes-generator": "^10.0.3", 59 | "@trivago/prettier-plugin-sort-imports": "^4.1.1", 60 | "@tsconfig/node-lts": "^18.12.1", 61 | "@types/node": "^18.15.11", 62 | "@typescript-eslint/eslint-plugin": "^5.58.0", 63 | "@typescript-eslint/parser": "^5.58.0", 64 | "conventional-changelog-cli": "^2.2.2", 65 | "conventional-changelog-conventionalcommits": "^5.0.0", 66 | "eslint": "^8.38.0", 67 | "eslint-config-google": "^0.14.0", 68 | "eslint-config-prettier": "^8.8.0", 69 | "eslint-import-resolver-typescript": "^3.5.5", 70 | "eslint-plugin-filenames": "^1.3.2", 71 | "eslint-plugin-import": "^2.27.5", 72 | "eslint-plugin-jest": "^27.2.1", 73 | "eslint-plugin-node": "^11.1.0", 74 | "eslint-plugin-prettier": "^4.2.1", 75 | "eslint-plugin-security": "^1.7.1", 76 | "jest": "^29.5.0", 77 | "prettier": "^2.8.7", 78 | "prettier-plugin-packagejson": "^2.4.3", 79 | "prettier-plugin-sh": "^0.12.8", 80 | "prettier-plugin-sort-json": "^1.0.0", 81 | "pretty-quick": "^3.1.3", 82 | "semantic-release": "^21.0.1", 83 | "semantic-release-mirror-version": "^1.1.2", 84 | "ts-jest": "^29.1.0", 85 | "typedoc": "^0.24.1", 86 | "typedoc-plugin-markdown": "^3.15.1", 87 | "typedoc-plugin-mdn-links": "^3.0.3", 88 | "typescript": "^5.0.4" 89 | }, 90 | "packageManager": "pnpm@9.15.0", 91 | "engines": { 92 | "node": ">=16", 93 | "pnpm": ">=8" 94 | }, 95 | "volta": { 96 | "node": "22.12.0", 97 | "pnpm": "9.15.0" 98 | }, 99 | "pnpm": { 100 | "updateConfig": { 101 | "ignoreDependencies": [ 102 | "faker" 103 | ] 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/hasher.ts: -------------------------------------------------------------------------------- 1 | import type { BinaryToTextEncoding } from 'crypto'; 2 | import { createHash } from 'crypto'; 3 | 4 | import type { SorterOptions } from './objectSorter'; 5 | import { objectSorter } from './objectSorter'; 6 | 7 | /** 8 | * Default hash algorithm 9 | */ 10 | const DEFAULT_ALG = 'sha256'; 11 | /** 12 | * Default hash string enoding 13 | */ 14 | const DEFAULT_ENC: BinaryToTextEncoding = 'hex'; 15 | 16 | /** 17 | * Object hasher options 18 | */ 19 | export interface HasherOptions extends SorterOptions { 20 | /** 21 | * Hash algorithm to use 22 | * @default 'sha256' 23 | */ 24 | alg?: string; 25 | /** 26 | * String encoding for hash 27 | * @default 'hex' 28 | */ 29 | enc?: BinaryToTextEncoding; 30 | } 31 | 32 | /** 33 | * If object implements Hashable interface then value from toHash 34 | * will be used for hash function. It means that the different objects 35 | * with the function toHash that return the same value will have the same hash 36 | */ 37 | export interface Hashable { 38 | toHashableString: () => string; 39 | } 40 | 41 | export interface Hasher { 42 | /** 43 | * Create hash of an object 44 | * @param object source object 45 | * @returns hash string of an object 46 | */ 47 | hash(object: Hashable | T, opts?: HasherOptions): string; 48 | /** 49 | * Create sorted string from an object 50 | * @param object source object 51 | * @returns sorted string from an object 52 | */ 53 | sort(object: T): string; 54 | /** 55 | * Create sorted string from an object 56 | * @param object source object 57 | * @returns sorted string from an object 58 | * @alias sort 59 | */ 60 | sortObject(object: T): string; 61 | } 62 | 63 | /** 64 | * Hasher constructor 65 | * @param options hasher options 66 | * @return hasher instance 67 | */ 68 | export const hasher = (options?: HasherOptions): Hasher => { 69 | const sortObject = objectSorter(options); 70 | 71 | /** 72 | * Object hash function 73 | * @param obj object to hash 74 | * @param opts hasher options 75 | * @returns hash string 76 | */ 77 | const hash = (obj: Hashable | T, opts?: HasherOptions): string => { 78 | const alg = opts?.alg || options?.alg || DEFAULT_ALG; 79 | const enc: BinaryToTextEncoding = opts?.enc || options?.enc || DEFAULT_ENC; 80 | const sorted = sortObject(obj); 81 | 82 | return createHash(alg).update(sorted).digest(enc); 83 | }; 84 | 85 | return { 86 | hash, 87 | sort: sortObject, 88 | sortObject, 89 | }; 90 | }; 91 | -------------------------------------------------------------------------------- /src/objectSorter.ts: -------------------------------------------------------------------------------- 1 | import type { Hashable } from './hasher'; 2 | import * as str from './stringifiers'; 3 | import { guessType } from './typeGuess'; 4 | 5 | /** 6 | * Advanced coerce options 7 | */ 8 | export interface CoerceOptions { 9 | /** 10 | * If `true` converts booleans to string `1` and `0` 11 | * @example 12 | * // coerce.boolean = true 13 | * true === 1; 14 | * false === '0'; 15 | * @example 16 | * // coerce.boolean = true 17 | * true !== 1; 18 | * false !== '0' 19 | * @default true 20 | */ 21 | boolean?: boolean; 22 | /** 23 | * If `true` converts numbers to strings 24 | * @example 25 | * // coerce.number = true 26 | * 1 === '1'; 27 | * @example 28 | * // coerce.number = false 29 | * 1 !== '1'; 30 | * @default true 31 | */ 32 | number?: boolean; 33 | /** 34 | * If `true` converts BigInt to string 35 | * @example 36 | * // coerce.bigint = true 37 | * 1n === '1'; 38 | * @example 39 | * // coerce.bigint = false 40 | * 1n !== '1'; 41 | * @default true 42 | */ 43 | bigint?: boolean; 44 | /** 45 | * If `true` strings and coerced string will be equal to coerced numbers, booleans, etc 46 | * @example 47 | * // coerce.string = true 48 | * '1' === true 49 | * @example 50 | * // coerce.string = false 51 | * '1' !== 1 52 | * @default true 53 | */ 54 | string?: boolean; 55 | /** 56 | * If `true` undefined will be equal to empty string 57 | * @example 58 | * // coerce.undefined = true 59 | * undefined === '' 60 | * @example 61 | * // coerce.undefined = false 62 | * undefined !== '' 63 | * @default true 64 | */ 65 | undefined?: boolean; 66 | /** 67 | * If `true` null will be equal to empty string 68 | * @example 69 | * // coerce.null = true 70 | * null === '' 71 | * @example 72 | * // coerce.null = false 73 | * null !== '' 74 | * @default true 75 | */ 76 | null?: boolean; 77 | /** 78 | * If `true` all symbols will have eual representation 79 | * @example 80 | * // coerce.symbol = true 81 | * Symbol.for('a') === Symbol.for('b') 82 | * @example 83 | * // coerce.symbol = false 84 | * Symbol.for('a') !== Symbol.for('b') 85 | * @default true 86 | */ 87 | symbol?: boolean; 88 | /** 89 | * If `true` functions may equal the same formatted strings 90 | * @example 91 | * // coerce.function = true 92 | * @example 93 | * // coerce.function = false 94 | * @default true 95 | */ 96 | function?: boolean; 97 | /** 98 | * If `true` dates may equal the same formatted strings 99 | * @example 100 | * // coerce.date = true 101 | * @example 102 | * // coerce.date = false 103 | * @default true 104 | */ 105 | date?: boolean; 106 | /** 107 | * If `true` set will be coerced to array 108 | * @example 109 | * // coerce.set = true 110 | * @example 111 | * // coerce.set = false 112 | * @default true 113 | */ 114 | set?: boolean; 115 | } 116 | 117 | /** 118 | * Advanced sort options 119 | */ 120 | export interface SortOptions { 121 | /** 122 | * If `true` sort array entries before hash 123 | */ 124 | array?: boolean; 125 | /** 126 | * If `true` sort TypedArray entries before hash 127 | */ 128 | typedArray?: boolean; 129 | /** 130 | * If `true` sort object entries before hash 131 | */ 132 | object?: boolean; 133 | /** 134 | * If `true` sort set entries before hash 135 | */ 136 | set?: boolean; 137 | /** 138 | * If `true` sort map entries before hash 139 | */ 140 | map?: boolean; 141 | /** 142 | * If `true` sort BigInt entries before hash 143 | */ 144 | bigint?: boolean; 145 | } 146 | 147 | /** 148 | * Advanced trim options 149 | */ 150 | export interface TrimOptions { 151 | /** 152 | * If `true` replaces multiple space with one and trims whitespaces in strings 153 | */ 154 | string?: boolean; 155 | /** 156 | * If `true` replaces multiple space with one and trims whitespaces in function body 157 | */ 158 | function?: boolean; 159 | } 160 | 161 | /** 162 | * Object sorter options 163 | */ 164 | export interface SorterOptions { 165 | /** 166 | * If `true` enables type coercion. 167 | * Advanced coerce options could be provided as object 168 | * @default true 169 | */ 170 | coerce?: boolean | CoerceOptions | undefined; 171 | /** 172 | * If `true` enables sorting. 173 | * Advanced sorting options could be provided as object 174 | * @default true 175 | */ 176 | sort?: boolean | SortOptions | undefined; 177 | /** 178 | * If `true` enables trimming and multiple whitespace replacement. 179 | * Advanced sorting options could be provided as object. 180 | * @default false 181 | */ 182 | trim?: boolean | TrimOptions | undefined; 183 | } 184 | 185 | export type StringifyFn = (obj: Hashable | T) => string; 186 | 187 | /** 188 | * Object sorter consturctor 189 | * @param options object transformation options 190 | * @return function that transforms object to strings 191 | */ 192 | export const objectSorter = (options?: SorterOptions): StringifyFn => { 193 | const { sort, coerce, trim } = { 194 | sort: true, 195 | coerce: true, 196 | trim: false, 197 | ...options, 198 | }; 199 | 200 | const sortOptions: SortOptions = { 201 | array: typeof sort === 'boolean' ? sort : sort?.array ?? false, 202 | typedArray: typeof sort === 'boolean' ? false : sort?.typedArray ?? false, 203 | object: typeof sort === 'boolean' ? sort : sort?.object ?? false, 204 | set: typeof sort === 'boolean' ? sort : sort?.set ?? false, 205 | map: typeof sort === 'boolean' ? sort : sort?.map ?? false, 206 | }; 207 | const coerceOptions: CoerceOptions = { 208 | boolean: typeof coerce === 'boolean' ? coerce : coerce?.boolean ?? false, 209 | number: typeof coerce === 'boolean' ? coerce : coerce?.number ?? false, 210 | bigint: typeof coerce === 'boolean' ? coerce : coerce?.bigint ?? false, 211 | string: typeof coerce === 'boolean' ? coerce : coerce?.string ?? false, 212 | undefined: typeof coerce === 'boolean' ? coerce : coerce?.undefined ?? false, 213 | null: typeof coerce === 'boolean' ? coerce : coerce?.null ?? false, 214 | symbol: typeof coerce === 'boolean' ? coerce : coerce?.symbol ?? false, 215 | function: typeof coerce === 'boolean' ? coerce : coerce?.function ?? false, 216 | date: typeof coerce === 'boolean' ? coerce : coerce?.date ?? false, 217 | set: typeof coerce === 'boolean' ? coerce : coerce?.set ?? false, 218 | }; 219 | const trimOptions: TrimOptions = { 220 | string: typeof trim === 'boolean' ? trim : trim?.string ?? false, 221 | function: typeof trim === 'boolean' ? trim : trim?.function ?? false, 222 | }; 223 | 224 | const stringifiers: str.Stringifiers = { 225 | // eslint-disable-next-line @typescript-eslint/ban-types 226 | unknown: function _unknown(obj: Object) { 227 | // `unknonw` - is a typo, saved for backward compatibility 228 | const constructorName: string = obj.constructor?.name ?? 'unknonw'; 229 | 230 | let objectName = 'unknown'; 231 | 232 | if (typeof obj.toString === 'function') { 233 | objectName = obj.toString(); 234 | } else if (Object.keys(obj).length > 0) { 235 | objectName = JSON.stringify(obj); 236 | } 237 | 238 | return `<:${constructorName}>:${objectName}`; 239 | }, 240 | }; 241 | 242 | stringifiers['hashable'] = str._hashable.bind(stringifiers) as StringifyFn; 243 | 244 | if (trimOptions.string) { 245 | stringifiers['string'] = coerceOptions.string 246 | ? (str._stringTrimCoerce.bind(stringifiers) as StringifyFn) 247 | : (str._stringTrim.bind(stringifiers) as StringifyFn); 248 | } else { 249 | stringifiers['string'] = coerceOptions.string 250 | ? (str._stringCoerce.bind(stringifiers) as StringifyFn) 251 | : (str._string.bind(stringifiers) as StringifyFn); 252 | } 253 | stringifiers['number'] = coerceOptions.number 254 | ? (str._numberCoerce.bind(stringifiers) as StringifyFn) 255 | : (str._number.bind(stringifiers) as StringifyFn); 256 | stringifiers['bigint'] = coerceOptions.bigint 257 | ? (str._bigIntCoerce.bind(stringifiers) as StringifyFn) 258 | : (str._bigInt.bind(stringifiers) as StringifyFn); 259 | stringifiers['boolean'] = coerceOptions.boolean 260 | ? (str._booleanCoerce.bind(stringifiers) as StringifyFn) 261 | : (str._boolean.bind(stringifiers) as StringifyFn); 262 | stringifiers['symbol'] = coerceOptions.symbol 263 | ? (str._symbolCoerce.bind(stringifiers) as StringifyFn) 264 | : (str._symbol.bind(stringifiers) as StringifyFn); 265 | stringifiers['undefined'] = coerceOptions.undefined 266 | ? (str._undefinedCoerce.bind(stringifiers) as StringifyFn) 267 | : (str._undefined.bind(stringifiers) as StringifyFn); 268 | stringifiers['null'] = coerceOptions.null 269 | ? (str._nullCoerce.bind(stringifiers) as StringifyFn) 270 | : (str._null.bind(stringifiers) as StringifyFn); 271 | if (trimOptions.function) { 272 | stringifiers['function'] = coerceOptions.function 273 | ? (str._functionTrimCoerce.bind(stringifiers) as StringifyFn) 274 | : (str._functionTrim.bind(stringifiers) as StringifyFn); 275 | } else { 276 | stringifiers['function'] = coerceOptions.function 277 | ? (str._functionCoerce.bind(stringifiers) as StringifyFn) 278 | : (str._function.bind(stringifiers) as StringifyFn); 279 | } 280 | stringifiers['date'] = coerceOptions.date 281 | ? (str._dateCoerce.bind(stringifiers) as StringifyFn) 282 | : (str._date.bind(stringifiers) as StringifyFn); 283 | stringifiers['array'] = sortOptions.array 284 | ? (str._arraySort.bind(stringifiers) as StringifyFn) 285 | : (str._array.bind(stringifiers) as StringifyFn); 286 | stringifiers['typedarray'] = sortOptions.typedArray 287 | ? (str._typedArraySort.bind(stringifiers) as StringifyFn) 288 | : (str._typedArray.bind(stringifiers) as StringifyFn); 289 | if (sortOptions.set) { 290 | stringifiers['set'] = coerceOptions.set 291 | ? (str._setSortCoerce.bind(stringifiers) as StringifyFn) 292 | : (str._setSort.bind(stringifiers) as StringifyFn); 293 | } else { 294 | stringifiers['set'] = coerceOptions.set 295 | ? (str._setCoerce.bind(stringifiers) as StringifyFn) 296 | : (str._set.bind(stringifiers) as StringifyFn); 297 | } 298 | stringifiers['object'] = sortOptions.object 299 | ? (str._objectSort.bind(stringifiers) as StringifyFn) 300 | : (str._object.bind(stringifiers) as StringifyFn); 301 | stringifiers['map'] = sortOptions.map 302 | ? (str._mapSort.bind(stringifiers) as StringifyFn) 303 | : (str._map.bind(stringifiers) as StringifyFn); 304 | 305 | /** 306 | * Serializes object to string 307 | * @param obj object 308 | */ 309 | function objectToString(obj: T): string { 310 | return stringifiers[guessType(obj)]!(obj); 311 | } 312 | 313 | return objectToString; 314 | }; 315 | -------------------------------------------------------------------------------- /src/stringifiers.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/no-explicit-any */ 2 | 3 | /* eslint-disable @typescript-eslint/no-this-alias */ 4 | 5 | /** 6 | * @private 7 | * @inner 8 | */ 9 | import type { Hashable } from './hasher'; 10 | import { guessType } from './typeGuess'; 11 | 12 | import TypedArray = NodeJS.TypedArray; 13 | 14 | /** 15 | * List of functions responsible for converting certain types to string 16 | */ 17 | // eslint-disable-next-line @typescript-eslint/no-explicit-any 18 | export type Stringifiers = { [key: string]: (obj: any) => string }; 19 | 20 | /** 21 | * Prefixes that used when type coercion is disabled 22 | */ 23 | export const PREFIX = { 24 | string: '<:s>', 25 | number: '<:n>', 26 | bigint: '<:bi>', 27 | boolean: '<:b>', 28 | symbol: '<:smbl>', 29 | undefined: '<:undf>', 30 | null: '<:null>', 31 | function: '<:func>', 32 | array: '', 33 | date: '<:date>', 34 | set: '<:set>', 35 | map: '<:map>', 36 | }; 37 | 38 | /** 39 | * Converts Hashable to string 40 | * @private 41 | * @param obj object to convert 42 | * @returns object string representation 43 | */ 44 | export function _hashable(obj: Hashable): string { 45 | return obj.toHashableString(); 46 | } 47 | 48 | /** 49 | * Converts string to string 50 | * @private 51 | * @param obj object to convert 52 | * @return object string representation 53 | */ 54 | export function _stringCoerce(obj: string): string { 55 | return obj; 56 | } 57 | /** 58 | * Converts string to string 59 | * @private 60 | * @param obj object to convert 61 | * @return object string representation 62 | */ 63 | export function _string(obj: string): string { 64 | return PREFIX.string + ':' + obj; 65 | } 66 | /** 67 | * Converts string to string 68 | * @private 69 | * @param obj object to convert 70 | * @return object string representation 71 | */ 72 | export function _stringTrimCoerce(obj: string): string { 73 | return obj.replace(/(\s+|\t|\r\n|\n|\r)/gm, ' ').trim(); 74 | } 75 | /** 76 | * Converts string to string 77 | * @private 78 | * @param obj object to convert 79 | * @return object string representation 80 | */ 81 | export function _stringTrim(obj: string): string { 82 | return PREFIX.string + ':' + obj.replace(/(\s+|\t|\r\n|\n|\r)/gm, ' ').trim(); 83 | } 84 | /** 85 | * Converts number to string 86 | * @private 87 | * @param obj object to convert 88 | * @return object string representation 89 | */ 90 | export function _numberCoerce(obj: number): string { 91 | return obj.toString(); 92 | } 93 | /** 94 | * Converts number to string 95 | * @private 96 | * @param obj object to convert 97 | * @return object string representation 98 | */ 99 | export function _number(obj: number): string { 100 | return `${PREFIX.number}:${obj}`; 101 | } 102 | /** 103 | * Converts BigInt to string 104 | * @private 105 | * @param obj object to convert 106 | * @return object string representation 107 | */ 108 | export function _bigIntCoerce(obj: bigint): string { 109 | return obj.toString(); 110 | } 111 | /** 112 | * Converts BigInt to string 113 | * @private 114 | * @param obj object to convert 115 | * @return object string representation 116 | */ 117 | export function _bigInt(obj: bigint): string { 118 | return `${PREFIX.bigint}:${obj.toString()}`; 119 | } 120 | /** 121 | * Converts boolean to string 122 | * @private 123 | * @param obj object to convert 124 | * @return object string representation 125 | */ 126 | export function _booleanCoerce(obj: boolean): string { 127 | return obj ? '1' : '0'; 128 | } 129 | /** 130 | * Converts boolean to string 131 | * @private 132 | * @param obj object to convert 133 | * @return object string representation 134 | */ 135 | export function _boolean(obj: boolean): string { 136 | return PREFIX.boolean + ':' + obj.toString(); 137 | } 138 | /** 139 | * Converts symbol to string 140 | * @private 141 | * @param obj object to convert 142 | * @return object string representation 143 | */ 144 | export function _symbolCoerce(): string { 145 | return PREFIX.symbol; 146 | } 147 | /** 148 | * Converts symbol to string 149 | * @private 150 | * @param obj object to convert 151 | * @return object string representation 152 | */ 153 | export function _symbol(obj: symbol): string { 154 | return PREFIX.symbol + ':' + obj.toString(); 155 | } 156 | /** 157 | * Converts undefined to string 158 | * @private 159 | * @param obj object to convert 160 | * @return object string representation 161 | */ 162 | export function _undefinedCoerce(): string { 163 | return ''; 164 | } 165 | /** 166 | * Converts undefined to string 167 | * @private 168 | * @param obj object to convert 169 | * @return object string representation 170 | */ 171 | export function _undefined(): string { 172 | return PREFIX.undefined; 173 | } 174 | /** 175 | * Converts null to string 176 | * @private 177 | * @param obj object to convert 178 | * @return object string representation 179 | */ 180 | export function _nullCoerce(): string { 181 | return ''; 182 | } 183 | /** 184 | * Converts null to string 185 | * @private 186 | * @param obj object to convert 187 | * @return object string representation 188 | */ 189 | export function _null(): string { 190 | return PREFIX.null; 191 | } 192 | /** 193 | * Converts function to string 194 | * @private 195 | * @param obj object to convert 196 | * @return object string representation 197 | */ 198 | // eslint-disable-next-line @typescript-eslint/ban-types 199 | export function _functionCoerce(obj: Function): string { 200 | return obj.name + '=>' + obj.toString(); 201 | } 202 | /** 203 | * Converts function to string 204 | * @private 205 | * @param obj object to convert 206 | * @return object string representation 207 | */ 208 | // eslint-disable-next-line @typescript-eslint/ban-types 209 | export function _function(obj: Function): string { 210 | return PREFIX.function + ':' + obj.name + '=>' + obj.toString(); 211 | } 212 | /** 213 | * Converts function to string 214 | * @private 215 | * @param obj object to convert 216 | * @return object string representation 217 | */ 218 | // eslint-disable-next-line @typescript-eslint/ban-types 219 | export function _functionTrimCoerce(obj: Function): string { 220 | return ( 221 | obj.name + 222 | '=>' + 223 | obj 224 | .toString() 225 | .replace(/(\s+|\t|\r\n|\n|\r)/gm, ' ') 226 | .trim() 227 | ); 228 | } 229 | /** 230 | * Converts function to string 231 | * @private 232 | * @param obj object to convert 233 | * @return object string representation 234 | */ 235 | // eslint-disable-next-line @typescript-eslint/ban-types 236 | export function _functionTrim(obj: Function): string { 237 | return ( 238 | PREFIX.function + 239 | ':' + 240 | obj.name + 241 | '=>' + 242 | obj 243 | .toString() 244 | .replace(/(\s+|\t|\r\n|\n|\r)/gm, ' ') 245 | .trim() 246 | ); 247 | } 248 | /** 249 | * Converts date to string 250 | * @private 251 | * @param obj object to convert 252 | * @return object string representation 253 | */ 254 | export function _dateCoerce(obj: Date): string { 255 | return obj.toISOString(); 256 | } 257 | /** 258 | * Converts date to string 259 | * @private 260 | * @param obj object to convert 261 | * @return object string representation 262 | */ 263 | export function _date(obj: Date): string { 264 | return PREFIX.date + ':' + obj.toISOString(); 265 | } 266 | /** 267 | * Converts array to string 268 | * @private 269 | * @param obj object to convert 270 | * @return object string representation 271 | */ 272 | export function _arraySort(this: Stringifiers, obj: any[]): string { 273 | const stringifiers: Stringifiers = this; 274 | return ( 275 | '[' + 276 | obj 277 | .map((item) => { 278 | return stringifiers[guessType(item)]!(item); 279 | }) 280 | .sort() 281 | .toString() + 282 | ']' 283 | ); 284 | } 285 | /** 286 | * Converts array to string 287 | * @private 288 | * @param obj object to convert 289 | * @return object string representation 290 | */ 291 | export function _array(this: Stringifiers, obj: any[]): string { 292 | const stringifiers: Stringifiers = this; 293 | return ( 294 | '[' + 295 | obj 296 | .map((item) => { 297 | return stringifiers[guessType(item)]!(item); 298 | }) 299 | .toString() + 300 | ']' 301 | ); 302 | } 303 | /** 304 | * Converts TypedArray to string 305 | * @private 306 | * @param obj object to convert 307 | * @return object string representation 308 | */ 309 | export function _typedArraySort(this: Stringifiers, obj: TypedArray): string { 310 | const stringifiers: Stringifiers = this; 311 | // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any 312 | const values: any[] = Array.prototype.slice.call(obj); 313 | return ( 314 | '[' + 315 | values 316 | .map((num) => { 317 | return stringifiers[guessType(num)]!(num); 318 | }) 319 | .sort() 320 | .toString() + 321 | ']' 322 | ); 323 | } 324 | /** 325 | * Converts TypedArray to string 326 | * @private 327 | * @param obj object to convert 328 | * @return object string representation 329 | */ 330 | export function _typedArray(this: Stringifiers, obj: TypedArray): string { 331 | const stringifiers: Stringifiers = this; 332 | const values: any[] = Array.prototype.slice.call(obj); 333 | return ( 334 | '[' + 335 | values 336 | .map((num) => { 337 | return stringifiers[guessType(num)]!(num); 338 | }) 339 | .toString() + 340 | ']' 341 | ); 342 | } 343 | /** 344 | * Converts set to string 345 | * @private 346 | * @param obj object to convert 347 | * @return object string representation 348 | */ 349 | export function _setSortCoerce(this: Stringifiers, obj: Set): string { 350 | return _arraySort.call(this, Array.from(obj)); 351 | } 352 | /** 353 | * Converts set to string 354 | * @private 355 | * @param obj object to convert 356 | * @return object string representation 357 | */ 358 | export function _setSort(this: Stringifiers, obj: Set): string { 359 | return `${PREFIX.set}:${_arraySort.call(this, Array.from(obj))}`; 360 | } 361 | /** 362 | * Converts set to string 363 | * @private 364 | * @param obj object to convert 365 | * @return object string representation 366 | */ 367 | export function _set(this: Stringifiers, obj: Set): string { 368 | return `${PREFIX.set}:${_array.call(this, Array.from(obj))}`; 369 | } 370 | /** 371 | * Converts set to string 372 | * @private 373 | * @param obj object to convert 374 | * @return object string representation 375 | */ 376 | export function _setCoerce(this: Stringifiers, obj: Set): string { 377 | return _array.call(this, Array.from(obj)); 378 | } 379 | /** 380 | * Converts object to string 381 | * @private 382 | * @param obj object to convert 383 | * @return object string representation 384 | */ 385 | export function _object(this: Stringifiers, obj: { [key: string]: any }): string { 386 | const stringifiers: Stringifiers = this; 387 | const keys = Object.keys(obj); 388 | const objArray = []; 389 | for (const key of keys) { 390 | const val = obj[key] as unknown; 391 | const valT = guessType(val); 392 | objArray.push(key + ':' + stringifiers[valT]!(val)); 393 | } 394 | return '{' + objArray.toString() + '}'; 395 | } 396 | /** 397 | * Converts object to string 398 | * @private 399 | * @param obj object to convert 400 | * @return object string representation 401 | */ 402 | export function _objectSort(this: Stringifiers, obj: { [key: string]: any }): string { 403 | const stringifiers: Stringifiers = this; 404 | const keys = Object.keys(obj).sort(); 405 | const objArray = []; 406 | for (const key of keys) { 407 | const val = obj[key] as unknown; 408 | const valT = guessType(val); 409 | objArray.push(key + ':' + stringifiers[valT]!(val)); 410 | } 411 | return '{' + objArray.toString() + '}'; 412 | } 413 | /** 414 | * Converts map to string 415 | * @private 416 | * @param obj object to convert 417 | * @return object string representation 418 | */ 419 | export function _map(this: Stringifiers, obj: Map): string { 420 | const stringifiers: Stringifiers = this; 421 | const arr = Array.from(obj); 422 | const mapped = []; 423 | for (const item of arr) { 424 | const [key, value] = item as unknown[]; 425 | mapped.push([stringifiers[guessType(key)]!(key), stringifiers[guessType(value)]!(value)]); 426 | } 427 | return '[' + mapped.join(';') + ']'; 428 | } 429 | /** 430 | * Converts map to string 431 | * @private 432 | * @param obj object to convert 433 | * @return object string representation 434 | */ 435 | export function _mapSort(this: Stringifiers, obj: Map): string { 436 | const stringifiers: Stringifiers = this; 437 | const arr = Array.from(obj); 438 | const mapped = []; 439 | for (const item of arr) { 440 | const [key, value] = item as unknown[]; 441 | mapped.push([stringifiers[guessType(key)]!(key), stringifiers[guessType(value)]!(value)]); 442 | } 443 | return '[' + mapped.sort().join(';') + ']'; 444 | } 445 | -------------------------------------------------------------------------------- /src/typeGuess.ts: -------------------------------------------------------------------------------- 1 | import type { Hashable } from './hasher'; 2 | 3 | /** 4 | * Type mapping rules. 5 | */ 6 | export const TYPE_MAP: { [type: string]: string } = { 7 | Array: 'array', 8 | Int8Array: 'typedarray', 9 | Uint8Array: 'typedarray', 10 | Uint8ClampedArray: 'typedarray', 11 | Int16Array: 'typedarray', 12 | Uint16Array: 'typedarray', 13 | Int32Array: 'typedarray', 14 | Uint32Array: 'typedarray', 15 | Float32Array: 'typedarray', 16 | Float64Array: 'typedarray', 17 | BigUint64Array: 'typedarray', 18 | BigInt64Array: 'typedarray', 19 | Buffer: 'typedarray', 20 | Map: 'map', 21 | Set: 'set', 22 | Date: 'date', 23 | String: 'string', 24 | Number: 'number', 25 | BigInt: 'bigint', 26 | Boolean: 'boolean', 27 | Object: 'object', 28 | }; 29 | 30 | /** 31 | * Guess object type 32 | * @param obj analyzed object 33 | * @return object type 34 | */ 35 | export const guessObjectType = (obj: T): string => { 36 | if (obj === null) { 37 | return 'null'; 38 | } 39 | 40 | if (instanceOfHashable(obj)) { 41 | return 'hashable'; 42 | } 43 | const type = obj?.constructor?.name ?? 'unknown'; 44 | return TYPE_MAP[type] || 'unknown'; 45 | }; 46 | 47 | /** 48 | * Guess variable type 49 | * @param obj analyzed variable 50 | * @return variable type 51 | */ 52 | export const guessType = (obj: T): string => { 53 | const type = typeof obj; 54 | return type !== 'object' ? type : guessObjectType(obj); 55 | }; 56 | 57 | /** 58 | * Identify if object is instance of Hashable interface 59 | * @param object analyzed variable 60 | * @return true if object has toHashableString property and this property is function 61 | * otherwise return false 62 | */ 63 | export const instanceOfHashable = (object: Hashable | T): boolean => { 64 | return typeof (object as Hashable).toHashableString === 'function'; 65 | }; 66 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | "outDir": "dist", 5 | "rootDir": "src", 6 | "noEmit": false 7 | }, 8 | "extends": "./tsconfig.json", 9 | "include": ["src/**/*"], 10 | "ts-node": { 11 | "files": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "compilerOptions": { 4 | // "resolvePackageJsonImports": true, 5 | // "resolvePackageJsonExports": true, 6 | "declaration": true, 7 | "declarationMap": true, 8 | "newLine": "LF", 9 | "resolveJsonModule": true, 10 | "sourceMap": true, 11 | "noEmit": true, 12 | // Not supported until move to ESM 13 | "verbatimModuleSyntax": false, 14 | "allowUnusedLabels": false, 15 | "allowUnreachableCode": false, 16 | "exactOptionalPropertyTypes": true, 17 | "noFallthroughCasesInSwitch": true, 18 | "noImplicitOverride": true, 19 | "noImplicitReturns": true, 20 | "noPropertyAccessFromIndexSignature": true, 21 | "noUncheckedIndexedAccess": true, 22 | "noUnusedLocals": true, 23 | "noUnusedParameters": true, 24 | 25 | "checkJs": false 26 | }, 27 | "exclude": ["dist/**/*", "coverage/**/*", "node_modules/**/*", "benchmark/**/*"], 28 | "extends": "@tsconfig/node-lts/tsconfig", 29 | "include": ["src/**/*", "package.json", "__tests__/**/*"], 30 | "ts-node": { 31 | "files": true 32 | }, 33 | "typeAcquisition": { 34 | "enable": true 35 | }, 36 | "typedocOptions": { 37 | "entryPoints": ["src/hasher.ts", "src/objectSorter.ts"], 38 | "out": "docs/api", 39 | "name": "# Node object hash", 40 | "excludeExternals": true, 41 | "includeVersion": true, 42 | "hideGenerator": true, 43 | "excludePrivate": true, 44 | "readme": "none" 45 | } 46 | } 47 | --------------------------------------------------------------------------------