diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index 17aab4f..d0af1e3 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -1,3 +1,4 @@ +# https://github.com/release-drafter/release-drafter#example name-template: 'redis-shake-v$RESOLVED_VERSION' tag-template: 'v$RESOLVED_VERSION' template: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4ba9c3e..34c20b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,6 +8,7 @@ jobs: strategy: matrix: redis-version: [ "2.8", "3.0", "4.0", "5.0", "6.0", "7.0" ] + container: ubuntu:latest steps: - name: Git checkout uses: actions/checkout@v2 @@ -19,7 +20,8 @@ jobs: - name: clone and make redis run: | - sudo apt-get install git + apt-get update + apt-get install -y --no-install-recommends git build-essential ca-certificates git clone https://github.com/redis/redis cd redis git checkout ${{ matrix.redis-version }} @@ -39,5 +41,5 @@ jobs: - name: test run: | - pip3 install -r tests/requirements.txt + python -m pip install -r tests/requirements.txt sh test.sh \ No newline at end of file diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 9cfcdaa..8cf2116 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -1,33 +1,63 @@ +# Sample workflow for building and deploying a VitePress site to GitHub Pages +# name: Pages + on: - workflow_dispatch: { } + # Runs on pushes targeting the `main` branch. Change this to `master` if you're + # using the `master` branch as the default branch. push: - branches: - - main + branches: [ v4 ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: pages + cancel-in-progress: false + jobs: - deploy: + # Build job + build: runs-on: ubuntu-latest - permissions: - pages: write - id-token: write - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 0 - - uses: actions/setup-node@v3 + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Node + uses: actions/setup-node@v3 with: - node-version: 16 + node-version: 18 cache: npm - - run: npm ci - - name: Build - run: npm run docs:build - - uses: actions/configure-pages@v2 - - uses: actions/upload-pages-artifact@v1 + cache-dependency-path: docs/package-lock.json + - name: Setup Pages + uses: actions/configure-pages@v3 + - name: Install dependencies + run: npm ci # or pnpm install / yarn install + working-directory: docs + - name: Build with VitePress + run: npm run docs:build # or pnpm docs:build / yarn docs:build + working-directory: docs + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 with: path: docs/.vitepress/dist - - name: Deploy + + # Deployment job + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + needs: build + runs-on: ubuntu-latest + name: Deploy + steps: + - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1 \ No newline at end of file + uses: actions/deploy-pages@v2 \ No newline at end of file diff --git a/README.md b/README.md index 23fa104..1bb1dd2 100644 --- a/README.md +++ b/README.md @@ -2,122 +2,17 @@ [![CI](https://RedisShake/actions/workflows/ci.yml/badge.svg?branch=v3)](https://RedisShake/actions/workflows/ci.yml) -- [中文文档](https://RedisShake/wiki) +- [中文文档](https://tair-opensource.github.io/RedisShake/) +- [English Document](https://tair-opensource.github.io/RedisShake/en/) redis-shake is a tool for Redis data migration and data filtering. - -## Feature - * 🚄 High performance -* ✅ Tested on Redis 5.0, Redis 6.0 and Redis 7.0 +* ✅ Tested on Redis 2.8, Redis 3.0, Redis 4.0, Redis 5.0, Redis 6.0 and Redis 7.0 * 🤗 Support custom filtering rules * 💪 Support large instance migration * 💖 Support `restore` mode, `sync` mode and `scan` mode * ☁️ Support Aliyun Redis and ElastiCache -For older versions of redis-shake (support codis, twemproxy) please -visit [here](https://RedisShake/tree/develop). - ![redis-shake2.PNG](https://s2.loli.net/2022/07/10/OZrSGutknlI8XNp.png) ![image.png](https://s2.loli.net/2022/06/30/vU346lVBrNofKzu.png) - -# Document - -## Install - -### Binary package - -Download from Release: [https://RedisShake/releases](https://RedisShake/releases) - -### Compile from source - -After downloading the source code, run the `sh build.sh` command to compile. - -```shell -git clone https://RedisShake -cd RedisShake -sh build.sh -``` - -## Usage - -1. Edit `sync.toml` or `restore.toml`. -2. Start redis-shake. - -```shell -./bin/redis-shake redis-shake.toml -# or -./bin/redis-shake restore.toml -``` - -3. Check data synchronization status. - -## Configure - -The redis-shake configuration file refers to `sync.toml` or `restore.toml`. - -## Data filtering - -redis-shake supports custom filtering rules using lua scripts. redis-shake can be started with -the following command: - -```shell -./bin/redis-shake sync.toml filter/xxx.lua -``` - -Some following filter templates are provided in `filter` directory: - -1. `filter/print.lua`:print all commands -2. `filter/swap_db.lua`:swap the data of db0 and db1 - -### Custom filter rules - -Refer to `filter/print.lua` to create a new lua script, and implement the filter function in the lua script. The -arguments of the function are: - -- id: command id -- is_base: is the command read from the dump.rdb file -- group: command group, see the description file - under [redis/src/commands](https://github.com/redis/redis/tree/unstable/src/commands) -- cmd_name: command name -- keys: keys in command -- slots: slots in command -- db_id: database id -- timestamp_ms: timestamp of the command in milliseconds. The current version does not support it. - -The return value is: - -- code - - 0: allow this command to pass - - 1: this command is not allowed to pass - - 2: this command should not appear, and let redis-shake exit with an error -- db_id: redirected db_id - -# Contribution - -## Lua script - -Welcome to share more creative lua scripts. - -1. Add lua scripts under `filters/`. -2. Add description to `README.md`. -3. Submit a pull request. - -## Redis Module support - -1. Add code under `internal/rdb/types`. -2. Add a command file under `scripts/commands`, and use the script to generate a `table.go` file and move it to - the `internal/commands` directory. -3. Add test cases under `test/cases`. -4. Submit a pull request. - -# 感谢 - -redis-shake 旧版是阿里云基于豌豆荚开源的 redis-port 进行二次开发的一个支持 Redis 异构集群实时同步的工具。 -redis-shake v3 在 redis-shake 旧版的基础上重新组织代码结构,使其更具可维护性的版本。 - -redis-shake v3 参考借鉴了以下项目: - -- https://github.com/HDT3213/rdb -- https://github.com/sripathikrishnan/redis-rdb-tools \ No newline at end of file diff --git a/cmd/redis-shake/main.go b/cmd/redis-shake/main.go index b39d1c1..7b1e550 100644 --- a/cmd/redis-shake/main.go +++ b/cmd/redis-shake/main.go @@ -24,46 +24,46 @@ func main() { // create reader var theReader reader.Reader - if v.IsSet("SyncStandaloneReader") { + if v.IsSet("sync_standalone_reader") { opts := new(reader.SyncStandaloneReaderOptions) defaults.SetDefaults(opts) - err := v.UnmarshalKey("SyncStandaloneReader", opts) + err := v.UnmarshalKey("sync_standalone_reader", opts) if err != nil { log.Panicf("failed to read the SyncReader config entry. err: %v", err) } theReader = reader.NewSyncStandaloneReader(opts) log.Infof("create SyncStandaloneReader: %v", opts.Address) - } else if v.IsSet("SyncClusterReader") { + } else if v.IsSet("sync_cluster_reader") { opts := new(reader.SyncClusterReaderOptions) defaults.SetDefaults(opts) - err := v.UnmarshalKey("SyncClusterReader", opts) + err := v.UnmarshalKey("sync_cluster_reader", opts) if err != nil { log.Panicf("failed to read the SyncReader config entry. err: %v", err) } theReader = reader.NewSyncClusterReader(opts) log.Infof("create SyncClusterReader: %v", opts.Address) - } else if v.IsSet("ScanStandaloneReader") { + } else if v.IsSet("scan_standalone_reader") { opts := new(reader.ScanStandaloneReaderOptions) defaults.SetDefaults(opts) - err := v.UnmarshalKey("ScanStandaloneReader", opts) + err := v.UnmarshalKey("scan_standalone_reader", opts) if err != nil { log.Panicf("failed to read the ScanReader config entry. err: %v", err) } theReader = reader.NewScanStandaloneReader(opts) log.Infof("create ScanStandaloneReader: %v", opts.Address) - } else if v.IsSet("ScanClusterReader") { + } else if v.IsSet("scan_cluster_reader") { opts := new(reader.ScanClusterReaderOptions) defaults.SetDefaults(opts) - err := v.UnmarshalKey("ScanClusterReader", opts) + err := v.UnmarshalKey("scan_cluster_reader", opts) if err != nil { log.Panicf("failed to read the ScanReader config entry. err: %v", err) } theReader = reader.NewScanClusterReader(opts) log.Infof("create ScanClusterReader: %v", opts.Address) - } else if v.IsSet("RdbReader") { + } else if v.IsSet("rdb_reader") { opts := new(reader.RdbReaderOptions) defaults.SetDefaults(opts) - err := v.UnmarshalKey("RdbReader", opts) + err := v.UnmarshalKey("rdb_reader", opts) if err != nil { log.Panicf("failed to read the RdbReader config entry. err: %v", err) } @@ -75,19 +75,19 @@ func main() { // create writer var theWriter writer.Writer - if v.IsSet("RedisStandaloneWriter") { + if v.IsSet("redis_standalone_writer") { opts := new(writer.RedisStandaloneWriterOptions) defaults.SetDefaults(opts) - err := v.UnmarshalKey("RedisStandaloneWriter", opts) + err := v.UnmarshalKey("redis_standalone_writer", opts) if err != nil { log.Panicf("failed to read the RedisStandaloneWriter config entry. err: %v", err) } theWriter = writer.NewRedisStandaloneWriter(opts) log.Infof("create RedisStandaloneWriter: %v", opts.Address) - } else if v.IsSet("RedisClusterWriter") { + } else if v.IsSet("redis_cluster_writer") { opts := new(writer.RedisClusterWriterOptions) defaults.SetDefaults(opts) - err := v.UnmarshalKey("RedisClusterWriter", opts) + err := v.UnmarshalKey("redis_cluster_writer", opts) if err != nil { log.Panicf("failed to read the RedisClusterWriter config entry. err: %v", err) } diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 9b1bba3..28163a5 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -2,28 +2,48 @@ import { defineConfig } from 'vitepress' // https://vitepress.dev/reference/site-config export default defineConfig({ - title: "RedisShake", - description: "RedisShake is a tool for processing and migrating Redis data.", - - themeConfig: { - // https://vitepress.dev/reference/default-theme-config - nav: [ - { text: 'Home', link: '/' }, - { text: 'Examples', link: '/markdown-examples' } - ], - - sidebar: [ - { - text: 'Examples', - items: [ - { text: 'Markdown Examples', link: '/markdown-examples' }, - { text: 'Runtime API Examples', link: '/api-examples' } - ] - } - ], - - socialLinks: [ - { icon: 'github', link: 'https://github.com/tair-opensource/RedisShake' } - ] - } + base: "/RedisShake/", + title: "RedisShake", + description: "RedisShake is a tool for processing and migrating Redis data.", + srcDir: './src', + locales: { + root: { + label: '中文', + lang: 'zh', // optional, will be added as `lang` attribute on `html` tag + themeConfig: { + // https://vitepress.dev/reference/default-theme-config + nav: [ + { text: '主页', link: '/' }, + { text: '使用文档', link: '/zh/guide/getting-started' }, + { text: '云原生内存数据库 Tair', link: 'https://www.aliyun.com/product/apsaradb/kvstore/tair' } + ], + sidebar: [ + { + text: '基础教程', + items: [ + { text: 'RedisShake 简介', link: '/zh/guide/getting-started' }, + { text: '快速上手', link: '/zh/guide/getting-started' }, + { text: '配置文件', link: '/zh/guide/config' } + ] + }, + { + text: '变换/过滤', + items: [ + { text: '上手使用', link: '/zh/transform/getting-started' }, + { text: '样例', link: '/zh/transform/examples' } + ] + } + ], + } + }, + en: { + label: 'English', + lang: 'en', + }, + }, + themeConfig: { + socialLinks: [ + { icon: 'github', link: 'https://github.com/tair-opensource/RedisShake' } + ], + } }) diff --git a/docs/package-lock.json b/docs/package-lock.json index 03785fe..8f9b78b 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -9,21 +9,34 @@ } }, "node_modules/@algolia/autocomplete-core": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.8.2.tgz", - "integrity": "sha512-mTeshsyFhAqw/ebqNsQpMtbnjr+qVOSKXArEj4K0d7sqc8It1XD0gkASwecm9mF/jlOQ4Z9RNg1HbdA8JPdRwQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.9.3.tgz", + "integrity": "sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==", "dev": true, "dependencies": { - "@algolia/autocomplete-shared": "1.8.2" + "@algolia/autocomplete-plugin-algolia-insights": "1.9.3", + "@algolia/autocomplete-shared": "1.9.3" + } + }, + "node_modules/@algolia/autocomplete-plugin-algolia-insights": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.9.3.tgz", + "integrity": "sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==", + "dev": true, + "dependencies": { + "@algolia/autocomplete-shared": "1.9.3" + }, + "peerDependencies": { + "search-insights": ">= 1 < 3" } }, "node_modules/@algolia/autocomplete-preset-algolia": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.8.2.tgz", - "integrity": "sha512-J0oTx4me6ZM9kIKPuL3lyU3aB8DEvpVvR6xWmHVROx5rOYJGQcZsdG4ozxwcOyiiu3qxMkIbzntnV1S1VWD8yA==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.9.3.tgz", + "integrity": "sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==", "dev": true, "dependencies": { - "@algolia/autocomplete-shared": "1.8.2" + "@algolia/autocomplete-shared": "1.9.3" }, "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", @@ -31,144 +44,148 @@ } }, "node_modules/@algolia/autocomplete-shared": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.8.2.tgz", - "integrity": "sha512-b6Z/X4MczChMcfhk6kfRmBzPgjoPzuS9KGR4AFsiLulLNRAAqhP+xZTKtMnZGhLuc61I20d5WqlId02AZvcO6g==", - "dev": true + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.9.3.tgz", + "integrity": "sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==", + "dev": true, + "peerDependencies": { + "@algolia/client-search": ">= 4.9.1 < 6", + "algoliasearch": ">= 4.9.1 < 6" + } }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.0.tgz", - "integrity": "sha512-myRSRZDIMYB8uCkO+lb40YKiYHi0fjpWRtJpR/dgkaiBlSD0plRyB6lLOh1XIfmMcSeBOqDE7y9m8xZMrXYfyQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.19.1.tgz", + "integrity": "sha512-FYAZWcGsFTTaSAwj9Std8UML3Bu8dyWDncM7Ls8g+58UOe4XYdlgzXWbrIgjaguP63pCCbMoExKr61B+ztK3tw==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.17.0" + "@algolia/cache-common": "4.19.1" } }, "node_modules/@algolia/cache-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.0.tgz", - "integrity": "sha512-g8mXzkrcUBIPZaulAuqE7xyHhLAYAcF2xSch7d9dABheybaU3U91LjBX6eJTEB7XVhEsgK4Smi27vWtAJRhIKQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.19.1.tgz", + "integrity": "sha512-XGghi3l0qA38HiqdoUY+wvGyBsGvKZ6U3vTiMBT4hArhP3fOGLXpIINgMiiGjTe4FVlTa5a/7Zf2bwlIHfRqqg==", "dev": true }, "node_modules/@algolia/cache-in-memory": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.0.tgz", - "integrity": "sha512-PT32ciC/xI8z919d0oknWVu3kMfTlhQn3MKxDln3pkn+yA7F7xrxSALysxquv+MhFfNAcrtQ/oVvQVBAQSHtdw==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.19.1.tgz", + "integrity": "sha512-+PDWL+XALGvIginigzu8oU6eWw+o76Z8zHbBovWYcrtWOEtinbl7a7UTt3x3lthv+wNuFr/YD1Gf+B+A9V8n5w==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.17.0" + "@algolia/cache-common": "4.19.1" } }, "node_modules/@algolia/client-account": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.0.tgz", - "integrity": "sha512-sSEHx9GA6m7wrlsSMNBGfyzlIfDT2fkz2u7jqfCCd6JEEwmxt8emGmxAU/0qBfbhRSuGvzojoLJlr83BSZAKjA==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.19.1.tgz", + "integrity": "sha512-Oy0ritA2k7AMxQ2JwNpfaEcgXEDgeyKu0V7E7xt/ZJRdXfEpZcwp9TOg4TJHC7Ia62gIeT2Y/ynzsxccPw92GA==", "dev": true, "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/client-analytics": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.0.tgz", - "integrity": "sha512-84ooP8QA3mQ958hQ9wozk7hFUbAO+81CX1CjAuerxBqjKIInh1fOhXKTaku05O/GHBvcfExpPLIQuSuLYziBXQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.19.1.tgz", + "integrity": "sha512-5QCq2zmgdZLIQhHqwl55ZvKVpLM3DNWjFI4T+bHr3rGu23ew2bLO4YtyxaZeChmDb85jUdPDouDlCumGfk6wOg==", "dev": true, "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/client-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.0.tgz", - "integrity": "sha512-jHMks0ZFicf8nRDn6ma8DNNsdwGgP/NKiAAL9z6rS7CymJ7L0+QqTJl3rYxRW7TmBhsUH40wqzmrG6aMIN/DrQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.19.1.tgz", + "integrity": "sha512-3kAIVqTcPrjfS389KQvKzliC559x+BDRxtWamVJt8IVp7LGnjq+aVAXg4Xogkur1MUrScTZ59/AaUd5EdpyXgA==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/client-personalization": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.0.tgz", - "integrity": "sha512-RMzN4dZLIta1YuwT7QC9o+OeGz2cU6eTOlGNE/6RcUBLOU3l9tkCOdln5dPE2jp8GZXPl2yk54b2nSs1+pAjqw==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.19.1.tgz", + "integrity": "sha512-8CWz4/H5FA+krm9HMw2HUQenizC/DxUtsI5oYC0Jxxyce1vsr8cb1aEiSJArQT6IzMynrERif1RVWLac1m36xw==", "dev": true, "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/client-search": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.0.tgz", - "integrity": "sha512-x4P2wKrrRIXszT8gb7eWsMHNNHAJs0wE7/uqbufm4tZenAp+hwU/hq5KVsY50v+PfwM0LcDwwn/1DroujsTFoA==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.19.1.tgz", + "integrity": "sha512-mBecfMFS4N+yK/p0ZbK53vrZbL6OtWMk8YmnOv1i0LXx4pelY8TFhqKoTit3NPVPwoSNN0vdSN9dTu1xr1XOVw==", "dev": true, "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/@algolia/logger-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.0.tgz", - "integrity": "sha512-DGuoZqpTmIKJFDeyAJ7M8E/LOenIjWiOsg1XJ1OqAU/eofp49JfqXxbfgctlVZVmDABIyOz8LqEoJ6ZP4DTyvw==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.19.1.tgz", + "integrity": "sha512-i6pLPZW/+/YXKis8gpmSiNk1lOmYCmRI6+x6d2Qk1OdfvX051nRVdalRbEcVTpSQX6FQAoyeaui0cUfLYW5Elw==", "dev": true }, "node_modules/@algolia/logger-console": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.0.tgz", - "integrity": "sha512-zMPvugQV/gbXUvWBCzihw6m7oxIKp48w37QBIUu/XqQQfxhjoOE9xyfJr1KldUt5FrYOKZJVsJaEjTsu+bIgQg==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.19.1.tgz", + "integrity": "sha512-jj72k9GKb9W0c7TyC3cuZtTr0CngLBLmc8trzZlXdfvQiigpUdvTi1KoWIb2ZMcRBG7Tl8hSb81zEY3zI2RlXg==", "dev": true, "dependencies": { - "@algolia/logger-common": "4.17.0" + "@algolia/logger-common": "4.19.1" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.0.tgz", - "integrity": "sha512-aSOX/smauyTkP21Pf52pJ1O2LmNFJ5iHRIzEeTh0mwBeADO4GdG94cAWDILFA9rNblq/nK3EDh3+UyHHjplZ1A==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.19.1.tgz", + "integrity": "sha512-09K/+t7lptsweRTueHnSnmPqIxbHMowejAkn9XIcJMLdseS3zl8ObnS5GWea86mu3vy4+8H+ZBKkUN82Zsq/zg==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.17.0" + "@algolia/requester-common": "4.19.1" } }, "node_modules/@algolia/requester-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.0.tgz", - "integrity": "sha512-XJjmWFEUlHu0ijvcHBoixuXfEoiRUdyzQM6YwTuB8usJNIgShua8ouFlRWF8iCeag0vZZiUm4S2WCVBPkdxFgg==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.19.1.tgz", + "integrity": "sha512-BisRkcWVxrDzF1YPhAckmi2CFYK+jdMT60q10d7z3PX+w6fPPukxHRnZwooiTUrzFe50UBmLItGizWHP5bDzVQ==", "dev": true }, "node_modules/@algolia/requester-node-http": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.0.tgz", - "integrity": "sha512-bpb/wDA1aC6WxxM8v7TsFspB7yBN3nqCGs2H1OADolQR/hiAIjAxusbuMxVbRFOdaUvAIqioIIkWvZdpYNIn8w==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.19.1.tgz", + "integrity": "sha512-6DK52DHviBHTG2BK/Vv2GIlEw7i+vxm7ypZW0Z7vybGCNDeWzADx+/TmxjkES2h15+FZOqVf/Ja677gePsVItA==", "dev": true, "dependencies": { - "@algolia/requester-common": "4.17.0" + "@algolia/requester-common": "4.19.1" } }, "node_modules/@algolia/transporter": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.0.tgz", - "integrity": "sha512-6xL6H6fe+Fi0AEP3ziSgC+G04RK37iRb4uUUqVAH9WPYFI8g+LYFq6iv5HS8Cbuc5TTut+Bwj6G+dh/asdb9uA==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.19.1.tgz", + "integrity": "sha512-nkpvPWbpuzxo1flEYqNIbGz7xhfhGOKGAZS7tzC+TELgEmi7z99qRyTfNSUlW7LZmB3ACdnqAo+9A9KFBENviQ==", "dev": true, "dependencies": { - "@algolia/cache-common": "4.17.0", - "@algolia/logger-common": "4.17.0", - "@algolia/requester-common": "4.17.0" + "@algolia/cache-common": "4.19.1", + "@algolia/logger-common": "4.19.1", + "@algolia/requester-common": "4.19.1" } }, "node_modules/@babel/parser": { - "version": "7.21.8", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.8.tgz", - "integrity": "sha512-6zavDGdzG3gUqAdWvlLFfk+36RilI+Pwyuuh7HItyeScCWP3k6i8vKclAQ0bM/0y/Kz/xiwvxhMv9MgTJP5gmA==", + "version": "7.22.10", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz", + "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -178,30 +195,30 @@ } }, "node_modules/@docsearch/css": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.3.4.tgz", - "integrity": "sha512-vDwCDoVXDgopw/hvr0zEADew2wWaGP8Qq0Bxhgii1Ewz2t4fQeyJwIRN/mWADeLFYPVkpz8TpEbxya/i6Tm0WA==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.5.1.tgz", + "integrity": "sha512-2Pu9HDg/uP/IT10rbQ+4OrTQuxIWdKVUEdcw9/w7kZJv9NeHS6skJx1xuRiFyoGKwAzcHXnLp7csE99sj+O1YA==", "dev": true }, "node_modules/@docsearch/js": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.3.4.tgz", - "integrity": "sha512-Xd2saBziXJ1UuVpcDz94zAFEFAM6ap993agh0za2e3LDZLhaW993b1f9gyUL4e1CZLsR076tztG2un2gVncvpA==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@docsearch/js/-/js-3.5.1.tgz", + "integrity": "sha512-EXi8de5njxgP6TV3N9ytnGRLG9zmBNTEZjR4VzwPcpPLbZxxTLG2gaFyJyKiFVQxHW/DPlMrDJA3qoRRGEkgZw==", "dev": true, "dependencies": { - "@docsearch/react": "3.3.4", + "@docsearch/react": "3.5.1", "preact": "^10.0.0" } }, "node_modules/@docsearch/react": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.3.4.tgz", - "integrity": "sha512-aeOf1WC5zMzBEi2SI6WWznOmIo9rnpN4p7a3zHXxowVciqlI4HsZGtOR9nFOufLeolv7HibwLlaM0oyUqJxasw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.5.1.tgz", + "integrity": "sha512-t5mEODdLzZq4PTFAm/dvqcvZFdPDMdfPE5rJS5SC8OUq9mPzxEy6b+9THIqNM9P0ocCb4UC5jqBrxKclnuIbzQ==", "dev": true, "dependencies": { - "@algolia/autocomplete-core": "1.8.2", - "@algolia/autocomplete-preset-algolia": "1.8.2", - "@docsearch/css": "3.3.4", + "@algolia/autocomplete-core": "1.9.3", + "@algolia/autocomplete-preset-algolia": "1.9.3", + "@docsearch/css": "3.5.1", "algoliasearch": "^4.0.0" }, "peerDependencies": { @@ -222,9 +239,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.18.tgz", - "integrity": "sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.19.tgz", + "integrity": "sha512-1uOoDurJYh5MNqPqpj3l/TQCI1V25BXgChEldCB7D6iryBYqYKrbZIhYO5AI9fulf66sM8UJpc3UcCly2Tv28w==", "cpu": [ "arm" ], @@ -238,9 +255,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.18.tgz", - "integrity": "sha512-/iq0aK0eeHgSC3z55ucMAHO05OIqmQehiGay8eP5l/5l+iEr4EIbh4/MI8xD9qRFjqzgkc0JkX0LculNC9mXBw==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.19.tgz", + "integrity": "sha512-4+jkUFQxZkQfQOOxfGVZB38YUWHMJX2ihZwF+2nh8m7bHdWXpixiurgGRN3c/KMSwlltbYI0/i929jwBRMFzbA==", "cpu": [ "arm64" ], @@ -254,9 +271,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.18.tgz", - "integrity": "sha512-x+0efYNBF3NPW2Xc5bFOSFW7tTXdAcpfEg2nXmxegm4mJuVeS+i109m/7HMiOQ6M12aVGGFlqJX3RhNdYM2lWg==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.19.tgz", + "integrity": "sha512-ae5sHYiP/Ogj2YNrLZbWkBmyHIDOhPgpkGvFnke7XFGQldBDWvc/AyYwSLpNuKw9UNkgnLlB/jPpnBmlF3G9Bg==", "cpu": [ "x64" ], @@ -270,9 +287,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.18.tgz", - "integrity": "sha512-6tY+djEAdF48M1ONWnQb1C+6LiXrKjmqjzPNPWXhu/GzOHTHX2nh8Mo2ZAmBFg0kIodHhciEgUBtcYCAIjGbjQ==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.19.tgz", + "integrity": "sha512-HIpQvNQWFYROmWDANMRL+jZvvTQGOiTuwWBIuAsMaQrnStedM+nEKJBzKQ6bfT9RFKH2wZ+ej+DY7+9xHBTFPg==", "cpu": [ "arm64" ], @@ -286,9 +303,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.18.tgz", - "integrity": "sha512-Qq84ykvLvya3dO49wVC9FFCNUfSrQJLbxhoQk/TE1r6MjHo3sFF2tlJCwMjhkBVq3/ahUisj7+EpRSz0/+8+9A==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.19.tgz", + "integrity": "sha512-m6JdvXJQt0thNLIcWOeG079h2ivhYH4B5sVCgqb/B29zTcFd7EE8/J1nIUHhdtwGeItdUeqKaqqb4towwxvglQ==", "cpu": [ "x64" ], @@ -302,9 +319,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.18.tgz", - "integrity": "sha512-fw/ZfxfAzuHfaQeMDhbzxp9mc+mHn1Y94VDHFHjGvt2Uxl10mT4CDavHm+/L9KG441t1QdABqkVYwakMUeyLRA==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.19.tgz", + "integrity": "sha512-G0p4EFMPZhGn/xVNspUyMQbORH3nlKTV0bFNHPIwLraBuAkTeMyxNviTe0ZXUbIXQrR1lrwniFjNFU4s+x7veQ==", "cpu": [ "arm64" ], @@ -318,9 +335,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.18.tgz", - "integrity": "sha512-FQFbRtTaEi8ZBi/A6kxOC0V0E9B/97vPdYjY9NdawyLd4Qk5VD5g2pbWN2VR1c0xhzcJm74HWpObPszWC+qTew==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.19.tgz", + "integrity": "sha512-hBxgRlG42+W+j/1/cvlnSa+3+OBKeDCyO7OG2ICya1YJaSCYfSpuG30KfOnQHI7Ytgu4bRqCgrYXxQEzy0zM5Q==", "cpu": [ "x64" ], @@ -334,9 +351,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.18.tgz", - "integrity": "sha512-jW+UCM40LzHcouIaqv3e/oRs0JM76JfhHjCavPxMUti7VAPh8CaGSlS7cmyrdpzSk7A+8f0hiedHqr/LMnfijg==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.19.tgz", + "integrity": "sha512-qtWyoQskfJlb9MD45mvzCEKeO4uCnDZ7lPFeNqbfaaJHqBiH9qA5Vu2EuckqYZuFMJWy1l4dxTf9NOulCVfUjg==", "cpu": [ "arm" ], @@ -350,9 +367,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.18.tgz", - "integrity": "sha512-R7pZvQZFOY2sxUG8P6A21eq6q+eBv7JPQYIybHVf1XkQYC+lT7nDBdC7wWKTrbvMXKRaGudp/dzZCwL/863mZQ==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.19.tgz", + "integrity": "sha512-X8g33tczY0GsJq3lhyBrjnFtaKjWVpp1gMq5IlF9BQJ3TUfSK74nQnz9mRIEejmcV+OIYn6bkOJeUaU1Knrljg==", "cpu": [ "arm64" ], @@ -366,9 +383,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.18.tgz", - "integrity": "sha512-ygIMc3I7wxgXIxk6j3V00VlABIjq260i967Cp9BNAk5pOOpIXmd1RFQJQX9Io7KRsthDrQYrtcx7QCof4o3ZoQ==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.19.tgz", + "integrity": "sha512-SAkRWJgb+KN+gOhmbiE6/wu23D6HRcGQi15cB13IVtBZZgXxygTV5GJlUAKLQ5Gcx0gtlmt+XIxEmSqA6sZTOw==", "cpu": [ "ia32" ], @@ -382,9 +399,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.18.tgz", - "integrity": "sha512-bvPG+MyFs5ZlwYclCG1D744oHk1Pv7j8psF5TfYx7otCVmcJsEXgFEhQkbhNW8otDHL1a2KDINW20cfCgnzgMQ==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.19.tgz", + "integrity": "sha512-YLAslaO8NsB9UOxBchos82AOMRDbIAWChwDKfjlGrHSzS3v1kxce7dGlSTsrb0PJwo1KYccypN3VNjQVLtz7LA==", "cpu": [ "loong64" ], @@ -398,9 +415,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.18.tgz", - "integrity": "sha512-oVqckATOAGuiUOa6wr8TXaVPSa+6IwVJrGidmNZS1cZVx0HqkTMkqFGD2HIx9H1RvOwFeWYdaYbdY6B89KUMxA==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.19.tgz", + "integrity": "sha512-vSYFtlYds/oTI8aflEP65xo3MXChMwBOG1eWPGGKs/ev9zkTeXVvciU+nifq8J1JYMz+eQ4J9JDN0O2RKF8+1Q==", "cpu": [ "mips64el" ], @@ -414,9 +431,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.18.tgz", - "integrity": "sha512-3dLlQO+b/LnQNxgH4l9rqa2/IwRJVN9u/bK63FhOPB4xqiRqlQAU0qDU3JJuf0BmaH0yytTBdoSBHrb2jqc5qQ==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.19.tgz", + "integrity": "sha512-tgG41lRVwlzqO9tv9l7aXYVw35BxKXLtPam1qALScwSqPivI8hjkZLNH0deaaSCYCFT9cBIdB+hUjWFlFFLL9A==", "cpu": [ "ppc64" ], @@ -430,9 +447,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.18.tgz", - "integrity": "sha512-/x7leOyDPjZV3TcsdfrSI107zItVnsX1q2nho7hbbQoKnmoeUWjs+08rKKt4AUXju7+3aRZSsKrJtaRmsdL1xA==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.19.tgz", + "integrity": "sha512-EgBZFLoN1S5RuB4cCJI31pBPsjE1nZ+3+fHRjguq9Ibrzo29bOLSBcH1KZJvRNh5qtd+fcYIGiIUia8Jw5r1lQ==", "cpu": [ "riscv64" ], @@ -446,9 +463,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.18.tgz", - "integrity": "sha512-cX0I8Q9xQkL/6F5zWdYmVf5JSQt+ZfZD2bJudZrWD+4mnUvoZ3TDDXtDX2mUaq6upMFv9FlfIh4Gfun0tbGzuw==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.19.tgz", + "integrity": "sha512-q1V1rtHRojAzjSigZEqrcLkpfh5K09ShCoIsdTakozVBnM5rgV58PLFticqDp5UJ9uE0HScov9QNbbl8HBo6QQ==", "cpu": [ "s390x" ], @@ -462,9 +479,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.18.tgz", - "integrity": "sha512-66RmRsPlYy4jFl0vG80GcNRdirx4nVWAzJmXkevgphP1qf4dsLQCpSKGM3DUQCojwU1hnepI63gNZdrr02wHUA==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.19.tgz", + "integrity": "sha512-D0IiYjpZRXxGZLQfsydeAD7ZWqdGyFLBj5f2UshJpy09WPs3qizDCsEr8zyzcym6Woj/UI9ZzMIXwvoXVtyt0A==", "cpu": [ "x64" ], @@ -478,9 +495,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.18.tgz", - "integrity": "sha512-95IRY7mI2yrkLlTLb1gpDxdC5WLC5mZDi+kA9dmM5XAGxCME0F8i4bYH4jZreaJ6lIZ0B8hTrweqG1fUyW7jbg==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.19.tgz", + "integrity": "sha512-3tt3SOS8L3D54R8oER41UdDshlBIAjYhdWRPiZCTZ1E41+shIZBpTjaW5UaN/jD1ENE/Ok5lkeqhoNMbxstyxw==", "cpu": [ "x64" ], @@ -494,9 +511,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.18.tgz", - "integrity": "sha512-WevVOgcng+8hSZ4Q3BKL3n1xTv5H6Nb53cBrtzzEjDbbnOmucEVcZeGCsCOi9bAOcDYEeBZbD2SJNBxlfP3qiA==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.19.tgz", + "integrity": "sha512-MxbhcuAYQPlfln1EMc4T26OUoeg/YQc6wNoEV8xvktDKZhLtBxjkoeESSo9BbPaGKhAPzusXYj5n8n5A8iZSrA==", "cpu": [ "x64" ], @@ -510,9 +527,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.18.tgz", - "integrity": "sha512-Rzf4QfQagnwhQXVBS3BYUlxmEbcV7MY+BH5vfDZekU5eYpcffHSyjU8T0xucKVuOcdCsMo+Ur5wmgQJH2GfNrg==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.19.tgz", + "integrity": "sha512-m0/UOq1wj25JpWqOJxoWBRM9VWc3c32xiNzd+ERlYstUZ6uwx5SZsQUtkiFHaYmcaoj+f6+Tfcl7atuAz3idwQ==", "cpu": [ "x64" ], @@ -526,9 +543,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.18.tgz", - "integrity": "sha512-Kb3Ko/KKaWhjeAm2YoT/cNZaHaD1Yk/pa3FTsmqo9uFh1D1Rfco7BBLIPdDOozrObj2sahslFuAQGvWbgWldAg==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.19.tgz", + "integrity": "sha512-L4vb6pcoB1cEcXUHU6EPnUhUc4+/tcz4OqlXTWPcSQWxegfmcOprhmIleKKwmMNQVc4wrx/+jB7tGkjjDmiupg==", "cpu": [ "arm64" ], @@ -542,9 +559,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.18.tgz", - "integrity": "sha512-0/xUMIdkVHwkvxfbd5+lfG7mHOf2FRrxNbPiKWg9C4fFrB8H0guClmaM3BFiRUYrznVoyxTIyC/Ou2B7QQSwmw==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.19.tgz", + "integrity": "sha512-rQng7LXSKdrDlNDb7/v0fujob6X0GAazoK/IPd9C3oShr642ri8uIBkgM37/l8B3Rd5sBQcqUXoDdEy75XC/jg==", "cpu": [ "ia32" ], @@ -558,9 +575,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.18.tgz", - "integrity": "sha512-qU25Ma1I3NqTSHJUOKi9sAH1/Mzuvlke0ioMJRthLXKm7JiSKVwFghlGbDLOO2sARECGhja4xYfRAZNPAkooYg==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.19.tgz", + "integrity": "sha512-z69jhyG20Gq4QL5JKPLqUT+eREuqnDAFItLbza4JCmpvUnIlY73YNjd5djlO7kBiiZnvTnJuAbOjIoZIOa1GjA==", "cpu": [ "x64" ], @@ -586,9 +603,9 @@ "dev": true }, "node_modules/@vitejs/plugin-vue": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.2.2.tgz", - "integrity": "sha512-kNH4wMAqs13UiZe/2If1ioO0Mjz71rr2oALTl2c5ajBIox9Vz/UGW/wGkr7GA3SC6Eb29c1HtzAtxdGfbXAkfQ==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.2.3.tgz", + "integrity": "sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==", "dev": true, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -599,39 +616,39 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.1.tgz", - "integrity": "sha512-5le1qYSBgLWg2jdLrbydlhnPJkkzMw46UrRUvTnOKlfg6pThtm9ohhqBhNPHbr0RcM1MCbK5WZe/3Ghz0SZjpQ==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz", + "integrity": "sha512-cquyDNvZ6jTbf/+x+AgM2Arrp6G4Dzbb0R64jiG804HRMfRiFXWI6kqUVqZ6ZR0bQhIoQjB4+2bhNtVwndW15g==", "dev": true, "dependencies": { "@babel/parser": "^7.21.3", - "@vue/shared": "3.3.1", + "@vue/shared": "3.3.4", "estree-walker": "^2.0.2", "source-map-js": "^1.0.2" } }, "node_modules/@vue/compiler-dom": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.1.tgz", - "integrity": "sha512-VmgIsoLivCft3+oNc5KM7b9wd0nZxP/g2qilMwi1hJyGA624KWnNKHn4hzBQs4FpzydUVpNy+TWVT8KiRCh3MQ==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.4.tgz", + "integrity": "sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==", "dev": true, "dependencies": { - "@vue/compiler-core": "3.3.1", - "@vue/shared": "3.3.1" + "@vue/compiler-core": "3.3.4", + "@vue/shared": "3.3.4" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.1.tgz", - "integrity": "sha512-G+FPwBbXSLaA4+Ry5/bdD9Oda+sRslQcE9o6JSZaougRiT4OjVL0vtkbQHPrGRTULZV28OcrAjRfSZOSB0OTXQ==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz", + "integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==", "dev": true, "dependencies": { "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.1", - "@vue/compiler-dom": "3.3.1", - "@vue/compiler-ssr": "3.3.1", - "@vue/reactivity-transform": "3.3.1", - "@vue/shared": "3.3.1", + "@vue/compiler-core": "3.3.4", + "@vue/compiler-dom": "3.3.4", + "@vue/compiler-ssr": "3.3.4", + "@vue/reactivity-transform": "3.3.4", + "@vue/shared": "3.3.4", "estree-walker": "^2.0.2", "magic-string": "^0.30.0", "postcss": "^8.1.10", @@ -639,13 +656,13 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.1.tgz", - "integrity": "sha512-QOQWGNCWuSeyKx4KvWSJlnIMGg+/2oCHgkFUYo7aJ+9Uaaz45yRgKQ+FNigy50NYBQIhpXn2e4OSR8GXh4knrQ==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.4.tgz", + "integrity": "sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==", "dev": true, "dependencies": { - "@vue/compiler-dom": "3.3.1", - "@vue/shared": "3.3.1" + "@vue/compiler-dom": "3.3.4", + "@vue/shared": "3.3.4" } }, "node_modules/@vue/devtools-api": { @@ -655,86 +672,178 @@ "dev": true }, "node_modules/@vue/reactivity": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.1.tgz", - "integrity": "sha512-zCfmazOtyUdC1NS/EPiSYJ4RqojqmTAviJyBbyVvY8zAv5NhK44Yfw0E1tt+m5vz0ZO1ptI9jDKBr3MWIEkpgw==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz", + "integrity": "sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==", "dev": true, "dependencies": { - "@vue/shared": "3.3.1" + "@vue/shared": "3.3.4" } }, "node_modules/@vue/reactivity-transform": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.1.tgz", - "integrity": "sha512-MkOrJauAGH4MNdxGW/PmrDegMyOGX0wGIdKUZJRBXOTpotDONg7/TPJe2QeGeBCow/5v9iOqZOWCfvmOWIaDMg==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.4.tgz", + "integrity": "sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==", "dev": true, "dependencies": { "@babel/parser": "^7.20.15", - "@vue/compiler-core": "3.3.1", - "@vue/shared": "3.3.1", + "@vue/compiler-core": "3.3.4", + "@vue/shared": "3.3.4", "estree-walker": "^2.0.2", "magic-string": "^0.30.0" } }, "node_modules/@vue/runtime-core": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.1.tgz", - "integrity": "sha512-Ljb37LYafhQqKIasc0r32Cva8gIh6VeSMjlwO6V03tCjHd18gmjP0F4UD+8/a59sGTysAgA8Rb9lIC2DVxRz2Q==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.4.tgz", + "integrity": "sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==", "dev": true, "dependencies": { - "@vue/reactivity": "3.3.1", - "@vue/shared": "3.3.1" + "@vue/reactivity": "3.3.4", + "@vue/shared": "3.3.4" } }, "node_modules/@vue/runtime-dom": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.1.tgz", - "integrity": "sha512-NBjYbQPtMklb7lsJsM2Juv5Ygry6mvZP7PdH1GZqrzfLkvlplQT3qCtQMd/sib6yiy8t9m/Y4hVU7X9nzb9Oeg==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.4.tgz", + "integrity": "sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==", "dev": true, "dependencies": { - "@vue/runtime-core": "3.3.1", - "@vue/shared": "3.3.1", + "@vue/runtime-core": "3.3.4", + "@vue/shared": "3.3.4", "csstype": "^3.1.1" } }, "node_modules/@vue/server-renderer": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.1.tgz", - "integrity": "sha512-sod8ggOwbkQXw3lBjfzrbdxRS9lw/lNHoMaXghHawNYowf+4WoaLWD5ouz6fPZadUqNKAsqK95p8DYb1vcVfPA==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz", + "integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==", "dev": true, "dependencies": { - "@vue/compiler-ssr": "3.3.1", - "@vue/shared": "3.3.1" + "@vue/compiler-ssr": "3.3.4", + "@vue/shared": "3.3.4" }, "peerDependencies": { - "vue": "3.3.1" + "vue": "3.3.4" } }, "node_modules/@vue/shared": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.1.tgz", - "integrity": "sha512-ybDBtQ+479HL/bkeIOIAwgpeAEACzztkvulJLbK3JMFuTOv4qDivmV3AIsR8RHYJ+RD9tQxcHWBsX4GqEcYrfw==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz", + "integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==", "dev": true }, "node_modules/@vueuse/core": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.1.2.tgz", - "integrity": "sha512-roNn8WuerI56A5uiTyF/TEYX0Y+VKlhZAF94unUfdhbDUI+NfwQMn4FUnUscIRUhv3344qvAghopU4bzLPNFlA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.3.0.tgz", + "integrity": "sha512-BEM5yxcFKb5btFjTSAFjTu5jmwoW66fyV9uJIP4wUXXU8aR5Hl44gndaaXp7dC5HSObmgbnR2RN+Un1p68Mf5Q==", "dev": true, "dependencies": { "@types/web-bluetooth": "^0.0.17", - "@vueuse/metadata": "10.1.2", - "@vueuse/shared": "10.1.2", - "vue-demi": ">=0.14.0" + "@vueuse/metadata": "10.3.0", + "@vueuse/shared": "10.3.0", + "vue-demi": ">=0.14.5" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/core/node_modules/vue-demi": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.1.tgz", - "integrity": "sha512-rt+yuCtXvscYot9SQQj3WKZJVSriPNqVkpVBNEHPzSgBv7QIYzsS410VqVgvx8f9AAPgjg+XPKvmV3vOqqkJQQ==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/@vueuse/integrations": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/integrations/-/integrations-10.3.0.tgz", + "integrity": "sha512-Jgiv7oFyIgC6BxmDtiyG/fxyGysIds00YaY7sefwbhCZ2/tjEx1W/1WcsISSJPNI30in28+HC2J4uuU8184ekg==", + "dev": true, + "dependencies": { + "@vueuse/core": "10.3.0", + "@vueuse/shared": "10.3.0", + "vue-demi": ">=0.14.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "async-validator": "*", + "axios": "*", + "change-case": "*", + "drauu": "*", + "focus-trap": "*", + "fuse.js": "*", + "idb-keyval": "*", + "jwt-decode": "*", + "nprogress": "*", + "qrcode": "*", + "sortablejs": "*", + "universal-cookie": "*" + }, + "peerDependenciesMeta": { + "async-validator": { + "optional": true + }, + "axios": { + "optional": true + }, + "change-case": { + "optional": true + }, + "drauu": { + "optional": true + }, + "focus-trap": { + "optional": true + }, + "fuse.js": { + "optional": true + }, + "idb-keyval": { + "optional": true + }, + "jwt-decode": { + "optional": true + }, + "nprogress": { + "optional": true + }, + "qrcode": { + "optional": true + }, + "sortablejs": { + "optional": true + }, + "universal-cookie": { + "optional": true + } + } + }, + "node_modules/@vueuse/integrations/node_modules/vue-demi": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "dev": true, "hasInstallScript": true, "bin": { @@ -758,30 +867,30 @@ } }, "node_modules/@vueuse/metadata": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.1.2.tgz", - "integrity": "sha512-3mc5BqN9aU2SqBeBuWE7ne4OtXHoHKggNgxZR2K+zIW4YLsy6xoZ4/9vErQs6tvoKDX6QAqm3lvsrv0mczAwIQ==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.3.0.tgz", + "integrity": "sha512-Ema3YhNOa4swDsV0V7CEY5JXvK19JI/o1szFO1iWxdFg3vhdFtCtSTP26PCvbUpnUtNHBY2wx5y3WDXND5Pvnw==", "dev": true, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared": { - "version": "10.1.2", - "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.1.2.tgz", - "integrity": "sha512-1uoUTPBlgyscK9v6ScGeVYDDzlPSFXBlxuK7SfrDGyUTBiznb3mNceqhwvZHjtDRELZEN79V5uWPTF1VDV8svA==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.3.0.tgz", + "integrity": "sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==", "dev": true, "dependencies": { - "vue-demi": ">=0.14.0" + "vue-demi": ">=0.14.5" }, "funding": { "url": "https://github.com/sponsors/antfu" } }, "node_modules/@vueuse/shared/node_modules/vue-demi": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.1.tgz", - "integrity": "sha512-rt+yuCtXvscYot9SQQj3WKZJVSriPNqVkpVBNEHPzSgBv7QIYzsS410VqVgvx8f9AAPgjg+XPKvmV3vOqqkJQQ==", + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.5.tgz", + "integrity": "sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==", "dev": true, "hasInstallScript": true, "bin": { @@ -805,31 +914,31 @@ } }, "node_modules/algoliasearch": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.0.tgz", - "integrity": "sha512-JMRh2Mw6sEnVMiz6+APsi7lx9a2jiDFF+WUtANaUVCv6uSU9UOLdo5h9K3pdP6frRRybaM2fX8b1u0nqICS9aA==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.19.1.tgz", + "integrity": "sha512-IJF5b93b2MgAzcE/tuzW0yOPnuUyRgGAtaPv5UUywXM8kzqfdwZTO4sPJBzoGz1eOy6H9uEchsJsBFTELZSu+g==", "dev": true, "dependencies": { - "@algolia/cache-browser-local-storage": "4.17.0", - "@algolia/cache-common": "4.17.0", - "@algolia/cache-in-memory": "4.17.0", - "@algolia/client-account": "4.17.0", - "@algolia/client-analytics": "4.17.0", - "@algolia/client-common": "4.17.0", - "@algolia/client-personalization": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/logger-common": "4.17.0", - "@algolia/logger-console": "4.17.0", - "@algolia/requester-browser-xhr": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/requester-node-http": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/cache-browser-local-storage": "4.19.1", + "@algolia/cache-common": "4.19.1", + "@algolia/cache-in-memory": "4.19.1", + "@algolia/client-account": "4.19.1", + "@algolia/client-analytics": "4.19.1", + "@algolia/client-common": "4.19.1", + "@algolia/client-personalization": "4.19.1", + "@algolia/client-search": "4.19.1", + "@algolia/logger-common": "4.19.1", + "@algolia/logger-console": "4.19.1", + "@algolia/requester-browser-xhr": "4.19.1", + "@algolia/requester-common": "4.19.1", + "@algolia/requester-node-http": "4.19.1", + "@algolia/transporter": "4.19.1" } }, "node_modules/ansi-sequence-parser": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.0.tgz", - "integrity": "sha512-lEm8mt52to2fT8GhciPCGeCXACSz2UwIN4X2e2LJSnZ5uAbn2/dsYdOmUXq0AtWS5cpAupysIneExOgH0Vd2TQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", "dev": true }, "node_modules/body-scroll-lock": { @@ -845,9 +954,9 @@ "dev": true }, "node_modules/esbuild": { - "version": "0.17.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.18.tgz", - "integrity": "sha512-z1lix43jBs6UKjcZVKOw2xx69ffE2aG0PygLL5qJ9OS/gy0Ewd1gW/PUQIOIQGXBHWNywSc0floSKoMFF8aK2w==", + "version": "0.18.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.19.tgz", + "integrity": "sha512-ra3CaIKCzJp5bU5BDfrCc0FRqKj71fQi+gbld0aj6lN0ifuX2fWJYPgLVLGwPfA+ruKna+OWwOvf/yHj6n+i0g==", "dev": true, "hasInstallScript": true, "bin": { @@ -857,28 +966,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.17.18", - "@esbuild/android-arm64": "0.17.18", - "@esbuild/android-x64": "0.17.18", - "@esbuild/darwin-arm64": "0.17.18", - "@esbuild/darwin-x64": "0.17.18", - "@esbuild/freebsd-arm64": "0.17.18", - "@esbuild/freebsd-x64": "0.17.18", - "@esbuild/linux-arm": "0.17.18", - "@esbuild/linux-arm64": "0.17.18", - "@esbuild/linux-ia32": "0.17.18", - "@esbuild/linux-loong64": "0.17.18", - "@esbuild/linux-mips64el": "0.17.18", - "@esbuild/linux-ppc64": "0.17.18", - "@esbuild/linux-riscv64": "0.17.18", - "@esbuild/linux-s390x": "0.17.18", - "@esbuild/linux-x64": "0.17.18", - "@esbuild/netbsd-x64": "0.17.18", - "@esbuild/openbsd-x64": "0.17.18", - "@esbuild/sunos-x64": "0.17.18", - "@esbuild/win32-arm64": "0.17.18", - "@esbuild/win32-ia32": "0.17.18", - "@esbuild/win32-x64": "0.17.18" + "@esbuild/android-arm": "0.18.19", + "@esbuild/android-arm64": "0.18.19", + "@esbuild/android-x64": "0.18.19", + "@esbuild/darwin-arm64": "0.18.19", + "@esbuild/darwin-x64": "0.18.19", + "@esbuild/freebsd-arm64": "0.18.19", + "@esbuild/freebsd-x64": "0.18.19", + "@esbuild/linux-arm": "0.18.19", + "@esbuild/linux-arm64": "0.18.19", + "@esbuild/linux-ia32": "0.18.19", + "@esbuild/linux-loong64": "0.18.19", + "@esbuild/linux-mips64el": "0.18.19", + "@esbuild/linux-ppc64": "0.18.19", + "@esbuild/linux-riscv64": "0.18.19", + "@esbuild/linux-s390x": "0.18.19", + "@esbuild/linux-x64": "0.18.19", + "@esbuild/netbsd-x64": "0.18.19", + "@esbuild/openbsd-x64": "0.18.19", + "@esbuild/sunos-x64": "0.18.19", + "@esbuild/win32-arm64": "0.18.19", + "@esbuild/win32-ia32": "0.18.19", + "@esbuild/win32-x64": "0.18.19" } }, "node_modules/estree-walker": { @@ -887,6 +996,15 @@ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, + "node_modules/focus-trap": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.2.tgz", + "integrity": "sha512-p6vGNNWLDGwJCiEjkSK6oERj/hEyI9ITsSwIUICBoKLlWiTWXJRfQibCwcoi50rTZdbi87qDtUlMCmQwsGSgPw==", + "dev": true, + "dependencies": { + "tabbable": "^6.2.0" + } + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -908,12 +1026,12 @@ "dev": true }, "node_modules/magic-string": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", - "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", + "version": "0.30.2", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.2.tgz", + "integrity": "sha512-lNZdu7pewtq/ZvWUp9Wpf/x7WzMTsR26TWV03BRZrXFsv+BI6dy8RAiKgm1uM/kyR0rCfUcqvOlXKG66KhIGug==", "dev": true, "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.13" + "@jridgewell/sourcemap-codec": "^1.4.15" }, "engines": { "node": ">=12" @@ -926,9 +1044,9 @@ "dev": true }, "node_modules/minisearch": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-6.0.1.tgz", - "integrity": "sha512-Ly1w0nHKnlhAAh6/BF/+9NgzXfoJxaJ8nhopFhQ3NcvFJrFIL+iCg9gw9e9UMBD+XIsp/RyznJ/o5UIe5Kw+kg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/minisearch/-/minisearch-6.1.0.tgz", + "integrity": "sha512-PNxA/X8pWk+TiqPbsoIYH0GQ5Di7m6326/lwU/S4mlo4wGQddIcf/V//1f9TB0V4j59b57b+HZxt8h3iMROGvg==", "dev": true }, "node_modules/nanoid": { @@ -956,9 +1074,9 @@ "dev": true }, "node_modules/postcss": { - "version": "8.4.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", - "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "version": "8.4.27", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz", + "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==", "dev": true, "funding": [ { @@ -984,9 +1102,9 @@ } }, "node_modules/preact": { - "version": "10.13.2", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.13.2.tgz", - "integrity": "sha512-q44QFLhOhty2Bd0Y46fnYW0gD/cbVM9dUVtNTDKPcdXSMA7jfY+Jpd6rk3GB0lcQss0z5s/6CmVP0Z/hV+g6pw==", + "version": "10.16.0", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.16.0.tgz", + "integrity": "sha512-XTSj3dJ4roKIC93pald6rWuB2qQJO9gO2iLLyTe87MrjQN+HklueLsmskbywEWqCHlclgz3/M4YLL2iBr9UmMA==", "dev": true, "funding": { "type": "opencollective", @@ -994,9 +1112,9 @@ } }, "node_modules/rollup": { - "version": "3.21.6", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.21.6.tgz", - "integrity": "sha512-SXIICxvxQxR3D4dp/3LDHZIJPC8a4anKMHd4E3Jiz2/JnY+2bEjqrOokAauc5ShGVNFHlEFjBXAXlaxkJqIqSg==", + "version": "3.27.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.27.2.tgz", + "integrity": "sha512-YGwmHf7h2oUHkVBT248x0yt6vZkYQ3/rvE5iQuVBh3WO8GcJ6BNeOkpoX1yMHIiBm18EMLjBPIoUDkhgnyxGOQ==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -1009,10 +1127,20 @@ "fsevents": "~2.3.2" } }, + "node_modules/search-insights": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.7.0.tgz", + "integrity": "sha512-GLbVaGgzYEKMvuJbHRhLi1qoBFnjXZGZ6l4LxOYPCp4lI2jDRB3jPU9/XNhMwv6kvnA9slTreq6pvK+b3o3aqg==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8.16.0" + } + }, "node_modules/shiki": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.2.tgz", - "integrity": "sha512-ltSZlSLOuSY0M0Y75KA+ieRaZ0Trf5Wl3gutE7jzLuIcWxLp5i/uEnLoQWNvgKXQ5OMpGkJnVMRLAuzjc0LJ2A==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.3.tgz", + "integrity": "sha512-U3S/a+b0KS+UkTyMjoNojvTgrBHjgp7L6ovhFVZsXmBGnVdQ4K4U9oK0z63w538S91ATngv1vXigHCSWOwnr+g==", "dev": true, "dependencies": { "ansi-sequence-parser": "^1.1.0", @@ -1030,15 +1158,21 @@ "node": ">=0.10.0" } }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", + "dev": true + }, "node_modules/vite": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.5.tgz", - "integrity": "sha512-0gEnL9wiRFxgz40o/i/eTBwm+NEbpUeTWhzKrZDSdKm6nplj+z4lKz8ANDgildxHm47Vg8EUia0aicKbawUVVA==", + "version": "4.4.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", + "integrity": "sha512-2mbUn2LlUmNASWwSCNSJ/EG2HuSRTnVNaydp6vMCm5VIqJsjMfbIWtbH2kDuwUVW5mMUKKZvGPX/rqeqVvv1XA==", "dev": true, "dependencies": { - "esbuild": "^0.17.5", - "postcss": "^8.4.23", - "rollup": "^3.21.0" + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" }, "bin": { "vite": "bin/vite.js" @@ -1046,12 +1180,16 @@ "engines": { "node": "^14.18.0 || >=16.0.0" }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, "optionalDependencies": { "fsevents": "~2.3.2" }, "peerDependencies": { "@types/node": ">= 14", "less": "*", + "lightningcss": "^1.21.0", "sass": "*", "stylus": "*", "sugarss": "*", @@ -1064,6 +1202,9 @@ "less": { "optional": true }, + "lightningcss": { + "optional": true + }, "sass": { "optional": true }, @@ -1079,22 +1220,24 @@ } }, "node_modules/vitepress": { - "version": "1.0.0-alpha.75", - "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.0.0-alpha.75.tgz", - "integrity": "sha512-twpPZ/6UnDR8X0Nmj767KwKhXlTQQM9V/J1i2BP9ryO29/w4hpxBfEum6nvfpNhJ4H3h+cIhwzAK/e9crZ6HEQ==", + "version": "1.0.0-beta.7", + "resolved": "https://registry.npmjs.org/vitepress/-/vitepress-1.0.0-beta.7.tgz", + "integrity": "sha512-P9Rw+FXatKIU4fVdtKxqwHl6fby8E/8zE3FIfep6meNgN4BxbWqoKJ6yfuuQQR9IrpQqwnyaBh4LSabyll6tWg==", "dev": true, "dependencies": { - "@docsearch/css": "^3.3.4", - "@docsearch/js": "^3.3.4", - "@vitejs/plugin-vue": "^4.2.1", + "@docsearch/css": "^3.5.1", + "@docsearch/js": "^3.5.1", + "@vitejs/plugin-vue": "^4.2.3", "@vue/devtools-api": "^6.5.0", - "@vueuse/core": "^10.1.0", + "@vueuse/core": "^10.2.1", + "@vueuse/integrations": "^10.2.1", "body-scroll-lock": "4.0.0-beta.0", + "focus-trap": "^7.5.2", "mark.js": "8.11.1", - "minisearch": "^6.0.1", - "shiki": "^0.14.2", - "vite": "^4.3.3", - "vue": "^3.2.47" + "minisearch": "^6.1.0", + "shiki": "^0.14.3", + "vite": "^4.4.7", + "vue": "^3.3.4" }, "bin": { "vitepress": "bin/vitepress.js" @@ -1113,16 +1256,16 @@ "dev": true }, "node_modules/vue": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.1.tgz", - "integrity": "sha512-3Rwy4I5idbPVSDZu6I+fFh6tdDSZbauImCTqLxE7y0LpHtiDvPeY01OI7RkFPbva1nk4hoO0sv/NzosH2h60sg==", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz", + "integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==", "dev": true, "dependencies": { - "@vue/compiler-dom": "3.3.1", - "@vue/compiler-sfc": "3.3.1", - "@vue/runtime-dom": "3.3.1", - "@vue/server-renderer": "3.3.1", - "@vue/shared": "3.3.1" + "@vue/compiler-dom": "3.3.4", + "@vue/compiler-sfc": "3.3.4", + "@vue/runtime-dom": "3.3.4", + "@vue/server-renderer": "3.3.4", + "@vue/shared": "3.3.4" } } } diff --git a/docs/api-examples.md b/docs/src/en/api-examples.md similarity index 100% rename from docs/api-examples.md rename to docs/src/en/api-examples.md diff --git a/docs/index.md b/docs/src/en/index.md similarity index 100% rename from docs/index.md rename to docs/src/en/index.md diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 0000000..ead6a7f --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,25 @@ +--- +# https://vitepress.dev/reference/default-theme-home-page +layout: home + +hero: + name: "RedisShake" + # text: "用于 Redis-like 数据库的数据迁移与处理服务" + tagline: 用于 Redis-like 数据库的数据迁移与处理服务 + actions: + - theme: brand + text: 快速上手 + link: /zh/guide/getting-started + # - theme: alt + # text: 云原生内存数据库Tair + # link: https://www.aliyun.com/product/apsaradb/kvstore/tair + +features: + - title: 数据迁移 + details: 支持 sync、scan 和 restore 三种数据迁移模式 + - title: 数据处理 + details: 支持使用 lua 脚本对数据进行过滤与修改 + - title: 云数据库支持 + details: 兼容主流云厂商的多种架构:主从、集群等 +--- + diff --git a/docs/src/zh/guide/config.md b/docs/src/zh/guide/config.md new file mode 100644 index 0000000..9f19a25 --- /dev/null +++ b/docs/src/zh/guide/config.md @@ -0,0 +1,155 @@ +--- +outline: deep +--- +# 配置文件 + +RedisShake 使用 [TOML](https://toml.io/cn/) 语言书写,所有的配置参数在 all.toml 中均有说明。 + +配置文件的组成如下: + +```toml +transform = "..." + +[xxx_reader] +... + +[xxx_writer] +... + +[advanced] +... +``` + +一般用法下,只需要书写 `xxx_reader`、`xxx_writer` 两个部分即可,`transform` 和 `advanced` 部分为进阶用法,用户可以根据自己的需求进行配置。 + +## reader 配置 + +根据源端的类型,RedisShake 提供了不同的 Reader 配置,用来对接不同的源端。 + +* 对于支持 [Redis Sync/Psync 协议](https://redis.io/docs/management/replication/)的源端,推荐使用 `sync_xxx_reader` +* 对于不支持 [Redis Sync/Psync 协议](https://redis.io/docs/management/replication/)的源端,可以使用 `scan_xxx_reader` +* 对于使用 dump.rdb 文件恢复数据场景,可以使用 `rdb_reader` + +### sync_xxx_reader + +对于源端为单机 Redis-like 数据库时,使用 `sync_standalone_reader`;对于源端为 Redis Cluster 时,使用 `sync_cluster_reader`。 + +#### sync_standlone_reader + +```toml +[sync_standlone_reader] +address = "127.0.0.1:6379" +username = "" # keep empty if not using ACL +password = "" # keep empty if no authentication is required +tls = false +``` + +#### sync_cluster_reader + +```toml +[sync_cluster_reader] +address = "127.0.0.1:6379" +username = "" # keep empty if not using ACL +password = "" # keep empty if no authentication is required +tls = false +``` + +### scan_xxx_reader + +对于源端为单机 Redis-like 数据库时,使用 `scan_standalone_reader`;对于源端为 Redis Cluster 时,使用 `scan_cluster_reader`。 + +#### scan_standlone_reader + +```toml +[scan_standlone_reader] +address = "127.0.0.1:6379" +username = "" # keep empty if not using ACL +password = "" # keep empty if no authentication is required +tls = false +``` + +#### scan_cluster_reader + +```toml +[scan_cluster_reader] +address = "127.0.0.1:6379" +username = "" # keep empty if not using ACL +password = "" # keep empty if no authentication is required +tls = false +``` + +### rdb_reader + +```toml +[rdb_reader] +filepath = "/path/to/dump.rdb" +``` + +filepath 为 dump.rdb 文件的路径,最好使用绝对路径。 + +## writer 配置 + +根据目标端的类型,RedisShake 提供了不同的 Writer 配置,用来对接不同的目标端。 +目前 RedisShake 支持的目标端有: +* 单机 Redis-like 数据库:redis_standalone_writer +* Redis Cluster:redis_cluster_writer + +### redis_standalone_writer + +```toml +[redis_standalone_writer] +address = "127.0.0.1:6380" +username = "" # keep empty if not using ACL +password = "" # keep empty if no authentication is required +tls = false +``` + +### redis_cluster_writer + +```toml +[redis_cluster_writer] +address = "127.0.0.1:6380" +username = "" # keep empty if not using ACL +password = "" # keep empty if no authentication is required +tls = false +``` + +## advanced 配置 + +```toml +[advanced] +dir = "data" +ncpu = 3 # runtime.GOMAXPROCS, 0 means use runtime.NumCPU() cpu cores + +pprof_port = 0 # pprof port, 0 means disable +status_port = 0 # status port, 0 means disable + +# log +log_file = "shake.log" +log_level = "info" # debug, info or warn +log_interval = 5 # in seconds + +# redis-shake gets key and value from rdb file, and uses RESTORE command to +# create the key in target redis. Redis RESTORE will return a "Target key name +# is busy" error when key already exists. You can use this configuration item +# to change the default behavior of restore: +# panic: redis-shake will stop when meet "Target key name is busy" error. +# rewrite: redis-shake will replace the key with new value. +# ignore: redis-shake will skip restore the key when meet "Target key name is busy" error. +rdb_restore_command_behavior = "rewrite" # panic, rewrite or skip + +# redis-shake uses pipeline to improve sending performance. +# This item limits the maximum number of commands in a pipeline. +pipeline_count_limit = 1024 + +# Client query buffers accumulate new commands. They are limited to a fixed +# amount by default. This amount is normally 1gb. +target_redis_client_max_querybuf_len = 1024_000_000 + +# In the Redis protocol, bulk requests, that are, elements representing single +# strings, are normally limited to 512 mb. +target_redis_proto_max_bulk_len = 512_000_000 + +# If the source is Elasticache or MemoryDB, you can set this item. +aws_psync = "" +``` \ No newline at end of file diff --git a/docs/src/zh/guide/getting-started.md b/docs/src/zh/guide/getting-started.md new file mode 100644 index 0000000..16f5e20 --- /dev/null +++ b/docs/src/zh/guide/getting-started.md @@ -0,0 +1,48 @@ +--- +outline: deep +--- +# 快速上手 + +## 安装 + +### 下载二进制包 + +直接在此处下载:https://github.com/tair-opensource/RedisShake/releases + +### 从源码编译 + +确保本地有 Golang 环境: + +```shell +git clone https://github.com/alibaba/RedisShake +cd RedisShake +sh build.sh +``` + +## 运行 + +假设现在有两个 Redis 实例: + +* 实例 A:127.0.0.1:6379 +* 实例 B:127.0.0.1:6380 + +新建文件 `shake.toml`: + +```toml +[sync_standalone_reader] +address = "127.0.0.1:6379" + +[redis_standalone_writer] +address = "127.0.0.1:6380" +``` + +启动 redis-shake: + +```shell +./redis-shake shake.toml + +``` + +运行日志如图: + +![img](./getting-started.png) \ No newline at end of file diff --git a/docs/src/zh/guide/getting-started.png b/docs/src/zh/guide/getting-started.png new file mode 100644 index 0000000..9978512 Binary files /dev/null and b/docs/src/zh/guide/getting-started.png differ diff --git a/docs/markdown-examples.md b/docs/src/zh/markdown-examples.md similarity index 100% rename from docs/markdown-examples.md rename to docs/src/zh/markdown-examples.md diff --git a/docs/src/zh/transform/examples.md b/docs/src/zh/transform/examples.md new file mode 100644 index 0000000..77ac165 --- /dev/null +++ b/docs/src/zh/transform/examples.md @@ -0,0 +1,65 @@ +--- +outline: deep +--- +# transform 样例 + +## 阿里云兼容 + +```lua +-- Aliyun Redis 4.0: skip OPINFO command +function transform(id, is_base, group, cmd_name, keys, slots, db_id, timestamp_ms) + if cmd_name == "OPINFO" then + return 1, db_id -- disallow + else + return 0, db_id -- allow + end +end +``` + +## AWS 兼容 + +```lua +-- ElastiCache: skip REPLCONF command +function transform(id, is_base, group, cmd_name, keys, slots, db_id, timestamp_ms) + if cmd_name == "REPLCONF" then + return 1, db_id -- disallow + else + return 0, db_id -- allow + end +end +``` + +## 过滤命令 + +### 过滤所有 lua 脚本 + +``` +-- skip all scripts included LUA scripts and Redis Functions. +function filter(id, is_base, group, cmd_name, keys, slots, db_id, timestamp_ms) + if group == "SCRIPTING" then + return 1, db_id -- disallow + else + return 0, db_id -- allow + end +end +``` + +## key 操作 + +### 按照前缀过滤 key + +``` +-- skip keys prefixed with ABC +function filter(id, is_base, group, cmd_name, keys, slots, db_id, timestamp_ms) + if #keys ~= 1 then + return 0, db_id -- allow + end + + if string.sub(keys[1], 0, 3) == "ABC" then + return 1, db_id -- disallow + end + + return 0, db_id -- allow +end +``` + diff --git a/docs/src/zh/transform/getting-started.md b/docs/src/zh/transform/getting-started.md new file mode 100644 index 0000000..726575f --- /dev/null +++ b/docs/src/zh/transform/getting-started.md @@ -0,0 +1,6 @@ +--- +outline: deep +--- +# 上手使用 + +TODO diff --git a/configs/all.toml b/shake.toml similarity index 100% rename from configs/all.toml rename to shake.toml diff --git a/tests/cases/auth_acl.py b/tests/cases/auth_acl.py index 07dbc9a..7df0d4d 100644 --- a/tests/cases/auth_acl.py +++ b/tests/cases/auth_acl.py @@ -20,10 +20,10 @@ def acl(): inserter.add_data(src, cross_slots_cmd=True) opts = h.ShakeOpts.create_sync_opts(src, dst) - opts["SyncStandaloneReader"]["username"] = "user0" - opts["SyncStandaloneReader"]["password"] = "password0" - opts["RedisStandaloneWriter"]["username"] = "user1" - opts["RedisStandaloneWriter"]["password"] = "password1" + opts["sync_standalone_reader"]["username"] = "user0" + opts["sync_standalone_reader"]["password"] = "password0" + opts["redis_standalone_writer"]["username"] = "user1" + opts["redis_standalone_writer"]["password"] = "password1" p.log(f"opts: {opts}") shake = h.Shake(opts) diff --git a/tests/helpers/shake.py b/tests/helpers/shake.py index 2d02a79..2597a35 100644 --- a/tests/helpers/shake.py +++ b/tests/helpers/shake.py @@ -29,35 +29,35 @@ class ShakeOpts: def create_sync_opts(src: Redis, dst: Redis) -> typing.Dict: d = {} if src.is_cluster(): - d["SyncClusterReader"] = {"address": src.get_address()} + d["sync_cluster_reader"] = {"address": src.get_address()} else: - d["SyncStandaloneReader"] = {"address": src.get_address()} + d["sync_standalone_reader"] = {"address": src.get_address()} if dst.is_cluster(): - d["RedisClusterWriter"] = {"address": dst.get_address()} + d["redis_cluster_writer"] = {"address": dst.get_address()} else: - d["RedisStandaloneWriter"] = {"address": dst.get_address()} + d["redis_standalone_writer"] = {"address": dst.get_address()} return d @staticmethod def create_scan_opts(src: Redis, dst: Redis) -> typing.Dict: d = {} if src.is_cluster(): - d["ScanClusterReader"] = {"address": src.get_address()} + d["scan_cluster_reader"] = {"address": src.get_address()} else: - d["ScanStandaloneReader"] = {"address": src.get_address()} + d["scan_standalone_reader"] = {"address": src.get_address()} if dst.is_cluster(): - d["RedisClusterWriter"] = {"address": dst.get_address()} + d["redis_cluster_writer"] = {"address": dst.get_address()} else: - d["RedisStandaloneWriter"] = {"address": dst.get_address()} + d["redis_standalone_writer"] = {"address": dst.get_address()} return d @staticmethod def create_rdb_opts(rdb_path: str, dts: Redis) -> typing.Dict: - d = {"RdbReader": {"filepath": rdb_path}} + d = {"rdb_reader": {"filepath": rdb_path}} if dts.is_cluster(): - d["RedisClusterWriter"] = {"address": dts.get_address()} + d["redis_cluster_writer"] = {"address": dts.get_address()} else: - d["RedisStandaloneWriter"] = {"address": dts.get_address()} + d["redis_standalone_writer"] = {"address": dts.get_address()} return d