Repository: wheresrhys/fetch-mock
Pull request #686 (2024-07-09 13:57:35)

Rhys/monorepo 2
Converts the repository into a monorepo with appropriate tooling for managing multiple packages



Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index d8d21b7..0562663 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -32,13 +32,6 @@ references:
       paths:
         - .
 
-  rebuild_test: &rebuild_test
-    steps:
-      - *workspace
-      - run: npm rebuild
-      - run: FETCH_MOCK_SRC=../cjs/server.js make test
-
-
 jobs:
   checkout_code:
     <<: *nodelts
@@ -57,45 +50,45 @@ jobs:
     <<: *nodelts
     steps:
       - *workspace
-      - run: make build
+      - run: npm run build
       - *persist
   lint:
     <<: *nodelts
     steps:
       - *workspace
-      - run: make lint-ci
+      - run: npm run lint:ci
 
   typecheck:
     <<: *nodelts
     steps:
       - *workspace
-      - run: make typecheck
+      - run: npm run lint:types
 
   test:
     <<: *nodelts
     steps:
       - *workspace
-      - run: make test-coverage
+      - run: npm run test:coverage
 
   nodefetch3:
     <<: *nodelts
     steps:
       - *workspace
       - run: npm install node-fetch@3
-      - run: make test-node-fetch
+      - run: TESTING_ENV=node-fetch npm run test
 
   commonjs:
     <<: *nodelts
     steps:
       - *workspace
-      - run: make build
-      - run: make test-commonjs
+      - run: npm run build
+      - run: TESTING_ENV=commonjs npm run test
   jest:
     <<: *nodelts
     steps:
       - *workspace
-      - run: make build
-      - run: make test-jest
+      - run: npm run build
+      - run: npm run test:jest
   # chrome:
   #   <<: *browsers
   #   steps:
@@ -109,12 +102,17 @@ jobs:
   #     - run: npm install karma-firefox-launcher
   #     - run: TEST_BROWSER=Firefox make test-browser
 
-  deploy:
+  publish:
     <<: *nodelts
     steps:
       - *workspace
-      - run: make build publish
-
+      - run: npm run build
+      - run: |
+          NPM_PUBLISH_TAG=$([[ $CIRCLE_TAG =~ -[a-z-]+ ]] && echo "pre-release" || echo "latest")
+          echo "//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}" > ${HOME}/.npmrc
+          cd ./packages/fetch-mock
+          npm version --no-git-tag-version $CIRCLE_TAG
+          npm publish --access public --tag $NPM_PUBLISH_TAG
 
 workflows:
   version: 2
@@ -154,8 +152,7 @@ workflows:
       # - firefox:
       #     <<: *triggerable-by-tag
       #     <<: *run-after-first-jobs
-      - deploy:
-          context: wheresrhys-npm-publish
+      - publish:
           requires:
             - nodefetch3
             # - chrome
diff --git a/.eslintignore b/.eslintignore
index a84e305..80297f8 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1,6 +1,6 @@
-test/fixtures/*
+packages/*/test/fixtures/*
 coverage/*
 .nyc_output/
 docs/js
 docs/_site
-dist/*
+packages/*/dist/*
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
index 49a21cc..9d84d71 100644
--- a/.eslintrc.cjs
+++ b/.eslintrc.cjs
@@ -7,7 +7,7 @@ module.exports = {
 	extends: ['origami-component', 'plugin:prettier/recommended'],
 	overrides: [
 		{
-			files: ['test/**/*.js'],
+			files: ['packages/*/test/**/*.js'],
 			globals: {
 				testGlobals: 'writable',
 			},
diff --git a/.gitignore b/.gitignore
index d3d4b5f..9d7169c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,4 @@ coverage/
 
 # built files
 /docs/_site/
-/dist
+/packages/**/dist
diff --git a/.husky/commit-msg b/.husky/commit-msg
new file mode 100644
index 0000000..da99483
--- /dev/null
+++ b/.husky/commit-msg
@@ -0,0 +1,1 @@
+npx --no -- commitlint --edit "$1"
diff --git a/.husky/pre-commit b/.husky/pre-commit
new file mode 100644
index 0000000..3867a0f
--- /dev/null
+++ b/.husky/pre-commit
@@ -0,0 +1,1 @@
+npm run lint
diff --git a/.npmignore b/.npmignore
deleted file mode 100644
index 052273a..0000000
--- a/.npmignore
+++ /dev/null
@@ -1,18 +0,0 @@
-/.circleci/
-/.nyc_output/
-/coverage/
-/docs/
-/test/
-.codeclimate.yml
-.eslint*
-.gitignore
-.prettierrc
-Gemfile
-Gemfile.lock
-ISSUE_TEMPLATE
-karma.conf.js
-Makefile
-package-lock.json
-README.md
-rollup.config.js
-TODO.txt
diff --git a/.prettierrc b/.prettierrc.json
similarity index 100%
rename from .prettierrc
rename to .prettierrc.json
diff --git a/Makefile b/Makefile
deleted file mode 100644
index 2654b2c..0000000
--- a/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-export PATH := $(PATH):./node_modules/.bin
-
-.PHONY: test docs
-
-SHELL := env "PATH=$(PATH)" /bin/bash
-NPM_PUBLISH_TAG := $(shell [[ "$(CIRCLE_TAG)" =~ -[a-z-]+ ]] && echo "pre-release" || echo "latest")
-TEST_BROWSER := $(shell [ -z $(TEST_BROWSER) ] && echo "Chrome" || echo ${TEST_BROWSER})
-
-typecheck:
-	dtslint --expectOnly types
-
-lint-ci:
-	eslint --ext .js,.cjs .
-	prettier *.md docs/*.md docs/**/*.md
-
-lint:
-	eslint --cache --fix --ext .js,.cjs .
-	prettier --cache --write *.md docs/*.md docs/**/*.md
-
-verify: lint
-
-coverage:
-	nyc --reporter=lcovonly --reporter=text make test
-	cat ./coverage/lcov.info | coveralls
-
-docs:
-	cd docs; jekyll serve build --watch
-
-build:
-	npx rollup -c
-
-publish:
-	echo "//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}" > ${HOME}/.npmrc
-	npm version --no-git-tag-version $(CIRCLE_TAG)
-	npm publish --access public --tag $(NPM_PUBLISH_TAG)
-
-test:
-	TESTING_ENV=server npx vitest ./test/specs
-
-test-coverage:
-	TESTING_ENV=server npx vitest run --coverage ./test/specs
-
-test-node-fetch:
-	TESTING_ENV=node-fetch npx vitest ./test/specs
-
-test-commonjs:
-	TESTING_ENV=commonjs npx vitest ./test/specs
-
-test-browser:
-	TESTING_ENV=browser npx vitest ./test/specs
-
-test-jest:
-	npx jest test/framework-compat/jest.spec.js
diff --git a/README.md b/README.md
index afcbf8c..85f5fbe 100644
--- a/README.md
+++ b/README.md
@@ -1,69 +1,3 @@
-# fetch-mock
+# fetch-mock monorepo
 
-Mock http requests made using [fetch](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch).
-
-Features include:
-
-- mocks most of the fetch API spec, even advanced behaviours such as streaming and aborting
-- declarative matching for most aspects of a http request, including url, headers, body and query parameters
-- shorthands for the most commonly used features, such as matching a http method or matching one fetch only
-- support for delaying responses, or using your own async functions to define custom race conditions
-- can be used as a spy to observe real network requests
-- can be extended with your own reusable custom matchers that can be used both for matching fetch-calls and inspecting the results
-- isomorphic, and supports either a global fetch instance or a locally required instance
-
-_New_ If using jest, try the new [fetch-mock-jest](https://www.npmjs.com/package/fetch-mock-jest) wrapper.
-
-_New_ [Cheatsheet](https://github.com/wheresrhys/fetch-mock/blob/master/docs/cheatsheet.md)
-
-![node version](https://img.shields.io/node/v/fetch-mock.svg?style=flat-square)
-[![licence](https://img.shields.io/npm/l/fetch-mock.svg?style=flat-square)](https://github.com/wheresrhys/fetch-mock/blob/master/LICENSE)
-![npm downloads](https://img.shields.io/npm/dm/fetch-mock.svg?style=flat-square)
-[![CircleCI](https://img.shields.io/circleci/project/github/wheresrhys/fetch-mock.svg?style=flat-square)](https://circleci.com/gh/wheresrhys/workflows/fetch-mock)
-[![Code coverage](https://img.shields.io/coveralls/github/wheresrhys/fetch-mock.svg?style=flat-square)](https://coveralls.io/github/wheresrhys/fetch-mock)
-[![Known Vulnerabilities](https://snyk.io/test/github/wheresrhys/fetch-mock/badge.svg?targetFile=package.json&style=flat-square)](https://snyk.io/test/github/wheresrhys/fetch-mock?targetFile=package.json)
-
-```js
-fetchMock.mock('http://example.com', 200);
-const res = await fetch('http://example.com');
-assert(res.ok);
-fetchMock.restore();
-```
-
-## Table of Contents
-
-- [Requirements](#requirements)
-- [Documentation and Usage](http://www.wheresrhys.co.uk/fetch-mock/)
-- [License](#license)
-- [Housekeeping](#housekeeping)
-
-**I devote a lot of time to maintaining fetch-mock for free. I don't ask for payment, but am raising money for a refugee charity - <a href="https://www.justgiving.com/refugee-support-europe">please consider donating</a>**
-
----
-
-## Requirements
-
-fetch-mock requires the following to run:
-
-- [Node.js](https://nodejs.org/) 8+ for full feature operation
-- [Node.js](https://nodejs.org/) 0.12+ with [limitations](http://www.wheresrhys.co.uk/fetch-mock/#usageinstallation)
-- [npm](https://www.npmjs.com/package/npm) (normally comes with Node.js)
-- Either of the following
-  - [node-fetch](https://www.npmjs.com/package/node-fetch) when testing in a nodejs
-  - A browser that supports the `fetch` API when testing in a browser
-
-## Documentation and Usage
-
-See the [project website](http://www.wheresrhys.co.uk/fetch-mock/) or [cheatsheet](https://github.com/wheresrhys/fetch-mock/blob/master/docs/cheatsheet.md)
-
-If you're using jest as your test runner, consider using [fetch-mock-jest](https://www.npmjs.com/package/fetch-mock-jest), a lightweight, jest-friendly wrapper around fetch-mock.
-
-## License
-
-fetch-mock is licensed under the [MIT](https://github.com/wheresrhys/fetch-mock/blob/master/LICENSE) license.
-Copyright © 2019, Rhys Evans
-
-## Housekeeping
-
-![npm version](https://img.shields.io/npm/v/fetch-mock.svg?style=flat-square)
-[![maintainability](https://api.codeclimate.com/v1/badges/7f8abbf54ec9f3d07df3/maintainability?style=flat-square)](https://codeclimate.com/github/wheresrhys/fetch-mock/maintainability)
+Where fetch-mock and a growing suite of utilities aimed at different testing frameworks lives.
diff --git a/TODO.txt b/TODO.txt
deleted file mode 100644
index a196a5e..0000000
--- a/TODO.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-Principles
-- Concentrate on building up a MOCK IMPLEMENTATION - that is core
-- Expect extensions is second (these _can_ export a standalone inspection library, but following vite/jest patterns is the central aim )
-- The actual switching out with real fetch... that is best left to the testing frameworks... but again export an API to do this for peopel who prefer manual control
-
-
-Corollaries:
-- rename 'mock' to something else
-- fallback to fetch... is this best left to jest too
-- Look in the wild to see how people are using it
-- rethink of inspecting API
-- rethink of restore API
-
-e.g vi.spyOn(globalThis, 'fetch').mockImplementation(fetchMock)
diff --git a/commitlint.config.js b/commitlint.config.js
new file mode 100644
index 0000000..3f5e287
--- /dev/null
+++ b/commitlint.config.js
@@ -0,0 +1,1 @@
+export default { extends: ['@commitlint/config-conventional'] };
diff --git a/package-lock.json b/package-lock.json
index 7f858f5..2bf848e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,24 +1,22 @@
 {
-  "name": "fetch-mock",
-  "version": "10.0.0-alpha.1",
+  "name": "fetch-mock-monorepo",
+  "version": "1.0.0",
   "lockfileVersion": 3,
   "requires": true,
   "packages": {
     "": {
-      "name": "fetch-mock",
-      "version": "10.0.0-alpha.1",
+      "name": "fetch-mock-monorepo",
+      "version": "1.0.0",
       "license": "MIT",
-      "dependencies": {
-        "debug": "^4.1.1",
-        "glob-to-regexp": "^0.4.0",
-        "is-subset": "^0.1.1",
-        "lodash.isequal": "^4.5.0",
-        "path-to-regexp": "^2.2.1",
-        "querystring": "^0.2.1"
-      },
+      "workspaces": [
+        "packages/*"
+      ],
       "devDependencies": {
+        "@commitlint/cli": "^19.3.0",
+        "@commitlint/config-conventional": "^19.2.2",
         "@rollup/plugin-commonjs": "^25.0.7",
         "@rollup/plugin-node-resolve": "^15.2.3",
+        "@types/node": "^20.14.10",
         "@vitest/browser": "^1.1.0",
         "@vitest/coverage-istanbul": "^1.1.0",
         "dtslint": "^1.0.2",
@@ -26,10 +24,12 @@
         "eslint-config-airbnb-base": "^15.0.0",
         "eslint-config-origami-component": "^2.2.0",
         "eslint-config-prettier": "^9.1.0",
-        "eslint-plugin-import": "^2.29.1",
-        "eslint-plugin-prettier": "^5.1.2",
+        "eslint-plugin-jsdoc": "^48.5.2",
+        "eslint-plugin-prettier": "^5.1.3",
+        "husky": "^9.0.11",
         "jest": "^29.7.0",
         "jsdom": "^23.0.1",
+        "lint-staged": "^15.2.7",
         "prettier": "^3.1.1",
         "rollup": "^4.9.1",
         "typescript": "^3.6.4",
@@ -38,15 +38,6 @@
       },
       "engines": {
         "node": ">=4.0.0"
-      },
-      "funding": {
-        "type": "charity",
-        "url": "https://www.justgiving.com/refugee-support-europe"
-      },
-      "peerDependenciesMeta": {
-        "node-fetch": {
-          "optional": true
-        }
       }
     },
     "node_modules/@aashutoshrathi/word-wrap": {
@@ -419,215 +410,837 @@
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.10.4"
       },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-json-strings": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+      "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-jsx": {
+      "version": "7.23.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz",
+      "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+      "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-numeric-separator": {
+      "version": "7.10.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+      "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.10.4"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-object-rest-spread": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+      "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+      "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-optional-chaining": {
+      "version": "7.8.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+      "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.8.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-top-level-await": {
+      "version": "7.14.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+      "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.14.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/plugin-syntax-typescript": {
+      "version": "7.23.3",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz",
+      "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-plugin-utils": "^7.22.5"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      },
+      "peerDependencies": {
+        "@babel/core": "^7.0.0-0"
+      }
+    },
+    "node_modules/@babel/template": {
+      "version": "7.22.15",
+      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+      "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.22.13",
+        "@babel/parser": "^7.22.15",
+        "@babel/types": "^7.22.15"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse": {
+      "version": "7.23.6",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz",
+      "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==",
+      "dev": true,
+      "dependencies": {
+        "@babel/code-frame": "^7.23.5",
+        "@babel/generator": "^7.23.6",
+        "@babel/helper-environment-visitor": "^7.22.20",
+        "@babel/helper-function-name": "^7.23.0",
+        "@babel/helper-hoist-variables": "^7.22.5",
+        "@babel/helper-split-export-declaration": "^7.22.6",
+        "@babel/parser": "^7.23.6",
+        "@babel/types": "^7.23.6",
+        "debug": "^4.3.1",
+        "globals": "^11.1.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/traverse/node_modules/globals": {
+      "version": "11.12.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+      "dev": true,
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.23.6",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz",
+      "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==",
+      "dev": true,
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.23.4",
+        "@babel/helper-validator-identifier": "^7.22.20",
+        "to-fast-properties": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@bcoe/v8-coverage": {
+      "version": "0.2.3",
+      "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+      "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+      "dev": true
+    },
+    "node_modules/@commitlint/cli": {
+      "version": "19.3.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.3.0.tgz",
+      "integrity": "sha512-LgYWOwuDR7BSTQ9OLZ12m7F/qhNY+NpAyPBgo4YNMkACE7lGuUnuQq1yi9hz1KA4+3VqpOYl8H1rY/LYK43v7g==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/format": "^19.3.0",
+        "@commitlint/lint": "^19.2.2",
+        "@commitlint/load": "^19.2.0",
+        "@commitlint/read": "^19.2.1",
+        "@commitlint/types": "^19.0.3",
+        "execa": "^8.0.1",
+        "yargs": "^17.0.0"
+      },
+      "bin": {
+        "commitlint": "cli.js"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+      "dev": true,
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/cliui": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+      "dev": true,
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.1",
+        "wrap-ansi": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/color-convert": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+      "dev": true,
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/color-name": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+      "dev": true
+    },
+    "node_modules/@commitlint/cli/node_modules/get-caller-file": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+      "dev": true,
+      "engines": {
+        "node": "6.* || 8.* || >= 10.*"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/string-width": {
+      "version": "4.2.3",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+      "dev": true,
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/wrap-ansi": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^4.0.0",
+        "string-width": "^4.1.0",
+        "strip-ansi": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/y18n": {
+      "version": "5.0.8",
+      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/yargs": {
+      "version": "17.7.2",
+      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+      "dev": true,
+      "dependencies": {
+        "cliui": "^8.0.1",
+        "escalade": "^3.1.1",
+        "get-caller-file": "^2.0.5",
+        "require-directory": "^2.1.1",
+        "string-width": "^4.2.3",
+        "y18n": "^5.0.5",
+        "yargs-parser": "^21.1.1"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/yargs-parser": {
+      "version": "21.1.1",
+      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@commitlint/config-conventional": {
+      "version": "19.2.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-19.2.2.tgz",
+      "integrity": "sha512-mLXjsxUVLYEGgzbxbxicGPggDuyWNkf25Ht23owXIH+zV2pv1eJuzLK3t1gDY5Gp6pxdE60jZnWUY5cvgL3ufw==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/types": "^19.0.3",
+        "conventional-changelog-conventionalcommits": "^7.0.2"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/config-validator": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz",
+      "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/types": "^19.0.3",
+        "ajv": "^8.11.0"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/config-validator/node_modules/ajv": {
+      "version": "8.16.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz",
+      "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==",
+      "dev": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2",
+        "uri-js": "^4.4.1"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+      "dev": true
+    },
+    "node_modules/@commitlint/ensure": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.0.3.tgz",
+      "integrity": "sha512-SZEpa/VvBLoT+EFZVb91YWbmaZ/9rPH3ESrINOl0HD2kMYsjvl0tF7nMHh0EpTcv4+gTtZBAe1y/SS6/OhfZzQ==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/types": "^19.0.3",
+        "lodash.camelcase": "^4.3.0",
+        "lodash.kebabcase": "^4.1.1",
+        "lodash.snakecase": "^4.1.1",
+        "lodash.startcase": "^4.4.0",
+        "lodash.upperfirst": "^4.3.1"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/execute-rule": {
+      "version": "19.0.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz",
+      "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==",
+      "dev": true,
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/format": {
+      "version": "19.3.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.3.0.tgz",
+      "integrity": "sha512-luguk5/aF68HiF4H23ACAfk8qS8AHxl4LLN5oxPc24H+2+JRPsNr1OS3Gaea0CrH7PKhArBMKBz5RX9sA5NtTg==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/types": "^19.0.3",
+        "chalk": "^5.3.0"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/format/node_modules/chalk": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+      "dev": true,
+      "engines": {
+        "node": "^12.17.0 || ^14.13 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/@commitlint/is-ignored": {
+      "version": "19.2.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.2.2.tgz",
+      "integrity": "sha512-eNX54oXMVxncORywF4ZPFtJoBm3Tvp111tg1xf4zWXGfhBPKpfKG6R+G3G4v5CPlRROXpAOpQ3HMhA9n1Tck1g==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/types": "^19.0.3",
+        "semver": "^7.6.0"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/is-ignored/node_modules/semver": {
+      "version": "7.6.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
+      "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@commitlint/lint": {
+      "version": "19.2.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.2.2.tgz",
+      "integrity": "sha512-xrzMmz4JqwGyKQKTpFzlN0dx0TAiT7Ran1fqEBgEmEj+PU98crOFtysJgY+QdeSagx6EDRigQIXJVnfrI0ratA==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/is-ignored": "^19.2.2",
+        "@commitlint/parse": "^19.0.3",
+        "@commitlint/rules": "^19.0.3",
+        "@commitlint/types": "^19.0.3"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/load": {
+      "version": "19.2.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.2.0.tgz",
+      "integrity": "sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/config-validator": "^19.0.3",
+        "@commitlint/execute-rule": "^19.0.0",
+        "@commitlint/resolve-extends": "^19.1.0",
+        "@commitlint/types": "^19.0.3",
+        "chalk": "^5.3.0",
+        "cosmiconfig": "^9.0.0",
+        "cosmiconfig-typescript-loader": "^5.0.0",
+        "lodash.isplainobject": "^4.0.6",
+        "lodash.merge": "^4.6.2",
+        "lodash.uniq": "^4.5.0"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/load/node_modules/argparse": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+      "dev": true
+    },
+    "node_modules/@commitlint/load/node_modules/chalk": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+      "dev": true,
+      "engines": {
+        "node": "^12.17.0 || ^14.13 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/@commitlint/load/node_modules/cosmiconfig": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
+      "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
+      "dev": true,
+      "dependencies": {
+        "env-paths": "^2.2.1",
+        "import-fresh": "^3.3.0",
+        "js-yaml": "^4.1.0",
+        "parse-json": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/d-fischer"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.9.5"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz",
+      "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==",
+      "dev": true,
+      "dependencies": {
+        "jiti": "^1.19.1"
+      },
+      "engines": {
+        "node": ">=v16"
+      },
+      "peerDependencies": {
+        "@types/node": "*",
+        "cosmiconfig": ">=8.2",
+        "typescript": ">=4"
+      }
+    },
+    "node_modules/@commitlint/load/node_modules/js-yaml": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+      "dev": true,
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/@commitlint/load/node_modules/typescript": {
+      "version": "5.5.3",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
+      "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
+      "dev": true,
+      "peer": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=14.17"
       }
     },
-    "node_modules/@babel/plugin-syntax-json-strings": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
-      "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+    "node_modules/@commitlint/message": {
+      "version": "19.0.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.0.0.tgz",
+      "integrity": "sha512-c9czf6lU+9oF9gVVa2lmKaOARJvt4soRsVmbR7Njwp9FpbBgste5i7l/2l5o8MmbwGh4yE1snfnsy2qyA2r/Fw==",
       "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "engines": {
+        "node": ">=v18"
       }
     },
-    "node_modules/@babel/plugin-syntax-jsx": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz",
-      "integrity": "sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==",
+    "node_modules/@commitlint/parse": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.0.3.tgz",
+      "integrity": "sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
+        "@commitlint/types": "^19.0.3",
+        "conventional-changelog-angular": "^7.0.0",
+        "conventional-commits-parser": "^5.0.0"
       },
       "engines": {
-        "node": ">=6.9.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+        "node": ">=v18"
       }
     },
-    "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
-      "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+    "node_modules/@commitlint/read": {
+      "version": "19.2.1",
+      "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.2.1.tgz",
+      "integrity": "sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
+        "@commitlint/top-level": "^19.0.0",
+        "@commitlint/types": "^19.0.3",
+        "execa": "^8.0.1",
+        "git-raw-commits": "^4.0.0",
+        "minimist": "^1.2.8"
       },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "engines": {
+        "node": ">=v18"
       }
     },
-    "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
-      "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+    "node_modules/@commitlint/resolve-extends": {
+      "version": "19.1.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.1.0.tgz",
+      "integrity": "sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
+        "@commitlint/config-validator": "^19.0.3",
+        "@commitlint/types": "^19.0.3",
+        "global-directory": "^4.0.1",
+        "import-meta-resolve": "^4.0.0",
+        "lodash.mergewith": "^4.6.2",
+        "resolve-from": "^5.0.0"
       },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "engines": {
+        "node": ">=v18"
       }
     },
-    "node_modules/@babel/plugin-syntax-numeric-separator": {
-      "version": "7.10.4",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
-      "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+    "node_modules/@commitlint/resolve-extends/node_modules/resolve-from": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
       "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.10.4"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "engines": {
+        "node": ">=8"
       }
     },
-    "node_modules/@babel/plugin-syntax-object-rest-spread": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
-      "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+    "node_modules/@commitlint/rules": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.0.3.tgz",
+      "integrity": "sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
+        "@commitlint/ensure": "^19.0.3",
+        "@commitlint/message": "^19.0.0",
+        "@commitlint/to-lines": "^19.0.0",
+        "@commitlint/types": "^19.0.3",
+        "execa": "^8.0.1"
       },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "engines": {
+        "node": ">=v18"
       }
     },
-    "node_modules/@babel/plugin-syntax-optional-catch-binding": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
-      "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+    "node_modules/@commitlint/to-lines": {
+      "version": "19.0.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.0.0.tgz",
+      "integrity": "sha512-vkxWo+VQU5wFhiP9Ub9Sre0FYe019JxFikrALVoD5UGa8/t3yOJEpEhxC5xKiENKKhUkTpEItMTRAjHw2SCpZw==",
       "dev": true,
-      "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
-      },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "engines": {
+        "node": ">=v18"
       }
     },
-    "node_modules/@babel/plugin-syntax-optional-chaining": {
-      "version": "7.8.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
-      "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+    "node_modules/@commitlint/top-level": {
+      "version": "19.0.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.0.0.tgz",
+      "integrity": "sha512-KKjShd6u1aMGNkCkaX4aG1jOGdn7f8ZI8TR1VEuNqUOjWTOdcDSsmglinglJ18JTjuBX5I1PtjrhQCRcixRVFQ==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.8.0"
+        "find-up": "^7.0.0"
       },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "engines": {
+        "node": ">=v18"
       }
     },
-    "node_modules/@babel/plugin-syntax-top-level-await": {
-      "version": "7.14.5",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
-      "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+    "node_modules/@commitlint/top-level/node_modules/find-up": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz",
+      "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.14.5"
+        "locate-path": "^7.2.0",
+        "path-exists": "^5.0.0",
+        "unicorn-magic": "^0.1.0"
       },
       "engines": {
-        "node": ">=6.9.0"
+        "node": ">=18"
       },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@babel/plugin-syntax-typescript": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz",
-      "integrity": "sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==",
+    "node_modules/@commitlint/top-level/node_modules/locate-path": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
+      "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-plugin-utils": "^7.22.5"
+        "p-locate": "^6.0.0"
       },
       "engines": {
-        "node": ">=6.9.0"
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
       },
-      "peerDependencies": {
-        "@babel/core": "^7.0.0-0"
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@babel/template": {
-      "version": "7.22.15",
-      "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
-      "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+    "node_modules/@commitlint/top-level/node_modules/p-limit": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
+      "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
       "dev": true,
       "dependencies": {
-        "@babel/code-frame": "^7.22.13",
-        "@babel/parser": "^7.22.15",
-        "@babel/types": "^7.22.15"
+        "yocto-queue": "^1.0.0"
       },
       "engines": {
-        "node": ">=6.9.0"
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@babel/traverse": {
-      "version": "7.23.6",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.6.tgz",
-      "integrity": "sha512-czastdK1e8YByZqezMPFiZ8ahwVMh/ESl9vPgvgdB9AmFMGP5jfpFax74AQgl5zj4XHzqeYAg2l8PuUeRS1MgQ==",
+    "node_modules/@commitlint/top-level/node_modules/p-locate": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
+      "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
       "dev": true,
       "dependencies": {
-        "@babel/code-frame": "^7.23.5",
-        "@babel/generator": "^7.23.6",
-        "@babel/helper-environment-visitor": "^7.22.20",
-        "@babel/helper-function-name": "^7.23.0",
-        "@babel/helper-hoist-variables": "^7.22.5",
-        "@babel/helper-split-export-declaration": "^7.22.6",
-        "@babel/parser": "^7.23.6",
-        "@babel/types": "^7.23.6",
-        "debug": "^4.3.1",
-        "globals": "^11.1.0"
+        "p-limit": "^4.0.0"
       },
       "engines": {
-        "node": ">=6.9.0"
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@babel/traverse/node_modules/globals": {
-      "version": "11.12.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
-      "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+    "node_modules/@commitlint/top-level/node_modules/path-exists": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
+      "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
       "dev": true,
       "engines": {
-        "node": ">=4"
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
       }
     },
-    "node_modules/@babel/types": {
-      "version": "7.23.6",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.6.tgz",
-      "integrity": "sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==",
+    "node_modules/@commitlint/types": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz",
+      "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-string-parser": "^7.23.4",
-        "@babel/helper-validator-identifier": "^7.22.20",
-        "to-fast-properties": "^2.0.0"
+        "@types/conventional-commits-parser": "^5.0.0",
+        "chalk": "^5.3.0"
       },
       "engines": {
-        "node": ">=6.9.0"
+        "node": ">=v18"
       }
     },
-    "node_modules/@bcoe/v8-coverage": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
-      "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
-      "dev": true
+    "node_modules/@commitlint/types/node_modules/chalk": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+      "dev": true,
+      "engines": {
+        "node": "^12.17.0 || ^14.13 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
     },
     "node_modules/@es-joy/jsdoccomment": {
-      "version": "0.20.1",
-      "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.20.1.tgz",
-      "integrity": "sha512-oeJK41dcdqkvdZy/HctKklJNkt/jh+av3PZARrZEl+fs/8HaHeeYoAvEwOV0u5I6bArTF17JEsTZMY359e/nfQ==",
+      "version": "0.43.1",
+      "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz",
+      "integrity": "sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog==",
       "dev": true,
       "dependencies": {
-        "comment-parser": "1.3.0",
-        "esquery": "^1.4.0",
-        "jsdoc-type-pratt-parser": "~2.2.3"
+        "@types/eslint": "^8.56.5",
+        "@types/estree": "^1.0.5",
+        "@typescript-eslint/types": "^7.2.0",
+        "comment-parser": "1.4.1",
+        "esquery": "^1.5.0",
+        "jsdoc-type-pratt-parser": "~4.0.0"
       },
       "engines": {
-        "node": "^12 || ^14 || ^16 || ^17"
+        "node": ">=16"
       }
     },
     "node_modules/@esbuild/aix-ppc64": {
@@ -2119,6 +2732,18 @@
         "node": ">=14"
       }
     },
+    "node_modules/@pkgr/core": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz",
+      "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==",
+      "dev": true,
+      "engines": {
+        "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/unts"
+      }
+    },
     "node_modules/@pkgr/utils": {
       "version": "2.4.2",
       "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz",
@@ -2713,6 +3338,25 @@
         "@babel/types": "^7.20.7"
       }
     },
+    "node_modules/@types/conventional-commits-parser": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz",
+      "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@types/eslint": {
+      "version": "8.56.10",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.10.tgz",
+      "integrity": "sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ==",
+      "dev": true,
+      "dependencies": {
+        "@types/estree": "*",
+        "@types/json-schema": "*"
+      }
+    },
     "node_modules/@types/estree": {
       "version": "1.0.5",
       "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
@@ -2758,6 +3402,12 @@
         "@types/istanbul-lib-report": "*"
       }
     },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.15",
+      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+      "dev": true
+    },
     "node_modules/@types/json5": {
       "version": "0.0.29",
       "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
@@ -2765,9 +3415,9 @@
       "dev": true
     },
     "node_modules/@types/node": {
-      "version": "20.10.5",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.5.tgz",
-      "integrity": "sha512-nNPsNE65wjMxEKI93yOP+NPGGBJz/PoN3kZsVLee0XMiJolxSekEVD8wRwBUBqkwc7UWop0edW50yrCQW4CyRw==",
+      "version": "20.14.10",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz",
+      "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==",
       "dev": true,
       "dependencies": {
         "undici-types": "~5.26.4"
@@ -2831,6 +3481,19 @@
         "@types/node": "*"
       }
     },
+    "node_modules/@typescript-eslint/types": {
+      "version": "7.16.0",
+      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz",
+      "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==",
+      "dev": true,
+      "engines": {
+        "node": "^18.18.0 || >=20.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/typescript-eslint"
+      }
+    },
     "node_modules/@ungap/structured-clone": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
@@ -3301,6 +3964,15 @@
         "node": ">=10"
       }
     },
+    "node_modules/are-docs-informative": {
+      "version": "0.0.2",
+      "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz",
+      "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==",
+      "dev": true,
+      "engines": {
+        "node": ">=14"
+      }
+    },
     "node_modules/argparse": {
       "version": "1.0.10",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
@@ -3332,6 +4004,12 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/array-ify": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz",
+      "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==",
+      "dev": true
+    },
     "node_modules/array-includes": {
       "version": "3.1.7",
       "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz",
@@ -3849,12 +4527,12 @@
       }
     },
     "node_modules/braces": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "version": "3.0.3",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+      "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
       "dev": true,
       "dependencies": {
-        "fill-range": "^7.0.1"
+        "fill-range": "^7.1.1"
       },
       "engines": {
         "node": ">=8"
@@ -4168,12 +4846,66 @@
         "node": ">=8"
       }
     },
-    "node_modules/cjs-module-lexer": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz",
-      "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==",
-      "dev": true
-    },
+    "node_modules/cjs-module-lexer": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz",
+      "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==",
+      "dev": true
+    },
+    "node_modules/cli-cursor": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz",
+      "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==",
+      "dev": true,
+      "dependencies": {
+        "restore-cursor": "^4.0.0"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cli-truncate": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz",
+      "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==",
+      "dev": true,
+      "dependencies": {
+        "slice-ansi": "^5.0.0",
+        "string-width": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/cli-truncate/node_modules/emoji-regex": {
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
+      "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==",
+      "dev": true
+    },
+    "node_modules/cli-truncate/node_modules/string-width": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+      "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^10.3.0",
+        "get-east-asian-width": "^1.0.0",
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/cliui": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
@@ -4246,6 +4978,12 @@
       "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
       "dev": true
     },
+    "node_modules/colorette": {
+      "version": "2.0.20",
+      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+      "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+      "dev": true
+    },
     "node_modules/combined-stream": {
       "version": "1.0.8",
       "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -4271,9 +5009,9 @@
       "dev": true
     },
     "node_modules/comment-parser": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.0.tgz",
-      "integrity": "sha512-hRpmWIKgzd81vn0ydoWoyPoALEOnF4wt8yKD35Ib1D6XC2siLiYaiqfGkYrunuKdsXGwpBpHU3+9r+RVw2NZfA==",
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz",
+      "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==",
       "dev": true,
       "engines": {
         "node": ">= 12.0.0"
@@ -4285,6 +5023,16 @@
       "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
       "dev": true
     },
+    "node_modules/compare-func": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
+      "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==",
+      "dev": true,
+      "dependencies": {
+        "array-ify": "^1.0.0",
+        "dot-prop": "^5.1.0"
+      }
+    },
     "node_modules/compress-commons": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-5.0.1.tgz",
@@ -4312,6 +5060,48 @@
       "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==",
       "dev": true
     },
+    "node_modules/conventional-changelog-angular": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz",
+      "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==",
+      "dev": true,
+      "dependencies": {
+        "compare-func": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/conventional-changelog-conventionalcommits": {
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-7.0.2.tgz",
+      "integrity": "sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==",
+      "dev": true,
+      "dependencies": {
+        "compare-func": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/conventional-commits-parser": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz",
+      "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==",
+      "dev": true,
+      "dependencies": {
+        "is-text-path": "^2.0.0",
+        "JSONStream": "^1.3.5",
+        "meow": "^12.0.1",
+        "split2": "^4.0.0"
+      },
+      "bin": {
+        "conventional-commits-parser": "cli.mjs"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
     "node_modules/convert-source-map": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -4487,6 +5277,18 @@
         "node": ">=14"
       }
     },
+    "node_modules/dargs": {
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz",
+      "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/dashdash": {
       "version": "1.14.1",
       "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -4856,6 +5658,18 @@
         "node": ">=6.0.0"
       }
     },
+    "node_modules/dot-prop": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
+      "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+      "dev": true,
+      "dependencies": {
+        "is-obj": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/dts-critic": {
       "version": "2.2.4",
       "resolved": "https://registry.npmjs.org/dts-critic/-/dts-critic-2.2.4.tgz",
@@ -5085,6 +5899,15 @@
         "url": "https://github.com/fb55/entities?sponsor=1"
       }
     },
+    "node_modules/env-paths": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+      "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/error-ex": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -5147,6 +5970,12 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/es-module-lexer": {
+      "version": "1.5.4",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
+      "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==",
+      "dev": true
+    },
     "node_modules/es-set-tostringtag": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz",
@@ -5349,6 +6178,94 @@
         "eslint-plugin-jsdoc": "^37.0.3"
       }
     },
+    "node_modules/eslint-config-origami-component/node_modules/@es-joy/jsdoccomment": {
+      "version": "0.20.1",
+      "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.20.1.tgz",
+      "integrity": "sha512-oeJK41dcdqkvdZy/HctKklJNkt/jh+av3PZARrZEl+fs/8HaHeeYoAvEwOV0u5I6bArTF17JEsTZMY359e/nfQ==",
+      "dev": true,
+      "dependencies": {
+        "comment-parser": "1.3.0",
+        "esquery": "^1.4.0",
+        "jsdoc-type-pratt-parser": "~2.2.3"
+      },
+      "engines": {
+        "node": "^12 || ^14 || ^16 || ^17"
+      }
+    },
+    "node_modules/eslint-config-origami-component/node_modules/comment-parser": {
+      "version": "1.3.0",
+      "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.3.0.tgz",
+      "integrity": "sha512-hRpmWIKgzd81vn0ydoWoyPoALEOnF4wt8yKD35Ib1D6XC2siLiYaiqfGkYrunuKdsXGwpBpHU3+9r+RVw2NZfA==",
+      "dev": true,
+      "engines": {
+        "node": ">= 12.0.0"
+      }
+    },
+    "node_modules/eslint-config-origami-component/node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+      "dev": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint-config-origami-component/node_modules/eslint-plugin-jsdoc": {
+      "version": "37.9.7",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-37.9.7.tgz",
+      "integrity": "sha512-8alON8yYcStY94o0HycU2zkLKQdcS+qhhOUNQpfONHHwvI99afbmfpYuPqf6PbLz5pLZldG3Te5I0RbAiTN42g==",
+      "dev": true,
+      "dependencies": {
+        "@es-joy/jsdoccomment": "~0.20.1",
+        "comment-parser": "1.3.0",
+        "debug": "^4.3.3",
+        "escape-string-regexp": "^4.0.0",
+        "esquery": "^1.4.0",
+        "regextras": "^0.8.0",
+        "semver": "^7.3.5",
+        "spdx-expression-parse": "^3.0.1"
+      },
+      "engines": {
+        "node": "^12 || ^14 || ^16 || ^17"
+      },
+      "peerDependencies": {
+        "eslint": "^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/eslint-config-origami-component/node_modules/jsdoc-type-pratt-parser": {
+      "version": "2.2.5",
+      "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-2.2.5.tgz",
+      "integrity": "sha512-2a6eRxSxp1BW040hFvaJxhsCMI9lT8QB8t14t+NY5tC5rckIR0U9cr2tjOeaFirmEOy6MHvmJnY7zTBHq431Lw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/eslint-config-origami-component/node_modules/semver": {
+      "version": "7.6.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
+      "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
+      "dev": true,
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/eslint-config-origami-component/node_modules/spdx-expression-parse": {
+      "version": "3.0.1",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
+      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "dev": true,
+      "dependencies": {
+        "spdx-exceptions": "^2.1.0",
+        "spdx-license-ids": "^3.0.0"
+      }
+    },
     "node_modules/eslint-config-prettier": {
       "version": "9.1.0",
       "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz",
@@ -5460,25 +6377,44 @@
       }
     },
     "node_modules/eslint-plugin-jsdoc": {
-      "version": "37.9.7",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-37.9.7.tgz",
-      "integrity": "sha512-8alON8yYcStY94o0HycU2zkLKQdcS+qhhOUNQpfONHHwvI99afbmfpYuPqf6PbLz5pLZldG3Te5I0RbAiTN42g==",
+      "version": "48.5.2",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.5.2.tgz",
+      "integrity": "sha512-VXBJFviQz30rynlOEQ+dNWLmeopjoAgutUVrWOZwm6Ki4EVDm4XkyIqAV/Zhf7FcDr0AG0aGmRn5FxxCtAF0tA==",
       "dev": true,
       "dependencies": {
-        "@es-joy/jsdoccomment": "~0.20.1",
-        "comment-parser": "1.3.0",
-        "debug": "^4.3.3",
+        "@es-joy/jsdoccomment": "~0.43.1",
+        "are-docs-informative": "^0.0.2",
+        "comment-parser": "1.4.1",
+        "debug": "^4.3.5",
         "escape-string-regexp": "^4.0.0",
-        "esquery": "^1.4.0",
-        "regextras": "^0.8.0",
-        "semver": "^7.3.5",
-        "spdx-expression-parse": "^3.0.1"
+        "esquery": "^1.5.0",
+        "parse-imports": "^2.1.0",
+        "semver": "^7.6.2",
+        "spdx-expression-parse": "^4.0.0",
+        "synckit": "^0.9.0"
       },
       "engines": {
-        "node": "^12 || ^14 || ^16 || ^17"
+        "node": ">=18"
       },
       "peerDependencies": {
-        "eslint": "^7.0.0 || ^8.0.0"
+        "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
+      }
+    },
+    "node_modules/eslint-plugin-jsdoc/node_modules/debug": {
+      "version": "4.3.5",
+      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz",
+      "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==",
+      "dev": true,
+      "dependencies": {
+        "ms": "2.1.2"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
       }
     },
     "node_modules/eslint-plugin-jsdoc/node_modules/escape-string-regexp": {
@@ -5493,43 +6429,44 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/eslint-plugin-jsdoc/node_modules/lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+    "node_modules/eslint-plugin-jsdoc/node_modules/semver": {
+      "version": "7.6.2",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
+      "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
       "dev": true,
-      "dependencies": {
-        "yallist": "^4.0.0"
+      "bin": {
+        "semver": "bin/semver.js"
       },
       "engines": {
         "node": ">=10"
       }
     },
-    "node_modules/eslint-plugin-jsdoc/node_modules/semver": {
-      "version": "7.5.4",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
-      "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
+    "node_modules/eslint-plugin-jsdoc/node_modules/synckit": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.0.tgz",
+      "integrity": "sha512-7RnqIMq572L8PeEzKeBINYEJDDxpcH8JEgLwUqBd3TkofhFRbkq4QLR0u+36avGAhCRbk2nnmjcW9SE531hPDg==",
       "dev": true,
       "dependencies": {
-        "lru-cache": "^6.0.0"
-      },
-      "bin": {
-        "semver": "bin/semver.js"
+        "@pkgr/core": "^0.1.0",
+        "tslib": "^2.6.2"
       },
       "engines": {
-        "node": ">=10"
+        "node": "^14.18.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/unts"
       }
     },
-    "node_modules/eslint-plugin-jsdoc/node_modules/yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+    "node_modules/eslint-plugin-jsdoc/node_modules/tslib": {
+      "version": "2.6.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz",
+      "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==",
       "dev": true
     },
     "node_modules/eslint-plugin-prettier": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.2.tgz",
-      "integrity": "sha512-dhlpWc9vOwohcWmClFcA+HjlvUpuyynYs0Rf+L/P6/0iQE6vlHW9l5bkfzN62/Stm9fbq8ku46qzde76T1xlSg==",
+      "version": "5.1.3",
+      "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz",
+      "integrity": "sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==",
       "dev": true,
       "dependencies": {
         "prettier-linter-helpers": "^1.0.0",
@@ -5868,6 +6805,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/eventemitter3": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+      "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+      "dev": true
+    },
     "node_modules/execa": {
       "version": "8.0.1",
       "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
@@ -6074,6 +7017,10 @@
         "node": "^12.20 || >= 14.13"
       }
     },
+    "node_modules/fetch-mock": {
+      "resolved": "packages/fetch-mock",
+      "link": true
+    },
     "node_modules/file-entry-cache": {
       "version": "6.0.1",
       "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
@@ -6087,9 +7034,9 @@
       }
     },
     "node_modules/fill-range": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "version": "7.1.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+      "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
       "dev": true,
       "dependencies": {
         "to-regex-range": "^5.0.1"
@@ -6385,6 +7332,18 @@
       "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==",
       "dev": true
     },
+    "node_modules/get-east-asian-width": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz",
+      "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/get-func-name": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
@@ -6496,6 +7455,23 @@
         "assert-plus": "^1.0.0"
       }
     },
+    "node_modules/git-raw-commits": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz",
+      "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==",
+      "dev": true,
+      "dependencies": {
+        "dargs": "^8.0.0",
+        "meow": "^12.0.1",
+        "split2": "^4.0.0"
+      },
+      "bin": {
+        "git-raw-commits": "cli.mjs"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
     "node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -6533,6 +7509,21 @@
       "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
       "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
     },
+    "node_modules/global-directory": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz",
+      "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==",
+      "dev": true,
+      "dependencies": {
+        "ini": "4.1.1"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/globals": {
       "version": "13.24.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
@@ -6854,6 +7845,21 @@
         "node": ">=16.17.0"
       }
     },
+    "node_modules/husky": {
+      "version": "9.0.11",
+      "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz",
+      "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==",
+      "dev": true,
+      "bin": {
+        "husky": "bin.mjs"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/typicode"
+      }
+    },
     "node_modules/iconv-lite": {
       "version": "0.6.3",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
@@ -6965,6 +7971,15 @@
       "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
       "dev": true
     },
+    "node_modules/ini": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
+      "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==",
+      "dev": true,
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
+    },
     "node_modules/internal-slot": {
       "version": "1.0.6",
       "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz",
@@ -7222,6 +8237,15 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/is-obj": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
+      "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/is-path-inside": {
       "version": "3.0.3",
       "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
@@ -7333,6 +8357,18 @@
         "url": "https://github.com/sponsors/ljharb"
       }
     },
+    "node_modules/is-text-path": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz",
+      "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==",
+      "dev": true,
+      "dependencies": {
+        "text-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
     "node_modules/is-typed-array": {
       "version": "1.1.12",
       "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz",
@@ -9455,6 +10491,15 @@
         "url": "https://github.com/chalk/supports-color?sponsor=1"
       }
     },
+    "node_modules/jiti": {
+      "version": "1.21.6",
+      "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
+      "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
+      "dev": true,
+      "bin": {
+        "jiti": "bin/jiti.js"
+      }
+    },
     "node_modules/js-tokens": {
       "version": "3.0.2",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz",
@@ -9481,9 +10526,9 @@
       "dev": true
     },
     "node_modules/jsdoc-type-pratt-parser": {
-      "version": "2.2.5",
-      "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-2.2.5.tgz",
-      "integrity": "sha512-2a6eRxSxp1BW040hFvaJxhsCMI9lT8QB8t14t+NY5tC5rckIR0U9cr2tjOeaFirmEOy6MHvmJnY7zTBHq431Lw==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz",
+      "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==",
       "dev": true,
       "engines": {
         "node": ">=12.0.0"
@@ -9604,6 +10649,31 @@
         "graceful-fs": "^4.1.6"
       }
     },
+    "node_modules/jsonparse": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
+      "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
+      "dev": true,
+      "engines": [
+        "node >= 0.2.0"
+      ]
+    },
+    "node_modules/JSONStream": {
+      "version": "1.3.5",
+      "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
+      "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
+      "dev": true,
+      "dependencies": {
+        "jsonparse": "^1.2.0",
+        "through": ">=2.2.7 <3"
+      },
+      "bin": {
+        "JSONStream": "bin.js"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/jsprim": {
       "version": "1.4.2",
       "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
@@ -9712,100 +10782,391 @@
         "node": ">=6"
       }
     },
-    "node_modules/levn": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
-      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+    "node_modules/levn": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+      "dev": true,
+      "dependencies": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/lilconfig": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
+      "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
+      "dev": true,
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antonk52"
+      }
+    },
+    "node_modules/lines-and-columns": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+      "dev": true
+    },
+    "node_modules/lint-staged": {
+      "version": "15.2.7",
+      "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.7.tgz",
+      "integrity": "sha512-+FdVbbCZ+yoh7E/RosSdqKJyUM2OEjTciH0TFNkawKgvFp1zbGlEC39RADg+xKBG1R4mhoH2j85myBQZ5wR+lw==",
+      "dev": true,
+      "dependencies": {
+        "chalk": "~5.3.0",
+        "commander": "~12.1.0",
+        "debug": "~4.3.4",
+        "execa": "~8.0.1",
+        "lilconfig": "~3.1.1",
+        "listr2": "~8.2.1",
+        "micromatch": "~4.0.7",
+        "pidtree": "~0.6.0",
+        "string-argv": "~0.3.2",
+        "yaml": "~2.4.2"
+      },
+      "bin": {
+        "lint-staged": "bin/lint-staged.js"
+      },
+      "engines": {
+        "node": ">=18.12.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/lint-staged"
+      }
+    },
+    "node_modules/lint-staged/node_modules/chalk": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+      "dev": true,
+      "engines": {
+        "node": "^12.17.0 || ^14.13 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/lint-staged/node_modules/commander": {
+      "version": "12.1.0",
+      "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+      "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      }
+    },
+    "node_modules/listenercount": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
+      "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==",
+      "dev": true
+    },
+    "node_modules/listr2": {
+      "version": "8.2.3",
+      "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.3.tgz",
+      "integrity": "sha512-Lllokma2mtoniUOS94CcOErHWAug5iu7HOmDrvWgpw8jyQH2fomgB+7lZS4HWZxytUuQwkGOwe49FvwVaA85Xw==",
+      "dev": true,
+      "dependencies": {
+        "cli-truncate": "^4.0.0",
+        "colorette": "^2.0.20",
+        "eventemitter3": "^5.0.1",
+        "log-update": "^6.0.0",
+        "rfdc": "^1.4.1",
+        "wrap-ansi": "^9.0.0"
+      },
+      "engines": {
+        "node": ">=18.0.0"
+      }
+    },
+    "node_modules/listr2/node_modules/ansi-styles": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+      "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/listr2/node_modules/emoji-regex": {
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
+      "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==",
+      "dev": true
+    },
+    "node_modules/listr2/node_modules/string-width": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+      "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+      "dev": true,
+      "dependencies": {
+        "emoji-regex": "^10.3.0",
+        "get-east-asian-width": "^1.0.0",
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/listr2/node_modules/wrap-ansi": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+      "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^6.2.1",
+        "string-width": "^7.0.0",
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+      }
+    },
+    "node_modules/local-pkg": {
+      "version": "0.5.0",
+      "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
+      "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==",
+      "dev": true,
+      "dependencies": {
+        "mlly": "^1.4.2",
+        "pkg-types": "^1.0.3"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/locate-app": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/locate-app/-/locate-app-2.1.0.tgz",
+      "integrity": "sha512-rcVo/iLUxrd9d0lrmregK/Z5Y5NCpSwf9KlMbPpOHmKmdxdQY1Fj8NDQ5QymJTryCsBLqwmniFv2f3JKbk9Bvg==",
+      "dev": true,
+      "dependencies": {
+        "n12": "0.4.0",
+        "type-fest": "2.13.0",
+        "userhome": "1.0.0"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "dev": true,
+      "dependencies": {
+        "p-locate": "^3.0.0",
+        "path-exists": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+      "dev": true
+    },
+    "node_modules/lodash.camelcase": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+      "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+      "dev": true
+    },
+    "node_modules/lodash.clonedeep": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+      "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
+      "dev": true
+    },
+    "node_modules/lodash.isequal": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+      "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
+    },
+    "node_modules/lodash.isplainobject": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+      "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+      "dev": true
+    },
+    "node_modules/lodash.kebabcase": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
+      "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
+      "dev": true
+    },
+    "node_modules/lodash.merge": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+      "dev": true
+    },
+    "node_modules/lodash.mergewith": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
+      "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
+      "dev": true
+    },
+    "node_modules/lodash.snakecase": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
+      "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
+      "dev": true
+    },
+    "node_modules/lodash.startcase": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
+      "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
+      "dev": true
+    },
+    "node_modules/lodash.uniq": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+      "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
+      "dev": true
+    },
+    "node_modules/lodash.upperfirst": {
+      "version": "4.3.1",
+      "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz",
+      "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==",
+      "dev": true
+    },
+    "node_modules/lodash.zip": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz",
+      "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==",
+      "dev": true
+    },
+    "node_modules/log-update": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz",
+      "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==",
+      "dev": true,
+      "dependencies": {
+        "ansi-escapes": "^6.2.0",
+        "cli-cursor": "^4.0.0",
+        "slice-ansi": "^7.0.0",
+        "strip-ansi": "^7.1.0",
+        "wrap-ansi": "^9.0.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/log-update/node_modules/ansi-escapes": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz",
+      "integrity": "sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/log-update/node_modules/ansi-styles": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+      "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/log-update/node_modules/emoji-regex": {
+      "version": "10.3.0",
+      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz",
+      "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==",
+      "dev": true
+    },
+    "node_modules/log-update/node_modules/is-fullwidth-code-point": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz",
+      "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==",
       "dev": true,
       "dependencies": {
-        "prelude-ls": "^1.2.1",
-        "type-check": "~0.4.0"
+        "get-east-asian-width": "^1.0.0"
       },
       "engines": {
-        "node": ">= 0.8.0"
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/lines-and-columns": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
-      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
-      "dev": true
-    },
-    "node_modules/listenercount": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
-      "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==",
-      "dev": true
-    },
-    "node_modules/local-pkg": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
-      "integrity": "sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==",
+    "node_modules/log-update/node_modules/slice-ansi": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz",
+      "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==",
       "dev": true,
       "dependencies": {
-        "mlly": "^1.4.2",
-        "pkg-types": "^1.0.3"
+        "ansi-styles": "^6.2.1",
+        "is-fullwidth-code-point": "^5.0.0"
       },
       "engines": {
-        "node": ">=14"
+        "node": ">=18"
       },
       "funding": {
-        "url": "https://github.com/sponsors/antfu"
+        "url": "https://github.com/chalk/slice-ansi?sponsor=1"
       }
     },
-    "node_modules/locate-app": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/locate-app/-/locate-app-2.1.0.tgz",
-      "integrity": "sha512-rcVo/iLUxrd9d0lrmregK/Z5Y5NCpSwf9KlMbPpOHmKmdxdQY1Fj8NDQ5QymJTryCsBLqwmniFv2f3JKbk9Bvg==",
+    "node_modules/log-update/node_modules/string-width": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+      "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
       "dev": true,
       "dependencies": {
-        "n12": "0.4.0",
-        "type-fest": "2.13.0",
-        "userhome": "1.0.0"
+        "emoji-regex": "^10.3.0",
+        "get-east-asian-width": "^1.0.0",
+        "strip-ansi": "^7.1.0"
+      },
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/locate-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
-      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+    "node_modules/log-update/node_modules/wrap-ansi": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+      "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
       "dev": true,
       "dependencies": {
-        "p-locate": "^3.0.0",
-        "path-exists": "^3.0.0"
+        "ansi-styles": "^6.2.1",
+        "string-width": "^7.0.0",
+        "strip-ansi": "^7.1.0"
       },
       "engines": {
-        "node": ">=6"
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
       }
     },
-    "node_modules/lodash": {
-      "version": "4.17.21",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
-      "dev": true
-    },
-    "node_modules/lodash.clonedeep": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
-      "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==",
-      "dev": true
-    },
-    "node_modules/lodash.isequal": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
-      "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
-    },
-    "node_modules/lodash.merge": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
-      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-      "dev": true
-    },
-    "node_modules/lodash.zip": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/lodash.zip/-/lodash.zip-4.2.0.tgz",
-      "integrity": "sha512-C7IOaBBK/0gMORRBd8OETNx3kmOkgIWIPvyDpZSCTwUrpYmgZwJkjZeOD8ww4xbOUOs4/attY+pciKvadNfFbg==",
-      "dev": true
-    },
     "node_modules/loglevel": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz",
@@ -9970,6 +11331,18 @@
         "node": ">=6"
       }
     },
+    "node_modules/meow": {
+      "version": "12.1.1",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz",
+      "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==",
+      "dev": true,
+      "engines": {
+        "node": ">=16.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/merge-stream": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
@@ -9986,12 +11359,12 @@
       }
     },
     "node_modules/micromatch": {
-      "version": "4.0.5",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
-      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+      "version": "4.0.7",
+      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
+      "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
       "dev": true,
       "dependencies": {
-        "braces": "^3.0.2",
+        "braces": "^3.0.3",
         "picomatch": "^2.3.1"
       },
       "engines": {
@@ -10738,6 +12111,19 @@
         "node": ">=6"
       }
     },
+    "node_modules/parse-imports": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-2.1.1.tgz",
+      "integrity": "sha512-TDT4HqzUiTMO1wJRwg/t/hYk8Wdp3iF/ToMIlAoVQfL1Xs/sTxq1dKWSMjMbQmIarfWKymOyly40+zmPHXMqCA==",
+      "dev": true,
+      "dependencies": {
+        "es-module-lexer": "^1.5.3",
+        "slashes": "^3.0.12"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
     "node_modules/parse-json": {
       "version": "5.2.0",
       "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
@@ -10882,6 +12268,18 @@
         "url": "https://github.com/sponsors/jonschlinkert"
       }
     },
+    "node_modules/pidtree": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
+      "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+      "dev": true,
+      "bin": {
+        "pidtree": "bin/pidtree.js"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
     "node_modules/pirates": {
       "version": "4.0.6",
       "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
@@ -11013,9 +12411,9 @@
       }
     },
     "node_modules/prettier": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.1.1.tgz",
-      "integrity": "sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==",
+      "version": "3.3.2",
+      "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz",
+      "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==",
       "dev": true,
       "bin": {
         "prettier": "bin/prettier.cjs"
@@ -11371,6 +12769,15 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/require-main-filename": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
@@ -11475,6 +12882,52 @@
       "integrity": "sha512-bCK/2Z4zLidyB4ReuIsvALH6w31YfAQDmXMqMx6FyfHqvBxtjC0eRumeSu4Bs3XtXwpyIywtSTrVT99BxY1f9w==",
       "dev": true
     },
+    "node_modules/restore-cursor": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz",
+      "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==",
+      "dev": true,
+      "dependencies": {
+        "onetime": "^5.1.0",
+        "signal-exit": "^3.0.2"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/restore-cursor/node_modules/mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/restore-cursor/node_modules/onetime": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "dev": true,
+      "dependencies": {
+        "mimic-fn": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/restore-cursor/node_modules/signal-exit": {
+      "version": "3.0.7",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+      "dev": true
+    },
     "node_modules/reusify": {
       "version": "1.0.4",
       "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
@@ -11485,6 +12938,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/rfdc": {
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+      "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+      "dev": true
+    },
     "node_modules/rgb2hex": {
       "version": "0.2.5",
       "resolved": "https://registry.npmjs.org/rgb2hex/-/rgb2hex-0.2.5.tgz",
@@ -11912,6 +13371,52 @@
         "node": ">=8"
       }
     },
+    "node_modules/slashes": {
+      "version": "3.0.12",
+      "resolved": "https://registry.npmjs.org/slashes/-/slashes-3.0.12.tgz",
+      "integrity": "sha512-Q9VME8WyGkc7pJf6QEkj3wE+2CnvZMI+XJhwdTPR8Z/kWQRXi7boAWLDibRPyHRTUTPx5FaU7MsyrjI3yLB4HA==",
+      "dev": true
+    },
+    "node_modules/slice-ansi": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
+      "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
+      "dev": true,
+      "dependencies": {
+        "ansi-styles": "^6.0.0",
+        "is-fullwidth-code-point": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+      }
+    },
+    "node_modules/slice-ansi/node_modules/ansi-styles": {
+      "version": "6.2.1",
+      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+      "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
+      "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/smart-buffer": {
       "version": "4.2.0",
       "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
@@ -11985,15 +13490,15 @@
       }
     },
     "node_modules/spdx-exceptions": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
-      "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+      "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
       "dev": true
     },
     "node_modules/spdx-expression-parse": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
-      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz",
+      "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==",
       "dev": true,
       "dependencies": {
         "spdx-exceptions": "^2.1.0",
@@ -12001,9 +13506,9 @@
       }
     },
     "node_modules/spdx-license-ids": {
-      "version": "3.0.16",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.16.tgz",
-      "integrity": "sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==",
+      "version": "3.0.18",
+      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.18.tgz",
+      "integrity": "sha512-xxRs31BqRYHwiMzudOrpSiHtZ8i/GeionCBDSilhYRj+9gIcI8wCZTlXZKu9vZIVqViP3dcp9qE5G6AlIaD+TQ==",
       "dev": true
     },
     "node_modules/split2": {
@@ -12098,6 +13603,15 @@
         "safe-buffer": "~5.2.0"
       }
     },
+    "node_modules/string-argv": {
+      "version": "0.3.2",
+      "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
+      "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.6.19"
+      }
+    },
     "node_modules/string-length": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
@@ -12432,6 +13946,18 @@
         "node": ">=8"
       }
     },
+    "node_modules/text-extensions": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz",
+      "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==",
+      "dev": true,
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -12796,6 +14322,18 @@
       "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
       "dev": true
     },
+    "node_modules/unicorn-magic": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz",
+      "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
     "node_modules/universalify": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
@@ -13951,6 +15489,18 @@
       "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
       "dev": true
     },
+    "node_modules/yaml": {
+      "version": "2.4.5",
+      "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz",
+      "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==",
+      "dev": true,
+      "bin": {
+        "yaml": "bin.mjs"
+      },
+      "engines": {
+        "node": ">= 14"
+      }
+    },
     "node_modules/yargs": {
       "version": "12.0.5",
       "resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
@@ -14034,6 +15584,30 @@
       "engines": {
         "node": ">= 12.0.0"
       }
+    },
+    "packages/fetch-mock": {
+      "version": "0.0.0",
+      "license": "MIT",
+      "dependencies": {
+        "debug": "^4.1.1",
+        "glob-to-regexp": "^0.4.0",
+        "is-subset": "^0.1.1",
+        "lodash.isequal": "^4.5.0",
+        "path-to-regexp": "^2.2.1",
+        "querystring": "^0.2.1"
+      },
+      "engines": {
+        "node": ">=4.0.0"
+      },
+      "funding": {
+        "type": "charity",
+        "url": "https://www.justgiving.com/refugee-support-europe"
+      },
+      "peerDependenciesMeta": {
+        "node-fetch": {
+          "optional": true
+        }
+      }
     }
   }
 }
diff --git a/package.json b/package.json
index 25bdb10..6b31aa6 100644
--- a/package.json
+++ b/package.json
@@ -1,62 +1,42 @@
 {
-  "name": "fetch-mock",
-  "version": "0.0.0",
+  "name": "fetch-mock-monorepo",
+  "version": "1.0.0",
   "description": "Mock http requests made using fetch (or isomorphic-fetch)",
-  "main": "./dist/commonjs.js",
-  "exports": {
-    "types": "./types/index.d.ts",
-    "browser": "./src/index.js",
-    "import": "./src/index.js",
-    "require": "./dist/commonjs.js"
-  },
-  "types": "./types/index.d.ts",
   "type": "module",
-  "scripts": {
-    "test": "make lint test",
-    "prepublishOnly": "make build"
-  },
-  "funding": {
-    "type": "charity",
-    "url": "https://www.justgiving.com/refugee-support-europe"
-  },
   "repository": {
     "type": "git",
     "url": "git+https://github.com/wheresrhys/fetch-mock.git"
   },
-  "keywords": [
-    "fetch",
-    "http",
-    "mock",
-    "testing",
-    "spy",
-    "xhr",
-    "ajax"
-  ],
   "author": "Rhys Evans",
   "license": "MIT",
   "bugs": {
     "url": "https://github.com/wheresrhys/fetch-mock/issues"
   },
   "homepage": "http://www.wheresrhys.co.uk/fetch-mock",
-  "dependencies": {
-    "debug": "^4.1.1",
-    "glob-to-regexp": "^0.4.0",
-    "is-subset": "^0.1.1",
-    "lodash.isequal": "^4.5.0",
-    "path-to-regexp": "^2.2.1",
-    "querystring": "^0.2.1"
-  },
-  "peerDependenciesMeta": {
-    "node-fetch": {
-      "optional": true
-    }
-  },
   "engines": {
     "node": ">=4.0.0"
   },
+  "workspaces": [
+    "packages/*"
+  ],
+  "scripts": {
+    "lint": "eslint --cache --fix --ext .js,.cjs . && prettier --cache --write *.md docs/*.md docs/**/*.md",
+    "lint:ci": "eslint --ext .js,.cjs . && prettier *.md docs/*.md docs/**/*.md",
+    "lint:types": "dtslint --expectOnly packages/fetch-mock/types",
+    "prepare": "husky",
+    "build": "rollup -c",
+    "docs:serve": "cd docs; jekyll serve build --watch",
+    "test": "vitest ./packages/fetch-mock/test/specs",
+    "test:coverage": "vitest run --coverage ./packages/fetch-mock/test/specs",
+    "test:jest": "jest test/framework-compat/jest.spec.js",
+    "coverage:send": "cat ./coverage/lcov.info | coveralls"
+  },
   "devDependencies": {
+    "@commitlint/cli": "^19.3.0",
+    "@commitlint/config-conventional": "^19.2.2",
     "@rollup/plugin-commonjs": "^25.0.7",
     "@rollup/plugin-node-resolve": "^15.2.3",
+    "@types/node": "^20.14.10",
     "@vitest/browser": "^1.1.0",
     "@vitest/coverage-istanbul": "^1.1.0",
     "dtslint": "^1.0.2",
@@ -64,10 +44,12 @@
     "eslint-config-airbnb-base": "^15.0.0",
     "eslint-config-origami-component": "^2.2.0",
     "eslint-config-prettier": "^9.1.0",
-    "eslint-plugin-import": "^2.29.1",
-    "eslint-plugin-prettier": "^5.1.2",
+    "eslint-plugin-jsdoc": "^48.5.2",
+    "eslint-plugin-prettier": "^5.1.3",
+    "husky": "^9.0.11",
     "jest": "^29.7.0",
     "jsdom": "^23.0.1",
+    "lint-staged": "^15.2.7",
     "prettier": "^3.1.1",
     "rollup": "^4.9.1",
     "typescript": "^3.6.4",
@@ -75,6 +57,11 @@
     "webdriverio": "^8.27.0"
   },
   "volta": {
-    "node": "18.19.0"
+    "node": "20.0.0"
+  },
+  "lint-staged": {
+    "**/*.js": [
+      "npm run lint"
+    ]
   }
 }
diff --git a/packages/fetch-mock/.npmignore b/packages/fetch-mock/.npmignore
new file mode 100644
index 0000000..1933786
--- /dev/null
+++ b/packages/fetch-mock/.npmignore
@@ -0,0 +1,1 @@
+/test/
diff --git a/packages/fetch-mock/README.md b/packages/fetch-mock/README.md
new file mode 100644
index 0000000..afcbf8c
--- /dev/null
+++ b/packages/fetch-mock/README.md
@@ -0,0 +1,69 @@
+# fetch-mock
+
+Mock http requests made using [fetch](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch).
+
+Features include:
+
+- mocks most of the fetch API spec, even advanced behaviours such as streaming and aborting
+- declarative matching for most aspects of a http request, including url, headers, body and query parameters
+- shorthands for the most commonly used features, such as matching a http method or matching one fetch only
+- support for delaying responses, or using your own async functions to define custom race conditions
+- can be used as a spy to observe real network requests
+- can be extended with your own reusable custom matchers that can be used both for matching fetch-calls and inspecting the results
+- isomorphic, and supports either a global fetch instance or a locally required instance
+
+_New_ If using jest, try the new [fetch-mock-jest](https://www.npmjs.com/package/fetch-mock-jest) wrapper.
+
+_New_ [Cheatsheet](https://github.com/wheresrhys/fetch-mock/blob/master/docs/cheatsheet.md)
+
+![node version](https://img.shields.io/node/v/fetch-mock.svg?style=flat-square)
+[![licence](https://img.shields.io/npm/l/fetch-mock.svg?style=flat-square)](https://github.com/wheresrhys/fetch-mock/blob/master/LICENSE)
+![npm downloads](https://img.shields.io/npm/dm/fetch-mock.svg?style=flat-square)
+[![CircleCI](https://img.shields.io/circleci/project/github/wheresrhys/fetch-mock.svg?style=flat-square)](https://circleci.com/gh/wheresrhys/workflows/fetch-mock)
+[![Code coverage](https://img.shields.io/coveralls/github/wheresrhys/fetch-mock.svg?style=flat-square)](https://coveralls.io/github/wheresrhys/fetch-mock)
+[![Known Vulnerabilities](https://snyk.io/test/github/wheresrhys/fetch-mock/badge.svg?targetFile=package.json&style=flat-square)](https://snyk.io/test/github/wheresrhys/fetch-mock?targetFile=package.json)
+
+```js
+fetchMock.mock('http://example.com', 200);
+const res = await fetch('http://example.com');
+assert(res.ok);
+fetchMock.restore();
+```
+
+## Table of Contents
+
+- [Requirements](#requirements)
+- [Documentation and Usage](http://www.wheresrhys.co.uk/fetch-mock/)
+- [License](#license)
+- [Housekeeping](#housekeeping)
+
+**I devote a lot of time to maintaining fetch-mock for free. I don't ask for payment, but am raising money for a refugee charity - <a href="https://www.justgiving.com/refugee-support-europe">please consider donating</a>**
+
+---
+
+## Requirements
+
+fetch-mock requires the following to run:
+
+- [Node.js](https://nodejs.org/) 8+ for full feature operation
+- [Node.js](https://nodejs.org/) 0.12+ with [limitations](http://www.wheresrhys.co.uk/fetch-mock/#usageinstallation)
+- [npm](https://www.npmjs.com/package/npm) (normally comes with Node.js)
+- Either of the following
+  - [node-fetch](https://www.npmjs.com/package/node-fetch) when testing in a nodejs
+  - A browser that supports the `fetch` API when testing in a browser
+
+## Documentation and Usage
+
+See the [project website](http://www.wheresrhys.co.uk/fetch-mock/) or [cheatsheet](https://github.com/wheresrhys/fetch-mock/blob/master/docs/cheatsheet.md)
+
+If you're using jest as your test runner, consider using [fetch-mock-jest](https://www.npmjs.com/package/fetch-mock-jest), a lightweight, jest-friendly wrapper around fetch-mock.
+
+## License
+
+fetch-mock is licensed under the [MIT](https://github.com/wheresrhys/fetch-mock/blob/master/LICENSE) license.
+Copyright © 2019, Rhys Evans
+
+## Housekeeping
+
+![npm version](https://img.shields.io/npm/v/fetch-mock.svg?style=flat-square)
+[![maintainability](https://api.codeclimate.com/v1/badges/7f8abbf54ec9f3d07df3/maintainability?style=flat-square)](https://codeclimate.com/github/wheresrhys/fetch-mock/maintainability)
diff --git a/packages/fetch-mock/package.json b/packages/fetch-mock/package.json
new file mode 100644
index 0000000..d5c34de
--- /dev/null
+++ b/packages/fetch-mock/package.json
@@ -0,0 +1,58 @@
+{
+  "name": "fetch-mock",
+  "version": "0.0.0",
+  "description": "Mock http requests made using fetch (or isomorphic-fetch)",
+  "main": "./dist/commonjs.js",
+  "exports": {
+    "types": "./types/index.d.ts",
+    "browser": "./src/index.js",
+    "import": "./src/index.js",
+    "require": "./dist/commonjs.js"
+  },
+  "types": "./types/index.d.ts",
+  "type": "module",
+  "scripts": {
+    "test": "make lint test",
+    "prepublishOnly": "make build"
+  },
+  "funding": {
+    "type": "charity",
+    "url": "https://www.justgiving.com/refugee-support-europe"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/wheresrhys/fetch-mock.git",
+    "directory": "packages/fetch-mock"
+  },
+  "keywords": [
+    "fetch",
+    "http",
+    "mock",
+    "testing",
+    "spy",
+    "xhr",
+    "ajax"
+  ],
+  "author": "Rhys Evans",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/wheresrhys/fetch-mock/issues"
+  },
+  "homepage": "http://www.wheresrhys.co.uk/fetch-mock",
+  "dependencies": {
+    "debug": "^4.1.1",
+    "glob-to-regexp": "^0.4.0",
+    "is-subset": "^0.1.1",
+    "lodash.isequal": "^4.5.0",
+    "path-to-regexp": "^2.2.1",
+    "querystring": "^0.2.1"
+  },
+  "peerDependenciesMeta": {
+    "node-fetch": {
+      "optional": true
+    }
+  },
+  "engines": {
+    "node": ">=4.0.0"
+  }
+}
diff --git a/test/framework-compat/jest.spec.js b/packages/fetch-mock/test/framework-compat/jest.spec.js
similarity index 100%
rename from test/framework-compat/jest.spec.js
rename to packages/fetch-mock/test/framework-compat/jest.spec.js
diff --git a/test/setup/browser.js b/packages/fetch-mock/test/setup/browser.js
similarity index 100%
rename from test/setup/browser.js
rename to packages/fetch-mock/test/setup/browser.js
diff --git a/test/setup/commonjs.cjs b/packages/fetch-mock/test/setup/commonjs.cjs
similarity index 100%
rename from test/setup/commonjs.cjs
rename to packages/fetch-mock/test/setup/commonjs.cjs
diff --git a/test/setup/node-fetch.js b/packages/fetch-mock/test/setup/node-fetch.js
similarity index 100%
rename from test/setup/node-fetch.js
rename to packages/fetch-mock/test/setup/node-fetch.js
diff --git a/test/setup/server.js b/packages/fetch-mock/test/setup/server.js
similarity index 100%
rename from test/setup/server.js
rename to packages/fetch-mock/test/setup/server.js
diff --git a/test/specs/abortable.test.js b/packages/fetch-mock/test/specs/abortable.test.js
similarity index 100%
rename from test/specs/abortable.test.js
rename to packages/fetch-mock/test/specs/abortable.test.js
diff --git a/test/specs/config/constructors.test.js b/packages/fetch-mock/test/specs/config/constructors.test.js
similarity index 100%
rename from test/specs/config/constructors.test.js
rename to packages/fetch-mock/test/specs/config/constructors.test.js
diff --git a/test/specs/config/fallbackToNetwork.test.js b/packages/fetch-mock/test/specs/config/fallbackToNetwork.test.js
similarity index 100%
rename from test/specs/config/fallbackToNetwork.test.js
rename to packages/fetch-mock/test/specs/config/fallbackToNetwork.test.js
diff --git a/test/specs/config/includeContentLength.test.js b/packages/fetch-mock/test/specs/config/includeContentLength.test.js
similarity index 100%
rename from test/specs/config/includeContentLength.test.js
rename to packages/fetch-mock/test/specs/config/includeContentLength.test.js
diff --git a/test/specs/config/matchPartialBody.test.js b/packages/fetch-mock/test/specs/config/matchPartialBody.test.js
similarity index 100%
rename from test/specs/config/matchPartialBody.test.js
rename to packages/fetch-mock/test/specs/config/matchPartialBody.test.js
diff --git a/test/specs/config/overwriteRoutes.test.js b/packages/fetch-mock/test/specs/config/overwriteRoutes.test.js
similarity index 100%
rename from test/specs/config/overwriteRoutes.test.js
rename to packages/fetch-mock/test/specs/config/overwriteRoutes.test.js
diff --git a/test/specs/config/sendAsJson.test.js b/packages/fetch-mock/test/specs/config/sendAsJson.test.js
similarity index 100%
rename from test/specs/config/sendAsJson.test.js
rename to packages/fetch-mock/test/specs/config/sendAsJson.test.js
diff --git a/test/specs/flush.test.js b/packages/fetch-mock/test/specs/flush.test.js
similarity index 100%
rename from test/specs/flush.test.js
rename to packages/fetch-mock/test/specs/flush.test.js
diff --git a/test/specs/global-fetch.test.js b/packages/fetch-mock/test/specs/global-fetch.test.js
similarity index 100%
rename from test/specs/global-fetch.test.js
rename to packages/fetch-mock/test/specs/global-fetch.test.js
diff --git a/test/specs/inspecting.test.js b/packages/fetch-mock/test/specs/inspecting.test.js
similarity index 100%
rename from test/specs/inspecting.test.js
rename to packages/fetch-mock/test/specs/inspecting.test.js
diff --git a/test/specs/repeat.test.js b/packages/fetch-mock/test/specs/repeat.test.js
similarity index 100%
rename from test/specs/repeat.test.js
rename to packages/fetch-mock/test/specs/repeat.test.js
diff --git a/test/specs/responses/client-only.test.js b/packages/fetch-mock/test/specs/responses/client-only.test.js
similarity index 100%
rename from test/specs/responses/client-only.test.js
rename to packages/fetch-mock/test/specs/responses/client-only.test.js
diff --git a/test/specs/responses/generation.test.js b/packages/fetch-mock/test/specs/responses/generation.test.js
similarity index 100%
rename from test/specs/responses/generation.test.js
rename to packages/fetch-mock/test/specs/responses/generation.test.js
diff --git a/test/specs/responses/negotiation.js b/packages/fetch-mock/test/specs/responses/negotiation.js
similarity index 100%
rename from test/specs/responses/negotiation.js
rename to packages/fetch-mock/test/specs/responses/negotiation.js
diff --git a/test/specs/responses/server-only.test.js b/packages/fetch-mock/test/specs/responses/server-only.test.js
similarity index 100%
rename from test/specs/responses/server-only.test.js
rename to packages/fetch-mock/test/specs/responses/server-only.test.js
diff --git a/test/specs/routing/body-matching.test.js b/packages/fetch-mock/test/specs/routing/body-matching.test.js
similarity index 100%
rename from test/specs/routing/body-matching.test.js
rename to packages/fetch-mock/test/specs/routing/body-matching.test.js
diff --git a/test/specs/routing/edge-cases.test.js b/packages/fetch-mock/test/specs/routing/edge-cases.test.js
similarity index 100%
rename from test/specs/routing/edge-cases.test.js
rename to packages/fetch-mock/test/specs/routing/edge-cases.test.js
diff --git a/test/specs/routing/function-matching.test.js b/packages/fetch-mock/test/specs/routing/function-matching.test.js
similarity index 100%
rename from test/specs/routing/function-matching.test.js
rename to packages/fetch-mock/test/specs/routing/function-matching.test.js
diff --git a/test/specs/routing/header-matching.test.js b/packages/fetch-mock/test/specs/routing/header-matching.test.js
similarity index 100%
rename from test/specs/routing/header-matching.test.js
rename to packages/fetch-mock/test/specs/routing/header-matching.test.js
diff --git a/test/specs/routing/matcher-object.test.js b/packages/fetch-mock/test/specs/routing/matcher-object.test.js
similarity index 100%
rename from test/specs/routing/matcher-object.test.js
rename to packages/fetch-mock/test/specs/routing/matcher-object.test.js
diff --git a/test/specs/routing/method-matching.test.js b/packages/fetch-mock/test/specs/routing/method-matching.test.js
similarity index 100%
rename from test/specs/routing/method-matching.test.js
rename to packages/fetch-mock/test/specs/routing/method-matching.test.js
diff --git a/test/specs/routing/multiple-routes.test.js b/packages/fetch-mock/test/specs/routing/multiple-routes.test.js
similarity index 100%
rename from test/specs/routing/multiple-routes.test.js
rename to packages/fetch-mock/test/specs/routing/multiple-routes.test.js
diff --git a/test/specs/routing/naming-routes.test.js b/packages/fetch-mock/test/specs/routing/naming-routes.test.js
similarity index 100%
rename from test/specs/routing/naming-routes.test.js
rename to packages/fetch-mock/test/specs/routing/naming-routes.test.js
diff --git a/test/specs/routing/path-parameter-matching.test.js b/packages/fetch-mock/test/specs/routing/path-parameter-matching.test.js
similarity index 100%
rename from test/specs/routing/path-parameter-matching.test.js
rename to packages/fetch-mock/test/specs/routing/path-parameter-matching.test.js
diff --git a/test/specs/routing/query-string-matching.test.js b/packages/fetch-mock/test/specs/routing/query-string-matching.test.js
similarity index 100%
rename from test/specs/routing/query-string-matching.test.js
rename to packages/fetch-mock/test/specs/routing/query-string-matching.test.js
diff --git a/test/specs/routing/unmatched-calls.test.js b/packages/fetch-mock/test/specs/routing/unmatched-calls.test.js
similarity index 100%
rename from test/specs/routing/unmatched-calls.test.js
rename to packages/fetch-mock/test/specs/routing/unmatched-calls.test.js
diff --git a/test/specs/routing/url-matching.test.js b/packages/fetch-mock/test/specs/routing/url-matching.test.js
similarity index 100%
rename from test/specs/routing/url-matching.test.js
rename to packages/fetch-mock/test/specs/routing/url-matching.test.js
diff --git a/test/specs/sandbox.test.js b/packages/fetch-mock/test/specs/sandbox.test.js
similarity index 100%
rename from test/specs/sandbox.test.js
rename to packages/fetch-mock/test/specs/sandbox.test.js
diff --git a/test/specs/set-up-and-tear-down.test.js b/packages/fetch-mock/test/specs/set-up-and-tear-down.test.js
similarity index 100%
rename from test/specs/set-up-and-tear-down.test.js
rename to packages/fetch-mock/test/specs/set-up-and-tear-down.test.js
diff --git a/test/specs/shorthands.test.js b/packages/fetch-mock/test/specs/shorthands.test.js
similarity index 100%
rename from test/specs/shorthands.test.js
rename to packages/fetch-mock/test/specs/shorthands.test.js
diff --git a/test/specs/spy.test.js b/packages/fetch-mock/test/specs/spy.test.js
similarity index 100%
rename from test/specs/spy.test.js
rename to packages/fetch-mock/test/specs/spy.test.js
diff --git a/test/specs/sticky-routes.test.js b/packages/fetch-mock/test/specs/sticky-routes.test.js
similarity index 100%
rename from test/specs/sticky-routes.test.js
rename to packages/fetch-mock/test/specs/sticky-routes.test.js
diff --git a/test/specs/user-defined-matchers.test.js b/packages/fetch-mock/test/specs/user-defined-matchers.test.js
similarity index 100%
rename from test/specs/user-defined-matchers.test.js
rename to packages/fetch-mock/test/specs/user-defined-matchers.test.js
diff --git a/types/fetch-mock-tests.ts b/packages/fetch-mock/types/fetch-mock-tests.ts
similarity index 100%
rename from types/fetch-mock-tests.ts
rename to packages/fetch-mock/types/fetch-mock-tests.ts
diff --git a/types/index.d.ts b/packages/fetch-mock/types/index.d.ts
similarity index 100%
rename from types/index.d.ts
rename to packages/fetch-mock/types/index.d.ts
diff --git a/types/tsconfig.json b/packages/fetch-mock/types/tsconfig.json
similarity index 100%
rename from types/tsconfig.json
rename to packages/fetch-mock/types/tsconfig.json
diff --git a/types/tslint.json b/packages/fetch-mock/types/tslint.json
similarity index 100%
rename from types/tslint.json
rename to packages/fetch-mock/types/tslint.json
diff --git a/rollup.config.js b/rollup.config.js
index e856ce9..6705783 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -7,16 +7,19 @@ function createCommonJsPackage() {
 	return {
 		name: 'cjs-package',
 		buildEnd: async () => {
-			await mkdir('./dist', { recursive: true });
-			await writeFile('./dist/package.json', JSON.stringify(pkg, null, 2));
+			await mkdir('./packages/fetch-mock/dist', { recursive: true });
+			await writeFile(
+				'./packages/fetch-mock/dist/package.json',
+				JSON.stringify(pkg, null, 2),
+			);
 		},
 	};
 }
 
 export default {
-	input: 'src/index.js',
+	input: 'packages/fetch-mock/src/index.js',
 	output: {
-		dir: 'dist',
+		dir: 'packages/fetch-mock/dist',
 		entryFileNames: 'commonjs.js',
 		format: 'commonjs',
 	},


Test patch:
diff --git a/src/Route/index.js b/packages/fetch-mock/src/Route/index.js
similarity index 100%
rename from src/Route/index.js
rename to packages/fetch-mock/src/Route/index.js
diff --git a/src/Route/matchers.js b/packages/fetch-mock/src/Route/matchers.js
similarity index 100%
rename from src/Route/matchers.js
rename to packages/fetch-mock/src/Route/matchers.js
diff --git a/src/index.js b/packages/fetch-mock/src/index.js
similarity index 100%
rename from src/index.js
rename to packages/fetch-mock/src/index.js
diff --git a/src/lib/debug.js b/packages/fetch-mock/src/lib/debug.js
similarity index 100%
rename from src/lib/debug.js
rename to packages/fetch-mock/src/lib/debug.js
diff --git a/src/lib/fetch-handler.js b/packages/fetch-mock/src/lib/fetch-handler.js
similarity index 100%
rename from src/lib/fetch-handler.js
rename to packages/fetch-mock/src/lib/fetch-handler.js
diff --git a/src/lib/index.js b/packages/fetch-mock/src/lib/index.js
similarity index 100%
rename from src/lib/index.js
rename to packages/fetch-mock/src/lib/index.js
diff --git a/src/lib/inspecting.js b/packages/fetch-mock/src/lib/inspecting.js
similarity index 100%
rename from src/lib/inspecting.js
rename to packages/fetch-mock/src/lib/inspecting.js
diff --git a/src/lib/request-utils.js b/packages/fetch-mock/src/lib/request-utils.js
similarity index 100%
rename from src/lib/request-utils.js
rename to packages/fetch-mock/src/lib/request-utils.js
diff --git a/src/lib/response-builder.js b/packages/fetch-mock/src/lib/response-builder.js
similarity index 100%
rename from src/lib/response-builder.js
rename to packages/fetch-mock/src/lib/response-builder.js
diff --git a/src/lib/set-up-and-tear-down.js b/packages/fetch-mock/src/lib/set-up-and-tear-down.js
similarity index 100%
rename from src/lib/set-up-and-tear-down.js
rename to packages/fetch-mock/src/lib/set-up-and-tear-down.js
diff --git a/src/lib/status-text.js b/packages/fetch-mock/src/lib/status-text.js
similarity index 100%
rename from src/lib/status-text.js
rename to packages/fetch-mock/src/lib/status-text.js
diff --git a/test/fixtures/fetch-proxy.js b/packages/fetch-mock/test/fixtures/fetch-proxy.js
similarity index 100%
rename from test/fixtures/fetch-proxy.js
rename to packages/fetch-mock/test/fixtures/fetch-proxy.js
diff --git a/test/fixtures/sw.js b/packages/fetch-mock/test/fixtures/sw.js
similarity index 75%
rename from test/fixtures/sw.js
rename to packages/fetch-mock/test/fixtures/sw.js
index 0bea4a5..0bb2578 100644
--- a/test/fixtures/sw.js
+++ b/packages/fetch-mock/test/fixtures/sw.js
@@ -1,15 +1,15 @@
 import fetchMock from '../../src/client';
 
-self.addEventListener('install', ev => {
+self.addEventListener('install', (ev) => {
 	fetchMock.mock(/.*/, 203);
 	ev.waitUntil(
 		fetch('http://egg.on.face/')
-			.then(res => {
+			.then((res) => {
 				if (res.status !== 203) {
 					console.log('Fetch mock not behaving as expected');//eslint-disable-line
 					throw 'Unexpected status';
 				}
 			})
-			.then(fetchMock.restore)
+			.then(fetchMock.restore),
 	);
 });
diff --git a/vitest.config.js b/vitest.config.js
index 5e61f6e..b911103 100644
--- a/vitest.config.js
+++ b/vitest.config.js
@@ -2,7 +2,7 @@ import { defineConfig } from 'vitest/config';
 
 const configs = {
 	browser: {
-		setupFiles: './test/setup/browser.js',
+		setupFiles: './packages/fetch-mock/test/setup/browser.js',
 		environment: 'jsdom',
 		// browser: {
 		//     enabled: true,
@@ -19,16 +19,16 @@ const configs = {
 	},
 
 	server: {
-		setupFiles: './test/setup/server.js',
+		setupFiles: './packages/fetch-mock/test/setup/server.js',
 		coverage: {
 			provider: 'istanbul',
 		},
 	},
 	['node-fetch']: {
-		setupFiles: './test/setup/node-fetch.js',
+		setupFiles: './packages/fetch-mock/test/setup/node-fetch.js',
 	},
 	commonjs: {
-		setupFiles: './test/setup/commonjs.cjs',
+		setupFiles: './packages/fetch-mock/test/setup/commonjs.cjs',
 	},
 };