diff --git a/.cspell.json b/.cspell.json index 91e5b0c4..62008b2e 100644 --- a/.cspell.json +++ b/.cspell.json @@ -4,7 +4,7 @@ "ignorePaths": [ "**/coverage/**", "**/node_modules/**", - "**/lib/**", + "**/dist/**", "**/**/CHANGELOG.md", "**/*.{json}", ".cspell.json", diff --git a/.eslintrc.json b/.eslintrc.json index a35fb084..4f0a9883 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -22,10 +22,9 @@ }, "ignorePatterns": [ "/coverage/", - "/deno-dist/", - "/lib/", - "/types/", - "/tests/types/**/*", + "/dist/", + "/tests/types/", + "/types-legacy/", "/**/*.cjs", "/**/*.js", "/**/*.md" diff --git a/.gitignore b/.gitignore index 3c8004d1..6e4852d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,6 @@ -/deno-dist/ -/lib/ /build/ /coverage/ - -!/types/ -/types/* -!/types/legacy +/dist/ .nyc_output/ node_modules/ diff --git a/.prettierignore b/.prettierignore index 37d3d484..3ddf010d 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,3 @@ /CHANGELOG.md -/lib/ -/types/ +/dist/ +/types-legacy/ diff --git a/.releaserc b/.releaserc index 0101167b..bffac427 100644 --- a/.releaserc +++ b/.releaserc @@ -33,7 +33,7 @@ plugins: All notable changes to this project will be documented in this file. Dates are displayed in UTC." - - "@semantic-release/git" - assets: - - deno-dist/ + - dist - CHANGELOG.md - "@semantic-release/npm" - - "@semantic-release/github" diff --git a/.vscode/settings.json b/.vscode/settings.json index b0e52195..92fb8df1 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -3,8 +3,7 @@ ".nyc_output/": true, "coverage/": true, "build/": true, - "deno-dist/": true, - "lib/": true, + "dist/": true, "ava.config.cjs": true, "rollup.config.cjs": true, }, @@ -13,8 +12,7 @@ "**/.git/": true, ".nyc_output/": true, ".vscode/": true, - "deno-dist/": true, - "lib/": true, + "dist/": true, "ava.config.cjs": true, "rollup.config.cjs": true, "yarn.lock": true, diff --git a/README.md b/README.md index 59fc38db..a6093c64 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ yarn add -D deepmerge-ts // import_map.json { "imports": { - "deepmerge-ts": "https://deno.land/x/deepmergets@__version__/index.ts" + "deepmerge-ts": "https://deno.land/x/deepmergets@__version__/dist/deno/index.ts" } } ``` diff --git a/deno-dist/CHANGELOG.md b/deno-dist/CHANGELOG.md deleted file mode 100644 index b9515ec4..00000000 --- a/deno-dist/CHANGELOG.md +++ /dev/null @@ -1,69 +0,0 @@ -# Changelog -All notable changes to this project will be documented in this file. Dates are displayed in UTC. - -## [1.1.6](https://github.com/RebeccaStevens/deepmerge-ts/compare/v1.1.5...v1.1.6) (2021-11-22) - - -### Performance Improvements - -* convert recursive types to tail-recursive versions ([#15](https://github.com/RebeccaStevens/deepmerge-ts/issues/15)) ([4401ac2](https://github.com/RebeccaStevens/deepmerge-ts/commit/4401ac2d1651093ab855d3d4bdf6c9628c0767ab)) - -## [1.1.5](https://github.com/RebeccaStevens/deepmerge-ts/compare/v1.1.4...v1.1.5) (2021-10-18) - - -### Bug Fixes - -* **deno:** deno release fixup ([4b8ca98](https://github.com/RebeccaStevens/deepmerge-ts/commit/4b8ca9868de78228244b099dc2040c4cb16a649d)) - -## [1.1.4](https://github.com/RebeccaStevens/deepmerge-ts/compare/v1.1.3...v1.1.4) (2021-10-18) - -## [1.1.3](https://github.com/RebeccaStevens/deepmerge-ts/compare/v1.1.2...v1.1.3) (2021-09-21) - - -### Bug Fixes - -* order of package exports ([#12](https://github.com/RebeccaStevens/deepmerge-ts/issues/12)) ([4117460](https://github.com/RebeccaStevens/deepmerge-ts/commit/41174607ee57568f123e1a5661f635d5d54f7c0c)) - -## [1.1.2](https://github.com/RebeccaStevens/deepmerge-ts/compare/v1.1.1...v1.1.2) (2021-09-17) - - -### Bug Fixes - -* current and legacy types trying to using the same file resulting in one being overridden ([#10](https://github.com/RebeccaStevens/deepmerge-ts/issues/10)) ([a5f334b](https://github.com/RebeccaStevens/deepmerge-ts/commit/a5f334b2c4f6735383ea419dd6d3206bcc0afe4a)) - - -### Performance Improvements - -* add early escapes to loos when merging unknown types ([17a92e1](https://github.com/RebeccaStevens/deepmerge-ts/commit/17a92e1676a6b6c20f7e3fb1cc966ed5673dccf6)) -* directly request enumerable keys so that they don't need to then be filtered ([04a2a5f](https://github.com/RebeccaStevens/deepmerge-ts/commit/04a2a5fb24b1086c8130203451c2836f196e92c6)) -* use imperative loops when building merged result of records ([b36f7bc](https://github.com/RebeccaStevens/deepmerge-ts/commit/b36f7bcec43858658c06f8f4ac6deb17a9d7b2fe)) - -## [1.1.1](https://github.com/RebeccaStevens/deepmerge-ts/compare/v1.1.0...v1.1.1) (2021-09-16) - - -### Bug Fixes - -* add legacy type information ([#6](https://github.com/RebeccaStevens/deepmerge-ts/issues/6)) ([c7e1019](https://github.com/RebeccaStevens/deepmerge-ts/commit/c7e1019f86818fe95b9f6291f2a09f077337a7f9)) -* only merge enumerable properties ([#8](https://github.com/RebeccaStevens/deepmerge-ts/issues/8)) ([0967070](https://github.com/RebeccaStevens/deepmerge-ts/commit/0967070d30427bb33f0c78793d61a9411dde3b49)) - -# [1.1.0](https://github.com/RebeccaStevens/deepmerge-ts/compare/v1.0.1...v1.1.0) (2021-09-13) - - -### Features - -* add support for custom merging ([#4](https://github.com/RebeccaStevens/deepmerge-ts/issues/4)) ([5413b81](https://github.com/RebeccaStevens/deepmerge-ts/commit/5413b81c0a568c798ff70081966dd9a0ace5fe3f)) - -## [1.0.1](https://github.com/RebeccaStevens/deepmerge-ts/compare/v1.0.0...v1.0.1) (2021-08-25) - - -### Bug Fixes - -* husky install no longer runs on postinstall ([7102229](https://github.com/RebeccaStevens/deepmerge-ts/commit/7102229a7078fef17ba2a24c9814a844fb525c67)) - -# 1.0.0 (2021-08-25) - - -### Features - -* add "module" property to package.json ([168747d](https://github.com/RebeccaStevens/deepmerge-ts/commit/168747daef0b49ab8ac3b0491fda965776eef2c2)) -* add basic functionality ([8e3ba66](https://github.com/RebeccaStevens/deepmerge-ts/commit/8e3ba66973d6e35cc421149a00a45b7c55c1de45)) diff --git a/deno-dist/LICENSE b/deno-dist/LICENSE deleted file mode 100644 index 13b6199e..00000000 --- a/deno-dist/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2021, Rebecca Stevens -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/deno-dist/README.md b/deno-dist/README.md deleted file mode 100644 index 59fc38db..00000000 --- a/deno-dist/README.md +++ /dev/null @@ -1,134 +0,0 @@ -
- -# DeepmergeTS - -[![npm version](https://img.shields.io/npm/v/deepmerge-ts.svg)](https://www.npmjs.com/package/deepmerge-ts) -[![deno version](https://img.shields.io/github/v/tag/RebeccaStevens/deepmerge-ts?label=deno)](https://deno.land/x/deepmergets) -[![CI](https://github.com/RebeccaStevens/deepmerge-ts/actions/workflows/ci.yml/badge.svg)](https://github.com/RebeccaStevens/deepmerge-ts/actions/workflows/ci.yml) -[![Coverage Status](https://codecov.io/gh/RebeccaStevens/deepmerge-ts/branch/main/graph/badge.svg?token=MVpR1oAbIT)](https://codecov.io/gh/RebeccaStevens/deepmerge-ts)\ -[![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) -[![GitHub Discussions](https://img.shields.io/github/discussions/RebeccaStevens/deepmerge-ts?style=flat-square)](https://github.com/RebeccaStevens/deepmerge-ts/discussions) -[![BSD 3 Clause license](https://img.shields.io/github/license/RebeccaStevens/deepmerge-ts.svg?style=flat-square)](https://opensource.org/licenses/BSD-3-Clause) -[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat-square)](https://commitizen.github.io/cz-cli/) -[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat-square)](https://github.com/semantic-release/semantic-release) - -Deeply merge 2 or more objects respecting type information. - -![classic merge animation](./assets/header.png) - -
- -## Installation - -### Node - -```sh -# Install with npm -npm install deepmerge-ts --save-dev - -# Install with yarn -yarn add -D deepmerge-ts -``` - -### Deno - -```jsonc -// import_map.json -{ - "imports": { - "deepmerge-ts": "https://deno.land/x/deepmergets@__version__/index.ts" - } -} -``` - -## Features - -- Smart merging - High performance. -- Merged output has correct typing. -- Record merging support. -- Array merging support. -- Map and Set merging support. -- Customized merging. - -## Usage - -### Example using default config - -```js -import { deepmerge } from "deepmerge-ts"; - -const x = { - record: { - prop1: "value1", - prop2: "value2", - }, - array: [1, 2, 3], - set: new Set([1, 2, 3]), - map: new Map([ - ["key1", "value1"], - ["key2", "value2"], - ]), -}; - -const y = { - record: { - prop1: "changed", - prop3: "value3", - }, - array: [2, 3, 4], - set: new Set([2, 3, 4]), - map: new Map([ - ["key2", "changed"], - ["key3", "value3"], - ]), -}; - -const merged = deepmerge(x, y); - -console.log(merged); - -// Prettierfied output: -// -// { -// record: { -// prop1: "changed", -// prop2: "value2", -// prop3: "value3" -// } -// array: (6) [1, 2, 3, 2, 3, 4] -// set: Set(4) {1, 2, 3, 4} -// map: Map(3) { -// "key1" => "value1", -// "key2" => "changed", -// "key3" => "value3" -// } -// } -``` - -### Using customized config - -[See deepmerge custom docs](./docs/deepmergeCustom.md). - -## Performance - -We use smart merging instead of the classic merging strategy which some alternative libraries use. This vastly improves performance, both in execution time and memory usage. - -### Classic Merge (not what we do) - -With classic merging, each input is merged with the next input until all inputs are merged. - -This strategy has large performance issues when lots of items need to be merged. - -![classic merge animation](./assets/classic-merge.gif) - -### Smart Merge (what we do) - -With our smart merging, we look ahead to see what can be merged and only merge those things. - -In addition to performance improvements, this strategy merges multiple inputs at once; allowing for benefits such as taking averages of the inputs. - -![smart merge animation](./assets/smart-merge.gif) - -## API - -[See API docs](./docs/API.md). diff --git a/deno-dist/assets/classic-merge.gif b/deno-dist/assets/classic-merge.gif deleted file mode 100644 index abebc43f..00000000 Binary files a/deno-dist/assets/classic-merge.gif and /dev/null differ diff --git a/deno-dist/assets/header.png b/deno-dist/assets/header.png deleted file mode 100644 index 79dbbe3d..00000000 Binary files a/deno-dist/assets/header.png and /dev/null differ diff --git a/deno-dist/assets/smart-merge.gif b/deno-dist/assets/smart-merge.gif deleted file mode 100644 index 7b40fbbe..00000000 Binary files a/deno-dist/assets/smart-merge.gif and /dev/null differ diff --git a/deno-dist/deepmerge.ts b/deno-dist/deepmerge.ts deleted file mode 100644 index 9cd4acbb..00000000 --- a/deno-dist/deepmerge.ts +++ /dev/null @@ -1,261 +0,0 @@ -import type { - DeepMergeHKT, - DeepMergeArraysDefaultHKT, - DeepMergeMergeFunctionsDefaultURIs, - DeepMergeMapsDefaultHKT, - DeepMergeMergeFunctionsURIs, - DeepMergeOptions, - DeepMergeRecordsDefaultHKT, - DeepMergeSetsDefaultHKT, - DeepMergeMergeFunctionUtils, - GetDeepMergeMergeFunctionsURIs, -} from "./types/index.ts"; -import { - getIterableOfIterables, - getKeys, - getObjectType, - ObjectType, - objectHasProperty, -} from "./utils.ts"; - -const defaultOptions = { - mergeMaps, - mergeSets, - mergeArrays, - mergeRecords, - mergeOthers: leaf, -} as const; - -/** - * The default merge functions. - */ -export type DeepMergeMergeFunctionsDefaults = typeof defaultOptions; - -/** - * Deeply merge objects. - * - * @param objects - The objects to merge. - */ -export function deepmerge>( - ...objects: readonly [...Ts] -): DeepMergeHKT { - return deepmergeCustom({})(...objects) as DeepMergeHKT< - Ts, - DeepMergeMergeFunctionsDefaultURIs - >; -} - -/** - * Deeply merge two or more objects using the given options. - * - * @param options - The options on how to customize the merge function. - */ -export function deepmergeCustom< - PMF extends Partial ->( - options: DeepMergeOptions -): >( - ...objects: Ts -) => DeepMergeHKT> { - /** - * The type of the customized deepmerge function. - */ - type CustomizedDeepmerge = >( - ...objects: Ts - ) => DeepMergeHKT>; - - const utils = getUtils(options, customizedDeepmerge as CustomizedDeepmerge); - - /** - * The customized deepmerge function. - */ - function customizedDeepmerge(...objects: ReadonlyArray) { - if (objects.length === 0) { - return undefined; - } - if (objects.length === 1) { - return objects[0]; - } - - return mergeUnknowns(objects, utils); - } - - return customizedDeepmerge as CustomizedDeepmerge; -} - -/** - * The the full options with defaults apply. - * - * @param options - The options the user specified - */ -function getUtils( - options: DeepMergeOptions, - customizedDeepmerge: DeepMergeMergeFunctionUtils["deepmerge"] -): DeepMergeMergeFunctionUtils { - return { - defaultMergeFunctions: defaultOptions, - mergeFunctions: { - ...defaultOptions, - ...Object.fromEntries( - Object.entries(options).map(([key, option]) => - option === false ? [key, leaf] : [key, option] - ) - ), - } as DeepMergeMergeFunctionUtils["mergeFunctions"], - deepmerge: customizedDeepmerge, - }; -} - -/** - * Merge unknown things. - * - * @param values - The values. - */ -function mergeUnknowns< - Ts extends ReadonlyArray, - U extends DeepMergeMergeFunctionUtils, - MF extends DeepMergeMergeFunctionsURIs ->(values: Ts, utils: U): DeepMergeHKT { - const type = getObjectType(values[0]); - - // eslint-disable-next-line functional/no-conditional-statement -- add an early escape for better performance. - if (type !== ObjectType.NOT && type !== ObjectType.OTHER) { - // eslint-disable-next-line functional/no-loop-statement -- using a loop here is more performant than mapping every value and then testing every value. - for (let mutableIndex = 1; mutableIndex < values.length; mutableIndex++) { - if (getObjectType(values[mutableIndex]) === type) { - continue; - } - - return utils.mergeFunctions.mergeOthers(values, utils) as DeepMergeHKT< - Ts, - MF - >; - } - } - - switch (type) { - case ObjectType.RECORD: - return utils.mergeFunctions.mergeRecords( - values as ReadonlyArray>>, - utils - ) as DeepMergeHKT; - - case ObjectType.ARRAY: - return utils.mergeFunctions.mergeArrays( - values as ReadonlyArray>, - utils - ) as DeepMergeHKT; - - case ObjectType.SET: - return utils.mergeFunctions.mergeSets( - values as ReadonlyArray>>, - utils - ) as DeepMergeHKT; - - case ObjectType.MAP: - return utils.mergeFunctions.mergeMaps( - values as ReadonlyArray>>, - utils - ) as DeepMergeHKT; - - default: - return utils.mergeFunctions.mergeOthers(values, utils) as DeepMergeHKT< - Ts, - MF - >; - } -} - -/** - * Merge records. - * - * @param values - The records. - */ -function mergeRecords< - Ts extends ReadonlyArray>, - U extends DeepMergeMergeFunctionUtils, - MF extends DeepMergeMergeFunctionsURIs ->(values: Ts, utils: U) { - const result: Record = {}; - - /* eslint-disable functional/no-loop-statement, functional/no-conditional-statement -- using a loop here is more performant. */ - - for (const key of getKeys(values)) { - const propValues = []; - - for (const value of values) { - if (objectHasProperty(value, key)) { - propValues.push(value[key]); - } - } - - // assert(propValues.length > 0); - - result[key] = - propValues.length === 1 - ? propValues[0] - : mergeUnknowns(propValues, utils); - } - - /* eslint-enable functional/no-loop-statement, functional/no-conditional-statement */ - - return result as DeepMergeRecordsDefaultHKT; -} - -/** - * Merge arrays. - * - * @param values - The arrays. - */ -function mergeArrays< - Ts extends ReadonlyArray>, - U extends DeepMergeMergeFunctionUtils, - MF extends DeepMergeMergeFunctionsURIs ->(values: Ts, utils: U) { - return values.flat() as DeepMergeArraysDefaultHKT; -} - -/** - * Merge sets. - * - * @param values - The sets. - */ -function mergeSets< - Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils, - MF extends DeepMergeMergeFunctionsURIs ->(values: Ts, utils: U) { - return new Set(getIterableOfIterables(values)) as DeepMergeSetsDefaultHKT< - Ts, - MF - >; -} - -/** - * Merge maps. - * - * @param values - The maps. - */ -function mergeMaps< - Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils, - MF extends DeepMergeMergeFunctionsURIs ->(values: Ts, utils: U) { - return new Map(getIterableOfIterables(values)) as DeepMergeMapsDefaultHKT< - Ts, - MF - >; -} - -/** - * Merge "other" things. - * - * @param values - The values. - */ -function leaf< - Ts extends ReadonlyArray, - U extends DeepMergeMergeFunctionUtils, - MF extends DeepMergeMergeFunctionsURIs ->(values: Ts, utils: U) { - return values[values.length - 1]; -} diff --git a/deno-dist/docs/API.md b/deno-dist/docs/API.md deleted file mode 100644 index 97a845cb..00000000 --- a/deno-dist/docs/API.md +++ /dev/null @@ -1,73 +0,0 @@ -# API - -## deepmerge(x, y, ...) - -Merges the given inputs together using the default configuration. - -### deepmerge(...inputs) - -Merges the array of inputs together using the default configuration. - -Note: If `inputs` isn't typed as a tuple then we cannot determine the output type. The output type will simply be `unknown`. - -## deepmergeCustom(options) - -Generate a customized deepmerge function using the given options. The returned function works just like `deepmerge` except it uses the customized configuration. - -### options - -The following options can be used to customize the deepmerge function.\ -All these options are optional. - -#### `mergeRecords` - -Type: `false | (values: Record[], utils: DeepMergeMergeFunctionUtils) => unknown` - -If false, records won't be merged. If set to a function, that function will be used to merge records. - -Note: Records are "vanilla" objects (e.g. `{ foo: "hello", bar: "world" }`). - -#### `mergeArrays` - -Type: `false | (values: unknown[][], utils: DeepMergeMergeFunctionUtils) => unknown` - -If false, arrays won't be merged. If set to a function, that function will be used to merge arrays. - -#### `mergeMaps` - -Type: `false | (values: Map[], utils: DeepMergeMergeFunctionUtils) => unknown` - -If false, maps won't be merged. If set to a function, that function will be used to merge maps. - -#### `mergeSets` - -Type: `false | (values: Set[], utils: DeepMergeMergeFunctionUtils) => unknown` - -If false, sets won't be merged. If set to a function, that function will be used to merge sets. - -#### `mergeOthers` - -Type: `(values: Set[], utils: DeepMergeMergeFunctionUtils) => unknown` - -If set to a function, that function will be used to merge everything else. - -Note: This includes merging mixed types, such as merging a map with an array. - -### DeepMergeMergeFunctionUtils - -This is a set of utility functions that are made available to your custom merge functions. - -#### `mergeFunctions` - -These are all the merge function being used to perform the deepmerge.\ -These will be the custom merge functions you gave, or the default merge functions for options you didn't customize. - -#### `defaultMergeFunctions` - -These are all the merge functions that the default, non-customize deepmerge function uses. - -#### `deepmerge` - -This is your top level customized deepmerge function. - -Note: Be careful when calling this as it is really easy to end up in an infinite loop. diff --git a/deno-dist/docs/deepmergeCustom.md b/deno-dist/docs/deepmergeCustom.md deleted file mode 100644 index 73d709be..00000000 --- a/deno-dist/docs/deepmergeCustom.md +++ /dev/null @@ -1,94 +0,0 @@ -# Deepmerge Custom - -`deepmergeCustom` allows you to customize the deepmerge function. It is a higher-order function; that is to say it returns a new customized deepmerge function. - -## Customizing the return type - -If you want to customize the deepmerge function, you probably also want the return type of the result to be correct too.\ -Unfortunately however, due to TypeScript limitations, we can not automatically infer this. -In order to get the correct return type, you need to provide us with type information about how you have customized the function (we do the very same to define the default configuration). - -We need to use HKTs (higher-kinded types) in order to generate the right output type. But again, unfortunately, TypeScript does not support HKTs. Luckily however, there is a workaround. -To use HKTs, we alias the type to a string type (a URI) and simply refer to that type by its alias until we need to resolve it. - -Here's a simple example that creates a custom deepmerge function that does not merge arrays. - -```js -import type { DeepMergeLeafURI } from "deepmerge-ts"; -import { deepmergeCustom } from "deepmerge-ts"; - -const customDeepmerge = deepmergeCustom<{ - DeepMergeArraysURI: DeepMergeLeafURI; // <-- Needed for correct output type. -}>({ - mergeArrays: false, -}); - -const x = { foo: [1, 2], bar: [3, 4] }; -const y = { foo: [5, 6] }; - -customDeepmerge(x, y); // => { foo: [5, 6], bar: [3, 4] } -``` - -When resolving a HKT, we use a lookup inside an interface called `DeepMergeMergeFunctionURItoKind`. -This interface needs to contain all the mappings of the URIs to their actual type. - -When defining your own HKT for use with deepmerge, you need to extend this interface with your mapping. -This can be done using [Declaration Merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) by declaring a module block for this library and defining the same interface. - -```ts -declare module "deepmerge-ts" { - interface DeepMergeMergeFunctionURItoKind, MF extends DeepMergeMergeFunctionsURIs> { - readonly MyCustomMergeURI: MyValue; - } -} -``` - -Here's an example of creating a custom deepmerge function that amalgamates dates into an array. - -```ts -import type { DeepMergeLeaf, DeepMergeMergeFunctionURItoKind, DeepMergeMergeFunctionsURIs } from "deepmerge-ts"; -import { deepmergeCustom } from "deepmerge-ts"; - -const customizedDeepmerge = deepmergeCustom<{ - DeepMergeOthersURI: "MyDeepMergeDatesURI"; // <-- Needed for correct output type. -}>({ - mergeOthers: (values, utils) => { - // If every value is a date, the return the amalgamated array. - if (values.every((value) => value instanceof Date)) { - return values; - } - // Otherwise, use the default merging strategy. - return utils.defaultMergeFunctions.mergeOthers(values, utils); - }, -}); - -const x = { foo: new Date("2020-01-01") }; -const y = { foo: new Date("2021-02-02") }; -const z = { foo: new Date("2022-03-03") }; - -customDeepmerge(x, y, z); // => { foo: [Date, Date, Date] } - -declare module "deepmerge-ts" { - interface DeepMergeMergeFunctionURItoKind< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs - > { - readonly MyDeepMergeDatesURI: EveryIsDate extends true ? Ts : DeepMergeLeaf; - } -} - -type EveryIsDate> = Ts extends readonly [ - infer Head, - ...infer Rest -] - ? Head extends Date - ? EveryIsDate - : false - : true; -``` - -Note: If you want to use HKTs in your own project, not related to deepmerge-ts, we recommend checking out [fp-ts](https://gcanti.github.io/fp-ts/modules/HKT.ts.html). - -## API - -[See deepmerge custom API](./API.md#deepmergecustomoptions). diff --git a/deno-dist/index.ts b/deno-dist/index.ts deleted file mode 100644 index 8fca291d..00000000 --- a/deno-dist/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -export { deepmerge, deepmergeCustom } from "./deepmerge.ts"; - -export type { DeepMergeMergeFunctionsDefaults } from "./deepmerge.ts"; -export type { - DeepMergeArraysDefaultHKT, - DeepMergeHKT, - DeepMergeLeaf, - DeepMergeLeafHKT, - DeepMergeLeafURI, - DeepMergeMapsDefaultHKT, - DeepMergeMergeFunctionsDefaultURIs, - DeepMergeMergeFunctionsURIs, - DeepMergeMergeFunctionURItoKind, - DeepMergeMergeFunctionUtils, - DeepMergeOptions, - DeepMergeRecordsDefaultHKT, - DeepMergeSetsDefaultHKT, -} from "./types/index.ts"; diff --git a/deno-dist/mod.ts b/deno-dist/mod.ts deleted file mode 100644 index da5ee324..00000000 --- a/deno-dist/mod.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./index.ts"; \ No newline at end of file diff --git a/deno-dist/types/basics.ts b/deno-dist/types/basics.ts deleted file mode 100644 index e3aade2e..00000000 --- a/deno-dist/types/basics.ts +++ /dev/null @@ -1,5 +0,0 @@ -/** - * A property that can index an object. - */ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type RecordProperty = keyof any; diff --git a/deno-dist/types/defaults.ts b/deno-dist/types/defaults.ts deleted file mode 100644 index 7b6b9989..00000000 --- a/deno-dist/types/defaults.ts +++ /dev/null @@ -1,199 +0,0 @@ -import type { - DeepMergeHKT, - DeepMergeLeafURI, - DeepMergeMergeFunctionsURIs, - DeepMergeMergeFunctionURItoKind, -} from "./merging.ts"; -import type { - FlatternAlias, - FilterOutNever, - OptionalKeysOf, - RequiredKeysOf, - UnionMapKeys, - UnionMapValues, - UnionSetValues, - ValueOfKey, -} from "./utils.ts"; - -/** - * The default merge function to merge records with. - */ -type DeepMergeRecordsDefaultURI = "DeepMergeRecordsDefaultURI"; - -/** - * The default merge function to merge arrays with. - */ -type DeepMergeArraysDefaultURI = "DeepMergeArraysDefaultURI"; - -/** - * The default merge function to merge sets with. - */ -type DeepMergeSetsDefaultURI = "DeepMergeSetsDefaultURI"; - -/** - * The default merge function to merge maps with. - */ -type DeepMergeMapsDefaultURI = "DeepMergeMapsDefaultURI"; - -/** - * The default merge functions to use when deep merging. - */ -export type DeepMergeMergeFunctionsDefaultURIs = { - DeepMergeRecordsURI: DeepMergeRecordsDefaultURI; - DeepMergeArraysURI: DeepMergeArraysDefaultURI; - DeepMergeSetsURI: DeepMergeSetsDefaultURI; - DeepMergeMapsURI: DeepMergeMapsDefaultURI; - DeepMergeOthersURI: DeepMergeLeafURI; -}; - -/** - * A union of all the props that should not be included in type information for - * merged records. - */ -type BlacklistedRecordProps = "__proto__"; - -/** - * Deep merge records. - */ -export type DeepMergeRecordsDefaultHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = Ts extends readonly [unknown, ...unknown[]] - ? FlatternAlias< - Omit< - DeepMergeRecordsDefaultHKTInternalProps, - BlacklistedRecordProps - > - > - : {}; - -/** - * Deep merge record props. - */ -type DeepMergeRecordsDefaultHKTInternalProps< - Ts extends readonly [unknown, ...unknown[]], - MF extends DeepMergeMergeFunctionsURIs -> = { - [K in OptionalKeysOf]?: DeepMergeHKT< - DeepMergeRecordsDefaultHKTInternalPropValue, - MF - >; -} & { - [K in RequiredKeysOf]: DeepMergeHKT< - DeepMergeRecordsDefaultHKTInternalPropValue, - MF - >; -}; - -/** - * Get the value of the property. - */ -type DeepMergeRecordsDefaultHKTInternalPropValue< - Ts extends readonly [unknown, ...unknown[]], - K extends PropertyKey -> = FilterOutNever< - DeepMergeRecordsDefaultHKTInternalPropValueHelper ->; - -/** - * Tail-recursive helper type for DeepMergeRecordsDefaultHKTInternalPropValue. - */ -type DeepMergeRecordsDefaultHKTInternalPropValueHelper< - Ts extends readonly [unknown, ...unknown[]], - K extends PropertyKey, - Acc extends ReadonlyArray -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Record - ? Rest extends readonly [unknown, ...unknown[]] - ? DeepMergeRecordsDefaultHKTInternalPropValueHelper< - Rest, - K, - [...Acc, ValueOfKey] - > - : [...Acc, ValueOfKey] - : never - : never; - -/** - * Deep merge 2 arrays. - */ -export type DeepMergeArraysDefaultHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = DeepMergeArraysDefaultHKTHelper; - -/** - * Tail-recursive helper type for DeepMergeArraysDefaultHKT. - */ -type DeepMergeArraysDefaultHKTHelper< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, - Acc extends ReadonlyArray -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends ReadonlyArray - ? Rest extends readonly [ - ReadonlyArray, - ...ReadonlyArray> - ] - ? DeepMergeArraysDefaultHKTHelper - : [...Acc, ...Head] - : never - : never; - -/** - * Deep merge 2 sets. - */ -export type DeepMergeSetsDefaultHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = Set>; - -/** - * Deep merge 2 maps. - */ -export type DeepMergeMapsDefaultHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = Map, UnionMapValues>; - -/** - * Get the merge functions with defaults apply from the given subset. - */ -export type GetDeepMergeMergeFunctionsURIs< - PMF extends Partial -> = { - // prettier-ignore - DeepMergeRecordsURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - PMF["DeepMergeRecordsURI"] extends keyof DeepMergeMergeFunctionURItoKind - ? PMF["DeepMergeRecordsURI"] - : DeepMergeRecordsDefaultURI; - - // prettier-ignore - DeepMergeArraysURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - PMF["DeepMergeArraysURI"] extends keyof DeepMergeMergeFunctionURItoKind - ? PMF["DeepMergeArraysURI"] - : DeepMergeArraysDefaultURI; - - // prettier-ignore - DeepMergeSetsURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - PMF["DeepMergeSetsURI"] extends keyof DeepMergeMergeFunctionURItoKind - ? PMF["DeepMergeSetsURI"] - : DeepMergeSetsDefaultURI; - - // prettier-ignore - DeepMergeMapsURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - PMF["DeepMergeMapsURI"] extends keyof DeepMergeMergeFunctionURItoKind - ? PMF["DeepMergeMapsURI"] - : DeepMergeMapsDefaultURI; - - // prettier-ignore - DeepMergeOthersURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any - PMF["DeepMergeOthersURI"] extends keyof DeepMergeMergeFunctionURItoKind - ? PMF["DeepMergeOthersURI"] - : DeepMergeLeafURI; -}; diff --git a/deno-dist/types/index.ts b/deno-dist/types/index.ts deleted file mode 100644 index f6ebaff2..00000000 --- a/deno-dist/types/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./defaults.ts"; -export * from "./merging.ts"; -export * from "./options.ts"; diff --git a/deno-dist/types/merging.ts b/deno-dist/types/merging.ts deleted file mode 100644 index 2f6356c9..00000000 --- a/deno-dist/types/merging.ts +++ /dev/null @@ -1,167 +0,0 @@ -import type { - DeepMergeRecordsDefaultHKT, - DeepMergeArraysDefaultHKT, - DeepMergeSetsDefaultHKT, - DeepMergeMapsDefaultHKT, -} from "./defaults.ts"; -import type { - EveryIsArray, - EveryIsMap, - EveryIsRecord, - EveryIsSet, - IsNever, - IsTuple, -} from "./utils.ts"; - -/** - * Mapping of merge function URIs to the merge function type. - */ -// eslint-disable-next-line @typescript-eslint/consistent-type-definitions -export interface DeepMergeMergeFunctionURItoKind< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> { - readonly DeepMergeLeafURI: DeepMergeLeafHKT; - readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; - readonly DeepMergeArraysDefaultURI: DeepMergeArraysDefaultHKT; - readonly DeepMergeSetsDefaultURI: DeepMergeSetsDefaultHKT; - readonly DeepMergeMapsDefaultURI: DeepMergeMapsDefaultHKT; -} - -/** - * Get the type of the given merge function via its URI. - */ -type DeepMergeMergeFunctionKind< - URI extends DeepMergeMergeFunctionURIs, - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = DeepMergeMergeFunctionURItoKind[URI]; - -/** - * A union of all valid merge function URIs. - */ -type DeepMergeMergeFunctionURIs = keyof DeepMergeMergeFunctionURItoKind< - ReadonlyArray, - DeepMergeMergeFunctionsURIs ->; - -/** - * The merge functions to use when deep merging. - */ -export type DeepMergeMergeFunctionsURIs = { - /** - * The merge function to merge records with. - */ - DeepMergeRecordsURI: DeepMergeMergeFunctionURIs; - - /** - * The merge function to merge arrays with. - */ - DeepMergeArraysURI: DeepMergeMergeFunctionURIs; - - /** - * The merge function to merge sets with. - */ - DeepMergeSetsURI: DeepMergeMergeFunctionURIs; - - /** - * The merge function to merge maps with. - */ - DeepMergeMapsURI: DeepMergeMergeFunctionURIs; - - /** - * The merge function to merge other things with. - */ - DeepMergeOthersURI: DeepMergeMergeFunctionURIs; -}; - -/** - * Deep merge types. - */ -export type DeepMergeHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = IsTuple extends true - ? Ts extends readonly [] - ? undefined - : Ts extends readonly [infer T1] - ? T1 - : EveryIsArray extends true - ? DeepMergeArraysHKT - : EveryIsMap extends true - ? DeepMergeMapsHKT - : EveryIsSet extends true - ? DeepMergeSetsHKT - : EveryIsRecord extends true - ? DeepMergeRecordsHKT - : DeepMergeOthersHKT - : unknown; - -/** - * Deep merge records. - */ -type DeepMergeRecordsHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = DeepMergeMergeFunctionKind; - -/** - * Deep merge arrays. - */ -type DeepMergeArraysHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = DeepMergeMergeFunctionKind; - -/** - * Deep merge sets. - */ -type DeepMergeSetsHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = DeepMergeMergeFunctionKind; - -/** - * Deep merge maps. - */ -type DeepMergeMapsHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = DeepMergeMergeFunctionKind; - -/** - * Deep merge other things. - */ -type DeepMergeOthersHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = DeepMergeMergeFunctionKind; - -/** - * The merge function that returns a leaf. - */ -export type DeepMergeLeafURI = "DeepMergeLeafURI"; - -/** - * Get the leaf type from 2 types that can't be merged. - */ -export type DeepMergeLeafHKT< - Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs -> = DeepMergeLeaf; - -/** - * Get the leaf type from many types that can't be merged. - */ -export type DeepMergeLeaf> = - Ts extends readonly [] - ? never - : Ts extends [infer T] - ? T - : Ts extends [...infer Rest, infer Tail] - ? IsNever extends true - ? Rest extends ReadonlyArray - ? DeepMergeLeaf - : never - : Tail - : never; diff --git a/deno-dist/types/options.ts b/deno-dist/types/options.ts deleted file mode 100644 index 00c58e8a..00000000 --- a/deno-dist/types/options.ts +++ /dev/null @@ -1,71 +0,0 @@ -import type { DeepMergeMergeFunctionsDefaults } from "@/deepmerge DENOIFY: DEPENDENCY UNMET (BUILTIN)"; - -/** - * The options the user can pass to customize deepmerge. - */ -export type DeepMergeOptions = Partial; - -/** - * All the options the user can pass to customize deepmerge. - */ -type DeepMergeOptionsFull = Readonly<{ - mergeRecords: DeepMergeMergeFunctions["mergeRecords"] | false; - mergeArrays: DeepMergeMergeFunctions["mergeArrays"] | false; - mergeMaps: DeepMergeMergeFunctions["mergeMaps"] | false; - mergeSets: DeepMergeMergeFunctions["mergeSets"] | false; - mergeOthers: DeepMergeMergeFunctions["mergeOthers"]; -}>; - -/** - * All the merge functions that deepmerge uses. - */ -type DeepMergeMergeFunctions = Readonly<{ - mergeRecords: < - Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils - >( - records: Ts, - utils: U - ) => unknown; - - mergeArrays: < - Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils - >( - records: Ts, - utils: U - ) => unknown; - - mergeMaps: < - Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils - >( - records: Ts, - utils: U - ) => unknown; - - mergeSets: < - Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils - >( - records: Ts, - utils: U - ) => unknown; - - mergeOthers: < - Ts extends ReadonlyArray, - U extends DeepMergeMergeFunctionUtils - >( - records: Ts, - utils: U - ) => unknown; -}>; - -/** - * The utils provided to the merge functions. - */ -export type DeepMergeMergeFunctionUtils = Readonly<{ - mergeFunctions: DeepMergeMergeFunctions; - defaultMergeFunctions: DeepMergeMergeFunctionsDefaults; - deepmerge: >(...values: Ts) => unknown; -}>; diff --git a/deno-dist/types/utils.ts b/deno-dist/types/utils.ts deleted file mode 100644 index c12e0cbb..00000000 --- a/deno-dist/types/utils.ts +++ /dev/null @@ -1,321 +0,0 @@ -/** - * Flatten a complex type such as a union or intersection of objects into a - * single object. - */ -export type FlatternAlias = { [P in keyof T]: T[P] } & {}; - -/** - * Get the value of the given key in the given object. - */ -export type ValueOfKey< - T extends Record, - K extends PropertyKey -> = K extends keyof T ? T[K] : never; - -/** - * Safely test whether or not the first given types extends the second. - * - * Needed in particular for testing if a type is "never". - */ -export type Is = [T1] extends [T2] ? true : false; - -/** - * Safely test whether or not the given type is "never". - */ -export type IsNever = Is; - -/** - * Returns whether or not all the given types are never. - */ -export type EveryIsNever> = Ts extends [ - infer Head, - ...infer Rest -] - ? IsNever extends true - ? Rest extends ReadonlyArray - ? EveryIsNever - : true - : false - : true; - -/** - * Returns whether or not the given type a record. - */ -export type IsRecord = And< - Not>, - T extends Readonly> ? true : false ->; - -/** - * Returns whether or not all the given types are records. - */ -export type EveryIsRecord> = Ts extends [ - infer Head, - ...infer Rest -] - ? IsRecord extends true - ? Rest extends ReadonlyArray - ? EveryIsRecord - : true - : false - : true; - -/** - * Returns whether or not the given type is an array. - */ -export type IsArray = And< - Not>, - T extends ReadonlyArray ? true : false ->; - -/** - * Returns whether or not all the given types are arrays. - */ -export type EveryIsArray> = Ts extends [ - infer T1 -] - ? IsArray - : Ts extends [infer Head, ...infer Rest] - ? IsArray extends true - ? Rest extends [unknown, ...ReadonlyArray] - ? EveryIsArray - : false - : false - : false; - -/** - * Returns whether or not the given type is an set. - * - * Note: This may also return true for Maps. - */ -export type IsSet = And< - Not>, - T extends Readonly> ? true : false ->; - -/** - * Returns whether or not all the given types are sets. - * - * Note: This may also return true if all are maps. - */ -export type EveryIsSet> = Ts extends [ - infer T1 -] - ? IsSet - : Ts extends [infer Head, ...infer Rest] - ? IsSet extends true - ? Rest extends [unknown, ...ReadonlyArray] - ? EveryIsSet - : false - : false - : false; - -/** - * Returns whether or not the given type is an map. - */ -export type IsMap = And< - Not>, - T extends Readonly> ? true : false ->; - -/** - * Returns whether or not all the given types are maps. - */ -export type EveryIsMap> = Ts extends [ - infer T1 -] - ? IsMap - : Ts extends [infer Head, ...infer Rest] - ? IsMap extends true - ? Rest extends [unknown, ...ReadonlyArray] - ? EveryIsMap - : false - : false - : false; - -/** - * And operator for types. - */ -export type And = T1 extends false - ? false - : T2; - -/** - * Or operator for types. - */ -export type Or = T1 extends true - ? true - : T2; - -/** - * Not operator for types. - */ -export type Not = T extends true ? false : true; - -/** - * Union of the sets' values' types - */ -export type UnionSetValues> = - UnionSetValuesHelper; - -/** - * Tail-recursive helper type for UnionSetValues. - */ -type UnionSetValuesHelper< - Ts extends ReadonlyArray, - Acc -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Set - ? Rest extends ReadonlyArray - ? UnionSetValuesHelper - : Acc | V1 - : never - : Acc; - -/** - * Union of the maps' values' types - */ -export type UnionMapKeys> = - UnionMapKeysHelper; - -/** - * Tail-recursive helper type for UnionMapKeys. - */ -type UnionMapKeysHelper< - Ts extends ReadonlyArray, - Acc -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Map - ? Rest extends readonly [] - ? Acc | K1 - : UnionMapKeysHelper - : never - : Acc; - -/** - * Union of the maps' keys' types - */ -export type UnionMapValues> = - UnionMapValuesHelper; - -/** - * Tail-recursive helper type for UnionMapValues. - */ -type UnionMapValuesHelper< - Ts extends ReadonlyArray, - Acc -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Map - ? Rest extends readonly [] - ? Acc | V1 - : UnionMapValuesHelper - : never - : Acc; - -/** - * Get all the keys of the given records. - */ -export type KeysOf> = KeysOfHelper; - -/** - * Tail-recursive helper type for KeysOf. - */ -type KeysOfHelper< - Ts extends ReadonlyArray, - Acc -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Record - ? Rest extends ReadonlyArray - ? KeysOfHelper - : Acc | keyof Head - : never - : Acc; - -/** - * Get the keys of the type what match a certain criteria. - */ -type KeysOfType = { - [K in keyof T]: T[K] extends U ? K : never; -}[keyof T]; - -/** - * Get the required keys of the type. - */ -type RequiredKeys = Exclude< - KeysOfType>, - undefined ->; - -/** - * Get all the required keys on the types in the tuple. - */ -export type RequiredKeysOf = - RequiredKeysOfHelper; - -/** - * Tail-recursive helper type for RequiredKeysOf. - */ -type RequiredKeysOfHelper< - Ts extends readonly [unknown, ...unknown[]], - Acc -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Record - ? Rest extends readonly [unknown, ...unknown[]] - ? RequiredKeysOfHelper> - : Acc | RequiredKeys - : never - : Acc; - -/** - * Get the optional keys of the type. - */ -type OptionalKeys = Exclude>; - -/** - * Get all the optional keys on the types in the tuple. - */ -export type OptionalKeysOf = - OptionalKeysOfHelper; - -/** - * Tail-recursive helper type for OptionalKeysOf. - */ -type OptionalKeysOfHelper< - Ts extends readonly [unknown, ...unknown[]], - Acc -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Record - ? Rest extends readonly [unknown, ...unknown[]] - ? OptionalKeysOfHelper> - : Acc | OptionalKeys - : never - : Acc; - -/** - * Filter out nevers from a tuple. - */ -export type FilterOutNever> = - FilterOutNeverHelper; - -/** - * Tail-recursive helper type for FilterOutNever. - */ -type FilterOutNeverHelper< - T extends ReadonlyArray, - Acc extends ReadonlyArray -> = T extends readonly [] - ? Acc - : T extends readonly [infer Head, ...infer Rest] - ? IsNever extends true - ? FilterOutNeverHelper - : FilterOutNeverHelper - : T; - -/** - * Is the type a tuple? - */ -export type IsTuple> = T extends readonly [] - ? true - : T extends readonly [unknown, ...unknown[]] - ? true - : false; diff --git a/deno-dist/utils.ts b/deno-dist/utils.ts deleted file mode 100644 index 74632027..00000000 --- a/deno-dist/utils.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { isPlainObject } from "https://raw.githubusercontent.com/jonschlinkert/is-plain-object/v5.0.0/is-plain-object.js"; - -/** - * The different types of objects deepmerge-ts support. - */ -export const enum ObjectType { - NOT, - RECORD, - ARRAY, - SET, - MAP, - OTHER, -} - -/** - * Get the type of the given object. - * - * @param object - The object to get the type of. - * @returns The type of the given object. - */ -export function getObjectType(object: unknown): ObjectType { - if (typeof object !== "object" || object === null) { - return ObjectType.NOT; - } - - if (Array.isArray(object)) { - return ObjectType.ARRAY; - } - - if (isPlainObject(object)) { - return ObjectType.RECORD; - } - - if (object instanceof Set) { - return ObjectType.SET; - } - - if (object instanceof Map) { - return ObjectType.MAP; - } - - return ObjectType.OTHER; -} - -/** - * Get the keys of the given objects including symbol keys. - * - * Note: Only keys to enumerable properties are returned. - * - * @param objects - An array of objects to get the keys of. - * @returns A set containing all the keys of all the given objects. - */ -export function getKeys( - objects: Readonly> -): Set { - const keys = new Set(); - - /* eslint-disable functional/no-loop-statement -- using a loop here is more efficient. */ - for (const object of objects) { - for (const key of [ - ...Object.keys(object), - ...Object.getOwnPropertySymbols(object), - ]) { - keys.add(key); - } - } - /* eslint-enable functional/no-loop-statement */ - - return keys; -} - -/** - * Does the given object have the given property. - * - * @param object - The object to test. - * @param property - The property to test. - * @returns Whether the object has the property. - */ -export function objectHasProperty( - object: object, - property: PropertyKey -): boolean { - return ( - typeof object === "object" && - Object.prototype.propertyIsEnumerable.call(object, property) - ); -} - -/** - * Get an iterable object that iterates over the given iterables. - */ -export function getIterableOfIterables( - iterables: ReadonlyArray>> -): Iterable { - return { - *[Symbol.iterator]() { - // eslint-disable-next-line functional/no-loop-statement - for (const iterable of iterables) { - // eslint-disable-next-line functional/no-loop-statement - for (const value of iterable) { - yield value; - } - } - }, - }; -} diff --git a/package.json b/package.json index 21dac884..d555e543 100644 --- a/package.json +++ b/package.json @@ -32,28 +32,27 @@ "email": "rebecca.stevens@outlook.co.nz" }, "exports": { - "import": "./lib/index.mjs", - "require": "./lib/index.cjs", - "default": "./lib/index.cjs" + "import": "./dist/node/index.mjs", + "require": "./dist/node/index.cjs", + "default": "./dist/node/index.cjs" }, - "main": "lib/index.cjs", - "module": "lib/index.mjs", - "types": "types/legacy/v4_0.d.ts", + "main": "dist/node/index.cjs", + "module": "dist/node/index.mjs", + "types": "dist/node/types/legacy/v4_0.d.ts", "typesVersions": { "<4.1": { "*": [ - "types/legacy/v4_0.d.ts" + "dist/node/types/legacy/v4_0.d.ts" ] }, ">=4.1": { "*": [ - "types/current/index.d.ts" + "dist/node/types/current/index.d.ts" ] } }, "files": [ - "lib/", - "types/", + "dist/node/", "package.json", "CHANGELOG.md", "LICENSE", @@ -65,9 +64,9 @@ "prebuild": "rimraf build", "build": "yarn build:npm && yarn build:deno", "postbuild": "rimraf build", - "pre:build:deno": "rimraf deno-dist", + "pre:build:deno": "rimraf dist/deno", "build:deno": "tsc -p tsconfig.build.deno.json && denoify", - "prebuild:npm": "rimraf lib types/current", + "prebuild:npm": "rimraf dist/node types/current", "build:npm": "rollup -c", "check-format": "prettier --list-different \"./**/*.{md,ts,yml}\"", "check-spelling": "cspell --config=.cspell.json \"**/*.{md,ts}\"", @@ -133,6 +132,7 @@ "rimraf": "^3.0.2", "rollup": "^2.56.3", "rollup-plugin-auto-external": "^2.0.0", + "rollup-plugin-copy": "^3.4.0", "rollup-plugin-dts": "^4.0.0", "semantic-release": "^17.4.7", "source-map-support": "^0.5.20", @@ -141,14 +141,7 @@ "typescript": "^4.4.3" }, "denoify": { - "out": "deno-dist", - "includes": [ - "assets", - "docs", - "CHANGELOG.md", - "LICENSE", - "README.md" - ], + "out": "dist/deno", "index": "src/index.ts", "ports": { "is-plain-object": "https://raw.githubusercontent.com/jonschlinkert/is-plain-object/v5.0.0/is-plain-object.js" diff --git a/rollup.config.ts b/rollup.config.ts index a8c1a83f..41c5c99b 100644 --- a/rollup.config.ts +++ b/rollup.config.ts @@ -6,6 +6,7 @@ import rollupPluginJSON from "@rollup/plugin-json"; import rollupPluginNodeResolve from "@rollup/plugin-node-resolve"; import rollupPluginTypescript from "@rollup/plugin-typescript"; import rollupPluginAutoExternal from "rollup-plugin-auto-external"; +import rollupPluginCopy from "rollup-plugin-copy"; import rollupPluginDts from "rollup-plugin-dts"; import pkg from "./package.json"; @@ -71,7 +72,7 @@ const dts = { ...common, output: { - file: "types/current/index.d.ts", + file: "dist/node/types/current/index.d.ts", format: "es", }, @@ -80,6 +81,11 @@ const dts = { tsconfig: "tsconfig.build.json", }), rollupPluginDts(), + rollupPluginCopy({ + targets: [ + { src: "types-legacy", dest: "dist/node/types", rename: "legacy" }, + ], + }), ], }; diff --git a/tsconfig.base.json b/tsconfig.base.json index a07e45f0..6867a46a 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -30,6 +30,6 @@ }, "exclude": [ "benchmark/", - "types/" + "types-legacy/" ] } diff --git a/tsconfig.build.deno.json b/tsconfig.build.deno.json index 8adcbbef..4476aa2e 100644 --- a/tsconfig.build.deno.json +++ b/tsconfig.build.deno.json @@ -6,7 +6,7 @@ "exclude": [ "node_modules", "build/deno/", - "deno-dist/", + "dist/", "src/**/*.deno.ts", "src/**/*.deno.tsx", ] diff --git a/types/legacy/v4_0.d.ts b/types-legacy/v4_0.d.ts similarity index 100% rename from types/legacy/v4_0.d.ts rename to types-legacy/v4_0.d.ts diff --git a/yarn.lock b/yarn.lock index ba9552d3..177abb3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1138,6 +1138,21 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/fs-extra@^8.0.1": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-8.1.2.tgz#7125cc2e4bdd9bd2fc83005ffdb1d0ba00cca61f" + integrity sha512-SvSrYXfWSc7R4eqnOzbQF4TZmfpNSM9FrSWLU3EUnWBuyZqNBOrv1B1JA3byUDPUl9z4Ab3jeZG2eDdySlgNMg== + dependencies: + "@types/node" "*" + +"@types/glob@^7.1.1": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + "@types/json-schema@^7.0.7": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -1155,6 +1170,11 @@ dependencies: "@types/unist" "*" +"@types/minimatch@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + "@types/minimist@^1.2.0": version "1.2.2" resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" @@ -2251,6 +2271,11 @@ color-support@^1.1.2: resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== +colorette@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.4.0.tgz#5190fbb87276259a86ad700bff2c6d6faa3fca40" + integrity sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g== + colorette@^1.2.2, colorette@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.3.0.tgz#ff45d2f0edb244069d3b772adeb04fed38d0a0af" @@ -3459,7 +3484,7 @@ fast-diff@^1.1.2, fast-diff@^1.2.0: resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== -fast-glob@^3.1.1: +fast-glob@^3.0.3, fast-glob@^3.1.1: version "3.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== @@ -3930,6 +3955,20 @@ globals@^13.6.0, globals@^13.9.0: dependencies: type-fest "^0.20.2" +globby@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" + integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + globby@^11.0.0, globby@^11.0.1, globby@^11.0.3: version "11.0.4" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" @@ -4511,6 +4550,11 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= +is-plain-object@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" + integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== + is-plain-object@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" @@ -5375,7 +5419,7 @@ merge-stream@^2.0.0: resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.2.3, merge2@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -6898,6 +6942,17 @@ rollup-plugin-auto-external@^2.0.0: safe-resolve "^1.0.0" semver "^5.5.0" +rollup-plugin-copy@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-copy/-/rollup-plugin-copy-3.4.0.tgz#f1228a3ffb66ffad8606e2f3fb7ff23141ed3286" + integrity sha512-rGUmYYsYsceRJRqLVlE9FivJMxJ7X6jDlP79fmFkL8sJs7VVMSVyA2yfyL+PGyO/vJs4A87hwhgVfz61njI+uQ== + dependencies: + "@types/fs-extra" "^8.0.1" + colorette "^1.1.0" + fs-extra "^8.1.0" + globby "10.0.1" + is-plain-object "^3.0.0" + rollup-plugin-dts@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/rollup-plugin-dts/-/rollup-plugin-dts-4.0.0.tgz#7645280183b7624e77375a548a11297f9916f6d8"