├── .editorconfig ├── .gitattributes ├── .github └── workflows │ ├── deploy-docs.yml │ ├── publish.yml │ ├── run-tests.yml │ └── test-deploy-docs.yml ├── .gitignore ├── .markdownlint.json ├── .npmignore ├── .npmrc ├── .prettierrc.js ├── CODE_OF_CONDUCT.md ├── LICENSE.md ├── README.md ├── docs ├── .gitignore ├── README.md ├── babel.config.js ├── docs │ ├── api │ │ ├── client.md │ │ ├── config.md │ │ ├── connections.md │ │ └── intro.md │ ├── best-practices.md │ ├── faq.md │ ├── installation.md │ ├── introduction.md │ ├── plugins │ │ └── rest-cache.md │ └── redis │ │ ├── basic.md │ │ ├── cluster.md │ │ ├── intro.md │ │ ├── redlock.md │ │ ├── sentinel.md │ │ └── tls-auth.md ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src │ ├── components │ │ └── HomepageFeatures │ │ │ ├── index.js │ │ │ └── styles.module.css │ └── css │ │ └── custom.css ├── static │ ├── .nojekyll │ └── img │ │ ├── docusaurus-social-card.jpg │ │ ├── docusaurus.png │ │ ├── favicon.ico │ │ ├── logo.svg │ │ ├── undraw_docusaurus_mountain.svg │ │ ├── undraw_docusaurus_react.svg │ │ └── undraw_docusaurus_tree.svg └── yarn.lock ├── package.json ├── server ├── config │ └── index.js ├── index.js ├── register.js └── services │ ├── connection.js │ └── index.js ├── strapi-server.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # From https://github.com/Danimoth/gitattributes/blob/master/Web.gitattributes 2 | 3 | # Handle line endings automatically for files detected as text 4 | # and leave all files detected as binary untouched. 5 | * text=auto 6 | 7 | # 8 | # The above will handle all files NOT found below 9 | # 10 | 11 | # 12 | ## These files are text and should be normalized (Convert crlf => lf) 13 | # 14 | 15 | # source code 16 | *.php text 17 | *.css text 18 | *.sass text 19 | *.scss text 20 | *.less text 21 | *.styl text 22 | *.js text eol=lf 23 | *.coffee text 24 | *.json text 25 | *.htm text 26 | *.html text 27 | *.xml text 28 | *.svg text 29 | *.txt text 30 | *.ini text 31 | *.inc text 32 | *.pl text 33 | *.rb text 34 | *.py text 35 | *.scm text 36 | *.sql text 37 | *.sh text 38 | *.bat text 39 | 40 | # templates 41 | *.ejs text 42 | *.hbt text 43 | *.jade text 44 | *.haml text 45 | *.hbs text 46 | *.dot text 47 | *.tmpl text 48 | *.phtml text 49 | 50 | # server config 51 | .htaccess text 52 | 53 | # git config 54 | .gitattributes text 55 | .gitignore text 56 | .gitconfig text 57 | 58 | # code analysis config 59 | .jshintrc text 60 | .jscsrc text 61 | .jshintignore text 62 | .csslintrc text 63 | 64 | # misc config 65 | *.yaml text 66 | *.yml text 67 | .editorconfig text 68 | 69 | # build config 70 | *.npmignore text 71 | *.bowerrc text 72 | 73 | # Heroku 74 | Procfile text 75 | .slugignore text 76 | 77 | # Documentation 78 | *.md text 79 | LICENSE text 80 | AUTHORS text 81 | 82 | 83 | # 84 | ## These files are binary and should be left untouched 85 | # 86 | 87 | # (binary is a macro for -text -diff) 88 | *.png binary 89 | *.jpg binary 90 | *.jpeg binary 91 | *.gif binary 92 | *.ico binary 93 | *.mov binary 94 | *.mp4 binary 95 | *.mp3 binary 96 | *.flv binary 97 | *.fla binary 98 | *.swf binary 99 | *.gz binary 100 | *.zip binary 101 | *.7z binary 102 | *.ttf binary 103 | *.eot binary 104 | *.woff binary 105 | *.pyc binary 106 | *.pdf binary 107 | -------------------------------------------------------------------------------- /.github/workflows/deploy-docs.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Docs to GitHub Pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | defaults: 9 | run: 10 | working-directory: docs 11 | 12 | jobs: 13 | build: 14 | name: Build Docusaurus 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 0 20 | - uses: actions/setup-node@v4 21 | with: 22 | node-version: 20 23 | cache: yarn 24 | 25 | - name: Install dependencies 26 | run: yarn install --frozen-lockfile 27 | - name: Build website 28 | run: yarn build 29 | 30 | - name: Upload Build Artifact 31 | uses: actions/upload-pages-artifact@v3 32 | with: 33 | path: ./docs/build 34 | 35 | deploy: 36 | name: Deploy to GitHub Pages 37 | needs: build 38 | 39 | # Grant GITHUB_TOKEN the permissions required to make a Pages deployment 40 | permissions: 41 | pages: write # to deploy to Pages 42 | id-token: write # to verify the deployment originates from an appropriate source 43 | 44 | # Deploy to the github-pages environment 45 | environment: 46 | name: github-pages 47 | url: ${{ steps.deployment.outputs.page_url }} 48 | 49 | runs-on: ubuntu-latest 50 | steps: 51 | - name: Deploy to GitHub Pages 52 | id: deployment 53 | uses: actions/deploy-pages@v4 54 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish Package to npmjs 2 | on: 3 | release: 4 | types: [published] 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | permissions: 9 | contents: read 10 | id-token: write 11 | steps: 12 | - uses: actions/checkout@v4 13 | - uses: actions/setup-node@v4 14 | with: 15 | node-version: '20.x' 16 | registry-url: 'https://registry.npmjs.org' 17 | - run: yarn install --frozen-lockfile 18 | - run: npm publish --provenance --access public 19 | env: 20 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 21 | -------------------------------------------------------------------------------- /.github/workflows/run-tests.yml: -------------------------------------------------------------------------------- 1 | name: 'Standard Tests' 2 | 3 | on: push 4 | 5 | jobs: 6 | # lint: 7 | # runs-on: ubuntu-latest 8 | # strategy: 9 | # matrix: 10 | # node: [14, 16] 11 | # steps: 12 | # - uses: actions/checkout@v2 13 | # - uses: actions/setup-node@v2-beta 14 | # with: 15 | # node-version: ${{ matrix.node }} 16 | # - name: Install modules 17 | # run: yarn 18 | # - name: Run lint 19 | # run: yarn eslint 20 | vulnerabilityScan: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@master 24 | - name: Run Snyk to check for vulnerabilities 25 | uses: snyk/actions/node@master 26 | continue-on-error: true # To make sure that SARIF upload gets called 27 | env: 28 | SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} 29 | with: 30 | args: --sarif-file-output=snyk.sarif 31 | - name: Upload result to GitHub Code Scanning 32 | uses: github/codeql-action/upload-sarif@v1 33 | with: 34 | sarif_file: snyk.sarif 35 | -------------------------------------------------------------------------------- /.github/workflows/test-deploy-docs.yml: -------------------------------------------------------------------------------- 1 | name: Test Deploy Docs to GitHub Pages 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | defaults: 9 | run: 10 | working-directory: docs 11 | 12 | jobs: 13 | test-deploy: 14 | name: Test deployment 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | with: 19 | fetch-depth: 0 20 | - uses: actions/setup-node@v4 21 | with: 22 | node-version: 20 23 | cache: yarn 24 | 25 | - name: Install dependencies 26 | run: yarn install --frozen-lockfile 27 | - name: Test build website 28 | run: yarn build 29 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ############################ 2 | # OS X 3 | ############################ 4 | 5 | .DS_Store 6 | .AppleDouble 7 | .LSOverride 8 | Icon 9 | .Spotlight-V100 10 | .Trashes 11 | ._* 12 | 13 | 14 | ############################ 15 | # Linux 16 | ############################ 17 | 18 | *~ 19 | 20 | 21 | ############################ 22 | # Windows 23 | ############################ 24 | 25 | Thumbs.db 26 | ehthumbs.db 27 | Desktop.ini 28 | $RECYCLE.BIN/ 29 | *.cab 30 | *.msi 31 | *.msm 32 | *.msp 33 | 34 | 35 | ############################ 36 | # Packages 37 | ############################ 38 | 39 | *.7z 40 | *.csv 41 | *.dat 42 | *.dmg 43 | *.gz 44 | *.iso 45 | *.jar 46 | *.rar 47 | *.tar 48 | *.zip 49 | *.com 50 | *.class 51 | *.dll 52 | *.exe 53 | *.o 54 | *.seed 55 | *.so 56 | *.swo 57 | *.swp 58 | *.swn 59 | *.swm 60 | *.out 61 | *.pid 62 | 63 | 64 | ############################ 65 | # Logs and databases 66 | ############################ 67 | 68 | .tmp 69 | *.log 70 | *.sql 71 | *.sqlite 72 | 73 | 74 | ############################ 75 | # Misc. 76 | ############################ 77 | 78 | *# 79 | .idea 80 | nbproject 81 | .vscode/ 82 | 83 | 84 | ############################ 85 | # Node.js 86 | ############################ 87 | 88 | lib-cov 89 | lcov.info 90 | pids 91 | logs 92 | results 93 | build 94 | node_modules 95 | .node_history 96 | package-lock.json 97 | **/package-lock.json 98 | !docs/package-lock.json 99 | *.heapsnapshot 100 | 101 | 102 | ############################ 103 | # Tests 104 | ############################ 105 | 106 | testApp 107 | coverage 108 | cypress/screenshots 109 | cypress/videos 110 | 111 | 112 | ############################ 113 | # Documentation 114 | ############################ 115 | 116 | dist 117 | 118 | ############################ 119 | # Builds 120 | ############################ 121 | 122 | packages/generators/app/files/public/ 123 | schema.graphql 124 | 125 | ############################ 126 | # Example app 127 | ############################ 128 | 129 | .dev 130 | # *.cache 131 | 132 | ############################ 133 | # Visual Studio Code 134 | ############################ 135 | 136 | front-workspace.code-workspace 137 | .yarn 138 | .yarnrc 139 | -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "default": true, 3 | "MD033": false, 4 | "MD013": false 5 | } 6 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store 4 | *.tgz 5 | *.log 6 | .idea 7 | .vscode 8 | *.sublime-project 9 | *.sublime-workspace 10 | *.swp 11 | *.swo 12 | *.bak 13 | *.tmp 14 | *.temp 15 | *.orig 16 | *.rej 17 | *.patch 18 | *.diff 19 | *.sublime-* 20 | docs* 21 | .github* 22 | .editorconfig 23 | .gitattributes 24 | .markdownlint.json 25 | .prettierrc.js 26 | CODE_OF_CONDUCT.md 27 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | endOfLine: 'lf', 3 | semi: true, 4 | singleQuote: true, 5 | tabWidth: 2, 6 | trailingComma: 'es5', 7 | printWidth: 100, 8 | }; 9 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | [@boazpoolman](https://twitter.com/boazpoolman) on twitter. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024 Strapi Community Org - https://github.com/strapi-community. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

Strapi Redis Plugin

3 | 4 |

Redis Connector Package for use in other plugins and packages.

5 | 6 |

7 | 8 | Strapi Discord 9 | 10 | 11 | NPM Version 12 | 13 | 14 | Monthly download on NPM 15 | 16 |

17 |
18 | 19 | ## Table of Contents 20 | 21 | - [🚦 Current Status](#-current-status) 22 | - [🛑 Foreword](#-foreword) 23 | - [✨ Features](#-features) 24 | - [🤔 Motivation](#-motivation) 25 | - [🖐 Requirements](#-requirements) 26 | - [⏳ Installation](#-installation) 27 | - [🔧 Configuration](#-configuration) 28 | - [Contributing](#contributing) 29 | - [License](#license) 30 | 31 | ## 🚦 Current Status 32 | 33 | This package is currently maintained and should be considered **Stable/GA** in terms of state. I/We are currently accepting contributions and/or dedicated contributors to help develop and maintain this package. 34 | 35 | For more information on contributing please see [the contrib message below](#contributing). 36 | 37 | ## 🛑 Foreword 38 | 39 | This package's lead maintainer is an employee of Strapi however this package is not officially maintained by Strapi Solutions SAS nor Strapi, Inc. and is currently maintained in the free time of the lead maintainer. 40 | 41 | > [!WARNING] 42 | **Absolutely no part of this code should be considered covered under any agreement you have with Strapi proper** including but not limited to any Enterprise and/or Cloud Agreement you have with Strapi. 43 | 44 | ## ✨ Features 45 | 46 | This plugin utilizes 2 core packages: 47 | 48 | - [ioredis](https://github.com/luin/ioredis) - for all connection management to any Redis or Redis-compatible database 49 | - [redlock](https://github.com/mike-marcacci/node-redlock) - for distributed locks related to Strapi's built in cron-tasks system 50 | 51 | These are the primary features that are finished or currently being worked on: 52 | 53 | - [ ] Updated/New Documentation outside of this README 54 | - [x] Multiple connections/databases 55 | - [x] Redlock capabilities with Strapi's built-in cron tasks 56 | - [ ] Admin Panel interface to see all existing connections 57 | - [ ] Admin Panel interface to see the stored key/values within the connections 58 | - [ ] Admin Panel interface to see the current server statistics 59 | 60 | ## 🤔 Motivation 61 | 62 | The purpose of this package is to have a universal Redis connector for all packages wanting to utilize a Redis database and/or for those wanting to develop custom functions and code within your Strapi project and would prefer a centralized Redis database for various purposes. 63 | 64 | A few examples of where Redis could be used within a Strapi application: 65 | 66 | - LRU-based response cache for REST 67 | - Apollo server GraphQL cache 68 | - IP Rate-limiting using something like [koa2-ratelimit](https://www.npmjs.com/package/koa2-ratelimit) 69 | - Server-side user session storage 70 | - So much more 71 | 72 | If you are currently using this package in your plugin and would like to be featured, please feel free to submit an issue to have your plugin added to the list below: 73 | 74 | - [strapi-plugin-rest-cache](https://www.npmjs.com/package/strapi-plugin-rest-cache) 75 | - via: [strapi-provider-rest-cache-redis](https://www.npmjs.com/package/strapi-provider-rest-cache-redis) 76 | - More plugins coming soon! 77 | 78 | Note the following packages used to use this package with Strapi v4 but have since been merged into this package: 79 | 80 | - [strapi-plugin-redcron](https://www.npmjs.com/package/strapi-plugin-redcron) 81 | 82 | ## 🖐 Requirements 83 | 84 | > [!CAUTION] 85 | > This plugin will not work with Strapi v3 projects as it utilizes APIs that don't exist in the v3! 86 | 87 | Supported Strapi Versions: 88 | 89 | | Strapi Version | Plugin Version | Supported | Tested On | 90 | |----------------|----------------|-----------|-----------| 91 | | v3.x.x | N/A | ❌ | N/A | 92 | | v4.x.x | 1.1.0 | ✅ | Sept 2024 | 93 | | v5.x.x | 2.0.0 | ✅ | Sept 2024 | 94 | 95 | ## ⏳ Installation 96 | 97 | > [!WARNING] 98 | For Strapi 4 projects you should use the `1.x.x` version of this plugin, for Strapi 5 projects you should use the `2.x.x` version of this plugin. 99 | 100 | > [!NOTE] 101 | For Strapi 5 the package name has changed from `strapi-plugin-redis` to `@strapi-community/plugin-redis`. 102 | 103 | Install the plugin in your Strapi project or your Strapi plugin. 104 | 105 | | Strapi Version | Plugin Version | Package Manager | Command | 106 | |----------------|----------------|-----------------|-------------------------------------------| 107 | | v4.x.x | 1.1.0 | Yarn | `yarn add strapi-plugin-redis@1.1.0` | 108 | | v5.x.x | Latest | Yarn | `yarn add @strapi-community/plugin-redis` | 109 | | v4.x.x | 1.1.0 | npm | `npm i strapi-plugin-redis@1.1.0` | 110 | | v5.x.x | Latest | npm | `npm i @strapi-community/plugin-redis` | 111 | 112 | ## 🔧 Configuration 113 | 114 | See our [Documentation](https://strapi-community.github.io/plugin-redis/) for more information on how to configure and use this plugin. 115 | 116 | ## Contributing 117 | 118 | I/We are actively looking for contributors, maintainers, and others to help shape this package. As this plugins sole purpose within the Strapi community is to be used by other developers and plugin maintainers to help ease the connection to Redis databases. 119 | 120 | Instead of reinventing the wheel every time you need to connect to Redis, the hope is to centralize the connections in a single plugin that all plugins can piggy back on. 121 | 122 | If interested please feel free to open up a GitHub issue/PR or ping `DMehaffy` on Discord. 123 | 124 | > [!NOTE] 125 | This package is maintained collectively by the [strapi community organization](https://github.com/strapi-community). While there may be a lead maintainer, they are not the sole maintainer of this code and this code does not belong to the lead maintainer. 126 | 127 | ## License 128 | 129 | See the [LICENSE](./LICENSE.md) file for licensing information. 130 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /docs/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/docs/api/client.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Client' 3 | slug: '/api/client' 4 | --- 5 | 6 | # API Client 7 | 8 | Accessed with: `strapi.redis.connections.default.client` 9 | *Note you can swap the default key with any other named database you have configured* 10 | 11 | From here you have full access to the [ioredis API](https://github.com/luin/ioredis/blob/master/API.md). 12 | -------------------------------------------------------------------------------- /docs/docs/api/config.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Config' 3 | slug: '/api/config' 4 | --- 5 | 6 | # API Config 7 | 8 | Access with: `strapi.redis.config` 9 | 10 | The config key contains the entire plugin config including all ioredis instances configurations. These should not be modified after bootstrapping your Strapi application (aka while the server is running). 11 | -------------------------------------------------------------------------------- /docs/docs/api/connections.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Connections' 3 | slug: '/api/connections' 4 | --- 5 | 6 | # API Connections 7 | 8 | Access with: `strapi.redis.connections` 9 | 10 | For each connection either a normal Redis client is created, or if the cluster setting is enabled and you have properly passed in an array of nodes (and optionally any cluster options) a Redis Cluster client. 11 | -------------------------------------------------------------------------------- /docs/docs/api/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Introduction' 3 | slug: '/api/intro' 4 | --- 5 | 6 | # API Introduction 7 | 8 | This plugin provides a Redis client for your Strapi application. It is based on the [ioredis](https://github.com/luin/ioredis/blob/master/API.md) package and provides a simple and easy-to-use interface for connecting to a Redis (or Redis alternative) database. 9 | 10 | More detailed examples for using this packages API will be coming shortly. 11 | -------------------------------------------------------------------------------- /docs/docs/best-practices.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Best Practices' 3 | slug: '/best-practices' 4 | --- 5 | 6 | # Best Practices 7 | 8 | Best practices will be coming soon, please check back later. 9 | -------------------------------------------------------------------------------- /docs/docs/faq.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'FAQ' 3 | slug: '/faq' 4 | --- 5 | 6 | # Frequently Asked Questions 7 | 8 | ## Do you plan on implementing a feature for X? 9 | 10 | Probably not unless the feature request has been opened on the [GitHub Repo](https://github.com/strapi-community/plugin-redis) and up voted by the community. However we do also accept PRs for new features. 11 | 12 | ## How do I contribute to the project? 13 | 14 | Please open up a PR on the [GitHub Repo](https://github.com/strapi-community/plugin-redis), we will review it and merge it if it meets our standards. If you would like to discuss something before you contribute you are welcome to open an issue on the repo. 15 | 16 | ## Do you plan on rewriting this in Typescript or providing Typescript support? 17 | 18 | No, we do not plan on rewriting this in Typescript or providing Types. Certainly we will accept PRs if you believe you can provide a good implementation that doesn't overly complicate the code-base but in general you should be able to use the existing types provided by the `ioredis` package. 19 | 20 | The Lead maintainer of this package has a strong preference for Javascript over Typescript and does not see the value in rewriting the package in Typescript. 21 | 22 | ## I can't get the package to work, can you help me? 23 | 24 | Please open an issue on the [GitHub Repo](https://github.com/strapi-community/plugin-redis) and we will do our best to help you. Please provide as much information as possible including the version of Strapi you are using, the version of the plugin you are using, and any error messages you are seeing. 25 | 26 | Most of the time the issue is not with this plugin and is with your Redis configuration or your Strapi configuration. In many cases certain cloud providers have very strict network firewalls or restrictions that can prevent the connection. 27 | -------------------------------------------------------------------------------- /docs/docs/installation.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Installation' 3 | slug: '/installation' 4 | --- 5 | 6 | import Tabs from '@theme/Tabs'; 7 | import TabItem from '@theme/TabItem'; 8 | 9 | # Installation 10 | 11 | As of plugin version 2.0.0+, the plugin package name has changed to `@strapi-community/plugin-redis`. 12 | This change was made to align with the naming convention of official Strapi plugins. 13 | 14 | As such the following table outlines the plugin versions vs the Strapi versions they are compatible with: 15 | 16 | | Strapi Version | Plugin Version | 17 | |----------------|----------------| 18 | | 5.x.x | 2.x.x | 19 | | 4.x.x | 1.x.x | 20 | | 3.x.x | N/A | 21 | 22 | ## Installation for Strapi 5.x.x 23 | 24 | To install the plugin, run the following command: 25 | 26 | 27 | 28 | 29 | ```bash 30 | yarn add @strapi-community/plugin-redis 31 | ``` 32 | 33 | 34 | 35 | 36 | ```bash 37 | npm install @strapi-community/plugin-redis --save 38 | ``` 39 | 40 | 41 | 42 | 43 | ## Installation for Strapi 4.x.x 44 | 45 | To install the plugin, run the following command: 46 | 47 | 48 | 49 | 50 | ```bash 51 | yarn add strapi-plugin-redis 52 | ``` 53 | 54 | 55 | 56 | 57 | ```bash 58 | npm install strapi-plugin-redis --save 59 | ``` 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /docs/docs/introduction.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Introduction' 3 | slug: '/' 4 | --- 5 | 6 | # Introduction 7 | 8 | The purpose of this package is to have a universal Redis connector for all packages wanting to utilize a Redis database and/or for those wanting to develop custom functions and code within your Strapi project and would prefer a centralized Redis database for various purposes. 9 | 10 | This package is a wrapper around the `ioredis` package and provides a simple and easy-to-use interface for connecting to a Redis (or Redis alternative) database. 11 | 12 | Likewise, this package also includes the `redlock` package for distributed locks. Currently, if you horizontally scale Strapi and use the cron feature, you will end up with multiple instances of Strapi running the same cron job at the same time, potentially causing race conditions. This can cause issues with your database or other services that you are trying to integrate with. If enabled the Redlock option will automatically force those cron jobs to establish a lock before running the job meaning that only one instance of Strapi will run the job at a time. 13 | 14 | ## Features 15 | 16 | - **Universal Redis Connector**: This package is a universal Redis connector for all packages wanting to utilize a Redis database. 17 | - **Multiple Redis Connections**: This package supports multiple Redis connections. 18 | - **Cluster/Sentinel Support**: This package supports Redis Cluster and Redis Sentinel. 19 | - **Redlock Support**: This package supports Redlock for distributed locks. 20 | - **Automatic Redlock CronTasks**: This package automatically uses Redlock for Strapi built-in CronTasks. 21 | 22 | ## Possible Future Features 23 | 24 | - **Admin Panel Interface to see all Redis Connections**: This package may include an admin panel interface to see all Redis connections and their status. 25 | - **Admin Panel Interface to see all Redis Key/Values**: This package may include an admin panel interface to see all Redis keys and their values. 26 | - **Admin Panel Interface to see all Redis Server Status**: This package may include an admin panel interface to see all Redis server status (memory usage, CPU usage, etc). 27 | 28 | ## Common Use-cases 29 | 30 | - **Caching**: This package can be used for caching data, for example see the LRU based plugin that uses this package called [REST Cache](/plugins/rest-cache). 31 | - **Apollo Server GraphQL Cache**: This package can be used for caching Apollo Server GraphQL data. 32 | - **IP based Rate Limiting**: This package can be used for IP based rate limiting using something like [koa2-ratelimit](https://www.npmjs.com/package/koa2-ratelimit). 33 | - **Server-side User Sessions**: This package can be used for server-side user session storage and management. 34 | - **So Much More**: The possibilities are endless! 35 | -------------------------------------------------------------------------------- /docs/docs/plugins/rest-cache.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'REST Cache' 3 | slug: '/plugins/rest-cache' 4 | --- 5 | 6 | # REST Cache Plugin 7 | 8 | Details on this plugin are coming soon! Please check back later. 9 | -------------------------------------------------------------------------------- /docs/docs/redis/basic.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Basic' 3 | slug: '/redis/basic' 4 | --- 5 | 6 | # Basic Single Node Config 7 | 8 | The default configuration for the Redis plugin is a single node configuration. This is the most common configuration for Redis and is the default configuration for the plugin. 9 | 10 | ```javascript 11 | // path ./config/plugins.js 12 | 13 | module.exports = { 14 | redis: { 15 | config: { 16 | settings:{ 17 | debug: false, 18 | enableRedlock: true, 19 | } 20 | connections: { 21 | default: { 22 | connection: { 23 | host: '127.0.0.1', 24 | port: 6379, 25 | db: 0, 26 | }, 27 | settings: { 28 | debug: false, 29 | }, 30 | }, 31 | }, 32 | }, 33 | }, 34 | }; 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/docs/redis/cluster.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Cluster' 3 | slug: '/redis/cluster' 4 | --- 5 | 6 | # Cluster Config 7 | 8 | Cluster Configuration enable coming soon! Please check back later. 9 | -------------------------------------------------------------------------------- /docs/docs/redis/intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Introduction' 3 | slug: '/redis/intro' 4 | --- 5 | 6 | # Configuration Introduction 7 | 8 | The Redis plugin for Strapi is a simple wrapper around the [ioredis](https://github.com/luin/ioredis) package but also includes the [redlock](https://www.npmjs.com/package/redlock) package for distributed locks. This plugin provides a simple and easy-to-use interface for connecting to a Redis (or Redis alternative) database. 9 | 10 | ## Complete Configuration 11 | 12 | This configuration table does not include **all possible options** as many of them come from [ioredis](https://github.com/luin/ioredis) directly and what is shown here is mostly those options related to the plugin specifically and showing the default values. 13 | 14 | | Key | Description | Type | Default | 15 | |-------------------------------------------|---------------------------------------------------|---------|-------------| 16 | | `settings` | The settings for the Redis plugin. | Object | N/A | 17 | | `settings.debug` | Whether to enable debug mode. | Boolean | `false` | 18 | | `settings.debugIORedis` | Whether to enable debug mode for ioredis. | Boolean | `false` | 19 | | `settings.enableRedlock` | Whether to enable redlock for distributed locks. | Boolean | `false` | 20 | | `settings.lockDelay` | The delay in milliseconds for the lock. | Number | `null` | 21 | | `settings.lockTTL` | The time-to-live in milliseconds for the lock. | Number | `5000` | 22 | | `settings.redlockConfig` | The redlock configuration. | Object | N/A | 23 | | `settings.redlockConfig.driftFactor` | The drift factor for redlock. | Number | `0.01` | 24 | | `settings.redlockConfig.retryCount` | The retry count for redlock. | Number | `10` | 25 | | `settings.redlockConfig.retryDelay` | The retry delay for redlock. | Number | `200` | 26 | | `settings.redlockConfig.retryJitter` | The retry jitter for redlock. | Number | `200` | 27 | | `connections` | The connections for the Redis plugin. | Object | N/A | 28 | | `connections.default` | The default connection for the Redis plugin. | Object | N/A | 29 | | `connections.default.connection` | The object passed to ioredis directly | Object | N/A | 30 | | `connections.default.connection.host` | The host for the connection. | String | `127.0.0.1` | 31 | | `connections.default.connection.port` | The port for the connection. | Number | `6379` | 32 | | `connections.default.connection.password` | The password for the connection. | String | `null` | 33 | | `connections.default.connection.db` | The database for the connection. | Number | `0` | 34 | | `connections.default.settings` | The settings for the connection. | Object | N/A | 35 | | `connections.default.settings.debug` | Whether to enable debug mode for this connection. | Boolean | `false` | 36 | -------------------------------------------------------------------------------- /docs/docs/redis/redlock.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Redlock' 3 | slug: '/redis/redlock' 4 | --- 5 | 6 | # Redlock Config 7 | 8 | Redlock configuration is fairly easy to get setup and additional details for using it within Strapi's Crontasks is also lightly detailed below. 9 | 10 | ```javascript 11 | // path ./config/plugins.js 12 | 13 | module.exports = { 14 | redis: { 15 | config: { 16 | settings:{ 17 | enableRedlock: true, 18 | lockDelay: null, 19 | lockTTL: 5000, 20 | redlockConfig: { 21 | driftFactor: 0.01, 22 | retryCount: 10, 23 | retryDelay: 200, 24 | retryJitter: 200, 25 | }, 26 | }, 27 | connections: { 28 | //... 29 | }, 30 | }, 31 | }, 32 | }; 33 | ``` 34 | 35 | ## Cron Task Example 36 | 37 | Adding the bypassRedlock property to your cron job will bypass the redlock logic and allow multiple instances of Strapi to run the same cron job at the same time. 38 | 39 | This plugin requires you to use the object format of the cron config. i.e if you are using the rule as the key, you will need to change it to an object with the rule as a property and the key as a unique name. This is because across your Strapi instances, Redis needs to lock onto a key that is the same across all instances. 40 | 41 | ### Normal Cron Task Example 42 | 43 | ```javascript 44 | // path ./config/cron-tasks.js 45 | 46 | module.exports = { 47 | myJob: { 48 | task: ({ strapi }) => {/* Add your own logic here */ }, 49 | bypassRedlock: false, // optional 50 | options: { 51 | rule: '0 0 1 * * 1', 52 | }, 53 | }, 54 | }; 55 | ``` 56 | 57 | ### Bootstrap Example 58 | 59 | ```javascript 60 | // path ./src/index.js 61 | 62 | module.exports = { 63 | register(/* { Strapi } */) {}, 64 | bootstrap({ strapi }) { 65 | strapi.cron.add({ 66 | myJob: { 67 | task: async ({ strapi }) => { 68 | console.log("hello from bootstrap") 69 | }, 70 | bypassRedlock: false, // optional 71 | options: { 72 | rule: '*/10 * * * * *', 73 | } 74 | }, 75 | }); 76 | } 77 | }; 78 | ``` 79 | -------------------------------------------------------------------------------- /docs/docs/redis/sentinel.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'Sentinel' 3 | slug: '/redis/sentinel' 4 | --- 5 | 6 | # Redis Sentinel Replica Config (3 Node) 7 | 8 | The Redis plugin supports Redis Sentinel for high availability and failover. This is a common configuration for Redis in production environments. 9 | 10 | ```javascript 11 | // path ./config/plugins.js 12 | 13 | module.exports = { 14 | redis: { 15 | config: { 16 | settings:{ 17 | debug: false, 18 | enableRedlock: true, 19 | } 20 | connections: { 21 | default: { 22 | connection: { 23 | sentinels: [ 24 | { host: '192.168.1.101', port: 26379 }, 25 | { host: '192.168.1.102', port: 26379 }, 26 | { host: '192.168.1.103', port: 26379 }, 27 | ], 28 | name: 'my-redis-replicaSet', 29 | db: 0, 30 | }, 31 | settings: { 32 | debug: false, 33 | }, 34 | }, 35 | }, 36 | }, 37 | }, 38 | }; 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/docs/redis/tls-auth.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_label: 'TLS Authentication' 3 | slug: '/redis/tls-auth' 4 | --- 5 | 6 | # TLS Authentication 7 | 8 | To enable TLS authentication, you need to provide the `tls` option in the connection configuration and load in the necessary certificates. 9 | 10 | ```javascript 11 | // path ./config/plugins.js 12 | const { readFileSync } = require('fs'); 13 | 14 | module.exports = { 15 | redis: { 16 | config: { 17 | settings:{ 18 | debug: false, 19 | enableRedlock: true, 20 | }, 21 | connections: { 22 | default: { 23 | connection: { 24 | // @see https://github.com/luin/ioredis/blob/master/API.md#new-redisport-host-options 25 | host: '127.0.0.1', 26 | port: 6379, 27 | db: 0, 28 | username: 'username', 29 | password: 'secret', 30 | // @see https://github.com/luin/ioredis#tls-options 31 | tls: { 32 | ca: readFileSync('cert.pem'), 33 | }, 34 | }, 35 | settings: { 36 | debug: false, 37 | }, 38 | }, 39 | }, 40 | }, 41 | }, 42 | }; 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/docusaurus.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | import { themes as prismThemes } from 'prism-react-renderer'; 4 | 5 | /** @type {import('@docusaurus/types').Config} */ 6 | const config = { 7 | title: 'Strapi Plugin Redis', 8 | tagline: 'Connecting Strapi to Redis with ease', 9 | favicon: 'img/favicon.ico', 10 | url: 'https://your-docusaurus-site.example.com', 11 | baseUrl: 'plugin-redis/', 12 | organizationName: 'strapi-community', // Usually your GitHub org/user name. 13 | projectName: 'plugin-redis', // Usually your repo name. 14 | onBrokenLinks: 'throw', 15 | onBrokenMarkdownLinks: 'warn', 16 | trailingSlash: false, 17 | 18 | themes: ['@docusaurus/theme-mermaid'], 19 | 20 | i18n: { 21 | defaultLocale: 'en', 22 | locales: ['en'], 23 | }, 24 | 25 | markdown: { 26 | mermaid: true, 27 | }, 28 | 29 | plugins: [ 30 | [ 31 | '@cmfcmf/docusaurus-search-local', 32 | { 33 | indexBlog: false, 34 | }, 35 | ], 36 | ], 37 | 38 | presets: [ 39 | [ 40 | 'classic', 41 | /** @type {import('@docusaurus/preset-classic').Options} */ 42 | { 43 | docs: { 44 | routeBasePath: '/', 45 | sidebarPath: './sidebars.js', 46 | editUrl: 'https://github.com/strapi-community/plugin-redis/docs/', 47 | }, 48 | blog: false, 49 | }, 50 | ], 51 | ], 52 | 53 | themeConfig: 54 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ 55 | ({ 56 | // Replace with your project's social card 57 | image: 'img/docusaurus-social-card.jpg', 58 | navbar: { 59 | title: 'Strapi Plugin Redis', 60 | logo: { 61 | alt: 'My Site Logo', 62 | src: 'img/logo.svg', 63 | }, 64 | items: [ 65 | { 66 | href: 'https://github.com/strapi-community/plugin-redis', 67 | label: 'GitHub', 68 | position: 'right', 69 | }, 70 | ], 71 | }, 72 | footer: { 73 | style: 'dark', 74 | copyright: `Copyright © ${new Date().getFullYear()} Strapi Community Organization`, 75 | }, 76 | prism: { 77 | theme: prismThemes.github, 78 | darkTheme: prismThemes.dracula, 79 | }, 80 | }), 81 | }; 82 | 83 | export default config; 84 | -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "2.0.0", 4 | "private": true, 5 | "scripts": { 6 | "docusaurus": "docusaurus", 7 | "start": "docusaurus start", 8 | "build": "docusaurus build", 9 | "swizzle": "docusaurus swizzle", 10 | "deploy": "docusaurus deploy", 11 | "clear": "docusaurus clear", 12 | "serve": "docusaurus serve", 13 | "write-translations": "docusaurus write-translations", 14 | "write-heading-ids": "docusaurus write-heading-ids" 15 | }, 16 | "dependencies": { 17 | "@cmfcmf/docusaurus-search-local": "^1.2.0", 18 | "@docusaurus/core": "3.5.2", 19 | "@docusaurus/preset-classic": "3.5.2", 20 | "@docusaurus/theme-mermaid": "^3.5.2", 21 | "@mdx-js/react": "^3.0.0", 22 | "clsx": "^2.0.0", 23 | "prism-react-renderer": "^2.3.0", 24 | "react": "^18.0.0", 25 | "react-dom": "^18.0.0" 26 | }, 27 | "devDependencies": { 28 | "@docusaurus/module-type-aliases": "3.5.2", 29 | "@docusaurus/types": "3.5.2" 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.5%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 3 chrome version", 39 | "last 3 firefox version", 40 | "last 5 safari version" 41 | ] 42 | }, 43 | "resolutions": { 44 | "cheerio": "1.0.0-rc.12" 45 | }, 46 | "engines": { 47 | "node": ">=18.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /docs/sidebars.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | 3 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 4 | const sidebars = { 5 | default: [ 6 | { 7 | type: 'doc', 8 | id: 'introduction', 9 | }, 10 | { 11 | type: 'doc', 12 | id: 'installation', 13 | }, 14 | { 15 | type: 'doc', 16 | id: 'best-practices', 17 | }, 18 | { 19 | type: 'doc', 20 | id: 'faq', 21 | }, 22 | { 23 | type: 'category', 24 | label: 'Configuration', 25 | items: [ 26 | 'redis/intro', 27 | 'redis/basic', 28 | 'redis/sentinel', 29 | 'redis/tls-auth', 30 | 'redis/cluster', 31 | 'redis/redlock', 32 | ], 33 | collapsed: false, 34 | }, 35 | { 36 | type: 'category', 37 | label: 'Plugins', 38 | items: ['plugins/rest-cache'], 39 | }, 40 | { 41 | type: 'category', 42 | label: 'API', 43 | items: ['api/intro', 'api/client', 'api/config', 'api/connections'], 44 | }, 45 | ], 46 | }; 47 | 48 | export default sidebars; 49 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures/index.js: -------------------------------------------------------------------------------- 1 | import clsx from 'clsx'; 2 | import Heading from '@theme/Heading'; 3 | import styles from './styles.module.css'; 4 | 5 | const FeatureList = [ 6 | { 7 | title: 'Easy to Use', 8 | Svg: require('@site/static/img/undraw_docusaurus_mountain.svg').default, 9 | description: ( 10 | <> 11 | Docusaurus was designed from the ground up to be easily installed and 12 | used to get your website up and running quickly. 13 | 14 | ), 15 | }, 16 | { 17 | title: 'Focus on What Matters', 18 | Svg: require('@site/static/img/undraw_docusaurus_tree.svg').default, 19 | description: ( 20 | <> 21 | Docusaurus lets you focus on your docs, and we'll do the chores. Go 22 | ahead and move your docs into the docs directory. 23 | 24 | ), 25 | }, 26 | { 27 | title: 'Powered by React', 28 | Svg: require('@site/static/img/undraw_docusaurus_react.svg').default, 29 | description: ( 30 | <> 31 | Extend or customize your website layout by reusing React. Docusaurus can 32 | be extended while reusing the same header and footer. 33 | 34 | ), 35 | }, 36 | ]; 37 | 38 | function Feature({Svg, title, description}) { 39 | return ( 40 |
41 |
42 | 43 |
44 |
45 | {title} 46 |

{description}

47 |
48 |
49 | ); 50 | } 51 | 52 | export default function HomepageFeatures() { 53 | return ( 54 |
55 |
56 |
57 | {FeatureList.map((props, idx) => ( 58 | 59 | ))} 60 |
61 |
62 |
63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /docs/src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #2e8555; 10 | --ifm-color-primary-dark: #29784c; 11 | --ifm-color-primary-darker: #277148; 12 | --ifm-color-primary-darkest: #205d3b; 13 | --ifm-color-primary-light: #33925d; 14 | --ifm-color-primary-lighter: #359962; 15 | --ifm-color-primary-lightest: #3cad6e; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme='dark'] { 22 | --ifm-color-primary: #25c2a0; 23 | --ifm-color-primary-dark: #21af90; 24 | --ifm-color-primary-darker: #1fa588; 25 | --ifm-color-primary-darkest: #1a8870; 26 | --ifm-color-primary-light: #29d5b0; 27 | --ifm-color-primary-lighter: #32d8b4; 28 | --ifm-color-primary-lightest: #4fddbf; 29 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); 30 | } 31 | -------------------------------------------------------------------------------- /docs/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strapi-community/plugin-redis/0c375ca642ad2b7d426fa286385a100e22c7e9f8/docs/static/.nojekyll -------------------------------------------------------------------------------- /docs/static/img/docusaurus-social-card.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strapi-community/plugin-redis/0c375ca642ad2b7d426fa286385a100e22c7e9f8/docs/static/img/docusaurus-social-card.jpg -------------------------------------------------------------------------------- /docs/static/img/docusaurus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strapi-community/plugin-redis/0c375ca642ad2b7d426fa286385a100e22c7e9f8/docs/static/img/docusaurus.png -------------------------------------------------------------------------------- /docs/static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/strapi-community/plugin-redis/0c375ca642ad2b7d426fa286385a100e22c7e9f8/docs/static/img/favicon.ico -------------------------------------------------------------------------------- /docs/static/img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/static/img/undraw_docusaurus_mountain.svg: -------------------------------------------------------------------------------- 1 | 2 | Easy to Use 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /docs/static/img/undraw_docusaurus_react.svg: -------------------------------------------------------------------------------- 1 | 2 | Powered by React 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /docs/static/img/undraw_docusaurus_tree.svg: -------------------------------------------------------------------------------- 1 | 2 | Focus on What Matters 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@strapi-community/plugin-redis", 3 | "version": "2.0.0", 4 | "description": "Plugin used to centralize management of Redis connections in Strapi", 5 | "strapi": { 6 | "displayName": "Redis", 7 | "name": "redis", 8 | "description": "Plugin used to centralize management of Redis connections in Strapi", 9 | "required": false, 10 | "kind": "plugin" 11 | }, 12 | "dependencies": { 13 | "chalk": "4.1.2", 14 | "debug": "4.3.5", 15 | "ioredis": "5.4.1", 16 | "redlock": "5.0.0-beta.2" 17 | }, 18 | "peerDependencies": { 19 | "@strapi/strapi": "^5.0.0" 20 | }, 21 | "scripts": {}, 22 | "author": { 23 | "name": "Derrick Mehaffy", 24 | "email": "derrickmehaffy@gmail.com", 25 | "url": "https://github.com/derrickmehaffy" 26 | }, 27 | "maintainers": [ 28 | { 29 | "name": "Strapi Community", 30 | "url": "https://github.com/strapi-community" 31 | }, 32 | { 33 | "name": "Derrick Mehaffy", 34 | "email": "derrickmehaffy@gmail.com", 35 | "url": "https://github.com/derrickmehaffy", 36 | "lead": true 37 | }, 38 | { 39 | "name": "Excl Networks Inc." 40 | } 41 | ], 42 | "bugs": { 43 | "url": "https://github.com/strapi-community/plugin-redis/issues" 44 | }, 45 | "repository": { 46 | "type": "git", 47 | "url": "github:strapi-community/plugin-redis" 48 | }, 49 | "homepage": "https://strapi-community.github.io/plugin-redis/", 50 | "license": "MIT" 51 | } 52 | -------------------------------------------------------------------------------- /server/config/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | default: { 5 | settings: { 6 | debug: false, 7 | debugIORedis: false, 8 | redlockConfig: { 9 | driftFactor: 0.01, 10 | retryCount: 10, 11 | retryDelay: 200, 12 | retryJitter: 200, 13 | }, 14 | enableRedlock: false, 15 | lockDelay: null, 16 | lockTTL: 5000, 17 | }, 18 | connections: { 19 | default: { 20 | connection: { 21 | host: '127.0.0.1', 22 | port: 6379, 23 | db: 0, 24 | }, 25 | }, 26 | }, 27 | }, 28 | validator() {}, 29 | }; 30 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const register = require('./register'); 4 | const config = require('./config'); 5 | const services = require('./services'); 6 | 7 | module.exports = { 8 | register, 9 | config, 10 | services, 11 | }; 12 | -------------------------------------------------------------------------------- /server/register.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const debug = require('debug'); 4 | const { default: Redlock } = require('redlock'); 5 | 6 | module.exports = async ({ strapi }) => { 7 | // Load plugin Config 8 | const coreConfig = strapi.config.get('plugin::redis'); 9 | 10 | // Configure plugin debug 11 | if (coreConfig.settings.debug === true) { 12 | debug.enable('strapi:strapi-plugin-redis'); 13 | } 14 | 15 | // Allow plugin + ioredis debug 16 | if (coreConfig.settings.debug === true && coreConfig.settings.debugIORedis === true) { 17 | debug.enable('strapi:strapi-plugin-redis,ioredis:*'); 18 | } 19 | 20 | // Construct Redis API 21 | strapi.redis = { 22 | config: coreConfig, 23 | connections: {}, 24 | }; 25 | 26 | // Build Redis database connections 27 | await strapi.plugin('redis').service('connection').buildAll(coreConfig); 28 | 29 | // Configure Redlock 30 | if (coreConfig.settings.enableRedlock === true) { 31 | const originalAdd = strapi.cron.add; 32 | const redlockConfig = coreConfig.settings.redlockConfig; 33 | 34 | strapi.cron.add = (tasks) => { 35 | const generateRedlockFunction = (originalFunction, name) => { 36 | return async (...args) => { 37 | const connections = Object.keys(strapi.redis.connections).map((key) => { 38 | return strapi.redis.connections[key].client; 39 | }); 40 | const redlock = new Redlock(connections, redlockConfig); 41 | 42 | let lock; 43 | try { 44 | lock = await redlock.acquire([name], coreConfig.settings.lockTTL); 45 | debug(`Job ${name} acquired lock`); 46 | await originalFunction(...args); 47 | } catch (e) { 48 | debug(`Job ${name} failed to acquire lock`); 49 | } finally { 50 | // wait some time so other processes will lose the lock 51 | let lockDelay = coreConfig.settings.lockDelay 52 | ? coreConfig.settings.lockDelay 53 | : coreConfig.settings.redlockConfig.retryCount * 54 | (coreConfig.settings.redlockConfig.retryDelay + 55 | coreConfig.settings.redlockConfig.retryJitter); 56 | debug(`Job ${name} waiting ${lockDelay}ms before releasing lock`); 57 | await new Promise((resolve) => setTimeout(resolve, lockDelay)); 58 | if (lock) { 59 | debug(`Job ${name} releasing lock`); 60 | try { 61 | await lock.release(); 62 | } catch (e) { 63 | debug(`Job ${name} failed to release lock ${e}`); 64 | } 65 | } 66 | } 67 | }; 68 | }; 69 | Object.keys(tasks).forEach((key) => { 70 | const taskValue = tasks[key]; 71 | if (typeof taskValue === 'function') { 72 | strapi.log.info('redlock requires tasks to use the object format'); 73 | return; 74 | } else if ( 75 | typeof taskValue === 'object' && 76 | taskValue && 77 | typeof taskValue.task === 'function' && 78 | taskValue.bypassRedlock !== true 79 | ) { 80 | // fallback to key if no name is provided 81 | const taskName = taskValue.name || key; 82 | taskValue.task = generateRedlockFunction(taskValue.task, 'redlock:' + taskName); 83 | } 84 | }); 85 | originalAdd(tasks); 86 | }; 87 | } 88 | }; 89 | -------------------------------------------------------------------------------- /server/services/connection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const Redis = require('ioredis'); 4 | const chalk = require('chalk'); 5 | const debug = require('debug')('strapi:strapi-plugin-redis'); 6 | 7 | module.exports = ({ strapi }) => ({ 8 | buildAll(config) { 9 | const coreConfig = config; 10 | 11 | // Loop through all connections and start building and mounting them 12 | Object.keys(coreConfig.connections).forEach((name) => { 13 | debug(`${chalk.yellow('Building')} ${name} connection`); 14 | const nameConfig = coreConfig.connections[name]; 15 | 16 | // Check for cluster 17 | if (nameConfig.connection.nodes) { 18 | try { 19 | strapi.redis.connections[name] = { 20 | client: new Redis.Cluster(nameConfig.connection.nodes, nameConfig.connection.options), 21 | }; 22 | debug(`${chalk.green('Built')} ${name} connection - ${chalk.blue('cluster')}`); 23 | } catch (e) { 24 | debug(`${chalk.red('Failed to build')} ${name} connection - ${chalk.blue('cluster')}`); 25 | } 26 | 27 | // Check for sentinel config 28 | } else if (nameConfig.connection.sentinels) { 29 | delete nameConfig.connection.host; 30 | delete nameConfig.connection.port; 31 | try { 32 | strapi.redis.connections[name] = { 33 | client: new Redis(nameConfig.connection), 34 | }; 35 | debug(`${chalk.green('Built')} ${name} connection - ${chalk.yellow('sentinel')}`); 36 | } catch (e) { 37 | debug(`${chalk.red('Failed to build')} ${name} connection - ${chalk.yellow('sentinel')}`); 38 | } 39 | 40 | // Check for regular single connection 41 | } else { 42 | try { 43 | strapi.redis.connections[name] = { 44 | client: new Redis(nameConfig.connection), 45 | }; 46 | debug(`${chalk.green('Built')} ${name} connection - ${chalk.magenta('stand-alone')}`); 47 | } catch (e) { 48 | debug( 49 | `${chalk.red('Failed to build')} ${name} connection - ${chalk.magenta('stand-alone')}` 50 | ); 51 | } 52 | } 53 | }); 54 | }, 55 | }); 56 | -------------------------------------------------------------------------------- /server/services/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const connection = require('./connection'); 4 | 5 | module.exports = { 6 | connection, 7 | }; 8 | -------------------------------------------------------------------------------- /strapi-server.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = require('./server'); 4 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@ioredis/commands@^1.1.1": 6 | version "1.2.0" 7 | resolved "https://registry.yarnpkg.com/@ioredis/commands/-/commands-1.2.0.tgz#6d61b3097470af1fdbbe622795b8921d42018e11" 8 | integrity sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg== 9 | 10 | ansi-styles@^4.1.0: 11 | version "4.3.0" 12 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" 13 | integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== 14 | dependencies: 15 | color-convert "^2.0.1" 16 | 17 | chalk@4.1.2: 18 | version "4.1.2" 19 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" 20 | integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== 21 | dependencies: 22 | ansi-styles "^4.1.0" 23 | supports-color "^7.1.0" 24 | 25 | cluster-key-slot@^1.1.0: 26 | version "1.1.2" 27 | resolved "https://registry.yarnpkg.com/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz#88ddaa46906e303b5de30d3153b7d9fe0a0c19ac" 28 | integrity sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA== 29 | 30 | color-convert@^2.0.1: 31 | version "2.0.1" 32 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 33 | integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== 34 | dependencies: 35 | color-name "~1.1.4" 36 | 37 | color-name@~1.1.4: 38 | version "1.1.4" 39 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" 40 | integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== 41 | 42 | debug@4.3.5: 43 | version "4.3.5" 44 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e" 45 | integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg== 46 | dependencies: 47 | ms "2.1.2" 48 | 49 | debug@^4.3.4: 50 | version "4.3.4" 51 | resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" 52 | integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== 53 | dependencies: 54 | ms "2.1.2" 55 | 56 | denque@^2.1.0: 57 | version "2.1.0" 58 | resolved "https://registry.yarnpkg.com/denque/-/denque-2.1.0.tgz#e93e1a6569fb5e66f16a3c2a2964617d349d6ab1" 59 | integrity sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw== 60 | 61 | has-flag@^4.0.0: 62 | version "4.0.0" 63 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" 64 | integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== 65 | 66 | ioredis@5.4.1: 67 | version "5.4.1" 68 | resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.4.1.tgz#1c56b70b759f01465913887375ed809134296f40" 69 | integrity sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA== 70 | dependencies: 71 | "@ioredis/commands" "^1.1.1" 72 | cluster-key-slot "^1.1.0" 73 | debug "^4.3.4" 74 | denque "^2.1.0" 75 | lodash.defaults "^4.2.0" 76 | lodash.isarguments "^3.1.0" 77 | redis-errors "^1.2.0" 78 | redis-parser "^3.0.0" 79 | standard-as-callback "^2.1.0" 80 | 81 | lodash.defaults@^4.2.0: 82 | version "4.2.0" 83 | resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" 84 | integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== 85 | 86 | lodash.isarguments@^3.1.0: 87 | version "3.1.0" 88 | resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" 89 | integrity sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg== 90 | 91 | ms@2.1.2: 92 | version "2.1.2" 93 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 94 | integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== 95 | 96 | node-abort-controller@^3.0.1: 97 | version "3.1.1" 98 | resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548" 99 | integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ== 100 | 101 | redis-errors@^1.0.0, redis-errors@^1.2.0: 102 | version "1.2.0" 103 | resolved "https://registry.yarnpkg.com/redis-errors/-/redis-errors-1.2.0.tgz#eb62d2adb15e4eaf4610c04afe1529384250abad" 104 | integrity sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w== 105 | 106 | redis-parser@^3.0.0: 107 | version "3.0.0" 108 | resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-3.0.0.tgz#b66d828cdcafe6b4b8a428a7def4c6bcac31c8b4" 109 | integrity sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A== 110 | dependencies: 111 | redis-errors "^1.0.0" 112 | 113 | redlock@5.0.0-beta.2: 114 | version "5.0.0-beta.2" 115 | resolved "https://registry.yarnpkg.com/redlock/-/redlock-5.0.0-beta.2.tgz#a629c07e07d001c0fdd9f2efa614144c4416fe44" 116 | integrity sha512-2RDWXg5jgRptDrB1w9O/JgSZC0j7y4SlaXnor93H/UJm/QyDiFgBKNtrh0TI6oCXqYSaSoXxFh6Sd3VtYfhRXw== 117 | dependencies: 118 | node-abort-controller "^3.0.1" 119 | 120 | standard-as-callback@^2.1.0: 121 | version "2.1.0" 122 | resolved "https://registry.yarnpkg.com/standard-as-callback/-/standard-as-callback-2.1.0.tgz#8953fc05359868a77b5b9739a665c5977bb7df45" 123 | integrity sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A== 124 | 125 | supports-color@^7.1.0: 126 | version "7.2.0" 127 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" 128 | integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== 129 | dependencies: 130 | has-flag "^4.0.0" 131 | --------------------------------------------------------------------------------