diff --git a/.codeclimate.yml b/.codeclimate.yml new file mode 100644 index 0000000..0ebf530 --- /dev/null +++ b/.codeclimate.yml @@ -0,0 +1,7 @@ +version: "2" +exclude_patterns: + - "scripts/" + - "**/*test.js" + - "**/*test.ts" + - "**/*spec.js" + - "**/*spec.ts" diff --git a/.commitlintrc.cjs b/.commitlintrc.cjs new file mode 100644 index 0000000..595b9b9 --- /dev/null +++ b/.commitlintrc.cjs @@ -0,0 +1 @@ +module.exports = require('./configs/commitlintrc.cjs'); diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..84b637c --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1 @@ +module.exports = require('./configs/eslintrc.cjs'); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..0890a08 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,65 @@ +name: ci + +# 当推送到 main分支 时 触发此工作流 +on: + push: + branches: + - main +permissions: + contents: write + +jobs: + build-and-deploy: + runs-on: ubuntu-latest + + steps: + - name: checkout + uses: actions/checkout@main + + # 全局安装 pnpm + - name: install pnpm + run: npm install -g pnpm + + # 使用 pnpm 安装依赖 + - name: install dependencies + run: pnpm install + + # 使用 pnpm 执行测试 + - name: run tests + run: pnpm test:ci + + # 上传覆盖率报告到 Coveralls + - name: Upload coverage reports to Codecov + uses: codecov/codecov-action@main + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + + # 使用 pnpm 构建 + - name: build + run: pnpm build + + # 自动发布 + - name: Auto Release + run: npx cvlar -r + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # 同步到 Gitee + - name: Sync to Gitee + uses: wearerequired/git-mirror-action@master + env: + SSH_PRIVATE_KEY: ${{ secrets.GITEE_PRIVATE_KEY }} + with: + source-repo: 'git@github.com:kwooshung/algorithm-sorts.git' + destination-repo: 'git@gitee.com:kwooshung/algorithm-sorts.git' + + # 自动发布到 npm + - name: Sync to Npm.js + uses: actions/setup-node@main + with: + node-version: '14.0.0' + registry-url: https://registry.npmjs.org/ + - name: Publish to Npm.js + run: npm publish --access public + env: + NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0dc1dc4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* +.eslintcache +.stylelintcache +node_modules +dist +dist-ssr +coverage +*.local +# Editor directories and files +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.cvlar-commit-message-*.tmp \ No newline at end of file diff --git a/.husky/commit-msg b/.husky/commit-msg new file mode 100644 index 0000000..0d30cdf --- /dev/null +++ b/.husky/commit-msg @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" +npx --no-install commitlint --edit $1 \ No newline at end of file diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 0000000..2542566 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +. "$(dirname -- "$0")/_/husky.sh" +npx lint-staged \ No newline at end of file diff --git a/.ks-cvlarrc.cjs b/.ks-cvlarrc.cjs new file mode 100644 index 0000000..9a8e6ac --- /dev/null +++ b/.ks-cvlarrc.cjs @@ -0,0 +1 @@ +module.exports = require('./configs/.ks-cvlarrc.cjs'); diff --git a/.lintstagedrc b/.lintstagedrc new file mode 100644 index 0000000..e3c5700 --- /dev/null +++ b/.lintstagedrc @@ -0,0 +1,4 @@ +{ + "*.{js,jsx,ts,tsx}": ["npx prettier --write", "npx eslint --fix"], + "*.json": ["npx prettier --write"] +} diff --git a/.prettierrc.cjs b/.prettierrc.cjs new file mode 100644 index 0000000..770cbce --- /dev/null +++ b/.prettierrc.cjs @@ -0,0 +1,41 @@ +module.exports = { + eslintInter: true, + // 一行最多 200 字符 + printWidth: 200, + // 使用 2 个空格缩进 + tabWidth: 2, + // 不使用缩进符,而使用空格 + useTabs: false, + // 行尾分号 + semi: true, + // 使用单引号 + singleQuote: true, + // 对象的 key 仅在必要时用引号 + quoteProps: 'as-needed', + // jsx 使用单引号 + jsxSingleQuote: true, + // 尾随逗号 + trailingComma: 'all', + // 大括号内的首尾需要空格 + bracketSpacing: true, + // jsx 标签的反尖括号需要换行 + jsxBracketSameLine: true, + // 箭头函数,只有一个参数的时候,也需要括号 + arrowParens: 'always', + // 每个文件格式化的范围是文件的全部内容 + rangeStart: 0, + // 需要格式化和检查的代码结束偏移值(从尾部开始) + rangeEnd: Infinity, + // 不需要写文件开头的 @prettier + requirePragma: false, + // 不需要自动在文件开头插入 @prettier + insertPragma: false, + // 使用默认的折行标准 + proseWrap: 'preserve', + // 根据显示样式决定 html 要不要折行 + htmlWhitespaceSensitivity: 'css', + // 去除对象最后一个逗号 + trailingComma: 'none', + // 换行符使用 lf + endOfLine: 'lf' +}; diff --git a/README.md b/README.md new file mode 100644 index 0000000..b7156ea --- /dev/null +++ b/README.md @@ -0,0 +1,132 @@ +
+ +# @kwooshung/algorithm-sorts + +![GitHub Release Date - Published_At](https://img.shields.io/github/release-date/kwooshung/algorithm-sorts?labelColor=272e3b&color=00b42A&logo=github) +![GitHub last commit](https://img.shields.io/github/last-commit/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +![GitHub top language](https://img.shields.io/github/languages/top/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +![GitHub pull requests](https://img.shields.io/github/issues-pr/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +![GitHub issues](https://img.shields.io/github/issues/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +[![NPM Version](https://img.shields.io/npm/v/@kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff)](https://www.npmjs.com/package/@kwooshung/algorithm-sorts) +[![Npm.js Downloads/Week](https://img.shields.io/npm/dw/@kwooshung/algorithm-sorts?labelColor=272e3b&labelColor=272e3b&color=165dff&logo=npm)](https://www.npmjs.com/package/@kwooshung/algorithm-sorts) +[![Github CI/CD](https://github.com/kwooshung/algorithm-sorts/actions/workflows/ci.yml/badge.svg)](https://github.com/kwooshung/algorithm-sorts/actions/) +[![codecov](https://codecov.io/gh/kwooshung/algorithm-sorts/graph/badge.svg?token=VVZJE7H0KD)](https://codecov.io/gh/kwooshung/algorithm-sorts) +[![Maintainability](https://api.codeclimate.com/v1/badges/325d0881b1ca19165d35/maintainability)](https://codeclimate.com/github/kwooshung/algorithm-sorts/maintainability/) +[![GitHub License](https://img.shields.io/github/license/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff)](LICENSE) +[![Gitee Repo](https://img.shields.io/badge/gitee-cvlar-165dff?logo=gitee)](https://gitee.com/kwooshung/algorithm-sorts/) +![Github Stars](https://img.shields.io/github/stars/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) + +

+ 中文 | + English +

+
+ +# Why was it developed? + +- During development, I needed to use algorithms and found the [algorithms.js](https://github.com/felipernb/algorithms.js) library. Its implementation is excellent. This project is based on [algorithms.js](https://github.com/felipernb/algorithms.js), with slight modifications in the [compare](src/internal/compare/index.ts) section. +- [algorithms.js](https://github.com/felipernb/algorithms.js) is implemented using the `commonjs` standard, not `esm`. This means it can't utilize `tree shaking`. While there are indirect methods to achieve this, they are not as convenient as using the `esm` standard directly. +- [algorithms.js](https://github.com/felipernb/algorithms.js) hasn't been maintained for several years. Some algorithms and implementation logic would be better with a modern approach. + +# Why Use It? + +- Written in `Typescript` with unit testing, ensuring code quality with `100%` coverage. +- Supports both `esm` and `commonjs` standards. The `esm` standard enables direct use of `tree shaking` to reduce the bundle size. +- Clear documentation, including comments in both Chinese and English, making it easy to read and understand, as shown below. + +```ts +/** + * 短冒泡排序 / Short Bubble Sort + * @description 短冒泡排序是冒泡排序的一种变体,当在整个排序过程中没有进行任何交换时,该算法会提前停止 / Short bubble sort is a variation of bubble sort that stops early if no swaps are made during the entire sorting process + * @usageScenario 适用于检测几乎已经排序好的数组 / Suitable for detecting nearly sorted arrays + * @timeComplexity 最好情况 O(n),平均和最坏情况 O(n^2) / Best case O(n), average and worst case O(n^2) + * @param {T[]} array 待排序数组 / Array to be sorted + * @param {boolean} [modifyOriginal=true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse=false] 是否反转结果 / Whether to reverse the result + */ +``` + +- Compared to [algorithms.js](https://github.com/felipernb/algorithms.js), our sorting algorithms include several additional ones, with more to be added in the future. +- In most cases, the efficiency of our library's algorithms is superior to [algorithms.js](https://github.com/felipernb/algorithms.js). There are comparative charts below, and you can also `git clone` this project and run `npm compare` for testing. + +# When Not to Use It? + +As the project name suggests, our project's algorithms only support `sorting`. If you need other types of algorithms, you might want to use [algorithms.js](https://github.com/felipernb/algorithms.js). + +# Efficiency Comparison + +The comparison involves random data of 1000 items, with string lengths varying from 6 to 32 and numbers ranging from 0 to 1,000,000, as shown below: + +| Algorithm | algorithms.js | @kwooshung/algorithm-sorts | Difference | +| :---------------------- | :-----------: | :------------------------: | :------------: | +| Bubble Sort | 65.0368 ms | 65.0298 ms | -0.0070 ms | +| Shout Bubble Sort | 13251.3260 ms | 128.2500 ms | -13123.0760 ms | +| Cocktail Sort | - | 52.7166 ms | - | +| Counting Sort | - | 12.3503 ms | - | +| Optimized Counting Sort | 33.2357 ms | 32.6380 ms | -0.5977 ms | +| Heap Sort | 8.3025 ms | 4.6525 ms | -3.6500 ms | +| Insertion Sort | 27.4480 ms | 27.4331 ms | -0.0149 ms | +| Merge Sort | 2.9167 ms | 2.5592 ms | -0.3575 ms | +| Pancake Sort | - | 57.7009 ms | 0 ms | +| Quick Sort | 3.0599 ms | 2.6374 ms | -0.4225 ms | +| Radix Sort | 0.2070 ms | 0.1339 ms | -0.0731 ms | +| Selection Sort | 55.8389 ms | 55.8000 ms | -0.0389 ms | +| Shell Sort | 3.1775 ms | 3.1564 ms | -0.0211 ms | +| Tim Sort | - | 6.7950 ms | - | + +# Install + +## npm + +```bash +npm install @kwooshung/algorithm-sorts --save-dev +``` + +## yarn + +```bash +yarn add @kwooshung/algorithm-sorts -D +``` + +## pnpm + +```bash +pnpm add @kwooshung/algorithm-sorts -D +``` + +# Usage + +## Importing + +### esm + +```ts +import { bubbleSort } from '@kwooshung/algorithm-sorts'; +``` + +### commonjs + +```ts +const { bubbleSort } = require('@kwooshung/algorithm-sorts'); +``` + +## Supported Algorithms + +> Currently, the following sorting algorithms are supported. For specific usage instructions, click on the sorting algorithm names below and refer to the comments and parameters: + +- [» Bubble Sort](src/sorts/bubble/index.ts) +- [» Short Bubble Sort](src/sorts/bubble/short/index.ts) +- [» Cocktail Sort](src/sorts/cocktail/index.ts) +- [» Counting Sort](src/sorts/counting/index.ts) +- [» Counting Sort (Optimized Version)](src/sorts/counting/optimized/index.ts) +- [» Heap Sort](src/sorts/heap/index.ts) +- [» Insertion Sort](src/sorts/insertion/index.ts) +- [» Merge Sort](src/sorts/merge/index.ts) +- [» Pancake Sorting](src/sorts/pancake/index.ts) +- [» Quick Sort](src/sorts/quick/index.ts) +- [» Radix Sort](src/sorts/radix/index.ts) +- [» Selection Sort](src/sorts/selection/index.ts) +- [» Shell Sort](src/sorts/shell/index.ts) +- [» Tim Sort](src/sorts/tim/index.ts) diff --git a/README.zh-CN.md b/README.zh-CN.md new file mode 100644 index 0000000..2882495 --- /dev/null +++ b/README.zh-CN.md @@ -0,0 +1,132 @@ +
+ +# @kwooshung/algorithm-sorts + +![GitHub Release Date - Published_At](https://img.shields.io/github/release-date/kwooshung/algorithm-sorts?labelColor=272e3b&color=00b42A&logo=github) +![GitHub last commit](https://img.shields.io/github/last-commit/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +![GitHub top language](https://img.shields.io/github/languages/top/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +![GitHub pull requests](https://img.shields.io/github/issues-pr/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +![GitHub issues](https://img.shields.io/github/issues/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) +[![NPM Version](https://img.shields.io/npm/v/@kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff)](https://www.npmjs.com/package/@kwooshung/algorithm-sorts) +[![Npm.js Downloads/Week](https://img.shields.io/npm/dw/@kwooshung/algorithm-sorts?labelColor=272e3b&labelColor=272e3b&color=165dff&logo=npm)](https://www.npmjs.com/package/@kwooshung/algorithm-sorts) +[![Github CI/CD](https://github.com/kwooshung/algorithm-sorts/actions/workflows/ci.yml/badge.svg)](https://github.com/kwooshung/algorithm-sorts/actions/) +[![codecov](https://codecov.io/gh/kwooshung/algorithm-sorts/graph/badge.svg?token=VVZJE7H0KD)](https://codecov.io/gh/kwooshung/algorithm-sorts) +[![Maintainability](https://api.codeclimate.com/v1/badges/325d0881b1ca19165d35/maintainability)](https://codeclimate.com/github/kwooshung/algorithm-sorts/maintainability/) +[![GitHub License](https://img.shields.io/github/license/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff)](LICENSE) +[![Gitee Repo](https://img.shields.io/badge/gitee-cvlar-165dff?logo=gitee)](https://gitee.com/kwooshung/algorithm-sorts/) +![Github Stars](https://img.shields.io/github/stars/kwooshung/algorithm-sorts?labelColor=272e3b&color=165dff) + +

+ English | + 中文 +

+
+ +# 为什么开发它? + +- 开发时,我需要用到算法,我找到了 [algorithms.js](https://github.com/felipernb/algorithms.js) 这个库,它的实现方式非常好,本项目就在 [compare](src/internal/compare/index.ts) [algorithms.js](https://github.com/felipernb/algorithms.js) 的基础略作修改。 +- [algorithms.js](https://github.com/felipernb/algorithms.js) 不是通过 `esm` 的规范实现的,而是通过 `commonjs` 的规范实现的,这样就不能使用 `树摇(tree-shaking)` 了,虽然有一些间接的方式实现,但不如直接使用 `esm`规范来的方便。 +- [algorithms.js](https://github.com/felipernb/algorithms.js) 已有多年没有维护了,一些算法和实现逻辑使用现代的方式实现会更好。 + +# 为什么使用它? + +- `Typescript` 编写,并进行了单元测试,保证了代码质量,代码覆盖率达到 `100%`; +- 支持 `esm` 和 `commonjs` 规范,`esm` 规范可以直接使用 `树摇(tree-shaking)`,减少打包体积; +- 清晰的注释,包含中英文注释,方便阅读和理解,如下所示; + +```ts +/** + * 短冒泡排序 / Short Bubble Sort + * @description 短冒泡排序是冒泡排序的一种变体,当在整个排序过程中没有进行任何交换时,该算法会提前停止 / Short bubble sort is a variation of bubble sort that stops early if no swaps are made during the entire sorting process + * @usageScenario 适用于检测几乎已经排序好的数组 / Suitable for detecting nearly sorted arrays + * @timeComplexity 最好情况 O(n),平均和最坏情况 O(n^2) / Best case O(n), average and worst case O(n^2) + * @param {T[]} array 待排序数组 / Array to be sorted + * @param {boolean} [modifyOriginal=true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse=false] 是否反转结果 / Whether to reverse the result + */ +``` + +- 排序算法相比 [algorithms.js](https://github.com/felipernb/algorithms.js) 多了几个,后续会继续添加; +- 大部分情况下,本库算法效率优于 [algorithms.js](https://github.com/felipernb/algorithms.js),下方有对比图表,您也可以 git clone 本项目,运行 `npm compare` 进行测试; + +# 什么时候不要使用它? + +就如项目名称而言,你也应该知道,本项目的算法只支持 `排序`,如果你需要其他算法,可以使用 [algorithms.js](https://github.com/felipernb/algorithms.js) + +# 效率对比 + +随机 1000 条数据,字符串长度在 6 到 32 之间,数字在 0 到 1,000,000 之间,对比如下: + +| 算法 | algorithms.js | @kwooshung/algorithm-sorts | 差异 | +| :------------------- | :-----------: | :------------------------: | :------------: | +| 冒泡排序 | 65.0368 ms | 65.0298 ms | -0.0070 ms | +| 短冒泡排序 | 13251.3260 ms | 128.2500 ms | -13123.0760 ms | +| 鸡尾酒排序 | - | 52.7166 ms | - | +| 计数排序 | - | 12.3503 ms | - | +| 计数排序(优化版本) | 33.2357 ms | 32.6380 ms | -0.5977 ms | +| 堆排序 | 8.3025 ms | 4.6525 ms | -3.6500 ms | +| 插入排序 | 27.4480 ms | 27.4331 ms | -0.0149 ms | +| 归并排序 | 2.9167 ms | 2.5592 ms | -0.3575 ms | +| 煎饼排序 | - | 57.7009 ms | 0 ms | +| 快速排序 | 3.0599 ms | 2.6374 ms | -0.4225 ms | +| 基数排序 | 0.2070 ms | 0.1339 ms | -0.0731 ms | +| 选择排序 | 55.8389 ms | 55.8000 ms | -0.0389 ms | +| 希尔排序 | 3.1775 ms | 3.1564 ms | -0.0211 ms | +| 定向排序 | - | 6.7950 ms | - | + +# 安装 + +## npm + +```bash +npm install @kwooshung/algorithm-sorts --save-dev +``` + +## yarn + +```bash +yarn add @kwooshung/algorithm-sorts -D +``` + +## pnpm + +```bash +pnpm add @kwooshung/algorithm-sorts -D +``` + +# 使用方法 + +## 引入 + +### esm + +```ts +import { bubbleSort } from '@kwooshung/algorithm-sorts'; +``` + +### commonjs + +```ts +const { bubbleSort } = require('@kwooshung/algorithm-sorts'); +``` + +## 已支持的算法 + +> 目前已支持如下排序算法,具体使用方法,点击下方排序名称,参考注释和参数即可: + +- [» 冒泡排序](src/sorts/bubble/index.ts) +- [» 短冒泡排序](src/sorts/bubble/short/index.ts) +- [» 鸡尾酒排序](src/sorts/cocktail/index.ts) +- [» 计数排序](src/sorts/counting/index.ts) +- [» 计数排序(优化版本)](src/sorts/counting/optimized/index.ts) +- [» 堆排序](src/sorts/heap/index.ts) +- [» 插入排序](src/sorts/insertion/index.ts) +- [» 归并排序](src/sorts/merge/index.ts) +- [» 煎饼排序 ](src/sorts/pancake/index.ts) +- [» 快速排序](src/sorts/quick/index.ts) +- [» 基数排序](src/sorts/radix/index.ts) +- [» 选择排序](src/sorts/selection/index.ts) +- [» 希尔排序](src/sorts/shell/index.ts) +- [» 定序排序](src/sorts/tim/index.ts) diff --git a/changelogs/.history b/changelogs/.history new file mode 100644 index 0000000..afaf360 --- /dev/null +++ b/changelogs/.history @@ -0,0 +1 @@ +1.0.0 \ No newline at end of file diff --git a/changelogs/.template b/changelogs/.template new file mode 100644 index 0000000..4b61f39 --- /dev/null +++ b/changelogs/.template @@ -0,0 +1,2 @@ +## 🎉 {{tag}} `{{date}}` +{{logs}} \ No newline at end of file diff --git a/changelogs/CHANGELOG.en.md b/changelogs/CHANGELOG.en.md new file mode 100644 index 0000000..1f38aec --- /dev/null +++ b/changelogs/CHANGELOG.en.md @@ -0,0 +1,10 @@ +## 🎉 1.0.0 `2024-01-12` +### 📚 Docs +- Explain that the document has been perfected ([#a4f2250](https://github.com/kwooshung/algorithm-sorts/commit/a4f225034537c529add94987d284267945ca4759)) +### 🐛 Fix +- Note from Chinese to Chinese and English ([#85c0485](https://github.com/kwooshung/algorithm-sorts/commit/85c048534e0bb51e15cf75b2d12b5b81d7362afb)) +### ✨ Feature +- Common sorting algorithm has been done ([#a5bd06d](https://github.com/kwooshung/algorithm-sorts/commit/a5bd06d36a558f1c149d1da2b14f72fe0e9d6a7b)) +### Other +- Initial commit ([#7367696](https://github.com/kwooshung/algorithm-sorts/commit/7367696c85f2e0f4207450e66b0f8bc14d096bbe)) + diff --git a/changelogs/CHANGELOG.ja.md b/changelogs/CHANGELOG.ja.md new file mode 100644 index 0000000..557959a --- /dev/null +++ b/changelogs/CHANGELOG.ja.md @@ -0,0 +1,10 @@ +## 🎉 1.0.0 `2024-01-12` +### 📚 Docs +- 文書が完成したことを説明してください ([#a4f2250](https://github.com/kwooshung/algorithm-sorts/commit/a4f225034537c529add94987d284267945ca4759)) +### 🐛 Fix +- 中国語から中国語、英語へのメモ ([#85c0485](https://github.com/kwooshung/algorithm-sorts/commit/85c048534e0bb51e15cf75b2d12b5b81d7362afb)) +### ✨ Feature +- 一般的なソートアルゴリズムが行われました ([#a5bd06d](https://github.com/kwooshung/algorithm-sorts/commit/a5bd06d36a558f1c149d1da2b14f72fe0e9d6a7b)) +### Other +- 最初のコミット ([#7367696](https://github.com/kwooshung/algorithm-sorts/commit/7367696c85f2e0f4207450e66b0f8bc14d096bbe)) + diff --git a/changelogs/CHANGELOG.ko.md b/changelogs/CHANGELOG.ko.md new file mode 100644 index 0000000..4472180 --- /dev/null +++ b/changelogs/CHANGELOG.ko.md @@ -0,0 +1,10 @@ +## 🎉 1.0.0 `2024-01-12` +### 📚 Docs +- 문서가 완성되었다고 설명하십시오 ([#a4f2250](https://github.com/kwooshung/algorithm-sorts/commit/a4f225034537c529add94987d284267945ca4759)) +### 🐛 Fix +- 중국어에서 중국어 및 영어에주의하십시오 ([#85c0485](https://github.com/kwooshung/algorithm-sorts/commit/85c048534e0bb51e15cf75b2d12b5b81d7362afb)) +### ✨ Feature +- 일반적인 정렬 알고리즘이 수행되었습니다 ([#a5bd06d](https://github.com/kwooshung/algorithm-sorts/commit/a5bd06d36a558f1c149d1da2b14f72fe0e9d6a7b)) +### Other +- 초기 커밋 ([#7367696](https://github.com/kwooshung/algorithm-sorts/commit/7367696c85f2e0f4207450e66b0f8bc14d096bbe)) + diff --git a/changelogs/CHANGELOG.ru.md b/changelogs/CHANGELOG.ru.md new file mode 100644 index 0000000..59294f8 --- /dev/null +++ b/changelogs/CHANGELOG.ru.md @@ -0,0 +1,10 @@ +## 🎉 1.0.0 `2024-01-12` +### 📚 Docs +- Объясните, что документ был усовершенствован ([#a4f2250](https://github.com/kwooshung/algorithm-sorts/commit/a4f225034537c529add94987d284267945ca4759)) +### 🐛 Fix +- Примечание от китайского на китайский и английский ([#85c0485](https://github.com/kwooshung/algorithm-sorts/commit/85c048534e0bb51e15cf75b2d12b5b81d7362afb)) +### ✨ Feature +- Общий алгоритм сортировки был сделан ([#a5bd06d](https://github.com/kwooshung/algorithm-sorts/commit/a5bd06d36a558f1c149d1da2b14f72fe0e9d6a7b)) +### Other +- Первоначальный коммит ([#7367696](https://github.com/kwooshung/algorithm-sorts/commit/7367696c85f2e0f4207450e66b0f8bc14d096bbe)) + diff --git a/changelogs/CHANGELOG.zh-cn.md b/changelogs/CHANGELOG.zh-cn.md new file mode 100644 index 0000000..7b7babc --- /dev/null +++ b/changelogs/CHANGELOG.zh-cn.md @@ -0,0 +1,10 @@ +## 🎉 1.0.0 `2024-01-12` +### 📚 Docs +- 说明该文档已经完善 ([#a4f2250](https://github.com/kwooshung/algorithm-sorts/commit/a4f225034537c529add94987d284267945ca4759)) +### 🐛 Fix +- 从中文到中文和英语的笔记 ([#85c0485](https://github.com/kwooshung/algorithm-sorts/commit/85c048534e0bb51e15cf75b2d12b5b81d7362afb)) +### ✨ Feature +- 通用排序算法已经完成 ([#a5bd06d](https://github.com/kwooshung/algorithm-sorts/commit/a5bd06d36a558f1c149d1da2b14f72fe0e9d6a7b)) +### Other +- 初始提交 ([#7367696](https://github.com/kwooshung/algorithm-sorts/commit/7367696c85f2e0f4207450e66b0f8bc14d096bbe)) + diff --git a/changelogs/CHANGELOG.zh-tw.md b/changelogs/CHANGELOG.zh-tw.md new file mode 100644 index 0000000..3d5ee8d --- /dev/null +++ b/changelogs/CHANGELOG.zh-tw.md @@ -0,0 +1,10 @@ +## 🎉 1.0.0 `2024-01-12` +### 📚 Docs +- 說明該文檔已經完善 ([#a4f2250](https://github.com/kwooshung/algorithm-sorts/commit/a4f225034537c529add94987d284267945ca4759)) +### 🐛 Fix +- 從中文到中文和英語的筆記 ([#85c0485](https://github.com/kwooshung/algorithm-sorts/commit/85c048534e0bb51e15cf75b2d12b5b81d7362afb)) +### ✨ Feature +- 通用排序算法已經完成 ([#a5bd06d](https://github.com/kwooshung/algorithm-sorts/commit/a5bd06d36a558f1c149d1da2b14f72fe0e9d6a7b)) +### Other +- 初始提交 ([#7367696](https://github.com/kwooshung/algorithm-sorts/commit/7367696c85f2e0f4207450e66b0f8bc14d096bbe)) + diff --git a/configs/.ks-cvlar.scopes.cjs b/configs/.ks-cvlar.scopes.cjs new file mode 100644 index 0000000..7be2bc4 --- /dev/null +++ b/configs/.ks-cvlar.scopes.cjs @@ -0,0 +1,90 @@ +module.exports = [ + { + name: 'components', + description: '组件相关' + }, + { + name: 'hooks', + description: 'hook 相关' + }, + { + name: 'utils', + description: 'utils 相关' + }, + { + name: 'lib', + description: 'lib 相关' + }, + { + name: 'styles', + description: '样式相关' + }, + { + name: 'ui', + description: '用户界面调整' + }, + { + name: 'auth', + description: '对 auth 修改' + }, + { + name: 'performance', + description: '性能优化' + }, + { + name: 'security', + description: '安全性更新' + }, + { + name: 'i18n', + description: '国际化' + }, + { + name: 'docs', + description: '文档更新' + }, + { + name: 'changelog', + description: '更新日志' + }, + { + name: 'deps', + description: '项目依赖' + }, + { + name: 'config', + description: '配置相关' + }, + { + name: 'test', + description: '测试相关' + }, + { + name: 'tools', + description: '工具相关文件的修改' + }, + { + name: 'experiments', + description: '实验性功能' + }, + { + name: 'egg', + description: '小彩蛋,小惊喜' + }, + { + name: 'backend', + description: '后端相关更改' + }, + { + name: 'workflows', + description: '工作流相关文件更改' + }, + { + name: 'tag', + description: '新版本,新标签' + }, + { + name: 'other', + description: '其他修改' + } +]; diff --git a/configs/.ks-cvlar.types.cjs b/configs/.ks-cvlar.types.cjs new file mode 100644 index 0000000..1e6613b --- /dev/null +++ b/configs/.ks-cvlar.types.cjs @@ -0,0 +1,172 @@ +module.exports = [ + { + emoji: '🍻 ', + name: 'initial', + description: '初始提交' + }, + { + emoji: '🆕 ', + name: 'add', + description: '新建文件' + }, + { + emoji: '✨ ', + name: 'feature', + description: '新的特性' + }, + { + emoji: '🐛 ', + name: 'fix', + description: '修复Bug' + }, + { + emoji: '📚 ', + name: 'docs', + description: '变更的只有文档' + }, + { + emoji: '💅 ', + name: 'format', + description: '空格、分号等格式修复' + }, + { + emoji: '♻️ ', + name: 'refactor', + description: '代码重构,注意和特性、修复区分开' + }, + { + emoji: '⚡️ ', + name: 'performance', + description: '提升性能' + }, + { + emoji: '💩 ', + name: 'optimization', + description: '代码优化' + }, + { + emoji: '⚰️ ', + name: 'remove', + description: '废弃代码' + }, + { + emoji: '🔒 ', + name: 'security', + description: '安全性修复或更新' + }, + { + emoji: '🔗 ', + name: 'dependency', + description: '更新依赖库或包' + }, + { + emoji: '⚙️ ', + name: 'config', + description: '配置文件的更改' + }, + { + emoji: '📡 ', + name: 'deployment', + description: '与项目部署相关的更改' + }, + { + emoji: '📦️ ', + name: 'release', + description: '发布新版本' + }, + { + emoji: '🗄️ ', + name: 'migration', + description: '数据库或数据相关的更改' + }, + { + emoji: '🖌️ ', + name: 'ui', + description: '调整和更改' + }, + { + emoji: '🏷️ ', + name: 'i18n', + description: '多语言国际化相关更改' + }, + { + emoji: '♿ ', + name: 'accessibility', + description: '提升产品的可访问性' + }, + { + emoji: '✅ ', + name: 'test', + description: '添加或更新测试' + }, + { + emoji: '🚧 ', + name: 'wip', + description: '尚未完成' + }, + { + emoji: '🚀 ', + name: 'tool', + description: '开发工具变动 (构建、脚手架工具等)' + }, + { + emoji: '🔄 ', + name: 'workflow', + description: 'CI 配置、脚本,等工作流相关文件更改' + }, + { + emoji: '💻 ', + name: 'dev Environment', + description: '开发工具、环境配置更改' + }, + { + emoji: '🏭 ', + name: 'prod Environment', + description: '生产环境配置更改' + }, + { + emoji: '⏪ ', + name: 'revert', + description: '代码回退' + }, + { + emoji: '⌛ ', + name: 'merge', + description: '合并代码' + }, + { + emoji: '📝 ', + name: 'changelog', + description: '更新 changelog' + }, + { + emoji: '⚗️ ', + name: 'experimental', + description: '实验性功能,可能存在错误等未知问题' + }, + { + emoji: '📜 ', + name: 'license', + description: '添加或更新许可证' + }, + { + emoji: '👀 ', + name: 'review', + description: '修改代码审查建议' + }, + { + emoji: '🥚 ', + name: 'easter', + description: '小惊喜' + }, + { + emoji: '🌐 ', + name: 'network', + description: '网络请求、通信相关的更改' + }, + { + emoji: '📂 ', + name: 'file', + description: '添加、删除、移动文件' + } +]; diff --git a/configs/.ks-cvlarrc.cjs b/configs/.ks-cvlarrc.cjs new file mode 100644 index 0000000..1f3195f --- /dev/null +++ b/configs/.ks-cvlarrc.cjs @@ -0,0 +1,839 @@ +const types = require('./.ks-cvlar.types.cjs'); +const scopes = require('./.ks-cvlar.scopes.cjs'); + +/** + * 以下所有配置项,均支持此种配置,如:开启配置:只赋值 'default'、'{}' 或 '无此项配置' 即可,这将启用 '默认配置'; + * 关闭配置:只需要赋值 'false' 即可; + * 推荐使用命令 'cvlar i' 初始化配置文件 + */ +module.exports = { + // Git提交,方便在菜单中选择性提交内容 + commit: { + types, + scopes, + // 使用自己的语言描述 'Git提交信息',而后会通过 'Google翻译' 自动翻译成 '英语',再执行 'Git提交' + submit: { + /** + * 你想通过什么语言来描述 'Git提交信息' + * 支持的语言列表:https://cloud.google.com/translate/docs/languages + */ + origin: 'zh-CN', + /** + * 你想将 'Git提交信息' 翻译成什么语言,支持的语言列表同上 + * 支持的语言列表:https://cloud.google.com/translate/docs/languages + */ + target: 'en' + } + }, + // 包管理,方便在菜单中选择性执行特定命令 + package: { + /** + * package.json 中的 scripts 配置项,赋值对象,如下所示: + * { + * dev: 'npm run dev', + * build: 'npm run build', + * 'test:watch': 'npm run build', + * ... + * } + * + * 格式说明: + * key:必须,表示命令名称,必须和 'package.json' 中的 'scripts' 配置项中的 'key' 一致,否则无法正确执行命令 + * value:必须,表示命令描述,用于在菜单中做说明 + * 空字符串,在菜单中,将直接使用key表示 + * 非空字符串,在菜单中,将直接使用value表示 + */ + scripts: { + prepare: '初始化', + dev: '开发', + build: '发布', + test: '测试', + 'test:watch': '测试', + 'test:ci': '测试', + compare: '比较', + eslint: '脚本检查' + }, + // 包管理工具 + manager: { + /** + * 包管理工具类型,赋值字符串,可赋值: + * npm, yarn, pnpm, 等其他包管理工具的名称 + */ + type: 'pnpm', + /** + * 依赖源,默认:auto,表示按照包管理工具的默认源,一般是:https://registry.npmjs.org + * 注意:此配置不会影响全局或当前项目的依赖源,只会影响通过本工具安装的依赖时的依赖源 + */ + registry: 'auto', + /** + * 包管理命令,格式说明: + * key:必须,表示命令名称,例如 'npm install xxx','key' 就是 'install' + * value:必须,表示命令描述,用于在菜单中做说明 + * 空字符串,在菜单中,将直接使用key表示 + * 非空字符串,在菜单中,将直接使用value表示 + * 注意: + * 1. 以下默认命令,均以 npm 为准,您可自行修改 + * 2. 如果您使用的是 yarn 或 pnpm,可能会出现不兼容的情况, + * 您可以自行修改与之对应的命令即可 + * 3. 新版本的 npm/yarn/pnpm 命令均互相兼容, + * 若出现不兼容的情况,自行修改下方命令或升级包管理工具 + */ + commands: { + install: '安装', + update: '更新', + uninstall: '卸载', + outdated: '列出过时的包', + list: '查看列表', + info: '查看信息', + search: '搜索', + login: '登录', + publish: '发布' + } + } + }, + // 版本管理,可用于升级、撤销 版本号,自动升级和提交 + version: { + // 是否自动更新 package.json 中的版本号,布尔类型,默认:true + package: true + }, + // 日志,自动根据 Git 提交记录生成日志 + changelog: { + // 日志文件相关配置 + file: { + save: './changelogs' + }, + // 日志翻译相关配置 + translate: { + /** + * CHANGELOG 文件的原始语言,default 'zh-CN' + * 支持的语言列表:https://cloud.google.com/translate/docs/languages + */ + origin: 'en', + /** + * CHANGELOG 文件的目标语言,default 'en',可以是数组,表示翻译成多种语言 + * 若已存在翻译版本的日志,仅对新生成的日志有效,你可选择 '重新生成所有日志' + * 支持的语言列表:https://cloud.google.com/translate/docs/languages + */ + target: ['zh-CN', 'zh-TW', 'ja', 'ko', 'ru'] + }, + // 日志模板相关配置 + template: { + /** + * CHANGELOG 文件的内容模板,支持 md 语法 + * 默认值: + * ## 🎉 {{tag}} `{{date}}` + * {{logs}} + * + * 日志会按照提交类型顺序分类 + * 目前支持的变量如下: + * tag:tag名 + * date:日期,如:2023-12-17 + * time:时间,如:04:59:39 + * logs:日志内容,对应下面的 logs 配置项 + * + *【注意】当已存在使用此模板生成的日志,且启用了 `cvlar -r/release` 自动发布, + * 建议重新生成所有日志,避免 `cvlar -r/release` 自动发布时,可能无法准确获取到日志内容' + */ + content: '## 🎉 {{tag}} `{{date}}`\n{{logs}}', + /** + * 根据type分类,具体的日志内容 + * 若已存在翻译版本的日志,仅对新生成的日志有效, + * 你可选择 '重新生成所有日志' + */ + logs: { + // 标题模板 + title: { + /** + * 标准的标题模板,也就是`提交类型`存在时的模板 + * + * 可使用的变量: + * emoji:`提交类型`对应的 emoji + * type:`提交类型`,变量首字母大写,则内容首字母也会大写 + * scope:提交范围,变量首字母大写,则内容首字母也会大写 + * date: 日期,如:2023-12-17 + * time: 时间,如:04:59:39 + */ + standard: '### {{emoji}} {{Type}}', + // 其他标题模板,也就是`提交类型`不存在时的模板,无法根据`提交类型`分类的标题 + other: '### Other' + }, + /** + * 每条日志消息的模板 + * + * 可使用的变量: + * message:日志消息,变量首字母大写,则内容首字母也会大写 + * commitlink:提交记录详情页链接 + * date: 日期,如:2023-12-17 + * time: 时间,如:04:59:39 + */ + item: '- {{message}} ({{commitlink}})', + /** + * CHANGELOG 文件中,每条日志均有具体的提交详情页 + * 用于跳转到提交记录详情页链接 + */ + commitlink: { + /** + * 链接文本 + * id:表示提交的ID + * [substr:n,l]: + * n(必要参数):表示从第几个字符开始截取,若l不存在,此参数就表示从 0 截取到 n 个字符 + * l(可选参数):表示截取多少个字符 + */ + text: '#{{id[substr:7]}}', + /** + * 链接地址 + * + * 可使用的变量: + * id:表示提交id,完整的ID一般为40位 + */ + url: 'https://github.com/kwooshung/algorithm-sorts/commit/{{id}}' + } + } + } + }, + release: { + /** + * 发布页面,tag版本标题模板 + * + * 可使用的变量: + * tag:tag名 + */ + subject: '🎉 {{tag}}', + /** + * 每当你创建新标签到暂存到git本地仓库,并且还未推送到远程仓库时, + * 会自动执行日志生成,翻译,写入文件等操作。 + * 这样会导致你的仓库文件发生变化,因此需要提交这些变化的文件到仓库(一般仅有日志变化), + * 因此需要提交信息,但总不能每次提交tag都要手动选择一遍 commit type 和 commit scope 吧,这样太麻烦了,而且每次提交信息都差不多,所以就有了这个配置项 + * + * 但是,由于暂存到本地仓库的标签,不包含新创建的日志 + * 所以,需要撤销本地仓库的标签,重新创建同样的标签,这样就会包含新的日志 + * + * 因此内部执行的流程看起来是这样的: + * 1、创建标签 1.0.0(肯定不会包含第二步的日志内容) + * 2、根据标签生成日志 + * 3、暂存日志到git本地仓库 + * 4、撤销本地git仓库标签 1.0.0 + * 5、重新创建标签 1.0.0(这样就会包含根据标签生成的日志) + * 6、推送本地仓库到远程仓库 + * 7、推送标签到远程仓库 + * + * + * 根据下面的 `type`、`scope` 和 `subject`,生成的提交信息的短说明: + * 程序内部执行的模板:{{emoji}}{{type}}({{scope}}): {{subject}} + * + * 如果使用的是默认 `commit types` 和 `commit scopes` 配置 + * 而且 `subject` 内容为 `new version {{tag}}` + * 那么最终结果如下: + * 📦️ release(tag): new version 1.0.0 + */ + pushTagMessage: { + /** + * 提交类型,参考本文配置文件中的 `commit.types` + * 将根据 `name` 字段,自动匹配到对应的提交类型 + * + * 【注意】建议与 `commit.types` 中的 `name` 字段保持一致 + */ + type: 'release', + /** + * 可选,`commit scopes`,提交范围,参考本文配置文件中的 `commit.scopes` + * + * 【注意】建议与 `commit.scopes` 中的 `name` 字段保持一致 + */ + scope: 'tag', + /** + * `commit subject`,提交信息的短说明 + * + * 可使用的变量: + * tag:tag名 + * + * 若是启用了提交信息翻译,即 `commit.submit` 配置项不为 false + * `commit.submit.origin` 这里指定什么语言,此选项就应该使用什么语言写内容 + * `commit.submit.target` 而后会根据这个配置,将内容翻译成指定的语言 + */ + subject: '新版本 {{tag}}' + }, + /** + * 当启用多语言 + * 即 `changelog.translate.origin` 和 `changelog.translate.target` 配置项不为 false 时,使用此配置项 + */ + lang: { + /** + * 多语言内容模板 + * + * 可使用的变量: + * name(必要参数):语言名称 + * code(可选参数):语言代码 + * + * 若不需要,可设置此项为false,将不会在日志中出现此标题 + */ + subject: '## 🌐 {{name}} ({{code}})', + // 分隔符 + separator: '\n\n' + }, + /** + * 布尔类型,默认:true + * 是否在 'Github Release' 内容中,每条 'Release' 的最后,加入如下md代码: + * > This [Changelog](changelog.file.save 的目录设置值), Powered by @kwooshung/[cvlar](https://github.com/kwooshung/cvlar/) + * 参考:https://github.com/kwooshung/cvlar/releases + */ + poweredby: true + }, + /** + * 用于此工具提示信息的国际化配置 + * 可自定义任何语言,以下内容根据内容自行翻译需要的语言即可 + */ + i18n: { + // 是,主要用于菜单中的单选,表示选中 + yes: '是', + // 否,主要用于菜单中的单选,表示未选中 + no: '否', + /** + * 最多可选数量,主要用于菜单中的选项, + * 表示最少展示多少个选项,多余的将需要滚动查看 + */ + choicesLimit: 15, + // 多选,只能用于菜单中的多选中的菜单相关配置 + checkbox: { + // 在多选菜单展示时,默认提示,表示按键操作 + instructions: '按<空格>进行选择,按切换全部,按反转选择,按<回车>确认选择' + }, + // 一级菜单的标题 + select: '我想 ...', + // package.json 中的 scripts,用于菜单中的运行脚本 + scripts: { + // 菜单中的运行脚本的标题 + message: '运行', + description: '选择要运行的脚本', + select: { + message: '主菜单 > 运行 > 选择脚本' + } + }, + // git相关 + git: { + message: 'Git', + description: 'Git版本控制', + // git 提交相关 + commit: { + message: '提交代码', + description: '提交代码到 Git 仓库', + select: { + message: '主菜单 > 版本控制' + }, + type: { + message: '选择提交类型' + }, + scope: { + message: '选择修改范围' + }, + /** + * git提交信息,短说明, + * + * 其中 + * transformer:可选,表示对值处理函数 + * validate:可选,表示验证函数 + * + * 两个函数均可自定义,具体请参考:https://github.com/SBoudrias/Inquirer.js/tree/master/packages/input + */ + subject: { + message: '短说明', + description: '不建议超过72个字符', + validate(val) { + val = val.trim(); + if (val.length <= 0) { + return '短说明不能为空'; + } else if (val.length > 72) { + return '短说明不能超过72个字符'; + } + return true; + } + }, + // 长说明,同样支持 `transformer` 和 `validate` + body: { + message: '长说明', + description: '使用 "|" 换行', + // 是否必填项,布尔类型,默认:false + required: false, + // 必填项的提示信息 + requiredMessage: '长说明不能为空' + }, + // 破坏性变更,不向下兼容, 同样支持 `transformer` 和 `validate` + breaking: { + message: 'BREAKING CHANGES(破坏性变更,不向下兼容)', + field: 'BREAKING CHANGE: ', + required: false, + requiredMessage: '长说明不能为空' + }, + /** + * 自定义字段,支持三种类型:`input`、`select`、`checkbox`,参考本项目仓库根目录下的 `.ks-cvlarrc.cjs` 文件 + * 在仓库说明中,也有此配置的详细说明 + * 若不需要,可删除 `custom` 字段 或 将 `custom` 字段赋值为 `false` + */ + custom: false, + // issues相关 + issues: { + message: '是否需要关闭 issue?', + default: false, + close: { + message: '选择关闭 issue 的关键词,支持多选', + // issues相关,可自定义关键字,默认:`fixes`、`resolves` 和 `closes` + choices: [ + { name: '修复', value: 'fixes', description: '修复' }, + { name: '增强', value: 'resolves', description: '增强' }, + { name: '关闭', value: 'closes', description: '关闭' } + ], + number: { + message: '{0} 的 issue 编号 (例如:#11 #17 #27)' + } + } + }, + translate: { + connect: { + message: '正在连接 Google翻译,并检查是否可用...', + success: '连接 Google翻译 成功', + fail: '连接 Google翻译 失败' + }, + process: { + message: '正在翻译提交信息:', + success: '翻译成功', + fail: '翻译失败,错误信息如下:' + }, + error: { + config: 'commit.submit 配置项错误' + } + }, + /** + * 生成提交信息后,触发此函数,可自行处理提交信息的格式 + * 返回值,是一个对象,包含两个属性,fail、val: + * fail:true时,则不会继续执行提交操作, + * val:提交信息 + * 也可用于自定义提示信息 + */ + complate(val) { + return { fail: false, val }; + }, + confirm: { + message: '请确认最终信息正确?', + yes: '正确,直接提交', + no: '不准确,使用 `文本编辑器` 修改后提交', + editor: { + message: '按下 <回车> 键,打开 `文本编辑器`,修改后保存并关闭,即可提交' + } + }, + push: { + message: '是否推送到远程仓库?', + // true:自动选择是,false:自动选择否,默认:false + default: false + }, + tag: { + message: '是否需要打标签?', + // true:自动选择是,false:自动选择否,默认:false + default: false + } + }, + // 升/降级版本号相关 + version: { + message: '版本号', + description: '版本号管理,可用于升级、撤销 版本号,自动升级和提交', + translate: { + check: { + message: '将使用 Google翻译,是否检查连接状态?', + success: '连接 Google翻译 成功', + fail: '连接失败', + retry: '是否重试?', + error: '无法连接 Google翻译,暂时不能生成日志' + } + }, + select: { + message: '请选择操作' + }, + upgrade: { + message: '升级版本(自动)', + description: '选择 主版本号、次版本号 或 补丁版本号,自动根据 当前版本号,计算下个版本号', + type: { + message: '您打算升级哪个版本', + major: { + message: '主要', + description: '一般引入了不向后兼容的 API 更改或重大功能更改。' + }, + minor: { + message: '次要', + description: '新的向后兼容功能,建议在确定新功能对项目有用时进行更新。' + }, + patch: { + message: '补丁', + description: '通常用于小的错误修复和更新,不影响软件的主要功能和向后兼容性。' + } + } + }, + specify: { + message: '升级版本(指定)', + description: '完全由您自定义,但是也得符合语义化版本规范(SemVer)', + input: { + message: '请输入版本号:' + } + }, + downgrade: { + message: '降级版本(回退/撤销)', + description: '撤销指定版本号,仅撤销版本,不会对文件产生修改', + select: { + message: '请选择要撤销的版本号', + confirm: { + message: '是否修改 package.json 中的版本号?', + default: true, + remote: { + message: '是否删除远程仓库中的 tag?', + default: false + }, + change: { + message: '您想使用哪个版本号 package.json 中?', + descriptions: { + auto: '自动计算前一个版本,但在以往的tags中,可能不存在这个版本号', + prevtag: '将使用前一个tag作为版本号' + }, + specify: { + message: '指定版本号' + } + } + }, + error: { + no: '没有可撤销的版本号,请重新选择' + } + } + }, + flag: { + message: '是否添加发布标识符?', + description: '可能是 稳定版本 或 预发布版本', + select: { + message: '选择发布标识符', + choices: [ + { name: '预览版 (alpha)', value: 'alpha', description: '{0},预览版,主要用于内部测试,可能包含很多BUG,功能不全,存在很多错误' }, + { name: '测试版 (beta)', value: 'beta', description: '{0},该版本任然存在很多BUG,但是相对alpha版要稳定一些,会不断增加新功能' }, + { name: '候选版本 (rc)', value: 'rc', description: '{0},这个版本接近最终产品,主要目的是查找可能的遗漏的问题。如果没有发现重大问题,这个版本可能就会成为最终发布的版本。' }, + { name: '正式版本 (stable)', value: 'stable', description: '{0},正式版本,该版本相对稳定,基本不会再修改代码,除非发现BUG,或者出现新的需求' } + ] + }, + iterations: { + message: { + no: '当前版本号:{0},不存在预发号,确认使用 {1} 作为预发版本号?', + add: '当前版本号:{0},预发版本类型为{1},迭代号为:{2},是否使用 {3} 作为预发版本号?', + newno: '当前版本号:{0},新版本号是:{1},不存在预发布版本号,是否使用:{2} 作为预发版本号?' + }, + input: { + message: '请输入迭代版本号:', + validate(val) { + val = val.trim(); + if (val.length <= 0) { + return '迭代版本号不能为空'; + } else if (!val.test(/([1-9]d*)/)) { + return '迭代版本号格式不正确'; + } + return true; + } + } + } + }, + annotate: { + message: '是否添加说明?', + no: '无说明', + short: '短说明', + long: '长说明(将使用文本编辑器打开)', + default: '' + }, + file: { + message: '是否更新 package.json 中的版本号?', + default: true + }, + push: { + message: '是否推送 tags 到远程仓库?', + default: true + }, + error: { + exists: '当前版本号 {0} 已存在,请重新输入', + format: '版本号格式不符合 Semver语义化标准,请重新输入' + } + } + }, + // 包管理相关 + package: { + message: '包管理', + description: '安装,更新,卸载,查看,登录,发布 等', + dependencies: '↓↓↓↓↓ [生产依赖] ↓↓↓↓↓', + devDependencies: '↓↓↓↓↓ [开发依赖] ↓↓↓↓↓', + commands: { + message: '主菜单 > 包管理 > 选择命令', + install: { + message: '包名:', + description: + "格式:vue react | vite vitest\n说明:\n · '|' 左边表示 'dependencies,右边表示 'devDependencies'\n · 若是单独安装 'dependencies',则不需要 '|'\n · 若是单独安装 'devDependencies',只需 '| vite vitest'", + error: { + format: '格式错误,请重新输入' + } + }, + uninstall: { + message: '选择要卸载的包' + }, + update: { + message: '选择要更新的包', + loadings: { + reading: '正在读取 package.json 文件 ...', + request: '正在拉取 https://registry.npmjs.org ...', + analysing: '正在分析依赖 ... {0}' + }, + error: { + noUpdate: '没有更新的包,是否重新检查?', + nonSelect: '请先选择要更新的包' + }, + dev: '开发依赖', + prod: '生产依赖', + category: { + major: { + message: '主要更新', + description: '可能引入了不向后兼容的 API 更改或重大功能更改。建议在更新之前仔细查看更新日志和文档,确保新版本不会破坏项目。' + }, + minor: { + message: '次要更新', + description: '新的向后兼容功能,建议在确定新功能对项目有用时进行更新。' + }, + patch: { + message: '补丁更新', + description: '通常用于小的错误修复和更新,不影响软件的主要功能和向后兼容性。' + }, + prerelease: { + message: '预发布', + description: '预发布版本,可能包含新功能,也可能包含错误修复。请慎重更新。' + }, + nonsemver: { + message: '不符合语义化版本规范', + description: '表示包的版本号不符合语义化版本规范(SemVer),通常是版本号小于 1.0.0。这些版本可能不稳定,会引入较大的更改,因此需要谨慎使用。' + } + } + }, + list: { + dependencies: '生产依赖', + devDependencies: '开发依赖' + }, + info: { + message: '选择要查看详情的包', + link: '主页:', + other: '还要查看其他包的信息吗?' + }, + search: { + message: '搜索包名:', + loading: '正在从 https://www.npmjs.com/ 拉取搜索数据,请稍等...', + result: { + date: { + format: 'YYYY-MM-DD HH:mm:ss', + second: '秒前', + seconds: '秒前', + minute: '分钟前', + minutes: '分钟前', + hour: '小时前', + hours: '小时前', + day: '天前', + days: '天前', + week: '周前', + weeks: '周前', + month: '月前', + months: '月前' + }, + flags: { + insecure: { + yes: '不安全:', + no: '安全' + }, + unstable: { + yes: '不稳定', + no: '稳定' + } + }, + score: { + final: '综合:', + quality: '质量:', + popularity: '欢迎:', + maintenance: '维护:', + process: { + /** + * 搜索结果的包打分的进度条符号 + * 若是设置为字符串:'▇' + * 则表示为:▇▇▇▇▇▇▇▇▇▇▇▇ + * + * 若设置为字符串数组:['▇', '_'] + * 则表示为:▇▇▇▇________ + */ + symbol: '▇', + /** + * 搜索结果的包打分的进度条长度, + * 默认:50 + * 会自动根据值计算百分比 + */ + length: 50, + // 表示激活的进度,是否加粗,布尔类型,默认:false + activeBold: false + } + }, + fields: { + author: '作者:', + keywords: '关键词:', + description: '描述:' + }, + error: { + empty: '请输入搜索内容', + abnormal: '搜索出现异常,请重试,错误信息如下:' + } + }, + pagination: { + message: '找到了 {0} 条结果,每页 {1} 条,总共 {2} 页,当前第 {3} 页,你打算:', + // 每页条数 + size: 10, + // 页码范围 + range: 10, + next: '下一页', + prev: '上一页', + n: '第 {0} 页', + first: '首页', + last: '尾页', + goto: { + jump: '跳转指定页', + message: '请输入页码:', + error: '页码格式错误,请重新输入' + }, + delimiter: { + keyword: '关键词:', + result: '结果:', + pageSize: '每页:', + pageTotal: '总页:', + pageCurrent: '当前:' + }, + error: { + format: '格式错误,请重新输入' + } + }, + error: { + input: '请输入搜索内容' + } + } + } + }, + // 日志相关,也与 `cvlar -r` 相关,若没有启用日志,则 `cvlar -r` 也无法使用 + changelog: { + message: '日志管理', + title: '主菜单 > 日志管理', + build: { + message: '生成日志', + description: '自动计算需要生成的日志', + success: '生成日志成功', + error: '生成日志失败,是否重试?', + translate: { + check: { + message: '由于 其他语言 将使用 Google翻译,是否检查连接状态?', + success: '连接 Google翻译 成功', + fail: '连接失败', + retry: '是否重试?', + error: '无法连接 Google翻译,暂时不能生成日志' + }, + fail: { + retry: '翻译失败,是否重试?' + }, + translateing: '翻译进度:' + } + }, + rebuild: { + message: '重新生成', + description: '将会删除之前生成的所有日志文件,重新生成日志文件', + confirm: { + message: '此操作可能需要较长的时间,是否继续?', + description: '此操作将会删除之前生成的所有日志文件,并重新生成,可能需要一定的时间' + }, + template: { + message: '由于日志模板 `changelog.template.content` 已修改,会导致 `cvlar -r` 发布功能无法准确识别待发布的日志内容,您需要重新生成所有日志,是否继续?' + } + }, + clean: { + message: '清理日志', + description: '删除之前生成的所有日志文件', + confirm: { + message: '此操作将会删除之前生成的所有日志文件,是否继续?', + description: '此过程不可逆' + }, + retry: { + message: '清理日志失败,是否重试?', + default: true + } + }, + loading: { + git: { + tag: { + reading: '正在读取本地 git 仓库 tag ...', + success: '读取本地 git 仓库 tag 成功', + retry: { + message: '读取 tag 失败,是否重试?', + default: true + } + }, + messages: { + reading: '正在读取本地 git 仓库提交消息 ...', + success: '读取本地 git 仓库 提交消息 成功', + retry: { + message: '读取 提交信息 失败,是否重试?', + default: true + } + } + }, + history: { + diffing: '正在对比 ...', + done: { + success: { + build: '开始生成日志 ...', + no: '没有需要生成的日志' + }, + fail: { + message: '没有找到记录文件 {0},是否生成所有日志?', + description: '这将会清理掉之前生成的所有日志文件,并重新生成,可能需要一定的时间', + default: true + } + } + }, + build: { + message: '正在生成日志 ...', + success: '生成日志成功', + fail: '生成日志失败,是否重试?' + }, + translate: { + connect: { + message: '正在连接 Google翻译,并检查是否可用...', + success: '连接 Google翻译 成功', + fail: '连接 Google翻译 失败' + }, + process: { + message: '正在翻译日志 ...', + success: '翻译成功', + fail: '翻译失败,错误信息如下:' + } + }, + write: { + message: '正在写入日志文件 ...', + success: '写入日志成功', + retry: '写入日志失败,是否重试?', + fail: '写入日志失败' + }, + clean: { + message: '正在清理日志 ...', + success: '清理日志成功' + } + } + }, + // 帮助相关 + help: { + message: '帮助', + description: '查看帮助信息' + }, + // 返回上级菜单 + back: { + message: '..', + description: '返回上级菜单' + }, + // 推出 + exit: { + message: '退出' + } + } +}; diff --git a/configs/commitlintrc.cjs b/configs/commitlintrc.cjs new file mode 100644 index 0000000..d2d5869 --- /dev/null +++ b/configs/commitlintrc.cjs @@ -0,0 +1,25 @@ +const types = require('./.ks-cvlar.types.cjs'); +const scopes = require('./.ks-cvlar.scopes.cjs'); +const { ConvertToLintTypes, ConvertToLintScopes } = require('@kwooshung/cvlar'); + +module.exports = { + parserPreset: { + parserOpts: { + headerPattern: /^(?.*\s\w*)(?:\((?.*)\))?!?:\s(?(?:(?!#).)*(?:(?!\s).))$/, + headerCorrespondence: ['type', 'scope', 'subject'] + } + }, + rules: { + 'header-max-length': [2, 'always', 140], + 'body-leading-blank': [2, 'always'], + 'footer-leading-blank': [2, 'always'], + 'scope-case': [2, 'always', 'lower-case'], + 'subject-empty': [2, 'never'], + 'subject-exclamation-mark': [2, 'never'], + 'subject-full-stop': [2, 'never', '.'], + 'type-case': [2, 'always', 'lower-case'], + 'type-empty': [2, 'never'], + 'type-enum': [2, 'always', ConvertToLintTypes(types)], + 'scope-enum': [2, 'always', ConvertToLintScopes(scopes)] + } +}; diff --git a/configs/eslintrc.cjs b/configs/eslintrc.cjs new file mode 100644 index 0000000..8cb7b22 --- /dev/null +++ b/configs/eslintrc.cjs @@ -0,0 +1,29 @@ +module.exports = { + root: true, + env: { + browser: true, + es2020: true + }, + extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier', 'plugin:prettier/recommended'], + ignorePatterns: ['dist', '.eslintrc.cjs', './configs/.eslintrc.cjs'], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true + }, + ecmaVersion: 'latest', + sourceType: 'module' + }, + rules: { + 'no-undef': 'off', + 'no-plusplus': 'off', + 'no-param-reassign': 'off', + 'no-unused-expressions': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/no-unused-expressions': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off' + } +}; diff --git a/configs/lintstagedrc.mjs b/configs/lintstagedrc.mjs new file mode 100644 index 0000000..426c6c7 --- /dev/null +++ b/configs/lintstagedrc.mjs @@ -0,0 +1,6 @@ +export default { + '*.{js,jsx,ts,tsx}': ['npx prettier --write', 'npx eslint --fix'], + '*.{css,less,scss}': ['npx prettier --write', 'npx stylelint --fix'], + '*.json': ['npx prettier --write'], + '*.test.{js,jsx,ts,tsx}': ['pnpm test:ci'] +}; diff --git a/configs/prettierrc.mjs b/configs/prettierrc.mjs new file mode 100644 index 0000000..12559a0 --- /dev/null +++ b/configs/prettierrc.mjs @@ -0,0 +1,36 @@ +export default { + // 一行最多 200 字符 + printWidth: 200, + // 使用 2 个空格缩进 + tabWidth: 2, + // 不使用缩进符,而使用空格 + useTabs: false, + // 行尾分号 + semi: true, + // 使用单引号 + singleQuote: true, + // 对象的 key 仅在必要时用引号 + quoteProps: 'as-needed', + // jsx 使用单引号 + jsxSingleQuote: true, + // 大括号内的首尾需要空格 + bracketSpacing: true, + // 箭头函数,只有一个参数的时候,也需要括号 + arrowParens: 'always', + // 每个文件格式化的范围是文件的全部内容 + rangeStart: 0, + // 需要格式化和检查的代码结束偏移值(从尾部开始) + rangeEnd: Infinity, + // 不需要写文件开头的 @prettier + requirePragma: false, + // 不需要自动在文件开头插入 @prettier + insertPragma: false, + // 使用默认的折行标准 + proseWrap: 'preserve', + // 根据显示样式决定 html 要不要折行 + htmlWhitespaceSensitivity: 'css', + // 去除对象最后一个逗号 + trailingComma: 'none', + // 换行符使用 lf + endOfLine: 'lf' +}; diff --git a/configs/typings.d.ts b/configs/typings.d.ts new file mode 100644 index 0000000..70d2856 --- /dev/null +++ b/configs/typings.d.ts @@ -0,0 +1,6 @@ +declare module 'chance'; +declare module 'algorithms'; +declare module '*.module.less' { + const classes: { [key: string]: string }; + export default classes; +} diff --git a/configs/vite.ts b/configs/vite.ts new file mode 100644 index 0000000..3665697 --- /dev/null +++ b/configs/vite.ts @@ -0,0 +1,84 @@ +import dts from 'vite-plugin-dts'; + +/** + * 服务器配置 + * @param { number } [port = 3000] 端口号 + * @returns { object } 配置 + */ +const configServer = (port: number = 3000): object => ({ + port, + host: '0.0.0.0' +}); + +/** + * css 配置 + */ +const configCss = { + modules: { + generateScopedName: '[local]' + } +}; + +/** + * TS 类型构建配置 + */ +const configDts = dts({ + rollupTypes: true, + insertTypesEntry: true, + copyDtsFiles: true +}); + +/** + * 构建配置 + * @param { string } name 变量名,一个有效的 JavaScript 标识符,因为它将被用作变量名,主要用于 UMD 构建 + * @param { string } filename 文件名 + * @param { [string] } formats 构建格式 + * @param { [string] } external 外部依赖 + * @param { [object] } globals 全局变量名称 + * @returns { object } 配置 + */ +const configBuild = (name: string, filename: string, formats: string[], external: string[] = [], globals: object = {}): object => ({ + minify: 'esbuild', + esbuild: { + legalComments: 'none', // 移除版权注释 + minifyWhitespace: true, // 压缩空白字符 + minifyIdentifiers: true, // 压缩标识符 + minifySyntax: true // 使用语法转换来实现更小的输出文件 + }, + lib: { + entry: 'src/index.ts', + name, + formats, + fileName: (format: string) => { + if (format === 'cjs') { + return `${filename}.cjs`; + } else if (format === 'esm') { + return `${filename}.mjs`; + } + return `${filename}.js`; + } + }, + rollupOptions: { + external, + output: { + globals, + assetFileNames: (assetInfo) => { + if (assetInfo.name === 'style.css') { + return `${filename}.css`; + } + return assetInfo.name; + } + } + } +}); + +/** + * 解析配置 + */ +const configResolve = { + alias: { + '@': '/src' + } +}; + +export { configServer, configCss, configDts, configBuild, configResolve }; diff --git a/configs/vitest.ts b/configs/vitest.ts new file mode 100644 index 0000000..549c05d --- /dev/null +++ b/configs/vitest.ts @@ -0,0 +1,14 @@ +/** + * 测试配置 + */ +const configTest = { + globals: true, + include: ['src/sorts/**/*.test.ts', 'src/internal/**/*.test.ts'], + exclude: ['**/node_modules/**', '**/dist/**'], + coverage: { + include: ['src/sorts/**/*.ts', 'src/internal/**/*.ts'], + exclude: ['src/internal/generate/index.ts'] + } +}; + +export default configTest; diff --git a/package.json b/package.json new file mode 100644 index 0000000..aedb165 --- /dev/null +++ b/package.json @@ -0,0 +1,88 @@ +{ + "name": "@kwooshung/algorithm-sorts", + "version": "1.0.0", + "title": "algorithm-sorts", + "description": "Better algorithm implementation library", + "private": false, + "tags": [ + "kwooshung", + "algorithms", + "algorithms.js", + "algorithm-sorts", + "algorithm-sorts.js", + "suanfa" + ], + "keywords": [ + "kwooshung", + "algorithms", + "algorithms.js", + "algorithm-sorts", + "algorithm-sorts.js", + "suanfa" + ], + "author": "kwooshung", + "homepage": "https://github.com/kwooshung/algorithm-sorts", + "repository": { + "type": "git", + "url": "https://github.com/kwooshung/algorithm-sorts.git" + }, + "bugs": { + "url": "https://github.com/kwooshung/algorithm-sorts/issues" + }, + "type": "module", + "main": "dist/algorithm-sorts.cjs", + "module": "dist/algorithm-sorts.mjs", + "unpkg": "dist/algorithm-sorts.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "require": "./dist/algorithm-sorts.cjs", + "import": "./dist/algorithm-sorts.mjs", + "types": "./dist/index.d.ts" + } + }, + "files": [ + "dist" + ], + "scripts": { + "prepare": "husky install", + "dev": "cross-env NODE_ENV=development vite", + "build": "tsc && vite build", + "test": "vitest", + "test:watch": "vitest watch --coverage", + "test:ci": "vitest run --coverage", + "compare": "node ./src/compare.cjs", + "eslint": "eslint . --fix --cache --quiet --report-unused-disable-directives --max-warnings 0 --ext .js,.cjs,.jsx,.ts,.cts,.tsx" + }, + "peerDependencies": { + "node": ">=14.0.0" + }, + "devDependencies": { + "@kwooshung/cvlar": "^1.3.4", + "@types/chance": "^1.1.6", + "@types/cli-progress": "^3.11.5", + "@types/lodash-es": "^4.17.12", + "@types/node": "^20.11.0", + "@typescript-eslint/eslint-plugin": "^6.18.1", + "@typescript-eslint/parser": "^6.18.1", + "@vitest/coverage-v8": "^1.1.3", + "algorithms": "^0.10.0", + "chalk": "4", + "chance": "^1.1.11", + "commitlint": "^18.4.4", + "cross-env": "^7.0.3", + "eslint": "^8.56.0", + "eslint-config-prettier": "^9.1.0", + "eslint-plugin-prettier": "^5.1.3", + "husky": "^8.0.3", + "lint-staged": "^15.2.0", + "prettier": "^3.1.1", + "terser": "^5.26.0", + "ts-loader": "^9.5.1", + "typescript": "^5.3.3", + "vite": "^5.0.11", + "vite-plugin-dts": "^3.7.0", + "vitest": "^1.1.3" + }, + "license": "MIT" +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..893f361 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,4838 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + node: + specifier: '>=14.0.0' + version: 21.2.0 + +devDependencies: + '@kwooshung/cvlar': + specifier: ^1.3.4 + version: 1.3.4(node@21.2.0)(typescript@5.3.3) + '@types/chance': + specifier: ^1.1.6 + version: 1.1.6 + '@types/cli-progress': + specifier: ^3.11.5 + version: 3.11.5 + '@types/lodash-es': + specifier: ^4.17.12 + version: 4.17.12 + '@types/node': + specifier: ^20.11.0 + version: 20.11.0 + '@typescript-eslint/eslint-plugin': + specifier: ^6.18.1 + version: 6.18.1(@typescript-eslint/parser@6.18.1)(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': + specifier: ^6.18.1 + version: 6.18.1(eslint@8.56.0)(typescript@5.3.3) + '@vitest/coverage-v8': + specifier: ^1.1.3 + version: 1.1.3(vitest@1.1.3) + algorithms: + specifier: ^0.10.0 + version: 0.10.0 + chalk: + specifier: '4' + version: 4.1.2 + chance: + specifier: ^1.1.11 + version: 1.1.11 + commitlint: + specifier: ^18.4.4 + version: 18.4.4(@types/node@20.11.0)(typescript@5.3.3) + cross-env: + specifier: ^7.0.3 + version: 7.0.3 + eslint: + specifier: ^8.56.0 + version: 8.56.0 + eslint-config-prettier: + specifier: ^9.1.0 + version: 9.1.0(eslint@8.56.0) + eslint-plugin-prettier: + specifier: ^5.1.3 + version: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.1.1) + husky: + specifier: ^8.0.3 + version: 8.0.3 + lint-staged: + specifier: ^15.2.0 + version: 15.2.0 + prettier: + specifier: ^3.1.1 + version: 3.1.1 + terser: + specifier: ^5.26.0 + version: 5.26.0 + ts-loader: + specifier: ^9.5.1 + version: 9.5.1(typescript@5.3.3)(webpack@5.89.0) + typescript: + specifier: ^5.3.3 + version: 5.3.3 + vite: + specifier: ^5.0.11 + version: 5.0.11(@types/node@20.11.0)(terser@5.26.0) + vite-plugin-dts: + specifier: ^3.7.0 + version: 3.7.0(@types/node@20.11.0)(typescript@5.3.3)(vite@5.0.11) + vitest: + specifier: ^1.1.3 + version: 1.1.3(@types/node@20.11.0)(terser@5.26.0) + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: true + + /@babel/code-frame@7.23.5: + resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.23.4 + chalk: 2.4.2 + dev: true + + /@babel/helper-string-parser@7.23.4: + resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/highlight@7.23.4: + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser@7.23.6: + resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/types@7.23.6: + resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.23.4 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true + + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@colors/colors@1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: true + optional: true + + /@commitlint/cli@18.4.4(@types/node@20.11.0)(typescript@5.3.3): + resolution: {integrity: sha512-Ro3wIo//fV3XiV1EkdpHog6huaEyNcUAVrSmtgKqYM5g982wOWmP4FXvEDFwRMVgz878CNBvvCc33dMZ5AQJ/g==} + engines: {node: '>=v18'} + hasBin: true + dependencies: + '@commitlint/format': 18.4.4 + '@commitlint/lint': 18.4.4 + '@commitlint/load': 18.4.4(@types/node@20.11.0)(typescript@5.3.3) + '@commitlint/read': 18.4.4 + '@commitlint/types': 18.4.4 + execa: 5.1.1 + lodash.isfunction: 3.0.9 + resolve-from: 5.0.0 + resolve-global: 1.0.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + dev: true + + /@commitlint/config-validator@18.4.4: + resolution: {integrity: sha512-/QI8KIg/h7O0Eus36fPcEcO3QPBcdXuGfZeCF5m15k0EB2bcU8s6pHNTNEa6xz9PrAefHCL+yzRJj7w20T6Mow==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 18.4.4 + ajv: 8.12.0 + dev: true + + /@commitlint/ensure@18.4.4: + resolution: {integrity: sha512-KjD19p6julB5WrQL+Cd8p+AePwpl1XzGAjB0jnuFMKWtji9L7ucCZUKDstGjlkBZGGzH/nvdB8K+bh5K27EVUg==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 18.4.4 + 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 + dev: true + + /@commitlint/execute-rule@18.4.4: + resolution: {integrity: sha512-a37Nd3bDQydtg9PCLLWM9ZC+GO7X5i4zJvrggJv5jBhaHsXeQ9ZWdO6ODYR+f0LxBXXNYK3geYXJrCWUCP8JEg==} + engines: {node: '>=v18'} + dev: true + + /@commitlint/format@18.4.4: + resolution: {integrity: sha512-2v3V5hVlv0R3pe7p66IX5F7cjeVvGM5JqITRIbBCFvGHPJ/CG74rjTkAu0RBEiIhlk3eOaLjVGq3d5falPkLBA==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 18.4.4 + chalk: 4.1.2 + dev: true + + /@commitlint/is-ignored@18.4.4: + resolution: {integrity: sha512-rXWes9owKBTjfTr6Od7YlflRg4N+ngkOH+dUZhk0qL/XQb26mHz0EgVgdixMVBac1OsohRwJaLmVHX+5F6vfmg==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 18.4.4 + semver: 7.5.4 + dev: true + + /@commitlint/lint@18.4.4: + resolution: {integrity: sha512-SoyQstVxMY5Z4GnFRtRzy+NWYb+yVseXgir+7BxnpB59oH05C9XztRrhDw6OnkNeXhjINTpi1HLnuY7So+CaAQ==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/is-ignored': 18.4.4 + '@commitlint/parse': 18.4.4 + '@commitlint/rules': 18.4.4 + '@commitlint/types': 18.4.4 + dev: true + + /@commitlint/load@18.4.4(@types/node@20.11.0)(typescript@5.3.3): + resolution: {integrity: sha512-RaDIa9qwOw2xRJ3Jr2DBXd14rmnHJIX2XdZF4kmoF1rgsg/+7cvrExLSUNAkQUNimyjCn1b/bKX2Omm+GdY0XQ==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/config-validator': 18.4.4 + '@commitlint/execute-rule': 18.4.4 + '@commitlint/resolve-extends': 18.4.4 + '@commitlint/types': 18.4.4 + chalk: 4.1.2 + cosmiconfig: 8.3.6(typescript@5.3.3) + cosmiconfig-typescript-loader: 5.0.0(@types/node@20.11.0)(cosmiconfig@8.3.6)(typescript@5.3.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + resolve-from: 5.0.0 + transitivePeerDependencies: + - '@types/node' + - typescript + dev: true + + /@commitlint/message@18.4.4: + resolution: {integrity: sha512-lHF95mMDYgAI1LBXveJUyg4eLaMXyOqJccCK3v55ZOEUsMPrDi8upqDjd/NmzWmESYihaOMBTAnxm+6oD1WoDQ==} + engines: {node: '>=v18'} + dev: true + + /@commitlint/parse@18.4.4: + resolution: {integrity: sha512-99G7dyn/OoyNWXJni0Ki0K3aJd01pEb/Im/Id6y4X7PN+kGOahjz2z/cXYYHn7xDdooqFVdiVrVLeChfgpWZ2g==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/types': 18.4.4 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + dev: true + + /@commitlint/read@18.4.4: + resolution: {integrity: sha512-r58JbWky4gAFPea/CZmvlqP9Ehbs+8gSEUqhIJOojKzTc3xlxFnZUDVPcEnnaqzQEEoV6C69VW7xuzdcBlu/FQ==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/top-level': 18.4.4 + '@commitlint/types': 18.4.4 + git-raw-commits: 2.0.11 + minimist: 1.2.8 + dev: true + + /@commitlint/resolve-extends@18.4.4: + resolution: {integrity: sha512-RRpIHSbRnFvmGifVk21Gqazf1QF/yeP+Kkg/e3PlkegcOKd/FGOXp/Kx9cvSO2K7ucSn4GD/oBvgasFoy+NCAw==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/config-validator': 18.4.4 + '@commitlint/types': 18.4.4 + import-fresh: 3.3.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + resolve-global: 1.0.0 + dev: true + + /@commitlint/rules@18.4.4: + resolution: {integrity: sha512-6Uzlsnl/GljEI+80NWjf4ThOfR8NIsbm18IfXYuCEchlwMHSxiuYG4rHSK5DNmG/+MIo8eR5VdQ0gQyt7kWzAA==} + engines: {node: '>=v18'} + dependencies: + '@commitlint/ensure': 18.4.4 + '@commitlint/message': 18.4.4 + '@commitlint/to-lines': 18.4.4 + '@commitlint/types': 18.4.4 + execa: 5.1.1 + dev: true + + /@commitlint/to-lines@18.4.4: + resolution: {integrity: sha512-mwe2Roa59NCz/krniAdCygFabg7+fQCkIhXqBHw00XQ8Y7lw4poZLLxeGI3p3bLpcEOXdqIDrEGLwHmG5lBdwQ==} + engines: {node: '>=v18'} + dev: true + + /@commitlint/top-level@18.4.4: + resolution: {integrity: sha512-PBwW1drgeavl9CadB7IPRUk6rkUP/O8jEkxjlC+ofuh3pw0bzJdAT+Kw7M1Yc9KtTb9xTaqUB8uvRtaybHa/tQ==} + engines: {node: '>=v18'} + dependencies: + find-up: 5.0.0 + dev: true + + /@commitlint/types@18.4.4: + resolution: {integrity: sha512-/FykLtodD8gKs3+VNkAUwofu4LBHankclj+I8fB2jTRvG6PV7k/OUt4P+VbM7ip853qS4F0g7Z6hLNa6JeMcAQ==} + engines: {node: '>=v18'} + dependencies: + chalk: 4.1.2 + dev: true + + /@esbuild/android-arm64@0.19.8: + resolution: {integrity: sha512-B8JbS61bEunhfx8kasogFENgQfr/dIp+ggYXwTqdbMAgGDhRa3AaPpQMuQU0rNxDLECj6FhDzk1cF9WHMVwrtA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.19.8: + resolution: {integrity: sha512-31E2lxlGM1KEfivQl8Yf5aYU/mflz9g06H6S15ITUFQueMFtFjESRMoDSkvMo8thYvLBax+VKTPlpnx+sPicOA==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.19.8: + resolution: {integrity: sha512-rdqqYfRIn4jWOp+lzQttYMa2Xar3OK9Yt2fhOhzFXqg0rVWEfSclJvZq5fZslnz6ypHvVf3CT7qyf0A5pM682A==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.19.8: + resolution: {integrity: sha512-RQw9DemMbIq35Bprbboyf8SmOr4UXsRVxJ97LgB55VKKeJOOdvsIPy0nFyF2l8U+h4PtBx/1kRf0BelOYCiQcw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.19.8: + resolution: {integrity: sha512-3sur80OT9YdeZwIVgERAysAbwncom7b4bCI2XKLjMfPymTud7e/oY4y+ci1XVp5TfQp/bppn7xLw1n/oSQY3/Q==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.19.8: + resolution: {integrity: sha512-WAnPJSDattvS/XtPCTj1tPoTxERjcTpH6HsMr6ujTT+X6rylVe8ggxk8pVxzf5U1wh5sPODpawNicF5ta/9Tmw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.19.8: + resolution: {integrity: sha512-ICvZyOplIjmmhjd6mxi+zxSdpPTKFfyPPQMQTK/w+8eNK6WV01AjIztJALDtwNNfFhfZLux0tZLC+U9nSyA5Zg==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.19.8: + resolution: {integrity: sha512-z1zMZivxDLHWnyGOctT9JP70h0beY54xDDDJt4VpTX+iwA77IFsE1vCXWmprajJGa+ZYSqkSbRQ4eyLCpCmiCQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.19.8: + resolution: {integrity: sha512-H4vmI5PYqSvosPaTJuEppU9oz1dq2A7Mr2vyg5TF9Ga+3+MGgBdGzcyBP7qK9MrwFQZlvNyJrvz6GuCaj3OukQ==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.19.8: + resolution: {integrity: sha512-1a8suQiFJmZz1khm/rDglOc8lavtzEMRo0v6WhPgxkrjcU0LkHj+TwBrALwoz/OtMExvsqbbMI0ChyelKabSvQ==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.19.8: + resolution: {integrity: sha512-fHZWS2JJxnXt1uYJsDv9+b60WCc2RlvVAy1F76qOLtXRO+H4mjt3Tr6MJ5l7Q78X8KgCFudnTuiQRBhULUyBKQ==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.19.8: + resolution: {integrity: sha512-Wy/z0EL5qZYLX66dVnEg9riiwls5IYnziwuju2oUiuxVc+/edvqXa04qNtbrs0Ukatg5HEzqT94Zs7J207dN5Q==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.19.8: + resolution: {integrity: sha512-ETaW6245wK23YIEufhMQ3HSeHO7NgsLx8gygBVldRHKhOlD1oNeNy/P67mIh1zPn2Hr2HLieQrt6tWrVwuqrxg==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.19.8: + resolution: {integrity: sha512-T2DRQk55SgoleTP+DtPlMrxi/5r9AeFgkhkZ/B0ap99zmxtxdOixOMI570VjdRCs9pE4Wdkz7JYrsPvsl7eESg==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.19.8: + resolution: {integrity: sha512-NPxbdmmo3Bk7mbNeHmcCd7R7fptJaczPYBaELk6NcXxy7HLNyWwCyDJ/Xx+/YcNH7Im5dHdx9gZ5xIwyliQCbg==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.19.8: + resolution: {integrity: sha512-lytMAVOM3b1gPypL2TRmZ5rnXl7+6IIk8uB3eLsV1JwcizuolblXRrc5ShPrO9ls/b+RTp+E6gbsuLWHWi2zGg==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.19.8: + resolution: {integrity: sha512-hvWVo2VsXz/8NVt1UhLzxwAfo5sioj92uo0bCfLibB0xlOmimU/DeAEsQILlBQvkhrGjamP0/el5HU76HAitGw==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.19.8: + resolution: {integrity: sha512-/7Y7u77rdvmGTxR83PgaSvSBJCC2L3Kb1M/+dmSIvRvQPXXCuC97QAwMugBNG0yGcbEGfFBH7ojPzAOxfGNkwQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.19.8: + resolution: {integrity: sha512-9Lc4s7Oi98GqFA4HzA/W2JHIYfnXbUYgekUP/Sm4BG9sfLjyv6GKKHKKVs83SMicBF2JwAX6A1PuOLMqpD001w==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.19.8: + resolution: {integrity: sha512-rq6WzBGjSzihI9deW3fC2Gqiak68+b7qo5/3kmB6Gvbh/NYPA0sJhrnp7wgV4bNwjqM+R2AApXGxMO7ZoGhIJg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.19.8: + resolution: {integrity: sha512-AIAbverbg5jMvJznYiGhrd3sumfwWs8572mIJL5NQjJa06P8KfCPWZQ0NwZbPQnbQi9OWSZhFVSUWjjIrn4hSw==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.19.8: + resolution: {integrity: sha512-bfZ0cQ1uZs2PqpulNL5j/3w+GDhP36k1K5c38QdQg+Swy51jFZWWeIkteNsufkQxp986wnqRRsb/bHbY1WQ7TA==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.56.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.23.0 + ignore: 5.3.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.56.0: + resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array@0.11.13: + resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.1 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.1: + resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + dev: true + + /@inquirer/checkbox@1.5.0: + resolution: {integrity: sha512-3cKJkW1vIZAs4NaS0reFsnpAjP0azffYII4I2R7PTI7ZTMg5Y1at4vzXccOH3762b2c2L4drBhpJpf9uiaGNxA==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/core': 5.1.1 + '@inquirer/type': 1.1.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + figures: 3.2.0 + dev: true + + /@inquirer/confirm@2.0.15: + resolution: {integrity: sha512-hj8Q/z7sQXsF0DSpLQZVDhWYGN6KLM/gNjjqGkpKwBzljbQofGjn0ueHADy4HUY+OqDHmXuwk/bY+tZyIuuB0w==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/core': 5.1.1 + '@inquirer/type': 1.1.5 + chalk: 4.1.2 + dev: true + + /@inquirer/core@5.1.1: + resolution: {integrity: sha512-IuJyZQUg75+L5AmopgnzxYrgcU6PJKL0hoIs332G1Gv55CnmZrhG6BzNOeZ5sOsTi1YCGOopw4rYICv74ejMFg==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/type': 1.1.5 + '@types/mute-stream': 0.0.4 + '@types/node': 20.11.0 + '@types/wrap-ansi': 3.0.0 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + cli-spinners: 2.9.2 + cli-width: 4.1.0 + figures: 3.2.0 + mute-stream: 1.0.0 + run-async: 3.0.0 + signal-exit: 4.1.0 + strip-ansi: 6.0.1 + wrap-ansi: 6.2.0 + dev: true + + /@inquirer/editor@1.2.13: + resolution: {integrity: sha512-gBxjqt0B9GLN0j6M/tkEcmcIvB2fo9Cw0f5NRqDTkYyB9AaCzj7qvgG0onQ3GVPbMyMbbP4tWYxrBOaOdKpzNA==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/core': 5.1.1 + '@inquirer/type': 1.1.5 + chalk: 4.1.2 + external-editor: 3.1.0 + dev: true + + /@inquirer/expand@1.1.14: + resolution: {integrity: sha512-yS6fJ8jZYAsxdxuw2c8XTFMTvMR1NxZAw3LxDaFnqh7BZ++wTQ6rSp/2gGJhMacdZ85osb+tHxjVgx7F+ilv5g==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/core': 5.1.1 + '@inquirer/type': 1.1.5 + chalk: 4.1.2 + figures: 3.2.0 + dev: true + + /@inquirer/input@1.2.14: + resolution: {integrity: sha512-tISLGpUKXixIQue7jypNEShrdzJoLvEvZOJ4QRsw5XTfrIYfoWFqAjMQLerGs9CzR86yAI89JR6snHmKwnNddw==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/core': 5.1.1 + '@inquirer/type': 1.1.5 + chalk: 4.1.2 + dev: true + + /@inquirer/password@1.1.14: + resolution: {integrity: sha512-vL2BFxfMo8EvuGuZYlryiyAB3XsgtbxOcFs4H9WI9szAS/VZCAwdVqs8rqEeaAf/GV/eZOghIOYxvD91IsRWSg==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/input': 1.2.14 + '@inquirer/type': 1.1.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + dev: true + + /@inquirer/prompts@3.3.0: + resolution: {integrity: sha512-BBCqdSnhNs+WziSIo4f/RNDu6HAj4R/Q5nMgJb5MNPFX8sJGCvj9BoALdmR0HTWXyDS7TO8euKj6W6vtqCQG7A==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/checkbox': 1.5.0 + '@inquirer/confirm': 2.0.15 + '@inquirer/core': 5.1.1 + '@inquirer/editor': 1.2.13 + '@inquirer/expand': 1.1.14 + '@inquirer/input': 1.2.14 + '@inquirer/password': 1.1.14 + '@inquirer/rawlist': 1.2.14 + '@inquirer/select': 1.3.1 + dev: true + + /@inquirer/rawlist@1.2.14: + resolution: {integrity: sha512-xIYmDpYgfz2XGCKubSDLKEvadkIZAKbehHdWF082AyC2I4eHK44RUfXaoOAqnbqItZq4KHXS6jDJ78F2BmQvxg==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/core': 5.1.1 + '@inquirer/type': 1.1.5 + chalk: 4.1.2 + dev: true + + /@inquirer/select@1.3.1: + resolution: {integrity: sha512-EgOPHv7XOHEqiBwBJTyiMg9r57ySyW4oyYCumGp+pGyOaXQaLb2kTnccWI6NFd9HSi5kDJhF7YjA+3RfMQJ2JQ==} + engines: {node: '>=14.18.0'} + dependencies: + '@inquirer/core': 5.1.1 + '@inquirer/type': 1.1.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + figures: 3.2.0 + dev: true + + /@inquirer/type@1.1.5: + resolution: {integrity: sha512-wmwHvHozpPo4IZkkNtbYenem/0wnfI6hvOcGKmPEa0DwuaH5XUQzFqy6OpEpjEegZMhYIk8HDYITI16BPLtrRA==} + engines: {node: '>=14.18.0'} + dev: true + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.20 + dev: true + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/source-map@0.3.5: + resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.20 + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.20: + resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@kwooshung/cvlar@1.3.4(node@21.2.0)(typescript@5.3.3): + resolution: {integrity: sha512-zIZ2/LaYByna6tGHUs6R02CVPehG5fr8YexpTwOo+XS5KdUrZY7ykHn6dPx/KTC3R+kEwVdxvFiZvfB4RW4QAQ==} + hasBin: true + peerDependencies: + node: '>=14.0.0' + dependencies: + '@inquirer/editor': 1.2.13 + '@inquirer/prompts': 3.3.0 + '@octokit/rest': 20.0.2 + '@translate-tools/core': 1.0.0 + boxen: 7.1.1 + cli-progress: 3.12.0 + cli-table3: 0.6.3 + cosmiconfig: 9.0.0(typescript@5.3.3) + detect-indent: 7.0.1 + iconv-lite: 0.6.3 + lodash-es: 4.17.21 + node: 21.2.0 + node-fetch: 3.3.2 + ora: 8.0.1 + package-json: 8.1.1 + picocolors: 1.0.0 + semver: 7.5.4 + transitivePeerDependencies: + - debug + - typescript + dev: true + + /@microsoft/api-extractor-model@7.28.3(@types/node@20.11.0): + resolution: {integrity: sha512-wT/kB2oDbdZXITyDh2SQLzaWwTOFbV326fP0pUwNW00WeliARs0qjmXBWmGWardEzp2U3/axkO3Lboqun6vrig==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.62.0(@types/node@20.11.0) + transitivePeerDependencies: + - '@types/node' + dev: true + + /@microsoft/api-extractor@7.39.0(@types/node@20.11.0): + resolution: {integrity: sha512-PuXxzadgnvp+wdeZFPonssRAj/EW4Gm4s75TXzPk09h3wJ8RS3x7typf95B4vwZRrPTQBGopdUl+/vHvlPdAcg==} + hasBin: true + dependencies: + '@microsoft/api-extractor-model': 7.28.3(@types/node@20.11.0) + '@microsoft/tsdoc': 0.14.2 + '@microsoft/tsdoc-config': 0.16.2 + '@rushstack/node-core-library': 3.62.0(@types/node@20.11.0) + '@rushstack/rig-package': 0.5.1 + '@rushstack/ts-command-line': 4.17.1 + colors: 1.2.5 + lodash: 4.17.21 + resolve: 1.22.8 + semver: 7.5.4 + source-map: 0.6.1 + typescript: 5.3.3 + transitivePeerDependencies: + - '@types/node' + dev: true + + /@microsoft/tsdoc-config@0.16.2: + resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + dependencies: + '@microsoft/tsdoc': 0.14.2 + ajv: 6.12.6 + jju: 1.4.0 + resolve: 1.19.0 + dev: true + + /@microsoft/tsdoc@0.14.2: + resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.15.0 + dev: true + + /@octokit/auth-token@4.0.0: + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + dev: true + + /@octokit/core@5.0.2: + resolution: {integrity: sha512-cZUy1gUvd4vttMic7C0lwPed8IYXWYp8kHIMatyhY8t8n3Cpw2ILczkV5pGMPqef7v0bLo0pOHrEHarsau2Ydg==} + engines: {node: '>= 18'} + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.0.2 + '@octokit/request': 8.1.6 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.4.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.1 + dev: true + + /@octokit/endpoint@9.0.4: + resolution: {integrity: sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==} + engines: {node: '>= 18'} + dependencies: + '@octokit/types': 12.4.0 + universal-user-agent: 6.0.1 + dev: true + + /@octokit/graphql@7.0.2: + resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==} + engines: {node: '>= 18'} + dependencies: + '@octokit/request': 8.1.6 + '@octokit/types': 12.4.0 + universal-user-agent: 6.0.1 + dev: true + + /@octokit/openapi-types@19.1.0: + resolution: {integrity: sha512-6G+ywGClliGQwRsjvqVYpklIfa7oRPA0vyhPQG/1Feh+B+wU0vGH1JiJ5T25d3g1JZYBHzR2qefLi9x8Gt+cpw==} + dev: true + + /@octokit/plugin-paginate-rest@9.1.5(@octokit/core@5.0.2): + resolution: {integrity: sha512-WKTQXxK+bu49qzwv4qKbMMRXej1DU2gq017euWyKVudA6MldaSSQuxtz+vGbhxV4CjxpUxjZu6rM2wfc1FiWVg==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + dependencies: + '@octokit/core': 5.0.2 + '@octokit/types': 12.4.0 + dev: true + + /@octokit/plugin-request-log@4.0.0(@octokit/core@5.0.2): + resolution: {integrity: sha512-2uJI1COtYCq8Z4yNSnM231TgH50bRkheQ9+aH8TnZanB6QilOnx8RMD2qsnamSOXtDj0ilxvevf5fGsBhBBzKA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + dependencies: + '@octokit/core': 5.0.2 + dev: true + + /@octokit/plugin-rest-endpoint-methods@10.2.0(@octokit/core@5.0.2): + resolution: {integrity: sha512-ePbgBMYtGoRNXDyKGvr9cyHjQ163PbwD0y1MkDJCpkO2YH4OeXX40c4wYHKikHGZcpGPbcRLuy0unPUuafco8Q==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + dependencies: + '@octokit/core': 5.0.2 + '@octokit/types': 12.4.0 + dev: true + + /@octokit/request-error@5.0.1: + resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==} + engines: {node: '>= 18'} + dependencies: + '@octokit/types': 12.4.0 + deprecation: 2.3.1 + once: 1.4.0 + dev: true + + /@octokit/request@8.1.6: + resolution: {integrity: sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==} + engines: {node: '>= 18'} + dependencies: + '@octokit/endpoint': 9.0.4 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.4.0 + universal-user-agent: 6.0.1 + dev: true + + /@octokit/rest@20.0.2: + resolution: {integrity: sha512-Ux8NDgEraQ/DMAU1PlAohyfBBXDwhnX2j33Z1nJNziqAfHi70PuxkFYIcIt8aIAxtRE7KVuKp8lSR8pA0J5iOQ==} + engines: {node: '>= 18'} + dependencies: + '@octokit/core': 5.0.2 + '@octokit/plugin-paginate-rest': 9.1.5(@octokit/core@5.0.2) + '@octokit/plugin-request-log': 4.0.0(@octokit/core@5.0.2) + '@octokit/plugin-rest-endpoint-methods': 10.2.0(@octokit/core@5.0.2) + dev: true + + /@octokit/types@12.4.0: + resolution: {integrity: sha512-FLWs/AvZllw/AGVs+nJ+ELCDZZJk+kY0zMen118xhL2zD0s1etIUHm1odgjP7epxYU1ln7SZxEUWYop5bhsdgQ==} + dependencies: + '@octokit/openapi-types': 19.1.0 + dev: true + + /@pkgr/core@0.1.0: + resolution: {integrity: sha512-Zwq5OCzuwJC2jwqmpEQt7Ds1DTi6BWSwoGkbb1n9pO3hzb35BoJELx7c0T23iDkBGkh2e7tvOtjF3tr3OaQHDQ==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dev: true + + /@pnpm/config.env-replace@1.1.0: + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + dev: true + + /@pnpm/network.ca-file@1.0.2: + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + dependencies: + graceful-fs: 4.2.10 + dev: true + + /@pnpm/npm-conf@2.2.2: + resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} + engines: {node: '>=12'} + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + dev: true + + /@rollup/pluginutils@5.1.0: + resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} + engines: {node: '>=14.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 + peerDependenciesMeta: + rollup: + optional: true + dependencies: + '@types/estree': 1.0.5 + estree-walker: 2.0.2 + picomatch: 2.3.1 + dev: true + + /@rollup/rollup-android-arm-eabi@4.6.1: + resolution: {integrity: sha512-0WQ0ouLejaUCRsL93GD4uft3rOmB8qoQMU05Kb8CmMtMBe7XUDLAltxVZI1q6byNqEtU7N1ZX1Vw5lIpgulLQA==} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-android-arm64@4.6.1: + resolution: {integrity: sha512-1TKm25Rn20vr5aTGGZqo6E4mzPicCUD79k17EgTLAsXc1zysyi4xXKACfUbwyANEPAEIxkzwue6JZ+stYzWUTA==} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-arm64@4.6.1: + resolution: {integrity: sha512-cEXJQY/ZqMACb+nxzDeX9IPLAg7S94xouJJCNVE5BJM8JUEP4HeTF+ti3cmxWeSJo+5D+o8Tc0UAWUkfENdeyw==} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-darwin-x64@4.6.1: + resolution: {integrity: sha512-LoSU9Xu56isrkV2jLldcKspJ7sSXmZWkAxg7sW/RfF7GS4F5/v4EiqKSMCFbZtDu2Nc1gxxFdQdKwkKS4rwxNg==} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm-gnueabihf@4.6.1: + resolution: {integrity: sha512-EfI3hzYAy5vFNDqpXsNxXcgRDcFHUWSx5nnRSCKwXuQlI5J9dD84g2Usw81n3FLBNsGCegKGwwTVsSKK9cooSQ==} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-gnu@4.6.1: + resolution: {integrity: sha512-9lhc4UZstsegbNLhH0Zu6TqvDfmhGzuCWtcTFXY10VjLLUe4Mr0Ye2L3rrtHaDd/J5+tFMEuo5LTCSCMXWfUKw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-arm64-musl@4.6.1: + resolution: {integrity: sha512-FfoOK1yP5ksX3wwZ4Zk1NgyGHZyuRhf99j64I5oEmirV8EFT7+OhUZEnP+x17lcP/QHJNWGsoJwrz4PJ9fBEXw==} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-gnu@4.6.1: + resolution: {integrity: sha512-DNGZvZDO5YF7jN5fX8ZqmGLjZEXIJRdJEdTFMhiyXqyXubBa0WVLDWSNlQ5JR2PNgDbEV1VQowhVRUh+74D+RA==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-linux-x64-musl@4.6.1: + resolution: {integrity: sha512-RkJVNVRM+piYy87HrKmhbexCHg3A6Z6MU0W9GHnJwBQNBeyhCJG9KDce4SAMdicQnpURggSvtbGo9xAWOfSvIQ==} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-arm64-msvc@4.6.1: + resolution: {integrity: sha512-v2FVT6xfnnmTe3W9bJXl6r5KwJglMK/iRlkKiIFfO6ysKs0rDgz7Cwwf3tjldxQUrHL9INT/1r4VA0n9L/F1vQ==} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-ia32-msvc@4.6.1: + resolution: {integrity: sha512-YEeOjxRyEjqcWphH9dyLbzgkF8wZSKAKUkldRY6dgNR5oKs2LZazqGB41cWJ4Iqqcy9/zqYgmzBkRoVz3Q9MLw==} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rollup/rollup-win32-x64-msvc@4.6.1: + resolution: {integrity: sha512-0zfTlFAIhgz8V2G8STq8toAjsYYA6eci1hnXuyOTUFnymrtJwnS6uGKiv3v5UrPZkBlamLvrLV2iiaeqCKzb0A==} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@rushstack/node-core-library@3.62.0(@types/node@20.11.0): + resolution: {integrity: sha512-88aJn2h8UpSvdwuDXBv1/v1heM6GnBf3RjEy6ZPP7UnzHNCqOHA2Ut+ScYUbXcqIdfew9JlTAe3g+cnX9xQ/Aw==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 20.11.0 + colors: 1.2.5 + fs-extra: 7.0.1 + import-lazy: 4.0.0 + jju: 1.4.0 + resolve: 1.22.8 + semver: 7.5.4 + z-schema: 5.0.5 + dev: true + + /@rushstack/rig-package@0.5.1: + resolution: {integrity: sha512-pXRYSe29TjRw7rqxD4WS3HN/sRSbfr+tJs4a9uuaSIBAITbUggygdhuG0VrO0EO+QqH91GhYMN4S6KRtOEmGVA==} + dependencies: + resolve: 1.22.8 + strip-json-comments: 3.1.1 + dev: true + + /@rushstack/ts-command-line@4.17.1: + resolution: {integrity: sha512-2jweO1O57BYP5qdBGl6apJLB+aRIn5ccIRTPDyULh0KMwVzFqWtw6IZWt1qtUoZD/pD2RNkIOosH6Cq45rIYeg==} + dependencies: + '@types/argparse': 1.0.38 + argparse: 1.0.10 + colors: 1.2.5 + string-argv: 0.3.2 + dev: true + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@sindresorhus/is@5.6.0: + resolution: {integrity: sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==} + engines: {node: '>=14.16'} + dev: true + + /@szmarczak/http-timer@5.0.1: + resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} + engines: {node: '>=14.16'} + dependencies: + defer-to-connect: 2.0.1 + dev: true + + /@translate-tools/core@1.0.0: + resolution: {integrity: sha512-FmK4f0SZl81uVIslgNABkZYqticpVyWSMf+JwKwSd/1CDdZXRyYN0YacZdMd8Rcg0pF80zaPOkW6FgvUR8e1vw==} + dependencies: + '@xmldom/xmldom': 0.8.10 + axios: 0.23.0 + lodash: 4.17.21 + query-string: 6.14.1 + xpath: 0.0.32 + transitivePeerDependencies: + - debug + dev: true + + /@types/argparse@1.0.38: + resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + dev: true + + /@types/chance@1.1.6: + resolution: {integrity: sha512-V+pm3stv1Mvz8fSKJJod6CglNGVqEQ6OyuqitoDkWywEODM/eJd1eSuIp9xt6DrX8BWZ2eDSIzbw1tPCUTvGbQ==} + dev: true + + /@types/cli-progress@3.11.5: + resolution: {integrity: sha512-D4PbNRbviKyppS5ivBGyFO29POlySLmA2HyUFE4p5QGazAMM3CwkKWcvTl8gvElSuxRh6FPKL8XmidX873ou4g==} + dependencies: + '@types/node': 20.11.0 + dev: true + + /@types/eslint-scope@3.7.7: + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + dependencies: + '@types/eslint': 8.44.8 + '@types/estree': 1.0.5 + dev: true + + /@types/eslint@8.44.8: + resolution: {integrity: sha512-4K8GavROwhrYl2QXDXm0Rv9epkA8GBFu0EI+XrrnnuCl7u8CWBRusX7fXJfanhZTDWSAL24gDI/UqXyUM0Injw==} + dependencies: + '@types/estree': 1.0.5 + '@types/json-schema': 7.0.15 + dev: true + + /@types/estree@1.0.5: + resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + dev: true + + /@types/http-cache-semantics@4.0.4: + resolution: {integrity: sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==} + dev: true + + /@types/istanbul-lib-coverage@2.0.6: + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/lodash-es@4.17.12: + resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} + dependencies: + '@types/lodash': 4.14.202 + dev: true + + /@types/lodash@4.14.202: + resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==} + dev: true + + /@types/minimist@1.2.5: + resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} + dev: true + + /@types/mute-stream@0.0.4: + resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} + dependencies: + '@types/node': 20.11.0 + dev: true + + /@types/node@20.10.6: + resolution: {integrity: sha512-Vac8H+NlRNNlAmDfGUP7b5h/KA+AtWIzuXy0E6OyP8f1tCLYAtPvKRRDJjAPqhpCb0t6U2j7/xqAuLEebW2kiw==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/node@20.11.0: + resolution: {integrity: sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/normalize-package-data@2.4.4: + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + dev: true + + /@types/semver@7.5.6: + resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} + dev: true + + /@types/wrap-ansi@3.0.0: + resolution: {integrity: sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==} + dev: true + + /@typescript-eslint/eslint-plugin@6.18.1(@typescript-eslint/parser@6.18.1)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 6.18.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.18.1 + '@typescript-eslint/type-utils': 6.18.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.18.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.18.1 + debug: 4.3.4 + eslint: 8.56.0 + graphemer: 1.4.0 + ignore: 5.3.0 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.18.1(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.18.1 + '@typescript-eslint/types': 6.18.1 + '@typescript-eslint/typescript-estree': 6.18.1(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.18.1 + debug: 4.3.4 + eslint: 8.56.0 + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.18.1: + resolution: {integrity: sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.18.1 + '@typescript-eslint/visitor-keys': 6.18.1 + dev: true + + /@typescript-eslint/type-utils@6.18.1(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.18.1(typescript@5.3.3) + '@typescript-eslint/utils': 6.18.1(eslint@8.56.0)(typescript@5.3.3) + debug: 4.3.4 + eslint: 8.56.0 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.18.1: + resolution: {integrity: sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.18.1(typescript@5.3.3): + resolution: {integrity: sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.18.1 + '@typescript-eslint/visitor-keys': 6.18.1 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.18.1(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.6 + '@typescript-eslint/scope-manager': 6.18.1 + '@typescript-eslint/types': 6.18.1 + '@typescript-eslint/typescript-estree': 6.18.1(typescript@5.3.3) + eslint: 8.56.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.18.1: + resolution: {integrity: sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.18.1 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /@vitest/coverage-v8@1.1.3(vitest@1.1.3): + resolution: {integrity: sha512-Uput7t3eIcbSTOTQBzGtS+0kah96bX+szW9qQrLeGe3UmgL2Akn8POnyC2lH7XsnREZOds9aCUTxgXf+4HX5RA==} + peerDependencies: + vitest: ^1.0.0 + dependencies: + '@ampproject/remapping': 2.2.1 + '@bcoe/v8-coverage': 0.2.3 + debug: 4.3.4 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.6 + magic-string: 0.30.5 + magicast: 0.3.2 + picocolors: 1.0.0 + std-env: 3.7.0 + test-exclude: 6.0.0 + v8-to-istanbul: 9.2.0 + vitest: 1.1.3(@types/node@20.11.0)(terser@5.26.0) + transitivePeerDependencies: + - supports-color + dev: true + + /@vitest/expect@1.1.3: + resolution: {integrity: sha512-MnJqsKc1Ko04lksF9XoRJza0bGGwTtqfbyrsYv5on4rcEkdo+QgUdITenBQBUltKzdxW7K3rWh+nXRULwsdaVg==} + dependencies: + '@vitest/spy': 1.1.3 + '@vitest/utils': 1.1.3 + chai: 4.4.0 + dev: true + + /@vitest/runner@1.1.3: + resolution: {integrity: sha512-Va2XbWMnhSdDEh/OFxyUltgQuuDRxnarK1hW5QNN4URpQrqq6jtt8cfww/pQQ4i0LjoYxh/3bYWvDFlR9tU73g==} + dependencies: + '@vitest/utils': 1.1.3 + p-limit: 5.0.0 + pathe: 1.1.1 + dev: true + + /@vitest/snapshot@1.1.3: + resolution: {integrity: sha512-U0r8pRXsLAdxSVAyGNcqOU2H3Z4Y2dAAGGelL50O0QRMdi1WWeYHdrH/QWpN1e8juWfVKsb8B+pyJwTC+4Gy9w==} + dependencies: + magic-string: 0.30.5 + pathe: 1.1.1 + pretty-format: 29.7.0 + dev: true + + /@vitest/spy@1.1.3: + resolution: {integrity: sha512-Ec0qWyGS5LhATFQtldvChPTAHv08yHIOZfiNcjwRQbFPHpkih0md9KAbs7TfeIfL7OFKoe7B/6ukBTqByubXkQ==} + dependencies: + tinyspy: 2.2.0 + dev: true + + /@vitest/utils@1.1.3: + resolution: {integrity: sha512-Dyt3UMcdElTll2H75vhxfpZu03uFpXRCHxWnzcrFjZxT1kTbq8ALUYIeBgGolo1gldVdI0YSlQRacsqxTwNqwg==} + dependencies: + diff-sequences: 29.6.3 + estree-walker: 3.0.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + + /@volar/language-core@1.11.1: + resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} + dependencies: + '@volar/source-map': 1.11.1 + dev: true + + /@volar/source-map@1.11.1: + resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==} + dependencies: + muggle-string: 0.3.1 + dev: true + + /@volar/typescript@1.11.1: + resolution: {integrity: sha512-iU+t2mas/4lYierSnoFOeRFQUhAEMgsFuQxoxvwn5EdQopw43j+J27a4lt9LMInx1gLJBC6qL14WYGlgymaSMQ==} + dependencies: + '@volar/language-core': 1.11.1 + path-browserify: 1.0.1 + dev: true + + /@vue/compiler-core@3.4.5: + resolution: {integrity: sha512-Daka7P1z2AgKjzuueWXhwzIsKu0NkLB6vGbNVEV2iJ8GJTrzraZo/Sk4GWCMRtd/qVi3zwnk+Owbd/xSZbwHtQ==} + dependencies: + '@babel/parser': 7.23.6 + '@vue/shared': 3.4.5 + entities: 4.5.0 + estree-walker: 2.0.2 + source-map-js: 1.0.2 + dev: true + + /@vue/compiler-dom@3.4.5: + resolution: {integrity: sha512-J8YlxknJVd90SXFJ4HwGANSAXsx5I0lK30sO/zvYV7s5gXf7gZR7r/1BmZ2ju7RGH1lnc6bpBc6nL61yW+PsAQ==} + dependencies: + '@vue/compiler-core': 3.4.5 + '@vue/shared': 3.4.5 + dev: true + + /@vue/language-core@1.8.27(typescript@5.3.3): + resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.4.5 + '@vue/shared': 3.4.5 + computeds: 0.0.1 + minimatch: 9.0.3 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + typescript: 5.3.3 + vue-template-compiler: 2.7.16 + dev: true + + /@vue/shared@3.4.5: + resolution: {integrity: sha512-6XptuzlMvN4l4cDnDw36pdGEV+9njYkQ1ZE0Q6iZLwrKefKaOJyiFmcP3/KBDHbt72cJZGtllAc1GaHe6XGAyg==} + dev: true + + /@webassemblyjs/ast@1.11.6: + resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} + dependencies: + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + dev: true + + /@webassemblyjs/floating-point-hex-parser@1.11.6: + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} + dev: true + + /@webassemblyjs/helper-api-error@1.11.6: + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} + dev: true + + /@webassemblyjs/helper-buffer@1.11.6: + resolution: {integrity: sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==} + dev: true + + /@webassemblyjs/helper-numbers@1.11.6: + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/helper-wasm-bytecode@1.11.6: + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} + dev: true + + /@webassemblyjs/helper-wasm-section@1.11.6: + resolution: {integrity: sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + dev: true + + /@webassemblyjs/ieee754@1.11.6: + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} + dependencies: + '@xtuc/ieee754': 1.2.0 + dev: true + + /@webassemblyjs/leb128@1.11.6: + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} + dependencies: + '@xtuc/long': 4.2.2 + dev: true + + /@webassemblyjs/utf8@1.11.6: + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} + dev: true + + /@webassemblyjs/wasm-edit@1.11.6: + resolution: {integrity: sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-opt': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + '@webassemblyjs/wast-printer': 1.11.6 + dev: true + + /@webassemblyjs/wasm-gen@1.11.6: + resolution: {integrity: sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: true + + /@webassemblyjs/wasm-opt@1.11.6: + resolution: {integrity: sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + dev: true + + /@webassemblyjs/wasm-parser@1.11.6: + resolution: {integrity: sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 + dev: true + + /@webassemblyjs/wast-printer@1.11.6: + resolution: {integrity: sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==} + dependencies: + '@webassemblyjs/ast': 1.11.6 + '@xtuc/long': 4.2.2 + dev: true + + /@xmldom/xmldom@0.8.10: + resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==} + engines: {node: '>=10.0.0'} + dev: true + + /@xtuc/ieee754@1.2.0: + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + dev: true + + /@xtuc/long@4.2.2: + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + dev: true + + /JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + dev: true + + /acorn-import-assertions@1.9.0(acorn@8.11.2): + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} + peerDependencies: + acorn: ^8 + dependencies: + acorn: 8.11.2 + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.2): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.2 + dev: true + + /acorn-walk@8.3.1: + resolution: {integrity: sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.11.2: + resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /ajv-keywords@3.5.2(ajv@6.12.6): + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + dependencies: + ajv: 6.12.6 + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + dev: true + + /algorithms@0.10.0: + resolution: {integrity: sha512-f5X+lDALkG6V4Y0IWrOLEEJ8GGW2enbaGSaJwcqddk4irIvzULkNMPqnTUQlRG/0eDdFc7agRhtfPmbFmuntgg==} + dev: true + + /ansi-align@3.0.1: + resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} + dependencies: + string-width: 4.2.3 + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-escapes@6.2.0: + resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} + engines: {node: '>=14.16'} + dependencies: + type-fest: 3.13.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /arrify@1.0.1: + resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==} + engines: {node: '>=0.10.0'} + dev: true + + /assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + + /axios@0.23.0: + resolution: {integrity: sha512-NmvAE4i0YAv5cKq8zlDoPd1VLKAqX5oLuZKs8xkJa4qi6RGn0uhCYFjWtHHC9EM/MwOwYWOs53W+V0aqEXq1sg==} + dependencies: + follow-redirects: 1.15.4 + transitivePeerDependencies: + - debug + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /before-after-hook@2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + dev: true + + /boxen@7.1.1: + resolution: {integrity: sha512-2hCgjEmP8YLWQ130n2FerGv7rYpfBmnmp9Uy2Le1vge6X3gZIfSmEzP5QTDElFxcvVcXlEn8Aq6MU/PZygIOog==} + engines: {node: '>=14.16'} + dependencies: + ansi-align: 3.0.1 + camelcase: 7.0.1 + chalk: 5.3.0 + cli-boxes: 3.0.0 + string-width: 5.1.2 + type-fest: 2.19.0 + widest-line: 4.0.1 + wrap-ansi: 8.1.0 + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.22.1: + resolution: {integrity: sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001565 + electron-to-chromium: 1.4.600 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.22.1) + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + dev: true + + /cacheable-lookup@7.0.0: + resolution: {integrity: sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==} + engines: {node: '>=14.16'} + dev: true + + /cacheable-request@10.2.14: + resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} + engines: {node: '>=14.16'} + dependencies: + '@types/http-cache-semantics': 4.0.4 + get-stream: 6.0.1 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + mimic-response: 4.0.0 + normalize-url: 8.0.0 + responselike: 3.0.0 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase-keys@6.2.2: + resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + map-obj: 4.3.0 + quick-lru: 4.0.1 + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@7.0.1: + resolution: {integrity: sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw==} + engines: {node: '>=14.16'} + dev: true + + /caniuse-lite@1.0.30001565: + resolution: {integrity: sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==} + dev: true + + /chai@4.4.0: + resolution: {integrity: sha512-x9cHNq1uvkCdU+5xTkNh5WtgD4e4yDFCsp9jVc7N7qVeKeftv3gO/ZrviX5d+3ZfxdYnZXZYujjRInu1RogU6A==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.3 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /chance@1.1.11: + resolution: {integrity: sha512-kqTg3WWywappJPqtgrdvbA380VoXO2eu9VCV895JgbyHsaErXdyHK9LOZ911OvAk6L0obK7kDk9CGs8+oBawVA==} + dev: true + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: true + + /check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /chrome-trace-event@1.0.3: + resolution: {integrity: sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==} + engines: {node: '>=6.0'} + dev: true + + /cli-boxes@3.0.0: + resolution: {integrity: sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==} + engines: {node: '>=10'} + dev: true + + /cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + restore-cursor: 4.0.0 + dev: true + + /cli-progress@3.12.0: + resolution: {integrity: sha512-tRkV3HJ1ASwm19THiiLIXLO7Im7wlTuKnvkYaTkyoAPefqjNg7W7DHKUlGRxy9vxDvbyCYQkQozvptuMkGCg8A==} + engines: {node: '>=4'} + dependencies: + string-width: 4.2.3 + dev: true + + /cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + dev: true + + /cli-table3@0.6.3: + resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + dev: true + + /cli-truncate@4.0.0: + resolution: {integrity: sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==} + engines: {node: '>=18'} + dependencies: + slice-ansi: 5.0.0 + string-width: 7.0.0 + dev: true + + /cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: true + + /colors@1.2.5: + resolution: {integrity: sha512-erNRLao/Y3Fv54qUa0LBB+//Uf3YwMUmdJinN20yMXm9zdKKqH9wt7R9IIVZ+K7ShzfpLV/Zg8+VyrBJYB4lpg==} + engines: {node: '>=0.1.90'} + dev: true + + /commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + dev: true + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: true + + /commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + requiresBuild: true + dev: true + optional: true + + /commitlint@18.4.4(@types/node@20.11.0)(typescript@5.3.3): + resolution: {integrity: sha512-O9ubyj1HKvaah/NGG76S6BPNb2J4I+17qYfGcnK7wtqXWEQ6dv/nZqydpA14PHxlpEmItEhjhqvQrnw9Q4bYpA==} + engines: {node: '>=v18'} + hasBin: true + dependencies: + '@commitlint/cli': 18.4.4(@types/node@20.11.0)(typescript@5.3.3) + '@commitlint/types': 18.4.4 + transitivePeerDependencies: + - '@types/node' + - typescript + dev: true + + /compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + dev: true + + /computeds@0.0.1: + resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + dev: true + + /conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + dependencies: + compare-func: 2.0.0 + dev: true + + /conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /cosmiconfig-typescript-loader@5.0.0(@types/node@20.11.0)(cosmiconfig@8.3.6)(typescript@5.3.3): + resolution: {integrity: sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==} + engines: {node: '>=v16'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=8.2' + typescript: '>=4' + dependencies: + '@types/node': 20.11.0 + cosmiconfig: 8.3.6(typescript@5.3.3) + jiti: 1.21.0 + typescript: 5.3.3 + dev: true + + /cosmiconfig@8.3.6(typescript@5.3.3): + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + typescript: 5.3.3 + dev: true + + /cosmiconfig@9.0.0(typescript@5.3.3): + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + typescript: 5.3.3 + dev: true + + /cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + dependencies: + cross-spawn: 7.0.3 + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /dargs@7.0.0: + resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==} + engines: {node: '>=8'} + dev: true + + /data-uri-to-buffer@4.0.1: + resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} + engines: {node: '>= 12'} + dev: true + + /de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /decamelize-keys@1.1.1: + resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} + engines: {node: '>=0.10.0'} + dependencies: + decamelize: 1.2.0 + map-obj: 1.0.1 + dev: true + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: true + + /decode-uri-component@0.2.2: + resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} + engines: {node: '>=0.10'} + dev: true + + /decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + dependencies: + mimic-response: 3.1.0 + dev: true + + /deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + dev: true + + /deprecation@2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + dev: true + + /detect-indent@7.0.1: + resolution: {integrity: sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==} + engines: {node: '>=12.20'} + dev: true + + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + dependencies: + is-obj: 2.0.0 + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /electron-to-chromium@1.4.600: + resolution: {integrity: sha512-KD6CWjf1BnQG+NsXuyiTDDT1eV13sKuYsOUioXkQweYTQIbgHkXPry9K7M+7cKtYHnSUPitVaLrXYB1jTkkYrw==} + dev: true + + /emoji-regex@10.3.0: + resolution: {integrity: sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} + engines: {node: '>=10.13.0'} + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + dev: true + + /entities@4.5.0: + resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} + engines: {node: '>=0.12'} + dev: true + + /env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-module-lexer@1.4.1: + resolution: {integrity: sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==} + dev: true + + /esbuild@0.19.8: + resolution: {integrity: sha512-l7iffQpT2OrZfH2rXIp7/FkmaeZM0vxbxN9KfiCwGYuZqzMg/JdvX26R31Zxn/Pxvsrg3Y9N6XTcnknqDyyv4w==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.19.8 + '@esbuild/android-arm64': 0.19.8 + '@esbuild/android-x64': 0.19.8 + '@esbuild/darwin-arm64': 0.19.8 + '@esbuild/darwin-x64': 0.19.8 + '@esbuild/freebsd-arm64': 0.19.8 + '@esbuild/freebsd-x64': 0.19.8 + '@esbuild/linux-arm': 0.19.8 + '@esbuild/linux-arm64': 0.19.8 + '@esbuild/linux-ia32': 0.19.8 + '@esbuild/linux-loong64': 0.19.8 + '@esbuild/linux-mips64el': 0.19.8 + '@esbuild/linux-ppc64': 0.19.8 + '@esbuild/linux-riscv64': 0.19.8 + '@esbuild/linux-s390x': 0.19.8 + '@esbuild/linux-x64': 0.19.8 + '@esbuild/netbsd-x64': 0.19.8 + '@esbuild/openbsd-x64': 0.19.8 + '@esbuild/sunos-x64': 0.19.8 + '@esbuild/win32-arm64': 0.19.8 + '@esbuild/win32-ia32': 0.19.8 + '@esbuild/win32-x64': 0.19.8 + dev: true + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /eslint-config-prettier@9.1.0(eslint@8.56.0): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.56.0 + dev: true + + /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.1.1): + resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.56.0 + eslint-config-prettier: 9.1.0(eslint@8.56.0) + prettier: 3.1.1 + prettier-linter-helpers: 1.0.0 + synckit: 0.8.8 + dev: true + + /eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.56.0: + resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.56.0 + '@humanwhocodes/config-array': 0.11.13 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.23.0 + graphemer: 1.4.0 + ignore: 5.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.2 + acorn-jsx: 5.3.2(acorn@8.11.2) + eslint-visitor-keys: 3.4.3 + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /estree-walker@2.0.2: + resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + dev: true + + /estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + dependencies: + '@types/estree': 1.0.5 + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + dev: true + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: true + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.15.0: + resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + dependencies: + reusify: 1.0.4 + dev: true + + /fetch-blob@3.2.0: + resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==} + engines: {node: ^12.20 || >= 14.13} + dependencies: + node-domexception: 1.0.0 + web-streams-polyfill: 3.3.2 + dev: true + + /figures@3.2.0: + resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} + engines: {node: '>=8'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /filter-obj@1.1.0: + resolution: {integrity: sha512-8rXg1ZnX7xzy2NGDVkBVaAy+lSlPNwad13BtgSlLuxfIslyt5Vg64U7tFcCt4WS1R0hvtnQybT/IyCkGZ3DpXQ==} + engines: {node: '>=0.10.0'} + dev: true + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true + + /follow-redirects@1.15.4: + resolution: {integrity: sha512-Cr4D/5wlrb0z9dgERpUL3LrmPKVDsETIJhaCMeDfuFYcqa5bldGV6wBsAN6X/vxlXQtFBMrXdXxdL8CbDTGniw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: true + + /form-data-encoder@2.1.4: + resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} + engines: {node: '>= 14.17'} + dev: true + + /formdata-polyfill@4.0.10: + resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} + engines: {node: '>=12.20.0'} + dependencies: + fetch-blob: 3.2.0 + dev: true + + /fs-extra@7.0.1: + resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} + engines: {node: '>=6 <7 || >=8'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-east-asian-width@1.2.0: + resolution: {integrity: sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==} + engines: {node: '>=18'} + dev: true + + /get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + + /git-raw-commits@2.0.11: + resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==} + engines: {node: '>=10'} + hasBin: true + dependencies: + dargs: 7.0.0 + lodash: 4.17.21 + meow: 8.1.2 + split2: 3.2.2 + through2: 4.0.2 + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /global-dirs@0.1.1: + resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==} + engines: {node: '>=4'} + dependencies: + ini: 1.3.8 + dev: true + + /globals@13.23.0: + resolution: {integrity: sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /got@12.6.1: + resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} + engines: {node: '>=14.16'} + dependencies: + '@sindresorhus/is': 5.6.0 + '@szmarczak/http-timer': 5.0.1 + cacheable-lookup: 7.0.0 + cacheable-request: 10.2.14 + decompress-response: 6.0.0 + form-data-encoder: 2.1.4 + get-stream: 6.0.1 + http2-wrapper: 2.2.1 + lowercase-keys: 3.0.0 + p-cancelable: 3.0.0 + responselike: 3.0.0 + dev: true + + /graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /hard-rejection@2.1.0: + resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==} + engines: {node: '>=6'} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + dev: true + + /hosted-git-info@2.8.9: + resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==} + dev: true + + /hosted-git-info@4.1.0: + resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} + engines: {node: '>=10'} + dependencies: + lru-cache: 6.0.0 + dev: true + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /http-cache-semantics@4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: true + + /http2-wrapper@2.2.1: + resolution: {integrity: sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==} + engines: {node: '>=10.19.0'} + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + dev: true + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + + /husky@8.0.3: + resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: true + + /ignore@5.3.0: + resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-lazy@4.0.0: + resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} + engines: {node: '>=8'} + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-fullwidth-code-point@4.0.0: + resolution: {integrity: sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==} + engines: {node: '>=12'} + dev: true + + /is-fullwidth-code-point@5.0.0: + resolution: {integrity: sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==} + engines: {node: '>=18'} + dependencies: + get-east-asian-width: 1.2.0 + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-plain-obj@1.1.0: + resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==} + engines: {node: '>=0.10.0'} + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + dependencies: + text-extensions: 2.4.0 + dev: true + + /is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + dev: true + + /is-unicode-supported@2.0.0: + resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} + engines: {node: '>=18'} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@3.1.6: + resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true + + /jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/node': 20.10.6 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jiti@1.21.0: + resolution: {integrity: sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==} + hasBin: true + dev: true + + /jju@1.4.0: + resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /jsonc-parser@3.2.0: + resolution: {integrity: sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==} + dev: true + + /jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: true + + /kolorist@1.8.0: + resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lilconfig@3.0.0: + resolution: {integrity: sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==} + engines: {node: '>=14'} + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /lint-staged@15.2.0: + resolution: {integrity: sha512-TFZzUEV00f+2YLaVPWBWGAMq7So6yQx+GG8YRMDeOEIf95Zn5RyiLMsEiX4KTNl9vq/w+NqRJkLA1kPIo15ufQ==} + engines: {node: '>=18.12.0'} + hasBin: true + dependencies: + chalk: 5.3.0 + commander: 11.1.0 + debug: 4.3.4 + execa: 8.0.1 + lilconfig: 3.0.0 + listr2: 8.0.0 + micromatch: 4.0.5 + pidtree: 0.6.0 + string-argv: 0.3.2 + yaml: 2.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /listr2@8.0.0: + resolution: {integrity: sha512-u8cusxAcyqAiQ2RhYvV7kRKNLgUvtObIbhOX2NCXqvp1UU32xIg5CT22ykS2TPKJXZWJwtK3IKLiqAGlGNE+Zg==} + engines: {node: '>=18.0.0'} + dependencies: + cli-truncate: 4.0.0 + colorette: 2.0.20 + eventemitter3: 5.0.1 + log-update: 6.0.0 + rfdc: 1.3.0 + wrap-ansi: 9.0.0 + dev: true + + /loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + dev: true + + /local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + dependencies: + mlly: 1.4.2 + pkg-types: 1.0.3 + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: true + + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: true + + /lodash.get@4.4.2: + resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} + dev: true + + /lodash.isequal@4.5.0: + resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} + dev: true + + /lodash.isfunction@3.0.9: + resolution: {integrity: sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==} + dev: true + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: true + + /lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + dev: true + + /lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + dev: true + + /lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + dev: true + + /lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + dev: true + + /lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /log-symbols@6.0.0: + resolution: {integrity: sha512-i24m8rpwhmPIS4zscNzK6MSEhk0DUWa/8iYQWxhffV8jkI4Phvs3F+quL5xvS0gdQR0FyTCMMH33Y78dDTzzIw==} + engines: {node: '>=18'} + dependencies: + chalk: 5.3.0 + is-unicode-supported: 1.3.0 + dev: true + + /log-update@6.0.0: + resolution: {integrity: sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==} + engines: {node: '>=18'} + dependencies: + ansi-escapes: 6.2.0 + cli-cursor: 4.0.0 + slice-ansi: 7.1.0 + strip-ansi: 7.1.0 + wrap-ansi: 9.0.0 + dev: true + + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + dependencies: + get-func-name: 2.0.2 + dev: true + + /lowercase-keys@3.0.0: + resolution: {integrity: sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /magic-string@0.30.5: + resolution: {integrity: sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /magicast@0.3.2: + resolution: {integrity: sha512-Fjwkl6a0syt9TFN0JSYpOybxiMCkYNEeOTnOTNRbjphirLakznZXAqrXgj/7GG3D1dvETONNwrBfinvAbpunDg==} + dependencies: + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + source-map-js: 1.0.2 + dev: true + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.4 + dev: true + + /map-obj@1.0.1: + resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==} + engines: {node: '>=0.10.0'} + dev: true + + /map-obj@4.3.0: + resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} + engines: {node: '>=8'} + dev: true + + /meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + dev: true + + /meow@8.1.2: + resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==} + engines: {node: '>=10'} + dependencies: + '@types/minimist': 1.2.5 + camelcase-keys: 6.2.2 + decamelize-keys: 1.1.1 + hard-rejection: 2.1.0 + minimist-options: 4.1.0 + normalize-package-data: 3.0.3 + read-pkg-up: 7.0.1 + redent: 3.0.0 + trim-newlines: 3.0.1 + type-fest: 0.18.1 + yargs-parser: 20.2.9 + dev: true + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: true + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: true + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + + /mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + dev: true + + /mimic-response@4.0.0: + resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist-options@4.1.0: + resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==} + engines: {node: '>= 6'} + dependencies: + arrify: 1.0.1 + is-plain-obj: 1.1.0 + kind-of: 6.0.3 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /mlly@1.4.2: + resolution: {integrity: sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg==} + dependencies: + acorn: 8.11.2 + pathe: 1.1.1 + pkg-types: 1.0.3 + ufo: 1.3.2 + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /muggle-string@0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + dev: true + + /mute-stream@1.0.0: + resolution: {integrity: sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: true + + /nanoid@3.3.7: + resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: true + + /node-bin-setup@1.1.3: + resolution: {integrity: sha512-opgw9iSCAzT2+6wJOETCpeRYAQxSopqQ2z+N6BXwIMsQQ7Zj5M8MaafQY8JMlolRR6R1UXg2WmhKp0p9lSOivg==} + + /node-domexception@1.0.0: + resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==} + engines: {node: '>=10.5.0'} + dev: true + + /node-fetch@3.3.2: + resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + data-uri-to-buffer: 4.0.1 + fetch-blob: 3.2.0 + formdata-polyfill: 4.0.10 + dev: true + + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: true + + /node@21.2.0: + resolution: {integrity: sha512-oiHX7SXGdO1wyg0/lZ1ZMy1iS7GgumsT5Ptt5BOye1WniC8OJ2TtYRuWfqNoKrUlYzI4+Bv1+NH5eDgxuThU2A==} + engines: {npm: '>=5.0.0'} + hasBin: true + requiresBuild: true + dependencies: + node-bin-setup: 1.1.3 + + /normalize-package-data@2.5.0: + resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} + dependencies: + hosted-git-info: 2.8.9 + resolve: 1.22.8 + semver: 5.7.2 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-package-data@3.0.3: + resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==} + engines: {node: '>=10'} + dependencies: + hosted-git-info: 4.1.0 + is-core-module: 2.13.1 + semver: 7.5.4 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-url@8.0.0: + resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} + engines: {node: '>=14.16'} + dev: true + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npm-run-path@5.1.0: + resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /ora@8.0.1: + resolution: {integrity: sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==} + engines: {node: '>=18'} + dependencies: + chalk: 5.3.0 + cli-cursor: 4.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 2.0.0 + log-symbols: 6.0.0 + stdin-discarder: 0.2.2 + string-width: 7.0.0 + strip-ansi: 7.1.0 + dev: true + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: true + + /p-cancelable@3.0.0: + resolution: {integrity: sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==} + engines: {node: '>=12.20'} + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + dependencies: + yocto-queue: 1.0.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /package-json@8.1.1: + resolution: {integrity: sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==} + engines: {node: '>=14.16'} + dependencies: + got: 12.6.1 + registry-auth-token: 5.0.2 + registry-url: 6.0.1 + semver: 7.5.4 + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.23.5 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /pathe@1.1.1: + resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} + dev: true + + /pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pidtree@0.6.0: + resolution: {integrity: sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==} + engines: {node: '>=0.10'} + hasBin: true + dev: true + + /pkg-types@1.0.3: + resolution: {integrity: sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==} + dependencies: + jsonc-parser: 3.2.0 + mlly: 1.4.2 + pathe: 1.1.1 + dev: true + + /postcss@8.4.33: + resolution: {integrity: sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg==} + engines: {node: ^10 || ^12 || >=14} + dependencies: + nanoid: 3.3.7 + picocolors: 1.0.0 + source-map-js: 1.0.2 + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier@3.1.1: + resolution: {integrity: sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + + /proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + dev: true + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /query-string@6.14.1: + resolution: {integrity: sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==} + engines: {node: '>=6'} + dependencies: + decode-uri-component: 0.2.2 + filter-obj: 1.1.0 + split-on-first: 1.1.0 + strict-uri-encode: 2.0.0 + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /quick-lru@4.0.1: + resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==} + engines: {node: '>=8'} + dev: true + + /quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + dev: true + + /randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: true + + /react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + + /read-pkg-up@7.0.1: + resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + read-pkg: 5.2.0 + type-fest: 0.8.1 + dev: true + + /read-pkg@5.2.0: + resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} + engines: {node: '>=8'} + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 2.5.0 + parse-json: 5.2.0 + type-fest: 0.6.0 + dev: true + + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: true + + /redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + dev: true + + /registry-auth-token@5.0.2: + resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} + engines: {node: '>=14'} + dependencies: + '@pnpm/npm-conf': 2.2.2 + dev: true + + /registry-url@6.0.1: + resolution: {integrity: sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==} + engines: {node: '>=12'} + dependencies: + rc: 1.2.8 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + dev: true + + /resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-global@1.0.0: + resolution: {integrity: sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==} + engines: {node: '>=8'} + dependencies: + global-dirs: 0.1.1 + dev: true + + /resolve@1.19.0: + resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /responselike@3.0.0: + resolution: {integrity: sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==} + engines: {node: '>=14.16'} + dependencies: + lowercase-keys: 3.0.0 + dev: true + + /restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rfdc@1.3.0: + resolution: {integrity: sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /rollup@4.6.1: + resolution: {integrity: sha512-jZHaZotEHQaHLgKr8JnQiDT1rmatjgKlMekyksz+yk9jt/8z9quNjnKNRoaM0wd9DC2QKXjmWWuDYtM3jfF8pQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.6.1 + '@rollup/rollup-android-arm64': 4.6.1 + '@rollup/rollup-darwin-arm64': 4.6.1 + '@rollup/rollup-darwin-x64': 4.6.1 + '@rollup/rollup-linux-arm-gnueabihf': 4.6.1 + '@rollup/rollup-linux-arm64-gnu': 4.6.1 + '@rollup/rollup-linux-arm64-musl': 4.6.1 + '@rollup/rollup-linux-x64-gnu': 4.6.1 + '@rollup/rollup-linux-x64-musl': 4.6.1 + '@rollup/rollup-win32-arm64-msvc': 4.6.1 + '@rollup/rollup-win32-ia32-msvc': 4.6.1 + '@rollup/rollup-win32-x64-msvc': 4.6.1 + fsevents: 2.3.3 + dev: true + + /run-async@3.0.0: + resolution: {integrity: sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==} + engines: {node: '>=0.12.0'} + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: true + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: true + + /schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + dev: true + + /semver@5.7.2: + resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} + hasBin: true + dev: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /serialize-javascript@6.0.1: + resolution: {integrity: sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==} + dependencies: + randombytes: 2.1.0 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slice-ansi@5.0.0: + resolution: {integrity: sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 4.0.0 + dev: true + + /slice-ansi@7.1.0: + resolution: {integrity: sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==} + engines: {node: '>=18'} + dependencies: + ansi-styles: 6.2.1 + is-fullwidth-code-point: 5.0.0 + dev: true + + /source-map-js@1.0.2: + resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + dev: true + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-license-ids@3.0.16: + resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} + dev: true + + /split-on-first@1.1.0: + resolution: {integrity: sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==} + engines: {node: '>=6'} + dev: true + + /split2@3.2.2: + resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} + dependencies: + readable-stream: 3.6.2 + dev: true + + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + dev: true + + /std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + dev: true + + /stdin-discarder@0.2.2: + resolution: {integrity: sha512-UhDfHmA92YAlNnCfhmq0VeNL5bDbiZGg7sZ2IvPsXubGkiNa9EC+tUTsjBRsYUAz87btI6/1wf4XoVvQ3uRnmQ==} + engines: {node: '>=18'} + dev: true + + /strict-uri-encode@2.0.0: + resolution: {integrity: sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==} + engines: {node: '>=4'} + dev: true + + /string-argv@0.3.2: + resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} + engines: {node: '>=0.6.19'} + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string-width@7.0.0: + resolution: {integrity: sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==} + engines: {node: '>=18'} + dependencies: + emoji-regex: 10.3.0 + get-east-asian-width: 1.2.0 + strip-ansi: 7.1.0 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + dependencies: + min-indent: 1.0.1 + dev: true + + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /strip-literal@1.3.0: + resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} + dependencies: + acorn: 8.11.2 + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /synckit@0.8.8: + resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/core': 0.1.0 + tslib: 2.6.2 + dev: true + + /tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + dev: true + + /terser-webpack-plugin@5.3.9(webpack@5.89.0): + resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + dependencies: + '@jridgewell/trace-mapping': 0.3.20 + jest-worker: 27.5.1 + schema-utils: 3.3.0 + serialize-javascript: 6.0.1 + terser: 5.26.0 + webpack: 5.89.0 + dev: true + + /terser@5.26.0: + resolution: {integrity: sha512-dytTGoE2oHgbNV9nTzgBEPaqAWvcJNl66VZ0BkJqlvp71IjO8CxdBx/ykCNb47cLnCmCvRZ6ZR0tLkqvZCdVBQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + '@jridgewell/source-map': 0.3.5 + acorn: 8.11.2 + commander: 2.20.3 + source-map-support: 0.5.21 + dev: true + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /through2@4.0.2: + resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} + dependencies: + readable-stream: 3.6.2 + dev: true + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /tinybench@2.5.1: + resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==} + dev: true + + /tinypool@0.8.1: + resolution: {integrity: sha512-zBTCK0cCgRROxvs9c0CGK838sPkeokNGdQVUUwHAbynHFlmyJYj825f/oRs528HaIJ97lo0pLIlDUzwN+IorWg==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy@2.2.0: + resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==} + engines: {node: '>=14.0.0'} + dev: true + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /trim-newlines@3.0.1: + resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} + engines: {node: '>=8'} + dev: true + + /ts-api-utils@1.0.3(typescript@5.3.3): + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.3.3 + dev: true + + /ts-loader@9.5.1(typescript@5.3.3)(webpack@5.89.0): + resolution: {integrity: sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==} + engines: {node: '>=12.0.0'} + peerDependencies: + typescript: '*' + webpack: ^5.0.0 + dependencies: + chalk: 4.1.2 + enhanced-resolve: 5.15.0 + micromatch: 4.0.5 + semver: 7.5.4 + source-map: 0.7.4 + typescript: 5.3.3 + webpack: 5.89.0 + dev: true + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest@0.18.1: + resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.6.0: + resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==} + engines: {node: '>=8'} + dev: true + + /type-fest@0.8.1: + resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} + engines: {node: '>=8'} + dev: true + + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: true + + /type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + dev: true + + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /ufo@1.3.2: + resolution: {integrity: sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA==} + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /universal-user-agent@6.0.1: + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} + dev: true + + /universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + dev: true + + /update-browserslist-db@1.0.13(browserslist@4.22.1): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.1 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /v8-to-istanbul@9.2.0: + resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.20 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + dev: true + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /validator@13.11.0: + resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} + engines: {node: '>= 0.10'} + dev: true + + /vite-node@1.1.3(@types/node@20.11.0)(terser@5.26.0): + resolution: {integrity: sha512-BLSO72YAkIUuNrOx+8uznYICJfTEbvBAmWClY3hpath5+h1mbPS5OMn42lrTxXuyCazVyZoDkSRnju78GiVCqA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.1 + picocolors: 1.0.0 + vite: 5.0.11(@types/node@20.11.0)(terser@5.26.0) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vite-plugin-dts@3.7.0(@types/node@20.11.0)(typescript@5.3.3)(vite@5.0.11): + resolution: {integrity: sha512-np1uPaYzu98AtPReB8zkMnbjwcNHOABsLhqVOf81b3ol9b5M2wPcAVs8oqPnOpr6Us+7yDXVauwkxsk5+ldmRA==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + typescript: '*' + vite: '*' + peerDependenciesMeta: + vite: + optional: true + dependencies: + '@microsoft/api-extractor': 7.39.0(@types/node@20.11.0) + '@rollup/pluginutils': 5.1.0 + '@vue/language-core': 1.8.27(typescript@5.3.3) + debug: 4.3.4 + kolorist: 1.8.0 + typescript: 5.3.3 + vite: 5.0.11(@types/node@20.11.0)(terser@5.26.0) + vue-tsc: 1.8.27(typescript@5.3.3) + transitivePeerDependencies: + - '@types/node' + - rollup + - supports-color + dev: true + + /vite@5.0.11(@types/node@20.11.0)(terser@5.26.0): + resolution: {integrity: sha512-XBMnDjZcNAw/G1gEiskiM1v6yzM4GE5aMGvhWTlHAYYhxb7S3/V1s3m2LDHa8Vh6yIWYYB0iJwsEaS523c4oYA==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || >=20.0.0 + less: '*' + lightningcss: ^1.21.0 + sass: '*' + stylus: '*' + sugarss: '*' + terser: ^5.4.0 + peerDependenciesMeta: + '@types/node': + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + dependencies: + '@types/node': 20.11.0 + esbuild: 0.19.8 + postcss: 8.4.33 + rollup: 4.6.1 + terser: 5.26.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /vitest@1.1.3(@types/node@20.11.0)(terser@5.26.0): + resolution: {integrity: sha512-2l8om1NOkiA90/Y207PsEvJLYygddsOyr81wLQ20Ra8IlLKbyQncWsGZjnbkyG2KwwuTXLQjEPOJuxGMG8qJBQ==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': ^1.0.0 + '@vitest/ui': ^1.0.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 20.11.0 + '@vitest/expect': 1.1.3 + '@vitest/runner': 1.1.3 + '@vitest/snapshot': 1.1.3 + '@vitest/spy': 1.1.3 + '@vitest/utils': 1.1.3 + acorn-walk: 8.3.1 + cac: 6.7.14 + chai: 4.4.0 + debug: 4.3.4 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.5 + pathe: 1.1.1 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 1.3.0 + tinybench: 2.5.1 + tinypool: 0.8.1 + vite: 5.0.11(@types/node@20.11.0)(terser@5.26.0) + vite-node: 1.1.3(@types/node@20.11.0)(terser@5.26.0) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + + /vue-template-compiler@2.7.16: + resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + dev: true + + /vue-tsc@1.8.27(typescript@5.3.3): + resolution: {integrity: sha512-WesKCAZCRAbmmhuGl3+VrdWItEvfoFIPXOvUJkjULi+x+6G/Dy69yO3TBRJDr9eUlmsNAwVmxsNZxvHKzbkKdg==} + hasBin: true + peerDependencies: + typescript: '*' + dependencies: + '@volar/typescript': 1.11.1 + '@vue/language-core': 1.8.27(typescript@5.3.3) + semver: 7.5.4 + typescript: 5.3.3 + dev: true + + /watchpack@2.4.0: + resolution: {integrity: sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==} + engines: {node: '>=10.13.0'} + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + dev: true + + /web-streams-polyfill@3.3.2: + resolution: {integrity: sha512-3pRGuxRF5gpuZc0W+EpwQRmCD7gRqcDOMt688KmdlDAgAyaB1XlN0zq2njfDNm44XVdIouE7pZ6GzbdyH47uIQ==} + engines: {node: '>= 8'} + dev: true + + /webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + dev: true + + /webpack@5.89.0: + resolution: {integrity: sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.5 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/wasm-edit': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + acorn: 8.11.2 + acorn-import-assertions: 1.9.0(acorn@8.11.2) + browserslist: 4.22.1 + chrome-trace-event: 1.0.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 1.4.1 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 3.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.9(webpack@5.89.0) + watchpack: 2.4.0 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + dev: true + + /widest-line@4.0.1: + resolution: {integrity: sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + dev: true + + /wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + + /wrap-ansi@9.0.0: + resolution: {integrity: sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==} + engines: {node: '>=18'} + dependencies: + ansi-styles: 6.2.1 + string-width: 7.0.0 + strip-ansi: 7.1.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /xpath@0.0.32: + resolution: {integrity: sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==} + engines: {node: '>=0.6.0'} + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yaml@2.3.4: + resolution: {integrity: sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==} + engines: {node: '>= 14'} + dev: true + + /yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + 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.8 + yargs-parser: 21.1.1 + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true + + /z-schema@5.0.5: + resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} + engines: {node: '>=8.0.0'} + hasBin: true + dependencies: + lodash.get: 4.4.2 + lodash.isequal: 4.5.0 + validator: 13.11.0 + optionalDependencies: + commander: 9.5.0 + dev: true diff --git a/src/compare.cjs b/src/compare.cjs new file mode 100644 index 0000000..6aaeb99 --- /dev/null +++ b/src/compare.cjs @@ -0,0 +1,335 @@ +const chalk = require('chalk'); +const { Chance } = require('chance'); +const algorithmOld = require('algorithms'); +const { + sortQuick, + sortMerge, + sortHeap, + sortInsertion, + sortSelection, + sortShell, + sortCounting, + sortOptimizedCounting, + sortRadix, + sortBubble, + sortShortBubble, + sortTim, + sortPancake, + sortCocktail +} = require('../dist/algorithm-sorts.cjs'); + +const fns = { + /** + * 通过参数替换字符串中的占位符 + * @param {string} str 带有占位符的字符串 + * @param {string[]} params 替换占位符的参数 + * @returns {string} 替换后的字符串 + */ + replacePlaceholders(str, ...params) { + return str.replace(/\{(\d+)\}/g, (_, index) => (params[index] || '').toString()); + }, + /** + * 比较 + * @param {any} a 比较值 a + * @param {any} b 比较值 b + * @returns 比较结果 + */ + compare(a, b) { + return `${a}`.localeCompare(`${b}`); + }, + /** + * 格式化 + */ + format: { + /** + * 数字格式化 + * @param {number} number 数字 + * @returns 格式化后的数字 + */ + number(number) { + return Number(number).toLocaleString('en-US'); + }, + /** + * 保留 n 位小数 + * @param {number} number 数字 + * @param {number} [digits = 2] 保留位数 + */ + decimal(number, digits = 4) { + return Number(number).toFixed(digits); + } + }, + /** + * 生成数据 + */ + generate: { + /** + * 生成随机字符串数组 + * @param {number} [arrayLength = 10000] 数组长度 + * @param {number} [minLength = 4] 最小长度 + * @param {number} [maxLength = 12] 最大长度 + * @param {number} [minNumber = 0] 最小数字 + * @param {number} [maxNumber = 99999] 最大数字 + * @param {boolean} [isKey = false] 是否生成键值对 + * @returns 随机字符串数组 + */ + array(arrayLength = 10000, minLength = 4, maxLength = 12, minNumber = 0, maxNumber = 99999, isKey = false) { + const chance = new Chance(); + + return Array.from({ length: arrayLength }, () => { + if (chance.bool()) { + const randomLength = chance.integer({ min: minLength, max: maxLength }); + const randomString = chance.string({ + length: randomLength, + pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+[]{}|;:,.<>?' + }); + return isKey ? { key: randomString } : randomString; + } else { + const randomNumber = chance.integer({ min: minNumber, max: maxNumber }); + return isKey ? { key: randomNumber } : randomNumber; + } + }); + } + }, + /** + * 速度测试相关 + */ + speeds: { + /** + * 获取数据 + * @param {number} [arrayLength = 10000] 数组长度 + * @param {number} [minLength = 4] 最小长度 + * @param {number} [maxLength = 12] 最大长度 + * @param {number} [minNumber = 0] 最小数字 + * @param {number} [maxNumber = 99999] 最大数字 + * @param {boolean} [isKey = false] 是否生成键值对 + */ + datas(arrayLength = 10000, minLength = 4, maxLength = 12, minNumber = 0, maxNumber = 99999, isKey = false) { + const formatSection = (text, formatFunc) => (formatFunc ? formatFunc(text) : text); + const formatData = (value, formatFunc) => `${formatFunc(fns.format.number(value))}`; + const contents = [ + formatSection('┌───────────────────────────────────────────────────────────────────────────', chalk.dim), + formatSection('│ ', chalk.dim), + `${formatSection('│', chalk.dim)} ${formatSection('以下比较均采用相同的比较算法逻辑', chalk.bold.cyan)}`, + `${formatSection('│', chalk.dim)} ${formatSection('此文件中的结果仅作参考', chalk.bold.cyan)}`, + `${formatSection('│', chalk.dim)} ${formatSection('实际情况会因各种原因导致测试结果不同', chalk.bold.cyan)}`, + `${formatSection('│', chalk.dim)} ${formatSection('此包中的算法考虑了一些边缘情况,', chalk.bold.magenta)}`, + `${formatSection('│', chalk.dim)} ${formatSection('个别场景中可能会略微牺牲一些性能', chalk.bold.magenta)}`, + `${formatSection('│', chalk.dim)} ${formatSection('可进行多次测试', chalk.bold.cyan)}`, + `${formatSection('│', chalk.dim)}`, + `${formatSection('│', chalk.dim)} ${formatSection('The comparisons in this document utilize the same algorithm logic.', chalk.bold.cyan)}`, + `${formatSection('│', chalk.dim)} ${formatSection('The results herein are for reference only.', chalk.bold.magenta)}`, + `${formatSection('│', chalk.dim)} ${formatSection('Actual outcomes may vary due to various factors.', chalk.bold.magenta)}`, + `${formatSection('│', chalk.dim)} ${formatSection('The algorithms in this package account for edge cases,', chalk.bold.cyan)}`, + `${formatSection('│', chalk.dim)} ${formatSection('which may slightly compromise performance in specific scenarios.', chalk.bold.cyan)}`, + `${formatSection('│', chalk.dim)} ${formatSection('Multiple tests are recommended.', chalk.bold.cyan)}`, + `${formatSection('│', chalk.dim)}`, + `${formatSection('│', chalk.dim)}`, + `${formatSection('├─', chalk.dim)} ${formatSection('Randomly generated data', chalk.bold.yellow)} ${formatData(arrayLength, chalk.bold.greenBright)} ${formatSection( + 'items', + chalk.bold.yellow + )}`, + `${formatSection('├──', chalk.dim)} ${chalk.dim('string length between')} ${formatData(minLength, chalk.bold.greenBright)} ${chalk.dim('and')} ${formatData( + maxLength, + chalk.bold.greenBright + )}`, + `${formatSection('├──', chalk.dim)} ${chalk.dim('numbers between')} ${formatData(minNumber, chalk.greenBright)} ${chalk.dim('and')} ${formatData(maxNumber, chalk.bold.greenBright)}`, + formatSection('│ ', chalk.dim), + formatSection('└───────────────────────────────────────────────────────────────────────────', chalk.dim) + ]; + + console.log(contents.join('\n')); + + return fns.generate.array(arrayLength, minLength, maxLength, minNumber, maxNumber, isKey); + }, + /** + * 提示 + * @param {string} tips 提示 + * @returns 提示 + */ + tips(tips) { + const arr = []; + if (tips.length) { + for (let i = 0, j = tips.length; i < j; i++) { + const list = []; + + for (let k = 0, l = tips[i].length; k < l; k++) { + list.push(`${chalk.dim('│')} ${chalk.dim(tips[i][k])}`); + } + + arr.push(`\n${list.join('\n')}`); + } + } + + return arr; + }, + /** + * 测试速度 + * @param {string} name 测试名称 + * @param {string} key 测试函数的 key + * @param {any[]} datas 测试数据 + * @param {string} [tips = []] 提示 + */ + test(name, key, datas, tips = []) { + tips = fns.speeds.tips(tips); + let data1 = [...datas]; + let data2 = [...datas]; + + let oldStartTime = 0; + let oldEndTime = 0; + let oldExecutionTime = 0; + let oldNoFunction = false; + + oldStartTime = performance.now(); + if (key === 'optimizedCounting') { + let inx = 0; + let oldCountingEmpty; + // 有的时候,老版本不能处理某些随机的数据,不知是什么原因导致最终结果为空数组,这里做一个循环,重新生成数据,直到结果不为空 + do { + // 首先,排序一次 + oldCountingEmpty = fns.algorithms.old[key](data1).length === 0; + + // 如果结果为空 + if (oldCountingEmpty) { + // 重新生成数据 + const result = fns.generate.array(1000, 6, 32, 0, 1000000, true); + data1 = [...result]; + data2 = [...result]; + inx++; + + // 重置排序开始时间 + oldStartTime = performance.now(); + } + } while (oldCountingEmpty); + + if (tips.length) { + tips.length === 1 && (tips[0] = fns.replacePlaceholders(tips[0], inx)); + tips.length === 2 && (tips[1] = fns.replacePlaceholders(tips[1], inx)); + } + } else { + if (fns.algorithms.old[key]) { + fns.algorithms.old[key](data1, fns.compare); + } else { + oldNoFunction = true; + } + } + + oldEndTime = performance.now(); + oldExecutionTime = oldEndTime - oldStartTime; + + const newStartTime = performance.now(); + if (key === 'optimizedCounting') { + fns.algorithms.new[key](data2, true); + } else if (key === 'radix') { + fns.algorithms.new[key]('lsd', data2, true); + } else { + fns.algorithms.new[key](data2, true, fns.compare); + } + const newEndTime = performance.now(); + const newExecutionTime = newEndTime - newStartTime; + + const isNewFaster = oldExecutionTime >= newExecutionTime; + const result = oldExecutionTime - newExecutionTime; + + console.log(`${chalk.dim('┌─')} ${chalk.bold.dim.cyan('【')} ${chalk.bold.cyan(`${name}`)} ${chalk.bold.dim.cyan('】')}`); + + if (oldNoFunction) { + console.log(`${chalk.dim('├──')} ${chalk.magenta('algorithms.js')} ${chalk.redBright('不存在对应算法 / The corresponding algorithm does not exist.')}`); + + console.log( + `${chalk.dim('├──')} ${chalk.green('@kwooshung/algorithm-sorts')} ${chalk.greenBright(fns.format.decimal(newExecutionTime))} ${chalk.dim('ms')} ${tips.length >= 2 ? tips[1] : ''}` + ); + + console.log(`${chalk.dim('└')} ${chalk.bold.greenBright('0')} ${chalk.dim('ms')}\n`); + } else { + console.log( + `${chalk.dim('├──')} ${chalk.magenta('algorithms.js')} ${chalk[isNewFaster ? 'redBright' : 'greenBright'](fns.format.decimal(oldExecutionTime))} ${chalk.dim('ms')} ${ + tips.length ? tips[0] : '' + }` + ); + + console.log( + `${chalk.dim('├──')} ${chalk.green('@kwooshung/algorithm-sorts')} ${chalk[isNewFaster ? 'greenBright' : 'redBright'](fns.format.decimal(newExecutionTime))} ${chalk.dim('ms')} ${ + tips.length >= 2 ? tips[1] : '' + }` + ); + + console.log( + `${chalk.dim('└')} ${chalk.bold[isNewFaster ? 'greenBright' : 'redBright']( + `${isNewFaster ? '-' : '+'}${fns.format.decimal(result < 0 ? Math.abs(result) : result)}` + )} ${chalk.dim('ms')}\n` + ); + } + } + }, + /** + * 算法 + */ + algorithms: { + /** + * 老算法 + */ + old: { + quick: algorithmOld.Sorting.quicksort, + merge: algorithmOld.Sorting.mergeSort, + heap: algorithmOld.Sorting.heapSort, + insertion: algorithmOld.Sorting.insertionSort, + selection: algorithmOld.Sorting.selectionSort, + shell: algorithmOld.Sorting.shellSort, + optimizedCounting: algorithmOld.Sorting.countingSort, + radix: algorithmOld.Sorting.radixSort, + bubble: algorithmOld.Sorting.bubbleSort, + shortBubble: algorithmOld.Sorting.shortBubbleSort + }, + /** + * 新算法 + */ + new: { + quick: sortQuick, + merge: sortMerge, + heap: sortHeap, + insertion: sortInsertion, + selection: sortSelection, + shell: sortShell, + counting: sortCounting, + optimizedCounting: sortOptimizedCounting, + radix: sortRadix, + bubble: sortBubble, + shortBubble: sortShortBubble, + tim: sortTim, + pancake: sortPancake, + cocktail: sortCocktail + } + } +}; + +(() => { + console.clear(); + + const count = 1000; + const datas = fns.speeds.datas(count, 6, 32, 0, 1000000); + const keyDatas = fns.generate.array(count, 6, 32, 0, 1000000, true); + + fns.speeds.test('冒泡排序 / Bubble Sort', 'bubble', datas); + fns.speeds.test('短冒泡排序 / Shout Bubble Sort', 'shortBubble', datas); + fns.speeds.test('鸡尾酒排序 / Cocktail Sort', 'cocktail', datas); + + fns.speeds.test('计数排序 / Counting Sort', 'counting', datas); + fns.speeds.test('计数排序(优化版本) / Optimized Counting Sort', 'optimizedCounting', keyDatas, [ + [ + `有的时候,${chalk.magenta('algorithms.js')} 不能处理某些随机的数据 (Sometimes, ${chalk.magenta('algorithms.js')} can't process certain random data.)`, + `不知是什么原因导致最终结果为${chalk.magenta('空数组')} (resulting in ${chalk.magenta('empty arrays')} for unknown reasons)`, + ` 这里做一个循环,重新生成数据,${chalk.magenta('直到结果不为空')} (Here, implement a loop to regenerate data ${chalk.magenta('until the result is not empty')})`, + ` ${chalk.magenta('尝试次数 {0}')} (${chalk.magenta('having tried {0} times.')})`, + '' + ] + ]); + fns.speeds.test('堆排序 / Heap Sort', 'heap', datas); + fns.speeds.test('插入排序 / Insertion Sort', 'insertion', datas); + fns.speeds.test('归并排序 / Merge Sort', 'merge', datas); + fns.speeds.test('煎饼排序 / Pancake Sort', 'pancake', datas); + fns.speeds.test('快速排序 / Quick Sort', 'quick', datas); + fns.speeds.test('基数排序 / Radix Sort', 'radix', datas); + fns.speeds.test('选择排序 / Selection Sort', 'selection', datas); + fns.speeds.test('希尔排序 / Shell Sort', 'shell', datas); + fns.speeds.test('定向排序 / Tim Sort', 'tim', datas); +})(); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..12a0bb9 --- /dev/null +++ b/src/index.ts @@ -0,0 +1,14 @@ +export { default as sortBubble } from '@/sorts/bubble'; +export { default as sortShortBubble } from '@/sorts/bubble/short'; +export { default as sortCocktail } from '@/sorts/cocktail'; +export { default as sortCounting } from '@/sorts/counting'; +export { default as sortOptimizedCounting } from '@/sorts/counting/optimized'; +export { default as sortHeap } from '@/sorts/heap'; +export { default as sortInsertion } from '@/sorts/insertion'; +export { default as sortMerge } from '@/sorts/merge'; +export { default as sortPancake } from '@/sorts/pancake'; +export { default as sortQuick } from '@/sorts/quick'; +export { default as sortRadix } from '@/sorts/radix'; +export { default as sortSelection } from '@/sorts/selection'; +export { default as sortShell } from '@/sorts/shell'; +export { default as sortTim } from '@/sorts/tim'; diff --git a/src/interface.d.ts b/src/interface.d.ts new file mode 100644 index 0000000..8f56db5 --- /dev/null +++ b/src/interface.d.ts @@ -0,0 +1,31 @@ +/** + * 类型:计数排序的优化版数据参数 + */ +type TCountingOptimizedData = { + key: number; +}; + +/** + * 类型:点数据 + */ +type TPoint = { x: number; y: number }; + +/** + * 类型:射线数据 + */ +type TRay = { + origin: TPoint; + direction: TPoint; +}; + +/** + * 类型:多边形数据 + */ +type TPolygon = TPolygon; + +/** + * 类型:矩形数据 + */ +type TRectangle = { topLeft: TPoint; bottomRight: TPoint }; + +export { TCountingOptimizedData, TPoint, TRay, TPolygon, TRectangle }; diff --git a/src/internal/compare/index.test.ts b/src/internal/compare/index.test.ts new file mode 100644 index 0000000..7291b16 --- /dev/null +++ b/src/internal/compare/index.test.ts @@ -0,0 +1,64 @@ +import Comparator from '.'; + +describe('Comparator 类的测试', () => { + let comparator: Comparator; + + beforeEach(() => { + comparator = new Comparator(); + }); + + it('默认比较函数应正确比较数字', () => { + expect(comparator.compare(1, 2)).toBe(-1); + expect(comparator.compare(2, 1)).toBe(1); + expect(comparator.compare(1, 1)).toBe(0); + }); + + it('默认比较函数应正确比较字符串', () => { + expect(comparator.compare('a', 'b')).toBe(-1); + expect(comparator.compare('b', 'a')).toBe(1); + expect(comparator.compare('a', 'a')).toBe(0); + }); + + it('lessThan 应正确工作', () => { + expect(comparator.lessThan(1, 2)).toBeTruthy(); + expect(comparator.lessThan(2, 1)).toBeFalsy(); + }); + + it('lessThanOrEqual 应正确工作', () => { + expect(comparator.lessThanOrEqual(1, 2)).toBeTruthy(); + expect(comparator.lessThanOrEqual(2, 2)).toBeTruthy(); + expect(comparator.lessThanOrEqual(2, 1)).toBeFalsy(); + }); + + it('greaterThan 应正确工作', () => { + expect(comparator.greaterThan(2, 1)).toBeTruthy(); + expect(comparator.greaterThan(1, 2)).toBeFalsy(); + }); + + it('greaterThanOrEqual 应正确工作', () => { + expect(comparator.greaterThanOrEqual(2, 1)).toBeTruthy(); + expect(comparator.greaterThanOrEqual(1, 1)).toBeTruthy(); + expect(comparator.greaterThanOrEqual(1, 2)).toBeFalsy(); + }); + + it('equal 应正确工作', () => { + expect(comparator.equal(1, 1)).toBeTruthy(); + expect(comparator.equal(1, 2)).toBeFalsy(); + expect(comparator.equal('a', 'a')).toBeTruthy(); + expect(comparator.equal('a', 'b')).toBeFalsy(); + }); + + it('reverse 应该反转比较逻辑', () => { + comparator.reverse(); + expect(comparator.compare(1, 2)).toBe(1); + expect(comparator.compare(2, 1)).toBe(-1); + expect(comparator.compare(1, 1)).toBe(0); + }); + + it('使用自定义比较函数', () => { + const customCompare = new Comparator((a, b) => a.length - b.length); + expect(customCompare.compare('a', 'bb')).toBe(-1); + expect(customCompare.compare('aaa', 'bb')).toBe(1); + expect(customCompare.compare('abc', 'abc')).toBe(0); + }); +}); diff --git a/src/internal/compare/index.ts b/src/internal/compare/index.ts new file mode 100644 index 0000000..fd55c9f --- /dev/null +++ b/src/internal/compare/index.ts @@ -0,0 +1,98 @@ +/** + * 这个类真的很棒,在原来的基础上,稍作优化 + * 引用自:https://github.com/felipernb/algorithms.js/blob/master/src/util/comparator.js + */ +class compare { + /** + * 构造函数,可传入一个比较函数 + * @param {(a: any, b: any)} [compareFn] 比较函数,比较函数,只能返回 number + */ + public constructor(compareFn?: (a: any, b: any) => number) { + compareFn && (this.compare = compareFn); + } + + /** + * 默认比较函数 + * @param {T} a 第一个比较值 + * @param {T} b 第二个比较值 + * @return {number} 比较结果 + */ + public compare(a: any, b: any): number { + if (a === b) { + return 0; + } else { + if (typeof a === 'number' && typeof b === 'number') { + if (a < b) { + return -1; + } else { + return 1; + } + } + + return `${a}`.localeCompare(`${b}`); + } + } + + /** + * 小于 + * @param {T} a 第一个比较值 + * @param {T} b 第二个比较值 + * @return {boolean} 比较结果 + */ + public lessThan(a: T, b: T): boolean { + return this.compare(a, b) < 0; + } + + /** + * 小于等于 + * @param {T} a 第一个比较值 + * @param {T} b 第二个比较值 + * @return {boolean} 比较结果 + */ + public lessThanOrEqual(a: T, b: T): boolean { + return this.compare(a, b) <= 0; + } + + /** + * 大于 + * @param {T} a 第一个比较值 + * @param {T} b 第二个比较值 + * @return {boolean} 比较结果 + */ + public greaterThan(a: T, b: T): boolean { + return this.compare(a, b) > 0; + } + + /** + * 大于等于 + * @param {T} a 第一个比较值 + * @param {T} b 第二个比较值 + * @return {boolean} 比较结果 + */ + public greaterThanOrEqual(a: T, b: T): boolean { + return this.greaterThan(a, b) || this.equal(a, b); + } + + /** + * 等于 + * @param {T} a 第一个比较值 + * @param {T} b 第二个比较值 + * @return {boolean} 比较结果 + */ + public equal(a: T, b: T): boolean { + return this.compare(a, b) === 0; + } + + /** + * 反转比较函数的逻辑 + * this.compare(a, b) => 1 + * this.reverse(); + * this.compare(a, b) => -1 + */ + public reverse() { + const originalCompareFn = this.compare; + this.compare = (a, b) => originalCompareFn(b, a); + } +} + +export default compare; diff --git a/src/internal/generate/array/index.test.ts b/src/internal/generate/array/index.test.ts new file mode 100644 index 0000000..cba20dc --- /dev/null +++ b/src/internal/generate/array/index.test.ts @@ -0,0 +1,108 @@ +import build from '.'; + +describe('测试 build 函数', () => { + it('使用默认参数', () => { + const result = build(); + expect(result).toHaveLength(10000); + }); + + it('测试生成的数组元素长度是否符合要求', () => { + const result = build(100, 2, 10, 0, 20); + result.forEach((item) => { + if (typeof item === 'string') { + expect(item.length).toBeGreaterThanOrEqual(2); + expect(item.length).toBeLessThanOrEqual(10); + } else { + expect(item).toBeGreaterThanOrEqual(0); + expect(item).toBeLessThanOrEqual(20); + } + }); + }); + + it('生成指定长度的数组', () => { + const length = 500; + const result = build(length); + expect(result).toHaveLength(length); + }); + + it('数组中包含字符串和数字', () => { + const result = build(100, 1, 1, 1, 1); + const hasString = result.some((item) => typeof item === 'string'); + const hasNumber = result.some((item) => typeof item === 'number'); + expect(hasString).toBeTruthy(); + expect(hasNumber).toBeTruthy(); + }); + + it('测试字符串长度的限制', () => { + const minLength = 3; + const maxLength = 8; + const result = build(100, minLength, maxLength); + result.forEach((item) => { + if (typeof item === 'string') { + expect(item.length).toBeGreaterThanOrEqual(minLength); + expect(item.length).toBeLessThanOrEqual(maxLength); + } + }); + }); + + it('测试数字范围的限制', () => { + const minNumber = 10; + const maxNumber = 500; + const result = build(100, 4, 12, minNumber, maxNumber); + result.forEach((item) => { + if (typeof item === 'number') { + expect(item).toBeGreaterThanOrEqual(minNumber); + expect(item).toBeLessThanOrEqual(maxNumber); + } + }); + }); + + it('测试 isKey 为 true 时的行为', () => { + const result = build(100, 4, 12, 10, 500, true); + result.forEach((item) => { + expect(typeof item).toBe('object'); + expect(item).toHaveProperty('key'); + }); + }); + + it('测试 isKey 为 false 时的行为', () => { + const result = build(100, 4, 12, 10, 500, false); + result.forEach((item) => { + expect(['string', 'number']).toContain(typeof item); + }); + }); + + it('测试字符串是否包含预期的字符集', () => { + const result = build(100, 10, 10); + result.forEach((item) => { + if (typeof item === 'string') { + expect(item).toMatch(/^[a-zA-Z0-9!@#$%^&*()_+[\]{}|;:,.<>?]+$/); + } + }); + }); + + it('测试最小和最大长度相同时字符串的长度', () => { + const fixedLength = 5; + const result = build(100, fixedLength, fixedLength); + result.forEach((item) => { + if (typeof item === 'string') { + expect(item.length).toBe(fixedLength); + } + }); + }); + + it('测试最小和最大数字相同时数字的值', () => { + const fixedNumber = 100; + const result = build(100, 4, 12, fixedNumber, fixedNumber); + result.forEach((item) => { + if (typeof item === 'number') { + expect(item).toBe(fixedNumber); + } + }); + }); + + it('测试数组长度为 0 时的行为', () => { + const result = build(0); + expect(result).toHaveLength(0); + }); +}); diff --git a/src/internal/generate/array/index.ts b/src/internal/generate/array/index.ts new file mode 100644 index 0000000..0ded3f6 --- /dev/null +++ b/src/internal/generate/array/index.ts @@ -0,0 +1,39 @@ +import { TCountingOptimizedData } from '@/interface'; +import { Chance } from 'chance'; + +/** + * 生成随机字符串数组 + * @param {number} [arrayLength = 10000] 数组长度 + * @param {number} [minLength = 4] 最小长度 + * @param {number} [maxLength = 12] 最大长度 + * @param {number} [minNumber = 0] 最小数字 + * @param {number} [maxNumber = 99999] 最大数字 + * @param {boolean} [isKey = false] 是否生成键值对 + * @returns {(string | TCountingOptimizedData)[]} 返回随机字符串数组 + */ +const build = ( + arrayLength: number = 10000, + minLength: number = 4, + maxLength: number = 12, + minNumber: number = 0, + maxNumber: number = 99999, + isKey: boolean = false +): (string | TCountingOptimizedData)[] => { + const chance = new Chance(); + + return Array.from({ length: arrayLength }, () => { + if (chance.bool()) { + const randomLength = chance.integer({ min: minLength, max: maxLength }); + const randomString = chance.string({ + length: randomLength, + pool: 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+[]{}|;:,.<>?' + }); + return isKey ? { key: randomString } : randomString; + } else { + const randomNumber = chance.integer({ min: minNumber, max: maxNumber }); + return isKey ? { key: randomNumber } : randomNumber; + } + }) as (string | TCountingOptimizedData)[]; +}; + +export default build; diff --git a/src/internal/generate/index.ts b/src/internal/generate/index.ts new file mode 100644 index 0000000..4026168 --- /dev/null +++ b/src/internal/generate/index.ts @@ -0,0 +1,7 @@ +import array from './array'; + +export { default as array } from './array'; + +export default { + array +}; diff --git a/src/sorts/bubble/index.test.ts b/src/sorts/bubble/index.test.ts new file mode 100644 index 0000000..5fd779e --- /dev/null +++ b/src/sorts/bubble/index.test.ts @@ -0,0 +1,79 @@ +import bubble from '.'; + +describe('冒泡排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = bubble(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = bubble(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = bubble(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = bubble(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + bubble(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = bubble(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = bubble(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = bubble(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = bubble(input, true); + expect(result).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = bubble(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/bubble/index.ts b/src/sorts/bubble/index.ts new file mode 100644 index 0000000..284e5b7 --- /dev/null +++ b/src/sorts/bubble/index.ts @@ -0,0 +1,41 @@ +import compare from '@/internal/compare'; + +/** + * 冒泡排序 / Bubble Sort + * @description 冒泡排序是一种简单的排序算法。通过重复遍历要排序的数列,比较两个元素,如果他们的顺序错误就把他们交换过来 / Bubble sort is a simple sorting algorithm. It repeatedly traverses the list to be sorted, comparing two elements and swapping them if they are in the wrong order + * @usageScenario 适用于小型数组或教学目的 / Suitable for small arrays or teaching purposes + * @timeComplexity 最好情况 O(n),平均和最坏情况 O(n^2) / Best case O(n), average and worst case O(n^2) + * @param {T[]} array 待排序数组 / Array to be sorted + * @param {boolean} [modifyOriginal=true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse=false] 是否反转结果 / Whether to reverse the result + */ +const bubble = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + if (array.length <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + let n = array.length; + let swapped: boolean; + + do { + swapped = false; + let newBound = 0; + for (let i = 1; i < n; i++) { + if (comp.greaterThan(array[i - 1], array[i])) { + [array[i - 1], array[i]] = [array[i], array[i - 1]]; + newBound = i; + swapped = true; + } + } + n = newBound; + } while (swapped); + + return array; +}; + +export default bubble; diff --git a/src/sorts/bubble/short/index.test.ts b/src/sorts/bubble/short/index.test.ts new file mode 100644 index 0000000..12e14c5 --- /dev/null +++ b/src/sorts/bubble/short/index.test.ts @@ -0,0 +1,79 @@ +import shortBubble from '.'; + +describe('短冒泡排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = shortBubble(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = shortBubble(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = shortBubble(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = shortBubble(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + shortBubble(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = shortBubble(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = shortBubble(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = shortBubble(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = shortBubble(input, true); + expect(result).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = shortBubble(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/bubble/short/index.ts b/src/sorts/bubble/short/index.ts new file mode 100644 index 0000000..ca0fab2 --- /dev/null +++ b/src/sorts/bubble/short/index.ts @@ -0,0 +1,38 @@ +import compare from '@/internal/compare'; + +/** + * 短冒泡排序 / Short Bubble Sort + * @description 短冒泡排序是冒泡排序的一种变体,当在整个排序过程中没有进行任何交换时,该算法会提前停止 / Short bubble sort is a variation of bubble sort that stops early if no swaps are made during the entire sorting process + * @usageScenario 适用于检测几乎已经排序好的数组 / Suitable for detecting nearly sorted arrays + * @timeComplexity 最好情况 O(n),平均和最坏情况 O(n^2) / Best case O(n), average and worst case O(n^2) + * @param {T[]} array 待排序数组 / Array to be sorted + * @param {boolean} [modifyOriginal=true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse=false] 是否反转结果 / Whether to reverse the result + */ +const short = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + if (array.length <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + let i = 0; + let swapped: boolean; + + do { + swapped = false; + for (i = 0; i < array.length - 1; i++) { + if (comp.greaterThan(array[i], array[i + 1])) { + [array[i], array[i + 1]] = [array[i + 1], array[i]]; + swapped = true; + } + } + } while (swapped); + + return array; +}; + +export default short; diff --git a/src/sorts/cocktail/index.test.ts b/src/sorts/cocktail/index.test.ts new file mode 100644 index 0000000..98e4917 --- /dev/null +++ b/src/sorts/cocktail/index.test.ts @@ -0,0 +1,102 @@ +import pancake from '.'; + +describe('煎饼排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = pancake(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = pancake(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = pancake(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = pancake(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1, 10]; + const expected = [1, 2, 3, 10]; + pancake(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = pancake(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = pancake(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = pancake(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = pancake(input, true); + expect(result).toEqual(expected); + }); + + it('对空数组进行排序', () => { + const input: any = []; + const expected: any = []; + const result = pancake(input); + expect(result).toEqual(expected); + }); + + it('对大型数组进行排序', () => { + const input = Array.from({ length: 64 }, () => Math.floor(Math.random() * 64)); + const expected = [...input].sort((a, b) => a - b); + const result = pancake(input); + expect(result).toEqual(expected); + }); + + it('使用不同的 runSize 进行排序', () => { + const input = [5, 4, 3, 2, 1]; + const expected = [1, 2, 3, 4, 5]; + const resultWithSmallRun = pancake(input, true); + const resultWithLargeRun = pancake(input, true); + expect(resultWithSmallRun).toEqual(expected); + expect(resultWithLargeRun).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = pancake(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/cocktail/index.ts b/src/sorts/cocktail/index.ts new file mode 100644 index 0000000..502692a --- /dev/null +++ b/src/sorts/cocktail/index.ts @@ -0,0 +1,57 @@ +import compare from '@/internal/compare'; + +/** + * 鸡尾酒排序 / Cocktail Sort + * @description 鸡尾酒排序是冒泡排序的变体,其中排序操作是双向的:先从左到右,然后从右到左。/ Cocktail sort is a variation of bubble sort where the sorting operation is bidirectional: first from left to right, then from right to left. + * @usageScenario 适用于大部分已排序但部分元素处于错误位置的数组。/ Suitable for mostly sorted arrays with some elements out of place. + * @timeComplexity 平均情况和最坏情况均为 O(n^2),最好情况为 O(n) / Average and worst case O(n^2), best case O(n) + * @param array {T[]} 要排序的数组 / Array to be sorted + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @returns {T[]} 返回排序后的数组 / Returns the sorted array + */ +const cocktail = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + const n = array.length; + if (n <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + let swapped = true; + let start = 0; + let end = n; + + while (swapped) { + swapped = false; + + // 从左到右的冒泡排序 + for (let i = start; i < end - 1; ++i) { + if (comp.greaterThan(array[i], array[i + 1])) { + [array[i], array[i + 1]] = [array[i + 1], array[i]]; + swapped = true; + } + } + + if (!swapped) break; + + swapped = false; + end--; + + // 从右到左的冒泡排序 + for (let i = end - 1; i >= start; i--) { + if (comp.greaterThan(array[i], array[i + 1])) { + [array[i], array[i + 1]] = [array[i + 1], array[i]]; + swapped = true; + } + } + + start++; + } + + return array; +}; + +export default cocktail; diff --git a/src/sorts/counting/index.test.ts b/src/sorts/counting/index.test.ts new file mode 100644 index 0000000..03ab54b --- /dev/null +++ b/src/sorts/counting/index.test.ts @@ -0,0 +1,56 @@ +import counting from '.'; + +describe('计数排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = counting(input); + + expect(result).to.deep.equal(expected); + }); + + // 测试基本的排序功能 + it('应该正确排序一个整数数组', () => { + const result = counting([4, 2, 3, 1, 2], true); + expect(result).toEqual([1, 2, 2, 3, 4]); + }); + + // 测试逆序排序功能 + it('应该能够逆序排序数组', () => { + const result = counting([4, 2, 3, 1, 5], true); + expect(result).toEqual([1, 2, 3, 4, 5]); + }); + + // 测试处理非数值元素 + it('字符应该在数字之后', () => { + const result = counting([3, 4, 'a', 3, 2, 'b', 1], true); + expect(result).toEqual([1, 2, 3, 3, 4, 'a', 'b']); + }); + + // 测试不修改原数组 + it('如果指定,应该不修改原数组', () => { + const original = [3, 1, 4, 2]; + const result = counting(original, false); + expect(result).not.toBe(original); + expect(result).toEqual([1, 2, 3, 4]); + }); + + // 测试空数组和单元素数组 + it('应该能正确处理空数组和单元素数组', () => { + expect(counting([], true)).toEqual([]); + expect(counting([1], true)).toEqual([1]); + }); + + // 测试最大值 + it('应该能正确处理最大值', () => { + const result = counting([-Infinity, 4, 2, 3, 1, 5, Infinity], true); + expect(result).toEqual([-Infinity, 1, 2, 3, 4, 5, Infinity]); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['apple', 'banana', 7, 6, 5, 3, 2]; + const result = counting(input, true, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/counting/index.ts b/src/sorts/counting/index.ts new file mode 100644 index 0000000..6f20487 --- /dev/null +++ b/src/sorts/counting/index.ts @@ -0,0 +1,59 @@ +/** + * 计数排序 / Counting Sort + * @description 计数排序是一种非比较型排序算法。适用于一定范围内的整数排序,在额外空间的帮助下,对元素计数然后输出排序后的数组。计数排序的优化版本有以下特点:/ Counting sort is a non-comparative sorting algorithm suitable for sorting integers within a certain range. It counts elements with the help of extra space and then outputs the sorted array. The optimized version of counting sort has the following characteristics: + * 1、适用于数组中的元素是对象,且每个对象有一个名为 'key' 的整数属性 / Suitable for arrays where elements are objects, each with an integer property named 'key' + * 2、通过直接使用 'key' 值作为索引,避免了额外的映射步骤,提高了排序效率 / Uses the 'key' value directly as an index, avoiding extra mapping steps and improving sorting efficiency + * 3、专门针对具有特定结构的数据进行优化 / Specifically optimized for data with a particular structure + * + * 与之相比,本函数为更通用的计数排序实现:/ In contrast, this function is a more general implementation of counting sort: + * 1、能够处理数字、字符串和其他非数字类型的元素 / Capable of handling numbers, strings, and other non-numeric elements + * 2、由于需要将非数字元素映射为索引,因此效率略低 / Slightly less efficient due to the need to map non-numeric elements to indices + * 3、适用于更广泛的数据类型,但牺牲了一些效率 / Suitable for a wider range of data types but sacrifices some efficiency + * @usageScenario 适用于小范围整数排序,特别是当O(n)的时间复杂度是必要的 / Suitable for sorting small range integers, especially when O(n) time complexity is necessary + * @timeComplexity O(n + k),其中k是整数的范围 / O(n + k), where k is the range of the integers + * @param {any[]} array 待排序数组 / Array to be sorted + * @param {boolean} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result + * @returns {any[]} 返回排序后的数组 / Returns the sorted array + */ +const countingSort = (array: any[], modifyOriginal: boolean = true, reverse: boolean = false): any[] => { + !modifyOriginal && (array = [...array]); + + if (array.length <= 1) { + return array; + } + + // 分离数字和非数字元素 + const numericElements = array.filter((item) => typeof item === 'number' && item !== Infinity && item !== -Infinity); + const nonNumericElements = array.filter((item) => typeof item !== 'number'); + + // 对数字元素进行计数排序 + const maxVal = Math.max(...numericElements); + const minVal = Math.min(...numericElements); + const counts = new Array(maxVal - minVal + 1).fill(0); + + numericElements.forEach((element) => { + counts[element - minVal]++; + }); + + // 重建排序后的数组 + const sortedArray: any[] = []; + counts.forEach((count, index) => { + for (let i = 0; i < count; i++) { + sortedArray.push(index + minVal); + } + }); + + // 将非数字元素追加到排序数组的尾部 + sortedArray.push(...nonNumericElements); + + // 处理 Infinity 和 -Infinity + const negInfinity = array.filter((element) => element === -Infinity); + const posInfinity = array.filter((element) => element === Infinity); + + const result = [...negInfinity, ...sortedArray, ...posInfinity]; + + return reverse ? result.reverse() : result; +}; + +export default countingSort; diff --git a/src/sorts/counting/optimized/index.test.ts b/src/sorts/counting/optimized/index.test.ts new file mode 100644 index 0000000..37fbc7e --- /dev/null +++ b/src/sorts/counting/optimized/index.test.ts @@ -0,0 +1,91 @@ +import { TCountingOptimizedData } from '@/interface'; +import optimized from '.'; + +describe('优化版计数排序测试', () => { + it('对 1个元素数组 进行排序', () => { + const input: TCountingOptimizedData[] = [{ key: 3 }]; + const expected = [{ key: 3 }]; + const result = optimized(input); + + expect(result).to.deep.equal(expected); + }); + + it('应正确排序包含数字key的对象数组', () => { + const input: TCountingOptimizedData[] = [{ key: 3 }, { key: 1 }, { key: 2 }, { key: 5 }, { key: 4 }]; + const expected = [{ key: 1 }, { key: 2 }, { key: 3 }, { key: 4 }, { key: 5 }]; + expect(optimized(input)).toEqual(expected); + }); + + it('应处理空数组', () => { + const input: TCountingOptimizedData[] = []; + const expected: TCountingOptimizedData[] = []; + expect(optimized(input)).toEqual(expected); + }); + + it('应处理仅有一个元素的数组', () => { + const input: TCountingOptimizedData[] = [{ key: 1 }]; + const expected = [{ key: 1 }]; + expect(optimized(input)).toEqual(expected); + }); + + it('字符串数字,应该滤掉', () => { + const input: any[] = [{ key: '1' }, { key: 2 }, { key: '3' }, { key: 4 }]; + const expected = [{ key: 2 }, { key: 4 }]; + expect(optimized(input)).toEqual(expected); + }); + + it('应正确处理具有混合类型key的数组', () => { + const input: any[] = [{ key: 'a' }, { key: 2 }, { key: 'b' }, { key: 1 }]; + const expected = [{ key: 1 }, { key: 2 }]; + expect(optimized(input)).toEqual(expected); + }); + + it('应当在reverse参数为true时返回反向排序结果', () => { + const input: TCountingOptimizedData[] = [{ key: 3 }, { key: 1 }, { key: 2 }]; + const expected = [{ key: 3 }, { key: 2 }, { key: 1 }]; + expect(optimized(input, true, true)).toEqual(expected); + }); + + it('在不修改原数组的情况下进行排序', () => { + const input: TCountingOptimizedData[] = [{ key: 3 }, { key: 1 }, { key: 2 }]; + const expected = [{ key: 1 }, { key: 2 }, { key: 3 }]; + const original = [...input]; + const sorted = optimized(input, false); + expect(sorted).toEqual(expected); + expect(input).toEqual(original); + }); + + it('处理所有key值相同的数组', () => { + const input = Array.from({ length: 5 }, () => ({ key: 2 })); + const expected = input.slice(); + expect(optimized(input)).toEqual(expected); + }); + + it('过滤掉非数字key的对象', () => { + const input: any = [{ key: 'a' }, { key: 2 }, { key: 'b' }, { key: 1 }, { key: true }]; + const expected = [{ key: 1 }, { key: 2 }]; + expect(optimized(input)).toEqual(expected); + }); + + it('反向排序且不修改原数组', () => { + const input = [{ key: 3 }, { key: 1 }, { key: 2 }]; + const expected = [{ key: 3 }, { key: 2 }, { key: 1 }]; + const original = [...input]; + expect(optimized(input, false, true)).toEqual(expected); + expect(input).toEqual(original); + }); + + it('处理具有非常大的key值的对象', () => { + const input = [{ key: 10000 }, { key: 9999 }, { key: 10001 }]; + const expected = [{ key: 9999 }, { key: 10000 }, { key: 10001 }]; + expect(optimized(input)).toEqual(expected); + }); + + it('处理非常长的数组', () => { + const longArray = Array.from({ length: 10000 }, (_, i) => ({ key: i % 100 })); + const result = optimized(longArray); + expect(result.length).toBe(10000); + expect(result[0]).toHaveProperty('key'); + expect(result[result.length - 1]).toHaveProperty('key'); + }); +}); diff --git a/src/sorts/counting/optimized/index.ts b/src/sorts/counting/optimized/index.ts new file mode 100644 index 0000000..dedd971 --- /dev/null +++ b/src/sorts/counting/optimized/index.ts @@ -0,0 +1,38 @@ +import { TCountingOptimizedData } from '@/interface'; + +/** + * 计数排序(优化版本)/ Counting Sort (Optimized Version) + * @description 这个 optimized 函数是一个优化版本的计数排序算法,专门用于对包含键值对的对象数组进行排序。该算法主要针对对象中的 key 属性进行排序,其中 key 需要是数字类型。/ This optimized function is an optimized version of the counting sort algorithm, specifically for sorting arrays of objects with key-value pairs. The algorithm primarily sorts based on the key attribute in the objects, where the key needs to be a numeric type. + * @usageScenario 适用于需要根据对象的某个数字键值进行排序的场景,尤其是当这些键值分布在一定范围内时。可以选择是否修改原数组以及是否反转排序结果。/ Suitable for scenarios where sorting is required based on a numeric key value of objects, especially when these key values are within a certain range. You can choose whether to modify the original array and whether to reverse the sort result. + * @timeComplexity 平均和最坏情况为 O(n + k),其中 n 是数组长度,k 是键值的范围。/ Average and worst-case complexity is O(n + k), where n is the length of the array and k is the range of the key values. + * @param {Array} array 要排序的数组 / Array to be sorted + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result + * @returns {Array} 返回排序后的数组 / Returns the sorted array + */ +const optimized = (array: TCountingOptimizedData[], modifyOriginal: boolean = true, reverse: boolean = false): TCountingOptimizedData[] => { + !modifyOriginal && (array = [...array]); + if (array.length <= 1) { + return array; + } + + const filteredArray = array.filter((obj) => typeof obj.key === 'number'); + const maxKey = filteredArray.reduce((max, obj) => Math.max(max, obj.key), 0); + const minKey = filteredArray.reduce((min, obj) => Math.min(min, obj.key), maxKey); + + const count: any[] = []; + filteredArray.forEach((obj: TCountingOptimizedData) => { + count[obj.key] = count[obj.key] ? [...count[obj.key], obj] : [obj]; + }); + + const result = []; + for (let i = minKey; i <= maxKey; i++) { + if (count[i]) { + result.push(...count[i]); + } + } + + return reverse ? result.reverse() : result; +}; + +export default optimized; diff --git a/src/sorts/heap/index.test.ts b/src/sorts/heap/index.test.ts new file mode 100644 index 0000000..61ae139 --- /dev/null +++ b/src/sorts/heap/index.test.ts @@ -0,0 +1,79 @@ +import heap from '.'; + +describe('堆排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = heap(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = heap(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = heap(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = heap(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + heap(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = heap(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = heap(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = heap(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = heap(input, true); + expect(result).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = heap(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/heap/index.ts b/src/sorts/heap/index.ts new file mode 100644 index 0000000..0a4f501 --- /dev/null +++ b/src/sorts/heap/index.ts @@ -0,0 +1,71 @@ +import compare from '@/internal/compare'; + +/** + * 调整堆(非递归方式)/ Adjust Heap (Non-recursive Method) + * @param arr {T[]} 原数组 / Original array + * @param size {number} 堆的大小 / Size of the heap + * @param i {number} 当前节点 / Current node + * @param {comp} comp 比较类实例 / Comparison class instance + */ +const heapify = (arr: T[], size: number, i: number, comp: compare) => { + let largest = i; + while (i < size) { + const left = 2 * i + 1; + const right = 2 * i + 2; + let newLargest = largest; + + if (left < size && comp.greaterThan(arr[left], arr[newLargest])) { + newLargest = left; + } + + if (right < size && comp.greaterThan(arr[right], arr[newLargest])) { + newLargest = right; + } + + if (newLargest !== largest) { + [arr[largest], arr[newLargest]] = [arr[newLargest], arr[largest]]; + largest = newLargest; + i = largest; // 更新当前节点,继续调整 + } else { + break; // 如果未发生交换,则结束循环 + } + } +}; + +/** + * 堆排序 / Heap Sort + * @description 堆排序利用堆这种数据结构所设计的排序算法,通过构造最大堆或最小堆来排序 / Heap sort is a sorting algorithm designed using the heap data structure, sorting by constructing a max heap or min heap + * @usageScenario 适用于无需全部存储在内存的大数据集 / Suitable for large datasets that do not need to be entirely stored in memory + * @timeComplexity 最好、最坏和平均情况均为 O(n log n) / Best, worst, and average cases all O(n log n) + * @param array {T[]} 要排序的数组 / Array to be sorted + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result + * @returns {T[]} 返回排序后的数组 / Returns the sorted array + */ +const heap = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + if (array.length <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + const n = array.length; + + // 建立最大堆 + for (let i = Math.floor(n / 2) - 1; i >= 0; i--) { + heapify(array, n, i, comp); + } + + // 一个个从堆顶取出元素 + for (let i = n - 1; i > 0; i--) { + [array[0], array[i]] = [array[i], array[0]]; // 交换 + heapify(array, i, 0, comp); + } + + return array; +}; + +export default heap; diff --git a/src/sorts/insertion/index.test.ts b/src/sorts/insertion/index.test.ts new file mode 100644 index 0000000..3a8d602 --- /dev/null +++ b/src/sorts/insertion/index.test.ts @@ -0,0 +1,79 @@ +import insertion from '.'; + +describe('插入排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = insertion(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = insertion(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = insertion(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = insertion(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + insertion(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = insertion(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = insertion(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = insertion(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = insertion(input, true); + expect(result).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = insertion(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/insertion/index.ts b/src/sorts/insertion/index.ts new file mode 100644 index 0000000..122d7f5 --- /dev/null +++ b/src/sorts/insertion/index.ts @@ -0,0 +1,38 @@ +import compare from '@/internal/compare'; + +/** + * 插入排序 / Insertion Sort + * @param array {T[]} 要排序的数组 / Array to be sorted + * @description 插入排序是一种简单直观的排序算法,通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入 / Insertion sort is a simple and intuitive sorting algorithm, building an ordered sequence by scanning backwards through the sorted sequence to find the appropriate position and insert the unsorted data + * @usageScenario 适合少量数据或基本有序的数据 / Suitable for small amounts of data or data that is mostly ordered + * @timeComplexity 平均和最坏情况 O(n^2),最好情况 O(n) / Average and worst case O(n^2), best case O(n) + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result + * @returns {T[]} 返回排序后的数组 / Returns the sorted array + */ +const insertion = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + if (array.length <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + for (let i = 1, j = array.length; i < j; i++) { + const current = array[i]; + let j = i; + + while (j > 0 && comp.lessThan(current, array[j - 1])) { + array[j] = array[j - 1]; + j--; + } + + array[j] = current; + } + + return array; +}; + +export default insertion; diff --git a/src/sorts/merge/index.test.ts b/src/sorts/merge/index.test.ts new file mode 100644 index 0000000..79d66e6 --- /dev/null +++ b/src/sorts/merge/index.test.ts @@ -0,0 +1,79 @@ +import merge from '.'; + +describe('归并排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = merge(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = merge(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = merge(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = merge(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + merge(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = merge(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = merge(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = merge(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = merge(input, true); + expect(result).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = merge(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/merge/index.ts b/src/sorts/merge/index.ts new file mode 100644 index 0000000..b08660c --- /dev/null +++ b/src/sorts/merge/index.ts @@ -0,0 +1,73 @@ +import compare from '@/internal/compare'; + +/** + * 归并两个子数组为一个排序数组。/ Merge two subarrays into one sorted array. + * @param {T[]} array 原数组 / Original array + * @param {number} start 起始索引 / Starting index + * @param {number} mid 中间索引 / Middle index + * @param {number} end 结束索引 / Ending index + * @param {T[]} tempArray 临时数组 / Temporary array + * @param {comp} comp 比较类实例 / Comparison class instance + */ +const toMerge = (array: T[], start: number, mid: number, end: number, tempArray: T[], comp: compare): void => { + let i = start, + j = mid + 1, + k = 0; + + // 归并到临时数组 + while (i <= mid && j <= end) { + tempArray[k++] = comp.lessThanOrEqual(array[i], array[j]) ? array[i++] : array[j++]; + } + + // 复制剩余的左侧元素 + while (i <= mid) { + tempArray[k++] = array[i++]; + } + + // 复制剩余的右侧元素 + while (j <= end) { + tempArray[k++] = array[j++]; + } + + // 将排序后的临时数组复制回原数组 + for (i = start, k = 0; i <= end; i++, k++) { + array[i] = tempArray[k]; + } +}; + +/** + * 归并排序 / Merge Sort + * @description 归并排序是一种稳定的排序算法,通过递归方式将数据分为更小的子集合,然后合并有序的子集合 / Merge sort is a stable sorting algorithm that divides data into smaller subsets through recursion, then merges the ordered subsets + * @usageScenario 适用于大型数据集,特别是链表类型的数据结构 / Suitable for large datasets, especially for linked-list type data structures + * @timeComplexity 平均、最坏和最好情况均为 O(n log n) / Average, worst, and best cases all O(n log n) + * @param array {T[]} 要排序的数组 / Array to be sorted + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result + * @returns {T[]} 返回排序后的数组 / Returns the sorted array + */ +const merge = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + const n = array.length; + if (array.length <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + const tempArray: T[] = new Array(Math.ceil(n / 2)); + + for (let size = 1; size < n; size *= 2) { + for (let leftStart = 0; leftStart < n - 1; leftStart += 2 * size) { + const mid = Math.min(leftStart + size - 1, n - 1); + const rightEnd = Math.min(leftStart + 2 * size - 1, n - 1); + + toMerge(array, leftStart, mid, rightEnd, tempArray, comp); + } + } + + return array; +}; + +export default merge; diff --git a/src/sorts/pancake/index.test.ts b/src/sorts/pancake/index.test.ts new file mode 100644 index 0000000..98e4917 --- /dev/null +++ b/src/sorts/pancake/index.test.ts @@ -0,0 +1,102 @@ +import pancake from '.'; + +describe('煎饼排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = pancake(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = pancake(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = pancake(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = pancake(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1, 10]; + const expected = [1, 2, 3, 10]; + pancake(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = pancake(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = pancake(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = pancake(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = pancake(input, true); + expect(result).toEqual(expected); + }); + + it('对空数组进行排序', () => { + const input: any = []; + const expected: any = []; + const result = pancake(input); + expect(result).toEqual(expected); + }); + + it('对大型数组进行排序', () => { + const input = Array.from({ length: 64 }, () => Math.floor(Math.random() * 64)); + const expected = [...input].sort((a, b) => a - b); + const result = pancake(input); + expect(result).toEqual(expected); + }); + + it('使用不同的 runSize 进行排序', () => { + const input = [5, 4, 3, 2, 1]; + const expected = [1, 2, 3, 4, 5]; + const resultWithSmallRun = pancake(input, true); + const resultWithLargeRun = pancake(input, true); + expect(resultWithSmallRun).toEqual(expected); + expect(resultWithLargeRun).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = pancake(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/pancake/index.ts b/src/sorts/pancake/index.ts new file mode 100644 index 0000000..09193b9 --- /dev/null +++ b/src/sorts/pancake/index.ts @@ -0,0 +1,65 @@ +import compare from '@/internal/compare'; + +/** + * 翻转数组 / Reverse Array + * @param {T[]} arr 要翻转的数组 / Array to be reversed + * @param {number} i 翻转的边界 / Boundary for reversal + */ +const flip = (arr: T[], i: number) => { + let start = 0; + while (start < i) { + [arr[start], arr[i]] = [arr[i], arr[start]]; + start++; + i--; + } +}; + +/** + * 查找数组中最大元素的索引 / Find the index of the largest element in an array + * @param {T[]} arr 要查找的数组 / Array to search + * @param {number} n 数组长度 / Length of the array + * @param {compare} comp 比较函数 / Comparison function + * @returns {number} 最大元素的索引 / Index of the largest element + */ +const findMaxIndex = (arr: T[], n: number, comp: compare): number => { + let maxIdx = 0; + for (let i = 1; i < n; i++) { + comp.greaterThan(arr[i], arr[maxIdx]) && (maxIdx = i); + } + return maxIdx; +}; + +/** + * 煎饼排序 / Pancake Sorting + * @description 煎饼排序是一种排序算法,通过一系列的煎饼翻转操作来排序数组。在煎饼排序中,允许的操作是反转数组的前 n 个元素。/ Pancake sorting is a sorting algorithm that sorts an array through a series of pancake flipping operations. In pancake sorting, the allowed operation is flipping the first n elements of the array. + * @usageScenario 适用于当翻转操作成本高于比较操作时的排序场景。/ Suitable for sorting scenarios where the cost of flipping operations is higher than comparison operations. + * @timeComplexity 平均情况和最坏情况均为 O(n^2),最好情况为 O(n) / Average and worst case O(n^2), best case O(n) + * @param array {T[]} 要排序的数组 / Array to be sorted + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result + * @returns {T[]} 返回排序后的数组 / Returns the sorted array + */ +const pancake = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + const n = array.length; + if (n <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + for (let currSize = array.length; currSize > 1; --currSize) { + const maxIdx = findMaxIndex(array, currSize, comp); + + if (maxIdx !== currSize - 1) { + flip(array, maxIdx); + flip(array, currSize - 1); + } + } + + return array; +}; + +export default pancake; diff --git a/src/sorts/quick/index.test.ts b/src/sorts/quick/index.test.ts new file mode 100644 index 0000000..a8e1952 --- /dev/null +++ b/src/sorts/quick/index.test.ts @@ -0,0 +1,79 @@ +import quick from '.'; + +describe('快速排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = quick(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = quick(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = quick(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 10, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 10, 'apple', 'b1', 'banana', 'cherry']; + const result = quick(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + quick(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = quick(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = quick(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = quick(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = quick(input, true); + expect(result).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = quick(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/quick/index.ts b/src/sorts/quick/index.ts new file mode 100644 index 0000000..f5ed698 --- /dev/null +++ b/src/sorts/quick/index.ts @@ -0,0 +1,90 @@ +import compare from '@/internal/compare'; + +/** + * 交换数组中的两个元素 / Swap two elements in an array + * @param {Array} arr 要交换元素的数组 / Array containing the elements to swap + * @param {number} x 要交换元素的索引 / Index of the first element to swap + * @param {number} y 要交换元素的索引 / Index of the second element to swap + * @returns {void} 无返回值 / No return value + */ +const swap = (arr: T[], x: number, y: number): void => { + const tmp: T = arr[y]; + arr[y] = arr[x]; + arr[x] = tmp; +}; + +/** + * 分区 / Partition + * @description 将数组分为两部分,左边的元素都小于枢纽元素,右边的元素都大于枢纽元素 / divides the array into two parts, left elements are less than the pivot, right elements are greater than the pivot + * @param {Array} array 要分区的数组 / Array to be partitioned + * @param {number} lo 要分区的数组的起始索引 / Starting index of the array to be partitioned + * @param {number} hi 要分区的数组的结束索引 / Ending index of the array to be partitioned + * @param {comp} comp 比较类实例 / Comparison class instance + * @returns {number} 返回枢纽元素的索引。/ Returns the index of the pivot element. + */ +const partition = (array: T[], lo: number, hi: number, comp: compare): number => { + // 随机选择枢纽元素 + const pivotIndex: number = Math.floor(Math.random() * (hi - lo + 1)) + lo; + const pivot: T = array[pivotIndex]; + + swap(array, pivotIndex, hi); + + let dividerPosition: number = lo; + + for (let i: number = lo; i < hi; i++) { + if (comp.lessThan(array[i], pivot)) { + swap(array, i, dividerPosition); + dividerPosition++; + } + } + + swap(array, dividerPosition, hi); + + return dividerPosition; +}; + +/** + * 快速排序 / Quick Sort + * @description 快速排序是一种基于分治法的高效排序算法。通过选取一个枢轴元素来划分数组,使得一部分元素小于枢轴,另一部分元素大于枢轴 / A highly efficient sorting algorithm based on the divide and conquer method. It partitions the array by selecting a pivot element so that some elements are less than the pivot and others are greater + * @usageScenario 适用于大数据集,不适用于几乎已排序的数据 / Suitable for large datasets, not for nearly sorted data + * @timeComplexity 平均情况 O(n log n),最坏情况 O(n^2) / Average case O(n log n), worst case O(n^2) + * @param {Array} array 要排序的数组 / Array to be sorted + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {(a:T, b:T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result + * @returns {Array} 返回排序后的数组 / Returns the sorted array + */ +const quick = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + if (array.length <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + const stack: number[] = []; + stack.push(0); + stack.push(array.length - 1); + + while (stack.length > 0) { + const hi: number = stack.pop()!; + const lo: number = stack.pop()!; + + const p: number = partition(array, lo, hi, comp); + + if (p - 1 > lo) { + stack.push(lo); + stack.push(p - 1); + } + + if (p + 1 < hi) { + stack.push(p + 1); + stack.push(hi); + } + } + + return array; +}; + +export default quick; diff --git a/src/sorts/radix/index.test.ts b/src/sorts/radix/index.test.ts new file mode 100644 index 0000000..743ce68 --- /dev/null +++ b/src/sorts/radix/index.test.ts @@ -0,0 +1,81 @@ +import radix from '.'; + +describe('基数排序', () => { + it('LSD:对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = radix('lsd', input); + + expect(result).to.deep.equal(expected); + }); + + it('LSD:对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = radix('lsd', input); + + expect(result).to.deep.equal(expected); + }); + + it('LSD:不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + radix('lsd', input); + expect(input).toEqual(expected); + }); + + it('LSD:传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = radix('lsd', input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('LSD:反转', () => { + const input = [3, 2, 1]; + const expected = [3, 2, 1]; + const result = radix('lsd', input, false, true); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('MSD:对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = radix('msd', input); + + expect(result).to.deep.equal(expected); + }); + + it('MSD:对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = radix('msd', input); + + expect(result).to.deep.equal(expected); + }); + + it('MSD:不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + radix('msd', input); + expect(input).toEqual(expected); + }); + + it('MSD:传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = radix('msd', input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('MSD:反转', () => { + const input = [3, 2, 1]; + const expected = [3, 2, 1]; + const result = radix('msd', input, false, true); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/radix/index.ts b/src/sorts/radix/index.ts new file mode 100644 index 0000000..9770309 --- /dev/null +++ b/src/sorts/radix/index.ts @@ -0,0 +1,93 @@ +/** + * 基数排序(LSD)/ Radix Sort (LSD) + * @param {number[]} array 要排序的数组。/ Array to be sorted. + * @returns {number[]} 返回排序后的数组 / Returns the sorted array + */ + +const lsd = (array: number[]): number[] => { + // 计算最大数的位数 + const maxNum = Math.max(...array); + let maxDigit = 0; + while (maxNum / Math.pow(10, maxDigit) >= 1) { + maxDigit++; + } + + for (let digit = 0; digit < maxDigit; digit++) { + // 按当前位数排序 + const buckets: number[][] = Array.from({ length: 10 }, () => []); + for (const num of array) { + const bucketIndex = Math.floor((num / Math.pow(10, digit)) % 10); + buckets[bucketIndex].push(num); + } + // 合并桶中的元素 + //array = [].concat(...(buckets as never[])); + array.splice(0, array.length, ...[].concat(...(buckets as never[]))); + } + + return array; +}; + +/** + * 基数排序(MSD)/ Radix Sort (MSD) + * @param {number[]} array 要排序的数组 / Array to be sorted + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @returns {number[]} 返回排序后的数组 / Returns the sorted array + */ +const msd = (array: number[], modifyOriginal: boolean = true): number[] => { + const getMaxDigits = (arr: number[]): number => { + const maxNum = Math.max(...arr); + return Math.floor(Math.log10(maxNum) + 1); + }; + + const msdSortHelper = (arr: number[], digit: number): number[] => { + if (digit === 0 || arr.length <= 1) { + return arr; + } + + const buckets: number[][] = Array.from({ length: 10 }, () => []); + const radix = Math.pow(10, digit - 1); + + for (let i = 0; i < arr.length; i++) { + const bucketIndex = Math.floor(arr[i] / radix) % 10; + buckets[bucketIndex].push(arr[i]); + } + + for (let i = 0; i < buckets.length; i++) { + buckets[i] = msdSortHelper(buckets[i], digit - 1); + } + + const flattened = [].concat(...(buckets as never[])); + if (modifyOriginal) { + arr.splice(0, arr.length, ...flattened); + return arr; + } else { + return flattened; + } + }; + + return msdSortHelper(array, getMaxDigits(array)); +}; + +/** + * 基数排序 / Radix Sort + * @description 基数排序是一种非比较型整数排序算法,通过分配和收集过程来排序 / A non-comparative integer sorting algorithm that sorts by distributing and collecting + * @usageScenario 适用于大范围整数或字符串排序 / Suitable for large range integer or string sorting + * @timeComplexity O(nk),其中n是排序元素的个数,k是数字的最大位数 / O(nk), where n is the number of elements to sort, k is the maximum number of digits + * @param {'lsd' | 'msd'} type 排序类型,lsd 表示最低位优先(适用于小数据集),msd 表示最高位优先(适用于大数据集) / Type of sort, 'lsd' for least significant digit first (for small datasets), 'msd' for most significant digit first (for large datasets) + * @param {number[]} array 要排序的数组。/ Array to be sorted. + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result + * @returns {number[]} 返回排序后的数组 / Returns the sorted array + */ +const radix = (type: 'lsd' | 'msd', array: number[], modifyOriginal: boolean = true, reverse: boolean = false): number[] => { + !modifyOriginal && (array = [...array]); + if (array.length <= 1) { + return array; + } + + array = type === 'lsd' ? lsd(array) : msd(array, modifyOriginal); + + return reverse ? array.reverse() : array; +}; + +export default radix; diff --git a/src/sorts/selection/index.test.ts b/src/sorts/selection/index.test.ts new file mode 100644 index 0000000..7b529f0 --- /dev/null +++ b/src/sorts/selection/index.test.ts @@ -0,0 +1,79 @@ +import selection from '.'; + +describe('选择排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = selection(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = selection(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = selection(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = selection(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + selection(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = selection(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = selection(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = selection(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = selection(input, true); + expect(result).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = selection(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/selection/index.ts b/src/sorts/selection/index.ts new file mode 100644 index 0000000..8d89721 --- /dev/null +++ b/src/sorts/selection/index.ts @@ -0,0 +1,40 @@ +import compare from '@/internal/compare'; + +/** + * 选择排序 / Selection Sort + * @description 选择排序是一种简单直观的排序算法。它的工作原理是每次从未排序的部分选出最小(或最大)的元素,存放在序列的起始位置 / A simple and intuitive sorting algorithm. It works by selecting the smallest (or largest) element from the unsorted part and placing it at the beginning of the sequence. + * @usageScenario 适用于小型数组 / Suitable for small arrays. + * @timeComplexity 最好、最坏和平均情况均为 O(n^2) / Best, worst, and average cases are all O(n^2). + * @param {T[]} array 要排序的数组 / Array to be sorted. + * @param {boolean} [modifyOriginal=true] 是否修改原数组。/ Whether to modify the original array. + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements. + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result. + * @returns {T[]} 返回排序后的数组 / Returns the sorted array. + */ +const selection = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + if (array.length <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + const n = array.length; + for (let i = 0; i < n - 1; i++) { + let min = i; + for (let j = i + 1; j < n; j++) { + if (comp.greaterThan(array[min], array[j])) { + min = j; + } + } + if (min !== i) { + const tmp = array[i]; + array[i] = array[min]; + array[min] = tmp; + } + } + return array; +}; + +export default selection; diff --git a/src/sorts/shell/index.test.ts b/src/sorts/shell/index.test.ts new file mode 100644 index 0000000..ac769dc --- /dev/null +++ b/src/sorts/shell/index.test.ts @@ -0,0 +1,79 @@ +import shell from '.'; + +describe('希尔排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = shell(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = shell(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = shell(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = shell(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + shell(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = shell(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = shell(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = shell(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = shell(input, true); + expect(result).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = shell(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/shell/index.ts b/src/sorts/shell/index.ts new file mode 100644 index 0000000..199eaa6 --- /dev/null +++ b/src/sorts/shell/index.ts @@ -0,0 +1,42 @@ +import compare from '@/internal/compare'; + +/** + * 希尔排序 / Shell Sort + * @description 希尔排序是插入排序的一种更高效的改进版本。它通过将原始列表分割成多个子列表,分别进行插入排序 / An enhanced version of insertion sort. It divides the original list into multiple sublists and sorts them individually. + * @usageScenario 适用于中等大小的数组 / Suitable for medium-sized arrays. + * @timeComplexity 时间复杂度取决于间隔序列,最坏情况可达 O(n^2),但对于某些间隔序列可低至 O(n log n) / Time complexity depends on the gap sequence; worst case can be O(n^2), but some sequences can lower it to O(n log n). + * @param array {T[]} 要排序的数组。/ Array to be sorted. + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array. + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements. + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result. + * @returns {T[]} 返回排序后的数组 / Returns the sorted array. + */ +const shell = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false): T[] => { + !modifyOriginal && (array = [...array]); + if (array.length <= 1) { + return array; + } + + const comp = new compare(compareFunction); + reverse && comp.reverse(); + + let gap = Math.floor(array.length / 2); + + while (gap > 0) { + for (let i = gap; i < array.length; i++) { + const temp = array[i]; + let j = i - gap; + while (j >= 0 && comp.greaterThan(array[j], temp)) { + array[j + gap] = array[j]; + j -= gap; + } + array[j + gap] = temp; + } + // 减小间隔 + gap = Math.floor(gap / 2); + } + + return array; +}; + +export default shell; diff --git a/src/sorts/tim/index.test.ts b/src/sorts/tim/index.test.ts new file mode 100644 index 0000000..4d0d964 --- /dev/null +++ b/src/sorts/tim/index.test.ts @@ -0,0 +1,102 @@ +import tim from '.'; + +describe('定序排序', () => { + it('对 1个元素数组 进行排序', () => { + const input = [3]; + const expected = [3]; + const result = tim(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 4, 5, 6, 9]; + const result = tim(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串数组 进行排序', () => { + const input = ['banana', 'apple', 'cherry']; + const expected = ['apple', 'banana', 'cherry']; + const result = tim(input); + + expect(result).to.deep.equal(expected); + }); + + it('对 字符串和数字数组 进行排序', () => { + const input = [3, 1, 4, 1, 'banana', 'b1', 5, 3, 5, 8, 9, 7, 9, 3, 'apple', 'cherry', 5, 9, 2, 6]; + const expected = [1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7, 8, 9, 9, 9, 'apple', 'b1', 'banana', 'cherry']; + const result = tim(input); + + expect(result).to.deep.equal(expected); + }); + + it('不传递 modifyOriginal 参数,应该修改原数组', () => { + const input = [3, 2, 1, 10]; + const expected = [1, 2, 3, 10]; + tim(input); + expect(input).toEqual(expected); + }); + + it('传递 modifyOriginal 为 false,不应修改原数组', () => { + const input = [3, 2, 1]; + const expected = [1, 2, 3]; + const result = tim(input, false); + expect(input).toEqual(input); + expect(result).toEqual(expected); + }); + + it('不传递 compareFunction 参数,使用默认比较函数', () => { + const input = ['b', 'a', 'c']; + const expected = ['a', 'b', 'c']; + const result = tim(input); + expect(result).toEqual(expected); + }); + + it('使用自定义 compareFunction 进行逆序排序', () => { + const customCompare = (a: string | number, b: string | number) => (a < b ? 1 : -1); + const input = [1, 3, 2]; + const expected = [3, 2, 1]; + const result = tim(input, true, customCompare); + expect(result).toEqual(expected); + }); + + it('传递自定义的比较函数,用于混合类型数组', () => { + const input = [3, 'banana', 2, 'apple']; + const expected = [2, 3, 'apple', 'banana']; + const result = tim(input, true); + expect(result).toEqual(expected); + }); + + it('对空数组进行排序', () => { + const input: any = []; + const expected: any = []; + const result = tim(input); + expect(result).toEqual(expected); + }); + + it('对大型数组进行排序', () => { + const input = Array.from({ length: 64 }, () => Math.floor(Math.random() * 64)); + const expected = [...input].sort((a, b) => a - b); + const result = tim(input); + expect(result).toEqual(expected); + }); + + it('使用不同的 runSize 进行排序', () => { + const input = [5, 4, 3, 2, 1]; + const expected = [1, 2, 3, 4, 5]; + const resultWithSmallRun = tim(input, true, undefined, false, 5); + const resultWithLargeRun = tim(input, true, undefined, false, 100); + expect(resultWithSmallRun).toEqual(expected); + expect(resultWithLargeRun).toEqual(expected); + }); + + it('反转排序', () => { + const input = [6, 5, 7, 'banana', 'apple', 3, 2]; + const expected = ['banana', 'apple', 7, 6, 5, 3, 2]; + const result = tim(input, true, undefined, true); + expect(result).toEqual(expected); + }); +}); diff --git a/src/sorts/tim/index.ts b/src/sorts/tim/index.ts new file mode 100644 index 0000000..f6bb6ce --- /dev/null +++ b/src/sorts/tim/index.ts @@ -0,0 +1,56 @@ +import insertion from '@/sorts/insertion'; +import merge from '@/sorts/merge'; + +/** + * 定序排序 / Tim Sort + * @description 定序排序是一种混合排序算法,结合了插入排序和归并排序的优点,对部分有序的数据集表现出色 / A hybrid sorting algorithm combining the best of insertion and merge sort, excellent for partially ordered datasets + * @usageScenario 适用于各种大小的数据集,特别是部分有序数据 / Suitable for datasets of various sizes, especially for partially ordered data + * @timeComplexity 平均情况 O(n log n),最坏情况 O(n log n),最好情况 O(n) / Average case O(n log n), worst case O(n log n), best case O(n) + * @param array {T[]} 要排序的数组 / Array to be sorted + * @param {modifyOriginal} [modifyOriginal = true] 是否修改原数组 / Whether to modify the original array + * @param {(a: T, b: T) => number} [compareFunction] 比较函数,定义元素的排序方式 / Comparison function, defines the sorting order of elements + * @param {boolean} [reverse = false] 是否反转结果 / Whether to reverse the result + * @param {number} [runSize = 32] 分块大小,用于决定何时使用插入排序 / Run size, used to determine when to use insertion sort + * @returns {T[]} 返回排序后的数组 / Returns the sorted array + */ +const tim = (array: T[], modifyOriginal: boolean = true, compareFunction?: (a: T, b: T) => number, reverse: boolean = false, runSize: number = 32): T[] => { + !modifyOriginal && (array = [...array]); + const n = array.length; + if (n <= 1) { + return array; + } + + // 对数组进行分块,并对每个块应用插入排序 + for (let i = 0; i < n; i += runSize) { + const end = Math.min(i + runSize, n); + // 先复制需要排序的子数组 + const tempArray = array.slice(i, end); + // 对子数组进行排序 + insertion(tempArray, true, compareFunction, reverse); + // 将排序后的子数组复制回 array + for (let j = i; j < end; j++) { + array[j] = tempArray[j - i]; + } + } + + // 归并已排序的块 + for (let size = runSize; size < n; size *= 2) { + for (let left = 0; left < n; left += 2 * size) { + // const mid = Math.min(left + size, n); + const right = Math.min(left + 2 * size, n); + + // 先复制需要归并的子数组 + const tempArray = array.slice(left, right); + // 对子数组进行归并排序 + merge(tempArray, true, compareFunction, reverse); + // 将排序后的子数组复制回 array + for (let j = left; j < right; j++) { + array[j] = tempArray[j - left]; + } + } + } + + return array; +}; + +export default tim; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..4164785 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + }, + "allowJs": true, + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["dom", "ES2020"], + "module": "ESNext", + "skipLibCheck": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true, + "types": ["vitest/globals"] + }, + "include": ["./src", "./typings.d.ts"], + "typeRoots": ["node_modules/@types", "vitest/globals", "./typings.d.ts"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..bd78fff --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "rootDir": "./" + }, + "include": ["vite.config.ts", "./configs/vite.ts", "./configs/vitest.ts"] +} diff --git a/typings.d.ts b/typings.d.ts new file mode 100644 index 0000000..626014c --- /dev/null +++ b/typings.d.ts @@ -0,0 +1,2 @@ +declare module 'chance'; +declare module 'algorithms'; diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..565cc0a --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,10 @@ +import { defineConfig } from 'vite'; +import { configServer, configDts, configBuild, configResolve } from './configs/vite'; + +export default defineConfig({ + base: './', + server: configServer(), + plugins: [configDts], + build: configBuild('AlgorithmSorts', 'algorithm-sorts', ['cjs', 'esm', 'umd']), + resolve: configResolve +}); diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 0000000..9e91530 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,8 @@ +import configTest from './configs/vitest'; +import { defineConfig } from 'vitest/config'; +import { configResolve } from './configs/vite'; + +export default defineConfig({ + test: configTest, + resolve: configResolve +});