diff --git a/.github/workflows/build-node.yml b/.github/workflows/build.yml
similarity index 80%
rename from .github/workflows/build-node.yml
rename to .github/workflows/build.yml
index d670bbf5..0c5d026b 100644
--- a/.github/workflows/build-node.yml
+++ b/.github/workflows/build.yml
@@ -6,9 +6,9 @@ on:
workflow_call:
jobs:
- build_node:
+ build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: ./.github/actions/prepare
- - run: pnpm run build:node
+ - run: pnpm run build
diff --git a/.github/workflows/check-dist-files.yml b/.github/workflows/check-dist-files.yml
deleted file mode 100644
index 9a339bd8..00000000
--- a/.github/workflows/check-dist-files.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-name: Check for dist file changes
-
-# From https://github.com/github/docs/blob/main/.github/workflows/triage-unallowed-contributions.yml
-
-on:
- pull_request_target:
- paths:
- - "dist/**"
-
-permissions:
- pull-requests: write
-
-jobs:
- triage:
- if: >-
- ${{
- github.event.pull_request.user.login != 'semantic-release-bot'
- }}
- runs-on: ubuntu-latest
- steps:
- - name: Get files changed
- uses: dorny/paths-filter@v3
- id: filter
- with:
- # Base branch used to get changed files
- base: "main"
-
- # Enables setting an output in the format in `${FILTER_NAME}_files
- # with the names of the matching files formatted as JSON array
- list-files: json
-
- # Returns list of changed files matching each filter
- filters: |
- notAllowed:
- - 'dist/**'
-
- # When there are changes to files we can't accept, leave a comment
- # explaining this to the PR author
- - name: "Comment about changes we can't accept"
- if: ${{ steps.filter.outputs.notAllowed }}
- uses: actions/github-script@v7
- with:
- script: |
- let reviewMessage = "👋 Hey there. It looks like you've modified some of the `dist` files.\nYou'll need to revert all of the changes that you've made to these files. Once you get those files reverted, we can continue with the review process. :octocat:"
- let workflowFailMessage = "It looks like you've modified some of the `dist` files."
-
- try {
- createdComment = await github.issues.createComment({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: context.payload.number,
- body: reviewMessage,
- })
-
- workflowFailMessage = `${workflowFailMessage} Please see ${createdComment.data.html_url} for details.`
- } catch(err) {
- console.log("Error creating comment.", err)
- }
-
- core.setFailed(workflowFailMessage)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index fe79d599..08ffda5c 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -7,6 +7,7 @@ on:
permissions:
contents: write
+ id-token: write
issues: write
pull-requests: write
diff --git a/.gitignore b/.gitignore
index 15fe09fa..501cab12 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,5 @@
node_modules/
-/build/
/coverage/
/dist/
diff --git a/.releaserc.yml b/.releaserc.yml
index b87b9692..6f514904 100644
--- a/.releaserc.yml
+++ b/.releaserc.yml
@@ -49,6 +49,7 @@ plugins:
- dist
- CHANGELOG.md
- "@semantic-release/npm"
+ - "@sebbo2002/semantic-release-jsr"
- - "@semantic-release/github"
- releasedLabels:
- "<%= nextRelease.channel === 'next' ? 'Status: Released on Next' : 'Status: Released' %>"
diff --git a/README.md b/README.md
index 795020ef..bd36123c 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
# 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&sort=semver)](https://deno.land/x/deepmergets)
+[![jsr Version](https://img.shields.io/jsr/v/@rebeccastevens/deepmerge)](https://jsr.io/@rebeccastevens/deepmerge)
[![CI](https://github.com/RebeccaStevens/deepmerge-ts/actions/workflows/release.yml/badge.svg)](https://github.com/RebeccaStevens/deepmerge-ts/actions/workflows/release.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)
@@ -32,7 +32,7 @@ your open source software supply chain meets enterprise standards now and into t
## Installation
-### Node
+### npm
```sh
# Install with npm
@@ -43,17 +43,22 @@ pnpm add deepmerge-ts
# Install with yarn
yarn add deepmerge-ts
+
+# Install with bun
+bun add deepmerge-ts
```
-### Deno
+### jsr
-```jsonc
-// import_map.json
-{
- "imports": {
- "deepmerge-ts": "https://deno.land/x/deepmergets@__version__/dist/deno/index.ts",
- },
-}
+```sh
+# Install in a node project
+npx jsr add @rebeccastevens/deepmerge
+
+# Install in a deno project
+deno add jsr:@rebeccastevens/deepmerge
+
+# Install in a bun project
+bunx jsr add @rebeccastevens/deepmerge
```
## Features
diff --git a/cspell.config.yml b/cspell.config.yml
index 3d86c053..a356336c 100644
--- a/cspell.config.yml
+++ b/cspell.config.yml
@@ -60,6 +60,7 @@ overrides:
- filename: "**/*.yml"
ignoreRegExpList:
- /^\s*(?:[a-z0-9]|-|_|\"|')+:/ui # ignore keys
+ - /@[a-z0-9-]+\/[a-z0-9-]+/u # scoped packages
- filename: ".github/(actions|workflows)/*.yml"
ignoreRegExpList:
diff --git a/dist/deno/LICENSE b/dist/deno/LICENSE
deleted file mode 100644
index 13b6199e..00000000
--- a/dist/deno/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/dist/deno/README.md b/dist/deno/README.md
deleted file mode 100644
index 795020ef..00000000
--- a/dist/deno/README.md
+++ /dev/null
@@ -1,180 +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&sort=semver)](https://deno.land/x/deepmergets)
-[![CI](https://github.com/RebeccaStevens/deepmerge-ts/actions/workflows/release.yml/badge.svg)](https://github.com/RebeccaStevens/deepmerge-ts/actions/workflows/release.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.
-
-![smart merge diagram](./assets/header.png)
-
-
-
-## Donate
-
-[Any donations would be much appreciated](./DONATIONS.md). 😄
-
-### Enterprise Users
-
-`deepmerge-ts` is available as part of the Tidelift Subscription.
-
-Tidelift is working with the maintainers of `deepmerge-ts` and a growing network of open source maintainers to ensure
-your open source software supply chain meets enterprise standards now and into the future.
-[Learn more.](https://tidelift.com/subscription/pkg/npm-deepmerge-ts?utm_source=npm-deepmerge-ts&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
-
-## Installation
-
-### Node
-
-```sh
-# Install with npm
-npm install deepmerge-ts
-
-# Install with pnpm
-pnpm add deepmerge-ts
-
-# Install with yarn
-yarn add deepmerge-ts
-```
-
-### Deno
-
-```jsonc
-// import_map.json
-{
- "imports": {
- "deepmerge-ts": "https://deno.land/x/deepmergets@__version__/dist/deno/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 z = {
- record: {
- prop1: undefined,
- prop3: undefined,
- prop2: undefined,
- prop4: undefined,
- },
- array: undefined,
- set: undefined,
- map: undefined,
-};
-
-const merged = deepmerge(x, y, z);
-
-console.log(merged);
-
-// Prettierfied output:
-//
-// Object {
-// "record": Object {
-// "prop1": "changed",
-// "prop2": "value2",
-// "prop3": "value3",
-// "prop4": undefined,
-// },
-// "array": Array [1, 2, 3, 2, 3, 4],
-// "set": Set { 1, 2, 3, 4 },
-// "map": Map {
-// "key1" => "value1",
-// "key2" => "changed",
-// "key3" => "value3",
-// },
-// }
-```
-
-You can try out this example at
-[codesandbox.io](https://codesandbox.io/s/deepmerge-ts-example-iltxby?file=/src/example.ts).
-
-### Merging into a Target
-
-You can use `deepmergeInto` if you want to update a target object with the merge result instead of creating a new
-object.
-
-This function is best used with objects that are all of the same type.
-
-Note: If the target object's type differs from the input objects, we'll assert that the target's type has changed
-(this is not done automatically with `deepmergeIntoCustom`).
-
-### Customized the Merging Process
-
-We provide a customizer function for each of our main deepmerge functions: `deepmergeCustom` and `deepmergeIntoCustom`.
-You can use these to customize the details of how values should be merged together.
-
-See [deepmerge custom docs](./docs/deepmergeCustom.md) for more details.
-
-## 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/dist/deno/actions.ts b/dist/deno/actions.ts
deleted file mode 100644
index e597db1f..00000000
--- a/dist/deno/actions.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * Special values that tell deepmerge to perform a certain action.
- */
-export const actions = {
- defaultMerge: Symbol("deepmerge-ts: default merge"),
- skip: Symbol("deepmerge-ts: skip"),
-} as const;
-
-/**
- * Special values that tell deepmergeInto to perform a certain action.
- */
-export const actionsInto = {
- defaultMerge: actions.defaultMerge,
-} as const;
diff --git a/dist/deno/deepmerge-into.ts b/dist/deno/deepmerge-into.ts
deleted file mode 100644
index 0abcdb2d..00000000
--- a/dist/deno/deepmerge-into.ts
+++ /dev/null
@@ -1,420 +0,0 @@
-import { actionsInto as actions } from "./actions.ts";
-import {
- defaultFilterValues,
- defaultMetaDataUpdater,
-} from "./defaults/general.ts";
-import { mergeIntoFunctions as defaultMergeIntoFunctions } from "./defaults/into.ts";
-import {
- type DeepMergeBuiltInMetaData,
- type DeepMergeFunctionsDefaultURIs,
- type DeepMergeHKT,
- type DeepMergeIntoFunctionUtils,
- type DeepMergeIntoOptions,
- type Reference,
-} from "./types/index.ts";
-import { type SimplifyObject } from "./types/utils.ts";
-import { ObjectType, getObjectType } from "./utils.ts";
-
-/**
- * Deeply merge objects into a target.
- *
- * @param target - This object will be mutated with the merge result.
- * @param objects - The objects to merge into the target.
- */
-export function deepmergeInto(
- target: T,
- ...objects: ReadonlyArray
-): void;
-
-/**
- * Deeply merge objects into a target.
- *
- * @param target - This object will be mutated with the merge result.
- * @param objects - The objects to merge into the target.
- */
-export function deepmergeInto<
- Target extends object,
- Ts extends ReadonlyArray,
->(
- target: Target,
- ...objects: Ts
-): asserts target is SimplifyObject<
- Target &
- DeepMergeHKT<
- [Target, ...Ts],
- DeepMergeFunctionsDefaultURIs,
- DeepMergeBuiltInMetaData
- >
->;
-
-export function deepmergeInto<
- Target extends object,
- Ts extends ReadonlyArray,
->(
- target: Target,
- ...objects: Ts
-): asserts target is SimplifyObject<
- Target &
- DeepMergeHKT<
- [Target, ...Ts],
- DeepMergeFunctionsDefaultURIs,
- DeepMergeBuiltInMetaData
- >
-> {
- return void deepmergeIntoCustom({})(target, ...objects);
-}
-
-/**
- * Deeply merge two or more objects using the given options.
- *
- * @param options - The options on how to customize the merge function.
- */
-export function deepmergeIntoCustom(
- options: DeepMergeIntoOptions<
- DeepMergeBuiltInMetaData,
- DeepMergeBuiltInMetaData
- >,
-): >(
- target: Target,
- ...objects: Ts
-) => void;
-
-/**
- * Deeply merge two or more objects using the given options and meta data.
- *
- * @param options - The options on how to customize the merge function.
- * @param rootMetaData - The meta data passed to the root items' being merged.
- */
-export function deepmergeIntoCustom<
- BaseTs = unknown,
- MetaData = DeepMergeBuiltInMetaData,
- MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData,
->(
- options: DeepMergeIntoOptions,
- rootMetaData?: MetaData,
-): >(
- target: Target,
- ...objects: Ts
-) => void;
-
-export function deepmergeIntoCustom<
- BaseTs,
- MetaData,
- MetaMetaData extends DeepMergeBuiltInMetaData,
->(
- options: DeepMergeIntoOptions,
- rootMetaData?: MetaData,
-): >(
- target: Target,
- ...objects: Ts
-) => void {
- /**
- * The type of the customized deepmerge function.
- */
- type CustomizedDeepmergeInto = <
- Target extends object,
- Ts extends ReadonlyArray,
- >(
- target: Target,
- ...objects: Ts
- ) => void;
-
- const utils: DeepMergeIntoFunctionUtils =
- getIntoUtils(options, customizedDeepmergeInto as CustomizedDeepmergeInto);
-
- /**
- * The customized deepmerge function.
- */
- function customizedDeepmergeInto(
- target: object,
- ...objects: ReadonlyArray
- ) {
- mergeUnknownsInto<
- ReadonlyArray,
- typeof utils,
- MetaData,
- MetaMetaData
- >({ value: target }, [target, ...objects], utils, rootMetaData);
- }
-
- return customizedDeepmergeInto as CustomizedDeepmergeInto;
-}
-
-/**
- * The the utils that are available to the merge functions.
- *
- * @param options - The options the user specified
- */
-function getIntoUtils<
- M,
- MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData,
->(
- options: DeepMergeIntoOptions,
- customizedDeepmergeInto: DeepMergeIntoFunctionUtils["deepmergeInto"],
-): DeepMergeIntoFunctionUtils {
- return {
- defaultMergeFunctions: defaultMergeIntoFunctions,
- mergeFunctions: {
- ...defaultMergeIntoFunctions,
- ...Object.fromEntries(
- Object.entries(options)
- .filter(([key, option]) =>
- Object.hasOwn(defaultMergeIntoFunctions, key),
- )
- .map(([key, option]) =>
- option === false
- ? [key, defaultMergeIntoFunctions.mergeOthers]
- : [key, option],
- ),
- ),
- } as DeepMergeIntoFunctionUtils["mergeFunctions"],
- metaDataUpdater: (options.metaDataUpdater ??
- defaultMetaDataUpdater) as unknown as DeepMergeIntoFunctionUtils<
- M,
- MM
- >["metaDataUpdater"],
- deepmergeInto: customizedDeepmergeInto,
- filterValues:
- options.filterValues === false
- ? undefined
- : options.filterValues ?? defaultFilterValues,
- actions,
- };
-}
-
-/**
- * Merge unknown things into a target.
- *
- * @param m_target - The target to merge into.
- * @param values - The values.
- */
-export function mergeUnknownsInto<
- Ts extends ReadonlyArray,
- U extends DeepMergeIntoFunctionUtils,
- M,
- MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData,
->(
- m_target: Reference,
- values: Ts,
- utils: U,
- meta: M | undefined,
- // eslint-disable-next-line ts/no-invalid-void-type
-): void | symbol {
- const filteredValues = utils.filterValues?.(values, meta) ?? values;
-
- if (filteredValues.length === 0) {
- return;
- }
- if (filteredValues.length === 1) {
- return void mergeOthersInto(
- m_target,
- filteredValues,
- utils,
- meta,
- );
- }
-
- const type = getObjectType(m_target.value);
-
- if (type !== ObjectType.NOT && type !== ObjectType.OTHER) {
- for (let m_index = 1; m_index < filteredValues.length; m_index++) {
- if (getObjectType(filteredValues[m_index]) === type) {
- continue;
- }
-
- return void mergeOthersInto(
- m_target,
- filteredValues,
- utils,
- meta,
- );
- }
- }
-
- switch (type) {
- case ObjectType.RECORD: {
- return void mergeRecordsInto(
- m_target as Reference>,
- filteredValues as ReadonlyArray>>,
- utils,
- meta,
- );
- }
-
- case ObjectType.ARRAY: {
- return void mergeArraysInto(
- m_target as Reference,
- filteredValues as ReadonlyArray>,
- utils,
- meta,
- );
- }
-
- case ObjectType.SET: {
- return void mergeSetsInto(
- m_target as Reference>,
- filteredValues as ReadonlyArray>>,
- utils,
- meta,
- );
- }
-
- case ObjectType.MAP: {
- return void mergeMapsInto(
- m_target as Reference