From 47efd3c81a44567a4d38d6556644005d4259e539 Mon Sep 17 00:00:00 2001 From: "Vanessa Pasque (Lith)" Date: Thu, 18 Feb 2021 12:20:50 +0100 Subject: [PATCH] First full release of Strapi plugin notification expo (beta version) Signed-off-by: Vanessa Pasque (Lith) --- .eslintignore | 3 + .eslintrc.back.js | 37 + .eslintrc.front.js | 117 + .eslintrc.js | 22 + .npmignore | 104 + .nycrc | 6 + .prettierrc.js | 8 + CODE_OF_CONDUCT.md | 74 + CONTRIBUTING.md | 80 + README.md | 96 +- SECURITY.md | 17 + admin/src/components/PreviewAndroid/index.js | 12 + admin/src/components/PreviewIOS/index.js | 12 + admin/src/components/Utils/getForm.js | 55 + admin/src/containers/AddPage/index.js | 152 + admin/src/containers/AddPage/init.js | 2 + admin/src/containers/AddPage/reducer.js | 47 + admin/src/containers/App/index.js | 31 + admin/src/containers/EditPage/index.js | 197 + admin/src/containers/EditPage/init.js | 2 + admin/src/containers/EditPage/reducer.js | 49 + admin/src/containers/HomePage/index.js | 218 + admin/src/containers/HomePage/init.js | 2 + admin/src/containers/HomePage/reducer.js | 55 + admin/src/containers/Initializer/index.js | 26 + admin/src/index.js | 46 + admin/src/lifecycles.js | 3 + admin/src/pluginId.js | 5 + admin/src/translations/ar.json | 45 + admin/src/translations/cs.json | 45 + admin/src/translations/de.json | 45 + admin/src/translations/en.json | 45 + admin/src/translations/es.json | 45 + admin/src/translations/fr.json | 45 + admin/src/translations/id.json | 45 + admin/src/translations/index.js | 49 + admin/src/translations/it.json | 45 + admin/src/translations/ko.json | 45 + admin/src/translations/ms.json | 45 + admin/src/translations/nl.json | 45 + admin/src/translations/pl.json | 45 + admin/src/translations/pt-BR.json | 45 + admin/src/translations/pt.json | 45 + admin/src/translations/ru.json | 45 + admin/src/translations/sk.json | 45 + admin/src/translations/th.json | 45 + admin/src/translations/tr.json | 45 + admin/src/translations/uk.json | 45 + admin/src/translations/vi.json | 45 + admin/src/translations/zh-Hans.json | 1 + admin/src/translations/zh.json | 1 + admin/src/utils/getFilters.js | 32 + admin/src/utils/getTrad.js | 12 + adminTranslations.babel | 4106 +++++++++++++++++ api/expotoken/config/routes.json | 60 - api/expotoken/controllers/Expotoken.js | 36 - api/expotoken/services/Expotoken.js | 8 - config/functions/cron.js | 11 + config/policies/isAdmin.js | 17 + config/policies/isLogged.js | 8 + config/routes.json | 108 + controllers/expo.js | 21 + controllers/exponotification.js | 121 + controllers/expotoken.js | 110 + middlewares/expoCron/index.js | 44 + models/exponotification.js | 44 + models/exponotification.settings.json | 66 + .../Expotoken.js => models/expotoken.js | 11 - .../expotoken.settings.json | 16 +- package.json | 62 + plugins/notification/config/routes.json | 12 - plugins/notification/controllers/Expo.js | 11 - plugins/notification/package.json | 31 - plugins/notification/services/Expo.js | 85 - services/expo.js | 86 + services/exponotification.js | 139 + services/expotoken.js | 99 + services/utils/notificationMessage.js | 73 + services/utils/usersByPlatform.js | 33 + yarn.lock | 2610 +++++++++++ 80 files changed, 10201 insertions(+), 300 deletions(-) create mode 100644 .eslintignore create mode 100644 .eslintrc.back.js create mode 100644 .eslintrc.front.js create mode 100644 .eslintrc.js create mode 100644 .npmignore create mode 100644 .nycrc create mode 100644 .prettierrc.js create mode 100644 CODE_OF_CONDUCT.md create mode 100644 CONTRIBUTING.md create mode 100644 SECURITY.md create mode 100644 admin/src/components/PreviewAndroid/index.js create mode 100644 admin/src/components/PreviewIOS/index.js create mode 100644 admin/src/components/Utils/getForm.js create mode 100644 admin/src/containers/AddPage/index.js create mode 100644 admin/src/containers/AddPage/init.js create mode 100644 admin/src/containers/AddPage/reducer.js create mode 100644 admin/src/containers/App/index.js create mode 100644 admin/src/containers/EditPage/index.js create mode 100644 admin/src/containers/EditPage/init.js create mode 100644 admin/src/containers/EditPage/reducer.js create mode 100644 admin/src/containers/HomePage/index.js create mode 100644 admin/src/containers/HomePage/init.js create mode 100644 admin/src/containers/HomePage/reducer.js create mode 100644 admin/src/containers/Initializer/index.js create mode 100644 admin/src/index.js create mode 100644 admin/src/lifecycles.js create mode 100644 admin/src/pluginId.js create mode 100644 admin/src/translations/ar.json create mode 100644 admin/src/translations/cs.json create mode 100644 admin/src/translations/de.json create mode 100644 admin/src/translations/en.json create mode 100644 admin/src/translations/es.json create mode 100644 admin/src/translations/fr.json create mode 100644 admin/src/translations/id.json create mode 100644 admin/src/translations/index.js create mode 100644 admin/src/translations/it.json create mode 100644 admin/src/translations/ko.json create mode 100644 admin/src/translations/ms.json create mode 100644 admin/src/translations/nl.json create mode 100644 admin/src/translations/pl.json create mode 100644 admin/src/translations/pt-BR.json create mode 100644 admin/src/translations/pt.json create mode 100644 admin/src/translations/ru.json create mode 100644 admin/src/translations/sk.json create mode 100644 admin/src/translations/th.json create mode 100644 admin/src/translations/tr.json create mode 100644 admin/src/translations/uk.json create mode 100644 admin/src/translations/vi.json create mode 100644 admin/src/translations/zh-Hans.json create mode 100644 admin/src/translations/zh.json create mode 100644 admin/src/utils/getFilters.js create mode 100644 admin/src/utils/getTrad.js create mode 100644 adminTranslations.babel delete mode 100644 api/expotoken/config/routes.json delete mode 100644 api/expotoken/controllers/Expotoken.js delete mode 100644 api/expotoken/services/Expotoken.js create mode 100644 config/functions/cron.js create mode 100644 config/policies/isAdmin.js create mode 100644 config/policies/isLogged.js create mode 100644 config/routes.json create mode 100644 controllers/expo.js create mode 100644 controllers/exponotification.js create mode 100644 controllers/expotoken.js create mode 100644 middlewares/expoCron/index.js create mode 100644 models/exponotification.js create mode 100644 models/exponotification.settings.json rename api/expotoken/models/Expotoken.js => models/expotoken.js (99%) rename api/expotoken/models/Expotoken.settings.json => models/expotoken.settings.json (65%) create mode 100644 package.json delete mode 100644 plugins/notification/config/routes.json delete mode 100644 plugins/notification/controllers/Expo.js delete mode 100644 plugins/notification/package.json delete mode 100644 plugins/notification/services/Expo.js create mode 100644 services/expo.js create mode 100644 services/exponotification.js create mode 100644 services/expotoken.js create mode 100644 services/utils/notificationMessage.js create mode 100644 services/utils/usersByPlatform.js create mode 100644 yarn.lock diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..a9d7744 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +# Test + +cypress/ diff --git a/.eslintrc.back.js b/.eslintrc.back.js new file mode 100644 index 0000000..f76a564 --- /dev/null +++ b/.eslintrc.back.js @@ -0,0 +1,37 @@ +'use strict'; + +module.exports = { + extends: [ + 'eslint:recommended', + 'prettier', + 'plugin:import/errors', + 'plugin:import/warnings', + 'plugin:node/recommended', + ], + env: { + es6: true, + node: true, + jest: true, + }, + globals: { + strapi: false, + }, + rules: { + 'node/no-unpublished-require': 'off', + 'require-atomic-updates': 'off', + 'no-process-exit': 'off', + strict: ['error', 'global'], + 'import/order': 'error', + 'import/no-cycle': 'error', + 'import/no-useless-path-segments': 'error', + 'import/first': 'error', + 'import/extensions': ['error', 'never'], + 'import/newline-after-import': 'error', + 'import/no-extraneous-dependencies': ["error", {"peerDependencies": true}], + 'node/exports-style': ['error', 'module.exports'], + 'node/no-new-require': 'error', + 'node/no-path-concat': 'error', + 'node/no-callback-literal': 'error', + 'node/handle-callback-err': 'error', + }, +}; diff --git a/.eslintrc.front.js b/.eslintrc.front.js new file mode 100644 index 0000000..9c737aa --- /dev/null +++ b/.eslintrc.front.js @@ -0,0 +1,117 @@ +'use strict'; + +module.exports = { + parser: 'babel-eslint', + extends: [ + 'airbnb', + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:redux-saga/recommended', + 'prettier', + ], + plugins: ['react', 'redux-saga', 'react-hooks', 'import', 'jsx-a11y'], + env: { + browser: true, + commonjs: true, + es6: true, + jest: true, + mocha: true, + }, + parserOptions: { + ecmaVersion: 2018, + ecmaFeatures: { + jsx: true, + }, + sourceType: 'module', + }, + globals: { + strapi: false, + window: false, + cy: false, + Cypress: false, + expect: false, + assert: false, + chai: false, + ENABLED_EE_FEATURES: false, + REMOTE_URL: true, + BACKEND_URL: true, + PUBLIC_PATH: true, + MODE: true, + NODE_ENV: true, + }, + settings: { + react: { + version: '16.5.2', + }, + }, + rules: { + 'import/no-unresolved': 0, + 'generator-star-spacing': 0, + 'no-console': 0, + 'require-atomic-updates': 0, + 'react-hooks/rules-of-hooks': 'warn', + 'react-hooks/exhaustive-deps': 'error', + 'arrow-body-style': 0, + 'arrow-parens': 0, + camelcase: 0, + 'comma-dangle': 0, + 'template-curly-spacing': 0, + 'func-names': ['error', 'never'], + 'function-paren-newline': 0, + 'implicit-arrow-linebreak': 0, + 'import/no-extraneous-dependencies': 0, + 'import/no-named-as-default': 0, + 'import/order': 2, + 'jsx-a11y/click-events-have-key-events': 1, + 'max-len': [ + 2, + { + code: 120, + ignoreComments: true, + ignoreUrls: true, + ignoreTrailingComments: true, + ignoreStrings: true, + ignoreTemplateLiterals: true, + }, + ], + 'newline-before-return': 2, + 'no-confusing-arrow': 0, + 'no-else-return': 1, + 'no-nested-ternary': ['error'], + 'no-return-assign': 0, + 'no-param-reassign': 0, + 'no-plusplus': 0, + 'no-shadow': 0, + 'no-underscore-dangle': 0, + 'no-use-before-define': ['error', { functions: false, classes: false, variables: false }], + 'object-curly-newline': [2, { multiline: true, consistent: true }], + 'operator-linebreak': 0, + 'padding-line-between-statements': [ + 'error', + { blankLine: 'always', prev: '*', next: 'if' }, + { blankLine: 'any', prev: 'block-like', next: 'if' }, + ], + 'prefer-arrow-callback': 0, + 'prefer-const': 0, + 'prefer-destructuring': 0, + 'prefer-object-spread': 0, + 'prefer-spread': 0, + 'space-before-function-paren': [ + 'error', + { + anonymous: 'never', + named: 'never', + asyncArrow: 'always', + }, + ], + 'react/destructuring-assignment': 0, + 'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }], + 'react/forbid-prop-types': 0, + 'react/no-unused-prop-types': 2, + 'react/jsx-props-no-spreading': 0, + 'react/jsx-one-expression-per-line': 0, + 'react/state-in-constructor': 0, + 'react/static-property-placement': 0, + 'react/display-name': 0, + }, +}; diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..167aef9 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,22 @@ +'use strict'; + +const frontPaths = [ + 'admin/src/**/**/*.js', +]; + +module.exports = { + parserOptions: { + ecmaVersion: 2018, + }, + overrides: [ + { + files: ['**/*.js'], + excludedFiles: frontPaths, + ...require('./.eslintrc.back.js'), + }, + { + files: frontPaths, + ...require('./.eslintrc.front.js'), + }, + ], +}; diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..af4e005 --- /dev/null +++ b/.npmignore @@ -0,0 +1,104 @@ +############################ +# OS X +############################ + +.DS_Store +.AppleDouble +.LSOverride +Icon +.Spotlight-V100 +.Trashes +._* + + +############################ +# Linux +############################ + +*~ + + +############################ +# Windows +############################ + +Thumbs.db +ehthumbs.db +Desktop.ini +$RECYCLE.BIN/ +*.cab +*.msi +*.msm +*.msp + + +############################ +# Packages +############################ + +*.7z +*.csv +*.dat +*.dmg +*.gz +*.iso +*.jar +*.rar +*.tar +*.zip +*.com +*.class +*.dll +*.exe +*.o +*.seed +*.so +*.swo +*.swp +*.swn +*.swm +*.out +*.pid + + +############################ +# Logs and databases +############################ + +.tmp +*.log +*.sql +*.sqlite + + +############################ +# Misc. +############################ + +*# +ssl +.editorconfig +.gitattributes +.idea +nbproject + + +############################ +# Node.js +############################ + +lib-cov +lcov.info +pids +logs +results +build +node_modules +.node_history + + +############################ +# Tests +############################ + +test diff --git a/.nycrc b/.nycrc new file mode 100644 index 0000000..bc615f0 --- /dev/null +++ b/.nycrc @@ -0,0 +1,6 @@ +{ + "all": true, + "include": [ + "lib" + ] +} diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..102e3fa --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,8 @@ +module.exports = { + endOfLine: 'lf', + semi: true, + singleQuote: true, + tabWidth: 2, + trailingComma: 'es5', + printWidth: 100, +}; diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..3af1dad --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,74 @@ +# Code of Conduct + +## Our Pledge + +In the interest of fostering an open and welcoming environment, we as +contributors and maintainers pledge to making participation in our project and +our community a harassment-free experience for everyone, regardless of age, body +size, disability, ethnicity, gender identity and expression, level of experience, +nationality, personal appearance, race, religion or sexual identity and +orientation. + +## Our Standards + +Examples of behavior that contributes to creating a positive environment +include: + +* Using welcoming and inclusive language +* Being respectful of differing viewpoints and experiences +* Gracefully accepting constructive criticism +* Focusing on what is best for the community +* Showing empathy towards other community members + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery and unwelcome sexual attention or + advances +* Trolling, insulting/derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or electronic + address, without explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Our Responsibilities + +Project maintainers are responsible for clarifying the standards of acceptable +behavior and are expected to take appropriate and fair corrective action in +response to any instances of unacceptable behavior. + +Project maintainers have the right and responsibility to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive or harmful. + +## Scope + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. Examples of +representing a project or community include using an official project e-mail +address, posting via an official social media account or acting as an appointed +representative at an online or offline event. Representation of a project may be +further defined and clarified by project maintainers. + +## Enforcement + +Instances of abusive, harassing or otherwise unacceptable behavior may be +reported by contacting the project team at [lith@amykron.com](lith@amykron.com). +All complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. The project team is +obligated to maintain confidentiality with regard to the reporter of an incident. +Further details of specific enforcement policies may be posted separately. + +Project maintainers who do not follow or enforce the Code of Conduct in good +faith may face temporary or permanent repercussions as determined by other +members of the project's leadership. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][homepage] version 1.4, +available at [http://contributor-covenant.org/version/1/4][version] + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d48a791 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,80 @@ +# Contributing + +When contributing to this repository, please first discuss the change you wish to make via issue, +email, or any other method with the owners of this repository before making a change. + +Please note we have a code of conduct, please follow it in all your interactions with the project. + +## Open Development & Community Driven + +This project is open-source under the [MIT license](LICENSE). All the work done is available on GitHub. + +## Code of Conduct + +This project and everyone participating in it are governed by a [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please read the [full text](CODE_OF_CONDUCT.md) so that you can read which actions may or may not be tolerated. + +## Bugs + +We are using [GitHub Issues](https://github.com/Lith/strapi-plugin-notification-expo/issues) to manage our public bugs. We keep a close eye on this so before filing a new issue, try to make sure the problem does not already exist. + +--- + +## Contribution Prerequisites + +* You have [Node](https://nodejs.org/en/) at v12.x.x only and [Yarn](https://yarnpkg.com/en/) at v1.2.0+. +* You are familiar with Git. + +This project is using `Yarn` so you need to use it for installation package. + +## Pull Request Process + +The team will review your pull request and will either merge it, request changes to it, or close it. + +**Before submitting your pull request** make sure the following requirements are fulfilled: + +1. Fork the repository and create your branch from `master`. + - Run `yarn install` in the repository root. + - If you’ve fixed a bug or added code that should be tested, add the tests and then link the corresponding issue in either your commit or your PR! + - Ensure the test suites are passing: + - `yarn test` or `npm run test` + - Make sure your code lints + - `yarn lint` or `npm run lint` + - Check coverage report + - `yarn coverage` or `npm run coverage` +2. Update the [README.md](README.md) with details of changes to the interface, this includes new environment + variables, exposed ports, useful file locations and container parameters. +3. You need to Signed-off-by all of your commits before push, like this example : + ```shell script + This is my commit message + + Signed-off-by: Random J Developer + ``` + Git even has a -s command line option to append this automatically to your commit message: + ``` + $ git commit -s -m 'This is my commit message' + ``` +4. A team leader will check, suggest modification, approve, merge, and close your request. + +--- + +## Miscellaneous + +### Reporting an issue + +Before submitting an issue you need to make sure: + +- You are experiencing a concrete technical issue with this plugin. +- You have already searched for related [issues](https://github.com/Lith/strapi-plugin-notification-expo/issues), and found none open (if you found a related _closed_ issue, please link to it from your post). +- Your issue title is concise, on-topic and polite. +- You can and do provide steps to reproduce your issue. +- You have tried all the following (if relevant) and your issue remains: + - Make sure you have the right application started. + - Make sure the [issue template](.github/ISSUE_TEMPLATE) is respected. + - Make sure your issue body is readable and [well formatted](https://guides.github.com/features/mastering-markdown). + - Make sure you've killed the Strapi server with CTRL+C and started it again. + - Make sure the application you are using to reproduce the issue has a clean `node_modules` directory, meaning: + - no dependencies are linked (e.g. you haven't run `npm link`) + - that you haven't made any inline changes to files in the `node_modules` folder + - that you don't have any weird global dependency loops. The easiest way to double-check any of the above, if you aren't sure, is to run: + - `$ rm -rf node_modules && npm cache clear && npm install`. + diff --git a/README.md b/README.md index 0e3573d..1e467de 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,76 @@ # strapi-plugin-notification-expo -This is a plugin of "expo notification" for Strapi. +![npm](https://img.shields.io/npm/v/strapi-plugin-notification-expo?style=flat-square) +![npm](https://img.shields.io/npm/dm/strapi-plugin-notification-expo?style=flat-square) +![GitHub package.json version](https://img.shields.io/github/package-json/v/Lith/strapi-plugin-notification-expo?style=flat-square) +![GitHub issues](https://img.shields.io/github/issues/Lith/strapi-plugin-notification-expo?style=flat-square) +![Gitlab code coverage](https://img.shields.io/gitlab/coverage/Lith/strapi-plugin-notification-expo/master?style=flat-square) -_Working with Strapi 3.\*.\* (beta and stable)_ +**(Non-official)** Strapi plugins to send Expo notifications -### /!\ Example Draft /!\ +## Installation -This is an example of implementation, adapt it for your case by copy/paste file (or code needed). +Install the package from your app root directory -An installable version is work in progress with an administration panel parts. +With `npm` +```shell +npm install strapi-plugin-notification-expo +``` +or `yarn` +```shell +yarn add strapi-plugin-notification-expo +``` +## Introduction -_Just to give inspiration to others_ +This plugin allow you to draft & publish Expo notification +### Feature +- Used `Draft and Publish` Strapi feature +- Build with [Buffetjs.io](https://www.buffetjs.io/) +- Follow Strapi rules and requirement -## Expo +### Include +- Administration panel with the list of all Notification, add, planify, edit and publish your notification in a click +- Automatic publish with a dedicated cron +- Read-only notification send -### Requirement +### Information +This plugin will add 3 tables into your project : +- `expotokens` : list of all Expo tokens (platform, "Expo push token", user) +- `exponotifications`: list of all Notification with a state +- `exponotifications_users` : list of all users than will received the notification -Install the expo server SDK package +## Requirement -```shell script -yarn add expo-server-sdk -``` +### Edit `config/server.js` + +This project launch a Cron Task to check every 10 minutes if notification need to be send, so you need to enabled `cron` in `config/server.js` : -### Add expotokens 'model' into Strapi API +```json + cron: { + enabled: true, + }, +``` -You need to register Expo token before send a notification to a user. +If you want disable cron task on staging or development environment, edit `config/env/development/server.js` and disabled `cron`. -This models allow us to save information in database, but you are free to use an other solution. +### Edit `config/middleware.js` -Keep in mind than a user can have many devices, each user can receive notifications on an iPad, Android, iPhone, ...etc +Enable the plugin's cron : +```json + expoCron: { + enabled: true, + }, +``` + +# FAQ -### Register token from Expo to Strapi +## How to register token from Expo to Strapi ? In your app, add some code to register the token linked to the user account on Strapi API : -_Be careful, I'm not a React developer, so this code is an ugly example_ ```typescript Permissions .askAsync(Permissions.NOTIFICATIONS) @@ -49,9 +82,9 @@ Permissions }) .then((token) => { return api - .post('/expotokens', { - userId, - token + .post('/notification-expo/expotokens', { + token, + platform: Platform.OS }) .catch((err) => { if (err && err.statusCode === 409) { @@ -68,24 +101,3 @@ Permissions }) .catch((err) => dispatch(registerNotificationsTokenFail(err))) ``` - -### Send a notification to user - -Copy plugins files, adapt the code with your own style. - -##### Example with an "inner" notification, use it from existing controller method - -```javascript -... - const datasExpo = { - customer: userId, // you need to have this information before :) - title: '✅ Awesome title', - body: 'Content of your notification', - data: { - url: 'myapp://deeplinking/pages' // useful if you want to redirect customer to the good screen - }, - channelId: `channel_name` // change this with - }; - await strapi.plugins.notification.services.expo.send(ctx, datasExpo); -... -``` diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..4396bc6 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,17 @@ +# Security Policy + +## Supported Versions + +| Strapi release | Plugin version | Supported | +| -------------- | -------------- | ------------------ | +| 3.4.6 | 1.0.0-beta.1 | :white_check_mark: | +| < 3.3.* | x | :x: | + +## Reporting a Vulnerability + +Please report (suspected) security vulnerabilities to **[security@amykron.com](mailto:security@amykron.com)** via the Strapi Slack. + +When reporting a (suspected) security vulnerability via slack please reach out to me directly: +- `@Lith` (/!\ not Strapi employee /!\) + +You will receive a response from me within 48h (depending week-end, day off...). diff --git a/admin/src/components/PreviewAndroid/index.js b/admin/src/components/PreviewAndroid/index.js new file mode 100644 index 0000000..117dc55 --- /dev/null +++ b/admin/src/components/PreviewAndroid/index.js @@ -0,0 +1,12 @@ + + +import React from 'react'; + +/** + * @todo - Create Android Push Notification Preview + */ +const PreviewAndroid = () => { + return
Preview Android
; +}; + +export default PreviewAndroid; diff --git a/admin/src/components/PreviewIOS/index.js b/admin/src/components/PreviewIOS/index.js new file mode 100644 index 0000000..c4b6859 --- /dev/null +++ b/admin/src/components/PreviewIOS/index.js @@ -0,0 +1,12 @@ + + +import React from 'react'; + +/** + * @todo - Create iOS Push Notification Preview + */ +const PreviewIOS = () => { + return
Preview IOS
; +}; + +export default PreviewIOS; diff --git a/admin/src/components/Utils/getForm.js b/admin/src/components/Utils/getForm.js new file mode 100644 index 0000000..14580b7 --- /dev/null +++ b/admin/src/components/Utils/getForm.js @@ -0,0 +1,55 @@ +import getTrad from '../../utils/getTrad'; + +const getForm = () => { + return { + platform: { + styleName: 'col-12', + description: getTrad('form.platform.description'), + label: getTrad('form.platform.label'), + type: 'enum', + options: [ + { value: 'ios', label: getTrad('form.platform.option1') }, + { value: 'android', label: getTrad('form.platform.option2') }, + { value: 'all', label: getTrad('form.platform.option3') }, + ], + value: 'all', + validations: { + required: true, + }, + }, + title: { + styleName: 'col-12', + description: getTrad('form.title.description'), + label: getTrad('form.title.label'), + placeholder: getTrad('form.title.placeholder'), + type: 'text', + validations: { + required: true, + maxLength: 40, + }, + }, + body: { + styleName: 'col-12', + description: getTrad('form.body.description'), + label: getTrad('form.body.label'), + placeholder: getTrad('form.body.placeholder'), + type: 'textarea', + validations: { + required: true, + maxLength: 178, + }, + }, + published_at: { + styleName: 'col-12', + description: getTrad('form.published_at.description'), + label: getTrad('form.published_at.label'), + type: 'datetime', + validations: { + required: true, + min: new Date().getTime(), // not working for now + }, + }, + }; +}; + +export default getForm; diff --git a/admin/src/containers/AddPage/index.js b/admin/src/containers/AddPage/index.js new file mode 100644 index 0000000..ad50c6e --- /dev/null +++ b/admin/src/containers/AddPage/index.js @@ -0,0 +1,152 @@ + + +import { Button, Flex, Padded } from '@buffetjs/core'; +import { Header, Inputs } from '@buffetjs/custom'; +import { faSave } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import React, { memo, useEffect, useReducer } from 'react'; +import { useHistory } from 'react-router-dom'; +import { request } from 'strapi-helper-plugin'; +import PreviewAndroid from '../../components/PreviewAndroid'; +import PreviewIOS from '../../components/PreviewIOS'; + +import getForm from '../../components/Utils/getForm'; +import pluginId from '../../pluginId'; +import getTrad from '../../utils/getTrad'; +import init from './init'; +import { initialState, reducer } from './reducer'; + +const AddPage = () => { + const form = getForm(); + const { push } = useHistory(); + + const previewEnabled = false; + + const [{ entity, isLoading }, dispatch] = useReducer(reducer, initialState, init); + + const handleChange = ({ target: { name, value } }) => { + dispatch({ + type: 'UPDATE_ENTITY', + name, + value, + }); + }; + + useEffect(() => { + dispatch({ + type: 'UNSET_IS_LOADING', + }); + }, []); + + /** + * Save form data + */ + + const saveForm = async (data) => { + if (!data || isLoading) return; + dispatch({ + type: 'SET_IS_LOADING', + }); + + try { + const entity = await request('/notification-expo/exponotifications', { + method: 'POST', + body: data, + }); + + dispatch({ + type: 'SAVE_DATA_SUCCEED', + entity, + }); + + if (entity.id) { + push({ + pathname: `/plugins/${pluginId}/edit/${entity.id}`, + }); + } + + strapi.notification.toggle({ + type: 'success', + message: { id: `${pluginId}.notification.success` }, + }); + } catch (err) { + strapi.notification.toggle({ + type: 'warning', + message: { id: 'notification.error' }, + }); + } + }; + + return ( +
+
+
+
+ +
+
+
+ {Object.keys(form).map((input) => ( +
+ +
+ ))} +
+
+ + + + + +
+ {previewEnabled ? ( +
+ + + + + + +
+ ) : ( +
{/* empty */}
+ )} +
+
+ ); +}; + +export default memo(AddPage); diff --git a/admin/src/containers/AddPage/init.js b/admin/src/containers/AddPage/init.js new file mode 100644 index 0000000..64fdcc0 --- /dev/null +++ b/admin/src/containers/AddPage/init.js @@ -0,0 +1,2 @@ +const init = (initialState) => initialState; +export default init; diff --git a/admin/src/containers/AddPage/reducer.js b/admin/src/containers/AddPage/reducer.js new file mode 100644 index 0000000..f7238e4 --- /dev/null +++ b/admin/src/containers/AddPage/reducer.js @@ -0,0 +1,47 @@ +import produce from 'immer'; + +const initialState = { + entity: {}, + isLoading: true, +}; + +const reducer = (state, action) => + produce(state, (draftState) => { + switch (action.type) { + case 'GET_DATA': { + console.warn('GET_DATA'); + +return initialState; + } + case 'GET_DATA_SUCCEEDED': { + console.warn('GET_DATA_SUCCEEDED'); + draftState.entity = action.entity; + draftState.isLoading = false; + break; + } + case 'UPDATE_ENTITY': { + console.warn('UPDATE_ENTITY'); + draftState.entity[action.name] = action.value; + break; + } + case 'SAVE_DATA_SUCCEED': { + console.warn('SAVE_DATA_SUCCEED'); + draftState.isLoading = false; + break; + } + case 'SET_IS_LOADING': { + console.warn('SET_IS_LOADING'); + draftState.isLoading = true; + break; + } + case 'UNSET_IS_LOADING': { + console.warn('UNSET_IS_LOADING'); + draftState.isLoading = false; + break; + } + default: + return draftState; + } + }); + +export { initialState, reducer }; diff --git a/admin/src/containers/App/index.js b/admin/src/containers/App/index.js new file mode 100644 index 0000000..4adc416 --- /dev/null +++ b/admin/src/containers/App/index.js @@ -0,0 +1,31 @@ +/** + * + * This component is the skeleton around the actual pages, and should only + * contain code that should be seen on all pages. (e.g. navigation bar) + * + */ + +import React from 'react'; +import { Switch, Route } from 'react-router-dom'; +import { NotFound } from 'strapi-helper-plugin'; +// Utils +import pluginId from '../../pluginId'; +// Containers +import HomePage from '../HomePage'; +import EditPage from '../EditPage'; +import AddPage from '../AddPage'; + +const App = () => { + return ( +
+ + + + + + +
+ ); +}; + +export default App; diff --git a/admin/src/containers/EditPage/index.js b/admin/src/containers/EditPage/index.js new file mode 100644 index 0000000..135630c --- /dev/null +++ b/admin/src/containers/EditPage/index.js @@ -0,0 +1,197 @@ +import {Button, Flex, Padded} from '@buffetjs/core'; +import {Header, Inputs} from '@buffetjs/custom'; +import {faSave} from '@fortawesome/free-solid-svg-icons'; +import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; +import React, {memo, useEffect, useMemo, useReducer, useRef} from 'react'; +import {useParams} from 'react-router-dom'; +import {request} from 'strapi-helper-plugin'; +import PreviewAndroid from '../../components/PreviewAndroid'; +import PreviewIOS from '../../components/PreviewIOS'; + +import getForm from '../../components/Utils/getForm'; +import pluginId from '../../pluginId'; +import getTrad from '../../utils/getTrad'; +import init from './init'; +import {initialState, reducer} from './reducer'; + +const EditPage = () => { + const getDataRef = useRef(); + + const form = getForm(); + const {id: notificationId} = useParams(); + + const previewEnabled = false; + + const [{entity, isLoading}, dispatch] = useReducer(reducer, initialState, init); + + const handleChange = ({target: {name, value}}) => { + dispatch({ + type: 'UPDATE_ENTITY', + name, + value, + }); + }; + + getDataRef.current = async () => { + // Show the loading state and reset the state + dispatch({ + type: 'GET_DATA', + }); + + try { + const entity = await request(`/notification-expo/exponotifications/${notificationId}`, { + method: 'GET', + }); + + dispatch({ + type: 'GET_DATA_SUCCEEDED', + entity, + }); + } catch (err) { + strapi.notification.toggle({ + type: 'warning', + message: {id: 'notification.error'}, + }); + } + }; + + useEffect(() => { + if (notificationId) { + getDataRef.current(); + } + }, [notificationId]); + + /** + * Verify if notification has already been send + * + * @returns {boolean} + */ + const notificationAlreadySend = useMemo(() => { + if (entity && entity.published_at && entity.status) { + if (entity.status !== 'pending') { + return true; + } + const publishedDate = new Date(entity.published_at); + const todayDate = new Date(); + + if (publishedDate.getTime() <= todayDate.getTime()) { + return true; + } + } + + return false; + }); + + /** + * Save form data + */ + + const saveForm = async (data) => { + if (!data || isLoading) return; + dispatch({ + type: 'SET_IS_LOADING', + }); + + try { + const entity = await request(`/notification-expo/exponotifications/${notificationId}`, { + method: 'PUT', + body: data, + }); + + dispatch({ + type: 'SAVE_DATA_SUCCEED', + entity, + }); + + strapi.notification.toggle({ + type: 'success', + message: {id: `${pluginId}.notification.success`}, + }); + } catch (err) { + strapi.notification.toggle({ + type: 'warning', + message: {id: 'notification.error'}, + }); + } + }; + + return ( +
+
+
+
+ +
+
+
+ {Object.keys(form).map((input) => ( +
+ +
+ ))} +
+
+ + + + + +
+ {previewEnabled ? ( +
+ + + + + + +
+ ) : ( +
{/* empty */}
+ )} +
+
+ ); +}; + +export default memo(EditPage); diff --git a/admin/src/containers/EditPage/init.js b/admin/src/containers/EditPage/init.js new file mode 100644 index 0000000..64fdcc0 --- /dev/null +++ b/admin/src/containers/EditPage/init.js @@ -0,0 +1,2 @@ +const init = (initialState) => initialState; +export default init; diff --git a/admin/src/containers/EditPage/reducer.js b/admin/src/containers/EditPage/reducer.js new file mode 100644 index 0000000..c6585aa --- /dev/null +++ b/admin/src/containers/EditPage/reducer.js @@ -0,0 +1,49 @@ +import produce from 'immer'; + +const initialState = { + id: 1, + entity: {}, + isLoading: true, +}; + +const reducer = (state, action) => + produce(state, (draftState) => { + switch (action.type) { + case 'GET_DATA': { + console.warn('GET_DATA'); + +return initialState; + } + case 'GET_DATA_SUCCEEDED': { + console.warn('GET_DATA_SUCCEEDED'); + draftState.id = action.entity.id; + draftState.entity = action.entity; + draftState.isLoading = false; + break; + } + case 'UPDATE_ENTITY': { + console.warn('UPDATE_ENTITY'); + draftState.entity[action.name] = action.value; + break; + } + case 'SAVE_DATA_SUCCEED': { + console.warn('SAVE_DATA_SUCCEED'); + draftState.isLoading = false; + break; + } + case 'SET_IS_LOADING': { + console.warn('SET_IS_LOADING'); + draftState.isLoading = true; + break; + } + case 'UNSET_IS_LOADING': { + console.warn('UNSET_IS_LOADING'); + draftState.isLoading = false; + break; + } + default: + return draftState; + } + }); + +export { initialState, reducer }; diff --git a/admin/src/containers/HomePage/index.js b/admin/src/containers/HomePage/index.js new file mode 100644 index 0000000..6d6125d --- /dev/null +++ b/admin/src/containers/HomePage/index.js @@ -0,0 +1,218 @@ + + +import { Button, Flex, Padded, Table } from '@buffetjs/core'; +import { Header } from '@buffetjs/custom'; +import { faPencilAlt, faPlus, faTrashAlt } from '@fortawesome/free-solid-svg-icons'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { sortBy as sort } from 'lodash'; +import React, { memo, useEffect, useMemo, useReducer, useRef } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; +import { PageFooter, request, useQuery } from 'strapi-helper-plugin'; +import pluginId from '../../pluginId'; +import getFilters from '../../utils/getFilters'; +import getTrad from '../../utils/getTrad'; +import init from './init'; +import { initialState, reducer } from './reducer'; + +const HomePage = () => { + const query = useQuery(); + const { push } = useHistory(); + const { search } = useLocation(); + const filters = useMemo(() => { + return getFilters(search); + }, [search]); + + const [ + { + data, + isLoading, + sortBy, + sortOrder, + pagination: { total }, + }, + dispatch, + ] = useReducer(reducer, initialState, init); + const pageSize = parseInt(query.get('pageSize') || 10, 10); + const page = parseInt(query.get('page') || 1, 10); + const _q = decodeURIComponent(query.get('_q') || ''); + const getDataRef = useRef(); + + getDataRef.current = async () => { + // Show the loading state and reset the state + dispatch({ + type: 'GET_DATA', + }); + + try { + const { + data: { results, pagination }, + } = await request(`/notification-expo/exponotifications${search}`, { method: 'GET' }); + + dispatch({ + type: 'GET_DATA_SUCCEEDED', + data: results, + pagination, + }); + } catch (err) { + console.error(err.response); + strapi.notification.toggle({ + type: 'warning', + message: { id: 'notification.error' }, + }); + } + }; + + useEffect(() => { + getDataRef.current(); + }, [search]); + + const updateSearchParams = (name, value, shouldDeleteSearch = false) => { + const currentSearch = new URLSearchParams(search); + // Update the currentSearch + currentSearch.set(name, value); + + if (shouldDeleteSearch) { + currentSearch.delete('_q'); + } + + push({ + search: currentSearch.toString(), + }); + }; + + const handleChangeFooterParams = ({ target: { name, value } }) => { + let paramName = name.split('.')[1].replace('_', ''); + + if (paramName === 'limit') { + paramName = 'pageSize'; + } + + updateSearchParams(paramName, value); + }; + + const addNotification = () => { + push({ + pathname: `/plugins/${pluginId}/add`, + }); + }; + + const editNotification = (event, data) => { + push({ + pathname: `/plugins/${pluginId}/edit/${data.id}`, + }); + }; + + /** + * @todo - implement todo + */ + const deleteNotification = (data) => { + console.warn(`Remove ${data.id} ? `); + strapi.notification.toggle({ + type: 'warning', + message: 'Not implemented yet', + }); + }; + + const sortedRowsBy = sort(data, [sortBy]); + const sortedRows = sortOrder === 'asc' ? sortedRowsBy : sortedRowsBy.reverse(); + + const headers = [ + { + name: getTrad('home.table.row.id'), + value: 'id', + isSortEnabled: true, + }, + { + name: getTrad('home.table.row.title'), + value: 'title', + }, + { + name: getTrad('home.table.row.body'), + value: 'body', + }, + { + name: getTrad('home.table.row.published_at'), + value: 'published_at', + isSortEnabled: true, + }, + { + name: getTrad('home.table.row.status'), + value: 'status', + isSortEnabled: true, + }, + { + name: getTrad('home.table.row.total'), + value: 'total', + }, + ]; + + return ( +
+
+
+
+ + + + + + { + if (isSortEnabled) { + dispatch({ + type: 'CHANGE_SORT', + sortBy, + nextElement: firstElementSort, + }); + } + }} + rowLinks={[ + { + icon: , + onClick: (data) => { + editNotification({}, data); + }, + }, + { + icon: , + onClick: (data) => { + deleteNotification(data); + }, + }, + ]} + /> +
+ + {}, + }} + count={total} + onChangeParams={handleChangeFooterParams} + params={{ _limit: pageSize, _page: page }} + /> + +
+ + ); +}; + +export default memo(HomePage); diff --git a/admin/src/containers/HomePage/init.js b/admin/src/containers/HomePage/init.js new file mode 100644 index 0000000..64fdcc0 --- /dev/null +++ b/admin/src/containers/HomePage/init.js @@ -0,0 +1,2 @@ +const init = (initialState) => initialState; +export default init; diff --git a/admin/src/containers/HomePage/reducer.js b/admin/src/containers/HomePage/reducer.js new file mode 100644 index 0000000..4b44f9f --- /dev/null +++ b/admin/src/containers/HomePage/reducer.js @@ -0,0 +1,55 @@ +import produce from 'immer'; + +const initialState = { + data: [], + isLoading: true, + sortBy: 'id', + sortOrder: 'asc', + pagination: { + page: 1, + pageSize: 10, + pageCount: 0, + total: 0, + }, +}; + +const reducer = (state, action) => + produce(state, (draftState) => { + switch (action.type) { + case 'GET_DATA': { + return initialState; + } + case 'GET_DATA_SUCCEEDED': { + draftState.data = action.data; + draftState.isLoading = false; + draftState.pagination = action.pagination; + break; + } + case 'CHANGE_SORT': { + if (draftState.sortBy === action.sortBy) { + let sortOrder = draftState.sortOrder === 'asc' ? 'desc' : 'asc'; + + if (sortOrder === 'asc') { + return {...draftState, sortOrder, sortBy: action.nextElement}; + } + + return {...draftState, sortOrder}; + } + if (draftState.sortBy !== action.sortBy) { + return {...draftState, sortOrder: 'asc', sortBy: action.sortBy}; + } + + draftState.sortBy = action.sortBy; + draftState.sortOrder = action.sortOrder; + break; + } + case 'UNSET_IS_LOADING': { + draftState.isLoading = false; + break; + } + default: + return draftState; + } + }); + +export {initialState, reducer}; diff --git a/admin/src/containers/Initializer/index.js b/admin/src/containers/Initializer/index.js new file mode 100644 index 0000000..06b5488 --- /dev/null +++ b/admin/src/containers/Initializer/index.js @@ -0,0 +1,26 @@ +/** + * + * Initializer + * + */ + +import { useEffect, useRef } from 'react'; +import PropTypes from 'prop-types'; +import pluginId from '../../pluginId'; + +const Initializer = ({ updatePlugin }) => { + const ref = useRef(); + ref.current = updatePlugin; + + useEffect(() => { + ref.current(pluginId, 'isReady', true); + }, []); + + return null; +}; + +Initializer.propTypes = { + updatePlugin: PropTypes.func.isRequired, +}; + +export default Initializer; diff --git a/admin/src/index.js b/admin/src/index.js new file mode 100644 index 0000000..b872104 --- /dev/null +++ b/admin/src/index.js @@ -0,0 +1,46 @@ +import pluginPkg from '../../package.json'; +import pluginId from './pluginId'; +import App from './containers/App'; +import Initializer from './containers/Initializer'; +import lifecycles from './lifecycles'; +import trads from './translations'; + +export default (strapi) => { + const pluginDescription = pluginPkg.strapi.description || pluginPkg.description; + const icon = pluginPkg.strapi.icon; + const name = pluginPkg.strapi.name; + + const plugin = { + blockerComponent: null, + blockerComponentProps: {}, + description: pluginDescription, + icon, + id: pluginId, + initializer: Initializer, + injectedComponents: [], + isReady: false, + isRequired: pluginPkg.strapi.required || false, + layout: null, + lifecycles, + mainComponent: App, + name, + preventComponentRendering: false, + trads, + menu: { + pluginsSectionLinks: [ + { + destination: `/plugins/${pluginId}`, + icon, + label: { + id: `${pluginId}.plugin.name`, + defaultMessage: name, + }, + name, + permissions: [], + }, + ], + }, + }; + + return strapi.registerPlugin(plugin); +}; diff --git a/admin/src/lifecycles.js b/admin/src/lifecycles.js new file mode 100644 index 0000000..81b0172 --- /dev/null +++ b/admin/src/lifecycles.js @@ -0,0 +1,3 @@ +function lifecycles() {} + +export default lifecycles; diff --git a/admin/src/pluginId.js b/admin/src/pluginId.js new file mode 100644 index 0000000..3c0d700 --- /dev/null +++ b/admin/src/pluginId.js @@ -0,0 +1,5 @@ +const pluginPkg = require('../../package.json'); + +const pluginId = pluginPkg.name.replace(/^strapi-plugin-/i, ''); + +module.exports = pluginId; diff --git a/admin/src/translations/ar.json b/admin/src/translations/ar.json new file mode 100644 index 0000000..218e0e5 --- /dev/null +++ b/admin/src/translations/ar.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "التحقق من صحة", + "add.navbar_title": "إضافة إشعار", + "add.title": "إضافة إخطار جديد", + "edit.button.save": "سجل", + "edit.navbar_title": "تحرير #", + "edit.title": "تحرير الإخطار #", + "form.body.description": "رسالة كاملة للإرسال", + "form.body.label": "رسالة", + "form.body.placeholder": "لا تفوت هذا الإخطار!", + "form.error.date": "التاريخ غير صحيح", + "form.error.email": "عنوان البريد الإلكتروني غير صحيح", + "form.error.json": "إنه ليس بتنسيق JSON", + "form.error.lowercase": "يجب كتابة سلسلة الأحرف بأحرف صغيرة", + "form.error.max": "القيمة كبيرة جدًا", + "form.error.maxLength": "النص طويل جدًا", + "form.error.min": "القيمة صغيرة جدًا", + "form.error.minLength": "النص قصير جدًا", + "form.error.number": "الرقم غير صحيح", + "form.error.regex": "التنسيق غير صحيح", + "form.error.required": "هدا الحقل اجباري", + "form.error.string": "سلسلة الأحرف غير صالحة", + "form.error.uppercase": "يجب كتابة سلسلة الأحرف بأحرف كبيرة", + "form.platform.description": "اختر منصة التوزيع", + "form.platform.label": "منصة", + "form.platform.option1": "دائرة الرقابة الداخلية", + "form.platform.option2": "الروبوت", + "form.platform.option3": "الكل", + "form.published_at.description": "تاريخ ووقت الإخطار", + "form.published_at.label": "أرسل على", + "form.title.description": "عنوان الإخطار", + "form.title.label": "لقب", + "form.title.placeholder": "مرحبا هنا!", + "home.button.add": "إشعار جديد", + "home.navbar_title": "قائمة الإخطارات", + "home.table.row.body": "رسالة", + "home.table.row.id": "الهوية", + "home.table.row.published_at": "تاريخ الارسال", + "home.table.row.status": "دولة", + "home.table.row.title": "لقب", + "home.table.row.total": "ملاحظة:", + "home.title": "قائمة الإخطارات", + "notification.success": "تم حفظ الإخطار بنجاح!", + "plugin.name": "إخطارات المعرض" +} diff --git a/admin/src/translations/cs.json b/admin/src/translations/cs.json new file mode 100644 index 0000000..2f815b4 --- /dev/null +++ b/admin/src/translations/cs.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "Potvrdit", + "add.navbar_title": "Přidat oznámení", + "add.title": "Přidání nového oznámení", + "edit.button.save": "rekord", + "edit.navbar_title": "Úpravy #", + "edit.title": "Upravit oznámení #", + "form.body.description": "Celá zpráva k odeslání", + "form.body.label": "Zpráva", + "form.body.placeholder": "Nenechte si ujít toto upozornění!", + "form.error.date": "Datum je nesprávné", + "form.error.email": "E-mailová adresa je nesprávná", + "form.error.json": "Není ve formátu JSON", + "form.error.lowercase": "Řetězec znaků musí být napsán malými písmeny", + "form.error.max": "Hodnota je příliš velká", + "form.error.maxLength": "Text je příliš dlouhý", + "form.error.min": "Hodnota je příliš malá", + "form.error.minLength": "Text je příliš krátký", + "form.error.number": "Číslo je nesprávné", + "form.error.regex": "Formát je nesprávný", + "form.error.required": "Toto pole je povinné", + "form.error.string": "Řetězec znaků je neplatný", + "form.error.uppercase": "Řetězec znaků musí být psán velkými písmeny", + "form.platform.description": "Vyberte si distribuční platformu", + "form.platform.label": "Plošina", + "form.platform.option1": "ios", + "form.platform.option2": "Android", + "form.platform.option3": "Všechno", + "form.published_at.description": "Datum a čas oznámení", + "form.published_at.label": "Poslat na", + "form.title.description": "Název oznámení", + "form.title.label": "nadpis", + "form.title.placeholder": "Ahoj tady!", + "home.button.add": "Nové oznámení", + "home.navbar_title": "Seznam oznámení", + "home.table.row.body": "Zpráva", + "home.table.row.id": "ID", + "home.table.row.published_at": "Datum odeslání", + "home.table.row.status": "Stát", + "home.table.row.title": "nadpis", + "home.table.row.total": "Upozornění Nb", + "home.title": "Seznam oznámení", + "notification.success": "Oznámení bylo úspěšně uloženo!", + "plugin.name": "Oznámení Expo" +} diff --git a/admin/src/translations/de.json b/admin/src/translations/de.json new file mode 100644 index 0000000..ceed2ff --- /dev/null +++ b/admin/src/translations/de.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "Bestätigen", + "add.navbar_title": "Benachrichtigung hinzufügen", + "add.title": "Hinzufügen einer neuen Benachrichtigung", + "edit.button.save": "Rekord", + "edit.navbar_title": "# Bearbeiten", + "edit.title": "Benachrichtigung bearbeiten #", + "form.body.description": "Vollständige Nachricht zum Senden", + "form.body.label": "Nachricht", + "form.body.placeholder": "Verpassen Sie diese Benachrichtigung nicht!", + "form.error.date": "Das Datum ist falsch", + "form.error.email": "E-Mail-Adresse ist falsch", + "form.error.json": "Es ist nicht im JSON-Format", + "form.error.lowercase": "Die Zeichenfolge muss in Kleinbuchstaben geschrieben werden", + "form.error.max": "Der Wert ist zu groß", + "form.error.maxLength": "Der Text ist zu lang", + "form.error.min": "Der Wert ist zu klein", + "form.error.minLength": "Der Text ist zu kurz", + "form.error.number": "Die Nummer ist falsch", + "form.error.regex": "Das Format ist falsch", + "form.error.required": "Dieses Feld ist erforderlich", + "form.error.string": "Die Zeichenfolge ist ungültig", + "form.error.uppercase": "Die Zeichenfolge muss in Großbuchstaben geschrieben werden", + "form.platform.description": "Wählen Sie eine Vertriebsplattform", + "form.platform.label": "Plattform", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "Alle", + "form.published_at.description": "Datum und Uhrzeit der Benachrichtigung", + "form.published_at.label": "Weiterleitung", + "form.title.description": "Benachrichtigungstitel", + "form.title.label": "Titel", + "form.title.placeholder": "Hallo hier!", + "home.button.add": "Neue Benachrichtigung", + "home.navbar_title": "Liste der Benachrichtigungen", + "home.table.row.body": "Nachricht", + "home.table.row.id": "Identifikation", + "home.table.row.published_at": "Absendedatum", + "home.table.row.status": "Zustand", + "home.table.row.title": "Titel", + "home.table.row.total": "Nb Benachrichtigung", + "home.title": "Liste der Benachrichtigungen", + "notification.success": "Die Benachrichtigung wird erfolgreich gespeichert!", + "plugin.name": "Expo-Benachrichtigungen" +} diff --git a/admin/src/translations/en.json b/admin/src/translations/en.json new file mode 100644 index 0000000..ce1ea1d --- /dev/null +++ b/admin/src/translations/en.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "Save", + "add.navbar_title": "Add notification", + "add.title": "Add a new notification", + "edit.button.save": "Save", + "edit.navbar_title": "Edit #", + "edit.title": "Edit notification #", + "form.body.description": "Full message to send", + "form.body.label": "Message", + "form.body.placeholder": "Don't miss this notification message", + "form.error.date": "This is not a date", + "form.error.email": "This is not an email", + "form.error.json": "This is not a JSON", + "form.error.lowercase": "This must be a lower case string", + "form.error.max": "This is too high", + "form.error.maxLength": "This is too long", + "form.error.min": "This is too small", + "form.error.minLength": "This is too short", + "form.error.number": "This is not a number", + "form.error.regex": "This does not match the format", + "form.error.required": "This value is required", + "form.error.string": "This is not a string", + "form.error.uppercase": "This must be a upper case string", + "form.platform.description": "Choose a platform", + "form.platform.label": "Platform", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "All", + "form.published_at.description": "Date and time scheduled", + "form.published_at.label": "Send at", + "form.title.description": "Notification title", + "form.title.label": "Title", + "form.title.placeholder": "Hello here !", + "home.button.add": "New notification", + "home.navbar_title": "Notifications list", + "home.table.row.body": "Message", + "home.table.row.id": "Id", + "home.table.row.published_at": "Schedule time", + "home.table.row.status": "State", + "home.table.row.title": "Title", + "home.table.row.total": "Nb notification", + "home.title": "Notification list", + "notification.success": "Everything is saved !", + "plugin.name": "Expo Notifications" +} diff --git a/admin/src/translations/es.json b/admin/src/translations/es.json new file mode 100644 index 0000000..f125ea3 --- /dev/null +++ b/admin/src/translations/es.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "validar", + "add.navbar_title": "Agregar notificación", + "add.title": "Agregar una nueva notificación", + "edit.button.save": "Registro", + "edit.navbar_title": "Editando #", + "edit.title": "Editar notificación #", + "form.body.description": "Mensaje completo para enviar", + "form.body.label": "Mensaje", + "form.body.placeholder": "¡No te pierdas esta notificación!", + "form.error.date": "La fecha es incorrecta", + "form.error.email": "Correo electrónico incorrecto", + "form.error.json": "No está en formato JSON", + "form.error.lowercase": "La cadena de caracteres debe escribirse en minúsculas.", + "form.error.max": "El valor es demasiado grande", + "form.error.maxLength": "El texto es demasiado largo", + "form.error.min": "El valor es demasiado pequeño", + "form.error.minLength": "El texto es demasiado corto", + "form.error.number": "El numero es incorrecto", + "form.error.regex": "El formato es incorrecto", + "form.error.required": "Este campo es obligatorio", + "form.error.string": "La cadena de caracteres no es válida", + "form.error.uppercase": "La cadena de caracteres debe escribirse en mayúsculas.", + "form.platform.description": "Elija una plataforma de distribución", + "form.platform.label": "Plataforma", + "form.platform.option1": "iOS", + "form.platform.option2": "Androide", + "form.platform.option3": "Todas", + "form.published_at.description": "Fecha y hora de notificación", + "form.published_at.label": "Enviar en", + "form.title.description": "Título de la notificación", + "form.title.label": "Título", + "form.title.placeholder": "Hola aqui!", + "home.button.add": "Nueva notificación", + "home.navbar_title": "Lista de notificaciones", + "home.table.row.body": "Mensaje", + "home.table.row.id": "identificación", + "home.table.row.published_at": "Fecha de envio", + "home.table.row.status": "Estado", + "home.table.row.title": "Título", + "home.table.row.total": "Nb notificación", + "home.title": "Lista de notificaciones", + "notification.success": "¡La notificación se guarda con éxito!", + "plugin.name": "Notificaciones de la Expo" +} diff --git a/admin/src/translations/fr.json b/admin/src/translations/fr.json new file mode 100644 index 0000000..d672976 --- /dev/null +++ b/admin/src/translations/fr.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "Valider", + "add.navbar_title": "Ajouter une notification", + "add.title": "Ajout d'une nouvelle notification", + "edit.button.save": "Enregistrer", + "edit.navbar_title": "Édition #", + "edit.title": "Édition de la notification #", + "form.body.description": "Message complet à envoyer", + "form.body.label": "Message", + "form.body.placeholder": "Ne râtez pas cette notification !", + "form.error.date": "La date est incorrecte", + "form.error.email": "L'adresse e-mail est incorrecte", + "form.error.json": "Ce n'est pas au format JSON", + "form.error.lowercase": "La chaîne de caractère doit Être écrite en minuscule", + "form.error.max": "La valeur est trop grande", + "form.error.maxLength": "Le texte est trop long", + "form.error.min": "La valeur est trop petite", + "form.error.minLength": "Le texte est trop court", + "form.error.number": "Le nombre est incorrecte", + "form.error.regex": "Le format est incorrecte", + "form.error.required": "Ce champ est obligatoire", + "form.error.string": "La chaîne de caractère est invalide", + "form.error.uppercase": "La chaîne de caractère doit être écrite en majuscule", + "form.platform.description": "Choisissez une plateforme de diffusion", + "form.platform.label": "Plateforme", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "Toutes", + "form.published_at.description": "Date et heure d'envoi de la notification", + "form.published_at.label": "À envoyer le", + "form.title.description": "Notification title", + "form.title.label": "Titre", + "form.title.placeholder": "Coucou ici !", + "home.button.add": "Nouvelle notification", + "home.navbar_title": "Liste des notifications", + "home.table.row.body": "Message", + "home.table.row.id": "Id", + "home.table.row.published_at": "Date d'envoi", + "home.table.row.status": "État", + "home.table.row.title": "Titre", + "home.table.row.total": "Nb notification", + "home.title": "Liste des notifications", + "notification.success": "La notification est enregistré avec succès !", + "plugin.name": "Notifications Expo" +} diff --git a/admin/src/translations/id.json b/admin/src/translations/id.json new file mode 100644 index 0000000..7349de2 --- /dev/null +++ b/admin/src/translations/id.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "Mengesahkan", + "add.navbar_title": "Tambahkan pemberitahuan", + "add.title": "Menambahkan pemberitahuan baru", + "edit.button.save": "Merekam", + "edit.navbar_title": "Mengedit #", + "edit.title": "Edit notifikasi #", + "form.body.description": "Pesan lengkap untuk dikirim", + "form.body.label": "Pesan", + "form.body.placeholder": "Jangan lewatkan notifikasi ini!", + "form.error.date": "Tanggalnya salah", + "form.error.email": "Alamat email salah", + "form.error.json": "Ini tidak dalam format JSON", + "form.error.lowercase": "String karakter harus ditulis dengan huruf kecil", + "form.error.max": "Nilainya terlalu besar", + "form.error.maxLength": "Teksnya terlalu panjang", + "form.error.min": "Nilainya terlalu kecil", + "form.error.minLength": "Teksnya terlalu pendek", + "form.error.number": "Nomornya salah", + "form.error.regex": "Formatnya salah", + "form.error.required": "Bagian ini diperlukan", + "form.error.string": "String karakter tidak valid", + "form.error.uppercase": "String karakter harus ditulis dalam huruf besar", + "form.platform.description": "Pilih platform distribusi", + "form.platform.label": "Peron", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "Semua", + "form.published_at.description": "Tanggal dan waktu pemberitahuan", + "form.published_at.label": "Kirim", + "form.title.description": "Judul pemberitahuan", + "form.title.label": "Judul", + "form.title.placeholder": "Halo di sini!", + "home.button.add": "Pemberitahuan baru", + "home.navbar_title": "Daftar pemberitahuan", + "home.table.row.body": "Pesan", + "home.table.row.id": "Indo", + "home.table.row.published_at": "Tanggal pengiriman", + "home.table.row.status": "Negara", + "home.table.row.title": "Judul", + "home.table.row.total": "Notifikasi Nb", + "home.title": "Daftar pemberitahuan", + "notification.success": "Pemberitahuan berhasil disimpan!", + "plugin.name": "Pemberitahuan Expo" +} diff --git a/admin/src/translations/index.js b/admin/src/translations/index.js new file mode 100644 index 0000000..d990d5a --- /dev/null +++ b/admin/src/translations/index.js @@ -0,0 +1,49 @@ +import ar from './ar.json'; +import cs from './cs.json'; +import de from './de.json'; +import en from './en.json'; +import es from './es.json'; +import fr from './fr.json'; +import id from './id.json'; +import it from './it.json'; +import ko from './ko.json'; +import ms from './ms.json'; +import nl from './nl.json'; +import pl from './pl.json'; +import ptBR from './pt-BR.json'; +import pt from './pt.json'; +import ru from './ru.json'; +import th from './th.json'; +import tr from './tr.json'; +import uk from './uk.json'; +import vi from './vi.json'; +import zhHans from './zh-Hans.json'; +import zh from './zh.json'; +import sk from './sk.json'; + +const trads = { + ar, + cs, + de, + en, + es, + fr, + id, + it, + ko, + ms, + nl, + pl, + 'pt-BR': ptBR, + pt, + ru, + th, + tr, + uk, + vi, + 'zh-Hans': zhHans, + zh, + sk, +}; + +export default trads; diff --git a/admin/src/translations/it.json b/admin/src/translations/it.json new file mode 100644 index 0000000..3e589e1 --- /dev/null +++ b/admin/src/translations/it.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "convalidare", + "add.navbar_title": "Aggiungi notifica", + "add.title": "Aggiunta di una nuova notifica", + "edit.button.save": "Registrare", + "edit.navbar_title": "La modifica #", + "edit.title": "Modifica notifica #", + "form.body.description": "Messaggio completo da inviare", + "form.body.label": "Messaggio", + "form.body.placeholder": "Non perdere questa notifica!", + "form.error.date": "La data non è corretta", + "form.error.email": "L'indirizzo e-mail non è corretto", + "form.error.json": "Non è in formato JSON", + "form.error.lowercase": "La stringa di caratteri deve essere scritta in minuscolo", + "form.error.max": "Il valore è troppo grande", + "form.error.maxLength": "Il testo è troppo lungo", + "form.error.min": "Il valore è troppo piccolo", + "form.error.minLength": "Il testo è troppo breve", + "form.error.number": "Il numero non è corretto", + "form.error.regex": "Il formato non è corretto", + "form.error.required": "Questo campo è richiesto", + "form.error.string": "La stringa di caratteri non è valida", + "form.error.uppercase": "La stringa di caratteri deve essere scritta in maiuscolo", + "form.platform.description": "Scegli una piattaforma di distribuzione", + "form.platform.label": "piattaforma", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "Tutte", + "form.published_at.description": "Data e ora della notifica", + "form.published_at.label": "Invia", + "form.title.description": "Titolo della notifica", + "form.title.label": "Titolo", + "form.title.placeholder": "Ciao qui!", + "home.button.add": "Nuova notifica", + "home.navbar_title": "Elenco delle notifiche", + "home.table.row.body": "Messaggio", + "home.table.row.id": "Id", + "home.table.row.published_at": "Data di invio", + "home.table.row.status": "stato", + "home.table.row.title": "Titolo", + "home.table.row.total": "Notifica NB", + "home.title": "Elenco delle notifiche", + "notification.success": "La notifica è stata salvata con successo!", + "plugin.name": "Notifiche Expo" +} diff --git a/admin/src/translations/ko.json b/admin/src/translations/ko.json new file mode 100644 index 0000000..b713e1a --- /dev/null +++ b/admin/src/translations/ko.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "확인", + "add.navbar_title": "알림 추가", + "add.title": "새 알림 추가", + "edit.button.save": "기록", + "edit.navbar_title": "편집 #", + "edit.title": "알림 수정 #", + "form.body.description": "보낼 전체 메시지", + "form.body.label": "메시지", + "form.body.placeholder": "이 알림을 놓치지 마세요!", + "form.error.date": "날짜가 잘못되었습니다.", + "form.error.email": "이메일 주소가 올바르지 않습니다.", + "form.error.json": "JSON 형식이 아닙니다.", + "form.error.lowercase": "문자열은 소문자로 작성해야합니다.", + "form.error.max": "값이 너무 큽니다.", + "form.error.maxLength": "텍스트가 너무 깁니다.", + "form.error.min": "값이 너무 작습니다.", + "form.error.minLength": "텍스트가 너무 짧습니다.", + "form.error.number": "번호가 잘못되었습니다", + "form.error.regex": "형식이 올바르지 않습니다.", + "form.error.required": "이 필드는 필수입니다", + "form.error.string": "문자열이 잘못되었습니다.", + "form.error.uppercase": "문자열은 대문자로 작성해야합니다.", + "form.platform.description": "배포 플랫폼 선택", + "form.platform.label": "플랫폼", + "form.platform.option1": "iOS", + "form.platform.option2": "기계적 인조 인간", + "form.platform.option3": "모두", + "form.published_at.description": "통지 일시", + "form.published_at.label": "보내기", + "form.title.description": "알림 제목", + "form.title.label": "이름", + "form.title.placeholder": "안녕하세요!", + "home.button.add": "새로운 알림", + "home.navbar_title": "알림 목록", + "home.table.row.body": "메시지", + "home.table.row.id": "신분증", + "home.table.row.published_at": "보내는 날짜", + "home.table.row.status": "상태", + "home.table.row.title": "이름", + "home.table.row.total": "Nb 알림", + "home.title": "알림 목록", + "notification.success": "알림이 성공적으로 저장되었습니다!", + "plugin.name": "엑스포 알림" +} diff --git a/admin/src/translations/ms.json b/admin/src/translations/ms.json new file mode 100644 index 0000000..65ff534 --- /dev/null +++ b/admin/src/translations/ms.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "Mengesahkan", + "add.navbar_title": "Tambahkan pemberitahuan", + "add.title": "Menambah pemberitahuan baru", + "edit.button.save": "Rekodkan", + "edit.navbar_title": "Menyunting #", + "edit.title": "Edit pemberitahuan #", + "form.body.description": "Mesej penuh untuk dihantar", + "form.body.label": "Mesej", + "form.body.placeholder": "Jangan terlepas pemberitahuan ini!", + "form.error.date": "Tarikhnya tidak betul", + "form.error.email": "Alamat e-mel tidak betul", + "form.error.json": "Ia tidak dalam format JSON", + "form.error.lowercase": "Rentetan watak mesti ditulis dengan huruf kecil", + "form.error.max": "Nilainya terlalu besar", + "form.error.maxLength": "Teksnya terlalu panjang", + "form.error.min": "Nilainya terlalu kecil", + "form.error.minLength": "Teksnya terlalu pendek", + "form.error.number": "Nombornya tidak betul", + "form.error.regex": "Formatnya tidak betul", + "form.error.required": "Bidang ini diperlukan", + "form.error.string": "Rentetan watak tidak sah", + "form.error.uppercase": "Rentetan watak mesti ditulis dengan huruf besar", + "form.platform.description": "Pilih platform pengedaran", + "form.platform.label": "pelantar", + "form.platform.option1": "ios", + "form.platform.option2": "Android", + "form.platform.option3": "Semua", + "form.published_at.description": "Tarikh dan masa pemberitahuan", + "form.published_at.label": "Hantar pada", + "form.title.description": "Tajuk pemberitahuan", + "form.title.label": "Tajuk", + "form.title.placeholder": "Helo di sini!", + "home.button.add": "Pemberitahuan baru", + "home.navbar_title": "Senarai pemberitahuan", + "home.table.row.body": "Mesej", + "home.table.row.id": "ID", + "home.table.row.published_at": "Tarikh menghantar", + "home.table.row.status": "Negeri", + "home.table.row.title": "Tajuk", + "home.table.row.total": "Pemberitahuan Nb", + "home.title": "Senarai pemberitahuan", + "notification.success": "Pemberitahuan berjaya disimpan!", + "plugin.name": "Pemberitahuan Ekspo" +} diff --git a/admin/src/translations/nl.json b/admin/src/translations/nl.json new file mode 100644 index 0000000..adb3265 --- /dev/null +++ b/admin/src/translations/nl.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "Bevestigen", + "add.navbar_title": "Voeg melding toe", + "add.title": "Een nieuwe melding toevoegen", + "edit.button.save": "Opnemen", + "edit.navbar_title": "Bewerken #", + "edit.title": "Bewerk melding #", + "form.body.description": "Volledig bericht om te verzenden", + "form.body.label": "Bericht", + "form.body.placeholder": "Mis deze melding niet!", + "form.error.date": "De datum is onjuist", + "form.error.email": "E-mailadres is niet correct", + "form.error.json": "Het is niet in JSON-indeling", + "form.error.lowercase": "De tekenreeks moet in kleine letters worden geschreven", + "form.error.max": "De waarde is te hoog", + "form.error.maxLength": "De tekst is te lang", + "form.error.min": "De waarde is te klein", + "form.error.minLength": "De tekst is te kort", + "form.error.number": "Het nummer is onjuist", + "form.error.regex": "Het formaat is onjuist", + "form.error.required": "dit veld is verplicht", + "form.error.string": "De tekenreeks is ongeldig", + "form.error.uppercase": "De tekenreeks moet in hoofdletters worden geschreven", + "form.platform.description": "Kies een distributieplatform", + "form.platform.label": "Platform", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "Alle", + "form.published_at.description": "Datum en tijd van melding", + "form.published_at.label": "Stuur door", + "form.title.description": "Meldingstitel", + "form.title.label": "titel", + "form.title.placeholder": "Hallo hier!", + "home.button.add": "Nieuwe melding", + "home.navbar_title": "Lijst met meldingen", + "home.table.row.body": "Bericht", + "home.table.row.id": "Id", + "home.table.row.published_at": "Verzenddatum", + "home.table.row.status": "staat", + "home.table.row.title": "titel", + "home.table.row.total": "NB melding", + "home.title": "Lijst met meldingen", + "notification.success": "De melding is succesvol opgeslagen!", + "plugin.name": "Expo-meldingen" +} diff --git a/admin/src/translations/pl.json b/admin/src/translations/pl.json new file mode 100644 index 0000000..d64419a --- /dev/null +++ b/admin/src/translations/pl.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "uprawomocnić", + "add.navbar_title": "Dodaj powiadomienie", + "add.title": "Dodanie nowego powiadomienia", + "edit.button.save": "rekord", + "edit.navbar_title": "Edycja #", + "edit.title": "Edytuj powiadomienie nr", + "form.body.description": "Pełna wiadomość do wysłania", + "form.body.label": "wiadomość", + "form.body.placeholder": "Nie przegap tego powiadomienia!", + "form.error.date": "Data jest nieprawidłowa", + "form.error.email": "Adres e-mail jest niepoprawny", + "form.error.json": "Nie jest w formacie JSON", + "form.error.lowercase": "Ciąg znaków musi być zapisany małymi literami", + "form.error.max": "Wartość jest za duża", + "form.error.maxLength": "Tekst jest za długi", + "form.error.min": "Wartość jest za mała", + "form.error.minLength": "Tekst jest za krótki", + "form.error.number": "Podana liczba jest nieprawidłowa", + "form.error.regex": "Format jest nieprawidłowy", + "form.error.required": "To pole jest wymagane", + "form.error.string": "Ciąg znaków jest nieprawidłowy", + "form.error.uppercase": "Ciąg znaków musi być pisany wielkimi literami", + "form.platform.description": "Wybierz platformę dystrybucyjną", + "form.platform.label": "platforma", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "wszyscy", + "form.published_at.description": "Data i godzina powiadomienia", + "form.published_at.label": "Przekazać dalej", + "form.title.description": "Tytuł powiadomienia", + "form.title.label": "Tytuł", + "form.title.placeholder": "Witam!", + "home.button.add": "Nowe powiadomienie", + "home.navbar_title": "Lista powiadomień", + "home.table.row.body": "wiadomość", + "home.table.row.id": "Id", + "home.table.row.published_at": "Data wysłania", + "home.table.row.status": "Stan", + "home.table.row.title": "Tytuł", + "home.table.row.total": "Powiadomienie NB", + "home.title": "Lista powiadomień", + "notification.success": "Powiadomienie zostało zapisane pomyślnie!", + "plugin.name": "Powiadomienia z Expo" +} diff --git a/admin/src/translations/pt-BR.json b/admin/src/translations/pt-BR.json new file mode 100644 index 0000000..79f76f0 --- /dev/null +++ b/admin/src/translations/pt-BR.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "validar", + "add.navbar_title": "Adicionar notificação", + "add.title": "Adicionando uma nova notificação", + "edit.button.save": "Registro", + "edit.navbar_title": "Editando #", + "edit.title": "Editar notificação #", + "form.body.description": "Mensagem completa para enviar", + "form.body.label": "mensagem", + "form.body.placeholder": "Não perca esta notificação!", + "form.error.date": "A data está incorreta", + "form.error.email": "Endereço de email está incorreto", + "form.error.json": "Não está no formato JSON", + "form.error.lowercase": "A string de caracteres deve ser escrita em minúsculas", + "form.error.max": "O valor é muito grande", + "form.error.maxLength": "O texto é muito longo", + "form.error.min": "O valor é muito pequeno", + "form.error.minLength": "O texto é muito curto", + "form.error.number": "O numero esta incorreto", + "form.error.regex": "O formato está incorreto", + "form.error.required": "Este campo é obrigatório", + "form.error.string": "A sequência de caracteres é inválida", + "form.error.uppercase": "A sequência de caracteres deve ser escrita em maiúsculas", + "form.platform.description": "Escolha uma plataforma de distribuição", + "form.platform.label": "Plataforma", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "Todos", + "form.published_at.description": "Data e hora da notificação", + "form.published_at.label": "Enviar em", + "form.title.description": "Título de Notificação", + "form.title.label": "Título", + "form.title.placeholder": "Olá aqui!", + "home.button.add": "Nova notificação", + "home.navbar_title": "Lista de Notificações", + "home.table.row.body": "mensagem", + "home.table.row.id": "Id", + "home.table.row.published_at": "Data de envio", + "home.table.row.status": "Estado", + "home.table.row.title": "Título", + "home.table.row.total": "Notificação Nb", + "home.title": "Lista de Notificações", + "notification.success": "A notificação foi salva com sucesso!", + "plugin.name": "Notificações de Expo" +} diff --git a/admin/src/translations/pt.json b/admin/src/translations/pt.json new file mode 100644 index 0000000..79f76f0 --- /dev/null +++ b/admin/src/translations/pt.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "validar", + "add.navbar_title": "Adicionar notificação", + "add.title": "Adicionando uma nova notificação", + "edit.button.save": "Registro", + "edit.navbar_title": "Editando #", + "edit.title": "Editar notificação #", + "form.body.description": "Mensagem completa para enviar", + "form.body.label": "mensagem", + "form.body.placeholder": "Não perca esta notificação!", + "form.error.date": "A data está incorreta", + "form.error.email": "Endereço de email está incorreto", + "form.error.json": "Não está no formato JSON", + "form.error.lowercase": "A string de caracteres deve ser escrita em minúsculas", + "form.error.max": "O valor é muito grande", + "form.error.maxLength": "O texto é muito longo", + "form.error.min": "O valor é muito pequeno", + "form.error.minLength": "O texto é muito curto", + "form.error.number": "O numero esta incorreto", + "form.error.regex": "O formato está incorreto", + "form.error.required": "Este campo é obrigatório", + "form.error.string": "A sequência de caracteres é inválida", + "form.error.uppercase": "A sequência de caracteres deve ser escrita em maiúsculas", + "form.platform.description": "Escolha uma plataforma de distribuição", + "form.platform.label": "Plataforma", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "Todos", + "form.published_at.description": "Data e hora da notificação", + "form.published_at.label": "Enviar em", + "form.title.description": "Título de Notificação", + "form.title.label": "Título", + "form.title.placeholder": "Olá aqui!", + "home.button.add": "Nova notificação", + "home.navbar_title": "Lista de Notificações", + "home.table.row.body": "mensagem", + "home.table.row.id": "Id", + "home.table.row.published_at": "Data de envio", + "home.table.row.status": "Estado", + "home.table.row.title": "Título", + "home.table.row.total": "Notificação Nb", + "home.title": "Lista de Notificações", + "notification.success": "A notificação foi salva com sucesso!", + "plugin.name": "Notificações de Expo" +} diff --git a/admin/src/translations/ru.json b/admin/src/translations/ru.json new file mode 100644 index 0000000..d9d8291 --- /dev/null +++ b/admin/src/translations/ru.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "утверждать", + "add.navbar_title": "Добавить уведомление", + "add.title": "Добавление нового уведомления", + "edit.button.save": "запись", + "edit.navbar_title": "Редактирование #", + "edit.title": "Изменить уведомление №", + "form.body.description": "Полное сообщение для отправки", + "form.body.label": "Сообщение", + "form.body.placeholder": "Не пропустите это уведомление!", + "form.error.date": "Дата неверная", + "form.error.email": "Адрес электронной почты неверный", + "form.error.json": "Это не в формате JSON", + "form.error.lowercase": "Строка символов должна быть написана строчными буквами.", + "form.error.max": "Значение слишком велико", + "form.error.maxLength": "Текст слишком длинный", + "form.error.min": "Значение слишком мало", + "form.error.minLength": "Текст слишком короткий", + "form.error.number": "Номер неверный", + "form.error.regex": "Формат неверный", + "form.error.required": "Это поле обязательно к заполнению", + "form.error.string": "Строка символов недействительна", + "form.error.uppercase": "Строка символов должна быть написана в верхнем регистре.", + "form.platform.description": "Выберите платформу распространения", + "form.platform.label": "платформы", + "form.platform.option1": "IOS", + "form.platform.option2": "Android", + "form.platform.option3": "все", + "form.published_at.description": "Дата и время уведомления", + "form.published_at.label": "Переслать", + "form.title.description": "Название уведомления", + "form.title.label": "название", + "form.title.placeholder": "Здравствуйте!", + "home.button.add": "Новое уведомление", + "home.navbar_title": "Список уведомлений", + "home.table.row.body": "Сообщение", + "home.table.row.id": "идентификатор", + "home.table.row.published_at": "Дата отправки", + "home.table.row.status": "состояние", + "home.table.row.title": "название", + "home.table.row.total": "Nb уведомление", + "home.title": "Список уведомлений", + "notification.success": "Уведомление успешно сохранено!", + "plugin.name": "Уведомления о выставке" +} diff --git a/admin/src/translations/sk.json b/admin/src/translations/sk.json new file mode 100644 index 0000000..c41c1a2 --- /dev/null +++ b/admin/src/translations/sk.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "potvrdiť", + "add.navbar_title": "Pridajte upozornenie", + "add.title": "Pridáva sa nové upozornenie", + "edit.button.save": "rekord", + "edit.navbar_title": "Úprava č.", + "edit.title": "Upraviť číslo upozornenia", + "form.body.description": "Celá správa na odoslanie", + "form.body.label": "SPRÁVA", + "form.body.placeholder": "Nepremeškajte toto upozornenie!", + "form.error.date": "Dátum je nesprávny", + "form.error.email": "E-mailová adresa je nesprávna", + "form.error.json": "Nie je vo formáte JSON", + "form.error.lowercase": "Reťazec znakov musí byť napísaný malými písmenami", + "form.error.max": "Hodnota je príliš veľká", + "form.error.maxLength": "Text je príliš dlhý", + "form.error.min": "Hodnota je príliš malá", + "form.error.minLength": "Text je príliš krátky", + "form.error.number": "Číslo je nesprávne", + "form.error.regex": "Formát je nesprávny", + "form.error.required": "Toto pole je povinné", + "form.error.string": "Reťazec znakov je neplatný", + "form.error.uppercase": "Reťazec znakov musí byť napísaný veľkými písmenami", + "form.platform.description": "Vyberte si distribučnú platformu", + "form.platform.label": "Plošina", + "form.platform.option1": "ios", + "form.platform.option2": "Android", + "form.platform.option3": "Všetky", + "form.published_at.description": "Dátum a čas oznámenia", + "form.published_at.label": "Pošli ďalej", + "form.title.description": "Názov oznámenia", + "form.title.label": "Názov", + "form.title.placeholder": "Ahoj tu!", + "home.button.add": "Nové upozornenie", + "home.navbar_title": "Zoznam oznámení", + "home.table.row.body": "SPRÁVA", + "home.table.row.id": "ID", + "home.table.row.published_at": "Dátum odosielania", + "home.table.row.status": "stáť", + "home.table.row.title": "Názov", + "home.table.row.total": "Oznámenie Nb", + "home.title": "Zoznam oznámení", + "notification.success": "Oznámenie sa úspešne uložilo!", + "plugin.name": "Expo oznámenia" +} diff --git a/admin/src/translations/th.json b/admin/src/translations/th.json new file mode 100644 index 0000000..69adb58 --- /dev/null +++ b/admin/src/translations/th.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "ตรวจสอบ", + "add.navbar_title": "เพิ่มการแจ้งเตือน", + "add.title": "การเพิ่มการแจ้งเตือนใหม่", + "edit.button.save": "บันทึก", + "edit.navbar_title": "กำลังแก้ไข #", + "edit.title": "แก้ไขการแจ้งเตือน #", + "form.body.description": "ข้อความเต็มที่จะส่ง", + "form.body.label": "ข่าวสาร", + "form.body.placeholder": "อย่าพลาดการแจ้งเตือนนี้!", + "form.error.date": "วันที่ไม่ถูกต้อง", + "form.error.email": "ที่อยู่อีเมลไม่ถูกต้อง", + "form.error.json": "ไม่ได้อยู่ในรูปแบบ JSON", + "form.error.lowercase": "สตริงอักขระต้องเขียนด้วยตัวพิมพ์เล็ก", + "form.error.max": "ค่าใหญ่เกินไป", + "form.error.maxLength": "ข้อความยาวเกินไป", + "form.error.min": "ค่าน้อยเกินไป", + "form.error.minLength": "ข้อความสั้นเกินไป", + "form.error.number": "หมายเลขไม่ถูกต้อง", + "form.error.regex": "รูปแบบไม่ถูกต้อง", + "form.error.required": "ฟิลด์นี้จำเป็น", + "form.error.string": "สตริงอักขระไม่ถูกต้อง", + "form.error.uppercase": "สตริงอักขระต้องเขียนเป็นตัวพิมพ์ใหญ่", + "form.platform.description": "เลือกแพลตฟอร์มการจัดจำหน่าย", + "form.platform.label": "แพลตฟอร์ม", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "ทั้งหมด", + "form.published_at.description": "วันที่และเวลาที่แจ้ง", + "form.published_at.label": "ส่งเมื่อ", + "form.title.description": "ชื่อการแจ้งเตือน", + "form.title.label": "หัวข้อ", + "form.title.placeholder": "สวัสดีที่นี่!", + "home.button.add": "การแจ้งเตือนใหม่", + "home.navbar_title": "รายการการแจ้งเตือน", + "home.table.row.body": "ข่าวสาร", + "home.table.row.id": "ID", + "home.table.row.published_at": "วันที่ส่ง", + "home.table.row.status": "สถานะ", + "home.table.row.title": "หัวข้อ", + "home.table.row.total": "การแจ้งเตือน Nb", + "home.title": "รายการการแจ้งเตือน", + "notification.success": "บันทึกการแจ้งเตือนเรียบร้อยแล้ว!", + "plugin.name": "การแจ้งเตือนงานเอ็กซ์โป" +} diff --git a/admin/src/translations/tr.json b/admin/src/translations/tr.json new file mode 100644 index 0000000..5945e86 --- /dev/null +++ b/admin/src/translations/tr.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "doğrulamak", + "add.navbar_title": "BİLDİRİM EKLE", + "add.title": "Yeni bir bildirim eklemek", + "edit.button.save": "kayıt", + "edit.navbar_title": "# Düzenleme", + "edit.title": "Bildirimi düzenle #", + "form.body.description": "Gönderilecek tam mesaj", + "form.body.label": "Mesaj", + "form.body.placeholder": "Bu bildirimi kaçırmayın!", + "form.error.date": "Tarih yanlış", + "form.error.email": "E-posta adresi yanlış", + "form.error.json": "JSON formatında değil", + "form.error.lowercase": "Karakter dizisi küçük harfle yazılmalıdır", + "form.error.max": "Değer çok büyük", + "form.error.maxLength": "Metin çok uzun", + "form.error.min": "Değer çok küçük", + "form.error.minLength": "Metin çok kısa", + "form.error.number": "Numara yanlış", + "form.error.regex": "Biçim yanlış", + "form.error.required": "Bu alan gereklidir", + "form.error.string": "Karakter dizisi geçersiz", + "form.error.uppercase": "Karakter dizisi büyük harfle yazılmalıdır", + "form.platform.description": "Bir dağıtım platformu seçin", + "form.platform.label": "platform", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "tüm", + "form.published_at.description": "Bildirim tarihi ve saati", + "form.published_at.label": "Gönder", + "form.title.description": "Bildirim başlığı", + "form.title.label": "Başlık", + "form.title.placeholder": "Merhabalar!", + "home.button.add": "Yeni bildirim", + "home.navbar_title": "Bildirim Listesi", + "home.table.row.body": "Mesaj", + "home.table.row.id": "ID", + "home.table.row.published_at": "Gönderim Tarihi", + "home.table.row.status": "durum", + "home.table.row.title": "Başlık", + "home.table.row.total": "Nb bildirimi", + "home.title": "Bildirim Listesi", + "notification.success": "Bildirim başarıyla kaydedildi!", + "plugin.name": "Expo Bildirimleri" +} diff --git a/admin/src/translations/uk.json b/admin/src/translations/uk.json new file mode 100644 index 0000000..2826147 --- /dev/null +++ b/admin/src/translations/uk.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "Підтвердити", + "add.navbar_title": "Додати сповіщення", + "add.title": "Додавання нового повідомлення", + "edit.button.save": "запис", + "edit.navbar_title": "Номер редагування", + "edit.title": "Змінити номер сповіщення", + "form.body.description": "Повне повідомлення для відправлення", + "form.body.label": "Повідомлення", + "form.body.placeholder": "Не пропустіть це сповіщення!", + "form.error.date": "Дата неправильна", + "form.error.email": "Неправильна електронна адреса", + "form.error.json": "Він не у форматі JSON", + "form.error.lowercase": "Рядок символів повинен бути записаний з малої літери", + "form.error.max": "Значення завелике", + "form.error.maxLength": "Текст задовгий", + "form.error.min": "Значення занадто мало", + "form.error.minLength": "Текст занадто короткий", + "form.error.number": "Номер неправильний", + "form.error.regex": "Формат неправильний", + "form.error.required": "Це поле є обов'язковим", + "form.error.string": "Рядок символів недійсний", + "form.error.uppercase": "Рядок символів потрібно писати з великої літери", + "form.platform.description": "Виберіть платформу розподілу", + "form.platform.label": "Платформа", + "form.platform.option1": "IOS", + "form.platform.option2": "Android", + "form.platform.option3": "всі", + "form.published_at.description": "Дата та час повідомлення", + "form.published_at.label": "Надсилайте далі", + "form.title.description": "Заголовок повідомлення", + "form.title.label": "назва", + "form.title.placeholder": "Привіт!", + "home.button.add": "Нове повідомлення", + "home.navbar_title": "Список повідомлень", + "home.table.row.body": "Повідомлення", + "home.table.row.id": "ідентифікатор", + "home.table.row.published_at": "Дата відправлення", + "home.table.row.status": "Держава", + "home.table.row.title": "назва", + "home.table.row.total": "Nb повідомлення", + "home.title": "Список повідомлень", + "notification.success": "Повідомлення успішно збережено!", + "plugin.name": "Повідомлення Expo" +} diff --git a/admin/src/translations/vi.json b/admin/src/translations/vi.json new file mode 100644 index 0000000..f69fe60 --- /dev/null +++ b/admin/src/translations/vi.json @@ -0,0 +1,45 @@ +{ + "add.button.save": "Xác thực", + "add.navbar_title": "Thêm thông báo", + "add.title": "Thêm thông báo mới", + "edit.button.save": "Ghi lại", + "edit.navbar_title": "Chỉnh sửa #", + "edit.title": "Chỉnh sửa thông báo #", + "form.body.description": "Toàn bộ tin nhắn để gửi", + "form.body.label": "Thông điệp", + "form.body.placeholder": "Đừng bỏ lỡ thông báo này!", + "form.error.date": "Ngày không chính xác", + "form.error.email": "Địa chỉ E-mail không chính xác", + "form.error.json": "Nó không ở định dạng JSON", + "form.error.lowercase": "Chuỗi ký tự phải được viết bằng chữ thường", + "form.error.max": "Giá trị quá lớn", + "form.error.maxLength": "Văn bản quá dài", + "form.error.min": "Giá trị quá nhỏ", + "form.error.minLength": "Văn bản quá ngắn", + "form.error.number": "Số không chính xác", + "form.error.regex": "Định dạng không chính xác", + "form.error.required": "Trường này là bắt buộc", + "form.error.string": "Chuỗi ký tự không hợp lệ", + "form.error.uppercase": "Chuỗi ký tự phải được viết bằng chữ hoa", + "form.platform.description": "Chọn một nền tảng phân phối", + "form.platform.label": "Nền tảng", + "form.platform.option1": "iOS", + "form.platform.option2": "Android", + "form.platform.option3": "Tất cả", + "form.published_at.description": "Ngày và giờ thông báo", + "form.published_at.label": "Gửi đi", + "form.title.description": "Tiêu đề thông báo", + "form.title.label": "Tiêu đề", + "form.title.placeholder": "Xin chào đây!", + "home.button.add": "Thông báo mới", + "home.navbar_title": "Danh sách thông báo", + "home.table.row.body": "Thông điệp", + "home.table.row.id": "Tối", + "home.table.row.published_at": "Ngày gửi", + "home.table.row.status": "Tiểu bang", + "home.table.row.title": "Tiêu đề", + "home.table.row.total": "Nb thông báo", + "home.title": "Danh sách thông báo", + "notification.success": "Thông báo được lưu thành công!", + "plugin.name": "Thông báo Expo" +} diff --git a/admin/src/translations/zh-Hans.json b/admin/src/translations/zh-Hans.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/admin/src/translations/zh-Hans.json @@ -0,0 +1 @@ +{} diff --git a/admin/src/translations/zh.json b/admin/src/translations/zh.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/admin/src/translations/zh.json @@ -0,0 +1 @@ +{} diff --git a/admin/src/utils/getFilters.js b/admin/src/utils/getFilters.js new file mode 100644 index 0000000..3f6531f --- /dev/null +++ b/admin/src/utils/getFilters.js @@ -0,0 +1,32 @@ + + +const getFilters = (search) => { + const query = new URLSearchParams(search); + const filters = []; + + // eslint-disable-next-line no-restricted-syntax + for (const pair of query.entries()) { + if (!['_sort', 'pageSize', 'page', '_q'].includes(pair[0])) { + const splitted = pair[0].split('_'); + let filterName; + let filterType; + + // Filter type === '=') + if (splitted.length === 1) { + filterType = '='; + filterName = pair[0]; + } else { + filterType = `_${splitted[1]}`; + filterName = splitted[0]; + } + + const value = decodeURIComponent(pair[1]); + + filters.push({ displayName: filterName, name: pair[0], filter: filterType, value }); + } + } + + return filters; +}; + +export default getFilters; diff --git a/admin/src/utils/getTrad.js b/admin/src/utils/getTrad.js new file mode 100644 index 0000000..cec60be --- /dev/null +++ b/admin/src/utils/getTrad.js @@ -0,0 +1,12 @@ + + +import { useGlobalContext } from 'strapi-helper-plugin'; +import pluginId from '../pluginId'; + +const getTrad = (id) => { + const { formatMessage } = useGlobalContext(); + +return formatMessage({ id: `${pluginId}.${id}` }); +}; + +export default getTrad; diff --git a/adminTranslations.babel b/adminTranslations.babel new file mode 100644 index 0000000..c507d8b --- /dev/null +++ b/adminTranslations.babel @@ -0,0 +1,4106 @@ + + + + generic-json + adminTranslations.babel + + + + + + add + + + button + + + save + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + navbar_title + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + title + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + edit + + + button + + + save + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + navbar_title + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + title + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + form + + + body + + + description + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + label + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + placeholder + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + error + + + date + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + email + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + json + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + lowercase + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + max + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + maxLength + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + min + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + minLength + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + number + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + regex + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + required + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + string + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + uppercase + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + platform + + + description + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + label + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + option1 + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + option2 + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + option3 + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + published_at + + + description + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + label + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + title + + + description + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + label + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + placeholder + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + + + home + + + button + + + add + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + navbar_title + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + table + + + row + + + body + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + id + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + published_at + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + status + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + title + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + total + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + + + title + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + notification + + + success + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + plugin + + + name + false + + + + + + ar-AE + false + + + cs-CZ + false + + + de-DE + false + + + en-US + false + + + es-ES + false + + + fr-FR + false + + + id-ID + false + + + it-IT + false + + + ko-KR + false + + + ms-MY + false + + + nl-NL + false + + + pl-PL + false + + + pt-BR + false + + + pt-PT + false + + + ru-RU + false + + + sk-SK + false + + + th-TH + false + + + tr-TR + false + + + uk-UA + false + + + vi-VN + false + + + + + + + + false + + + ar-AE + + admin/src/translations/ar.json + + + cs-CZ + + admin/src/translations/cs.json + + + de-DE + + admin/src/translations/de.json + + + en-US + + admin/src/translations/en.json + + + es-ES + + admin/src/translations/es.json + + + fr-FR + + admin/src/translations/fr.json + + + id-ID + + admin/src/translations/id.json + + + it-IT + + admin/src/translations/it.json + + + ko-KR + + admin/src/translations/ko.json + + + ms-MY + + admin/src/translations/ms.json + + + nl-NL + + admin/src/translations/nl.json + + + pl-PL + + admin/src/translations/pl.json + + + pt-BR + + admin/src/translations/pt-BR.json + + + pt-PT + + admin/src/translations/pt.json + + + ru-RU + + admin/src/translations/ru.json + + + sk-SK + + admin/src/translations/sk.json + + + th-TH + + admin/src/translations/th.json + + + tr-TR + + admin/src/translations/tr.json + + + uk-UA + + admin/src/translations/uk.json + + + vi-VN + + admin/src/translations/vi.json + + + + + admin/src/translations/ar.json + + + admin/src/translations/cs.json + + + admin/src/translations/de.json + + + admin/src/translations/en.json + + + admin/src/translations/es.json + + + admin/src/translations/fr.json + + + admin/src/translations/id.json + + + admin/src/translations/it.json + + + admin/src/translations/ko.json + + + admin/src/translations/ms.json + + + admin/src/translations/nl.json + + + admin/src/translations/pl.json + + + admin/src/translations/pt-BR.json + + + admin/src/translations/pt.json + + + admin/src/translations/ru.json + + + admin/src/translations/sk.json + + + admin/src/translations/th.json + + + admin/src/translations/tr.json + + + admin/src/translations/uk.json + + + admin/src/translations/vi.json + + + + true + + '%1' + + + + + fr-FR + + tab + json + true + + diff --git a/api/expotoken/config/routes.json b/api/expotoken/config/routes.json deleted file mode 100644 index 53d200b..0000000 --- a/api/expotoken/config/routes.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "routes": [ - { - "method": "GET", - "path": "/expotokens", - "handler": "Expotoken.find", - "config": { - "policies": [] - } - }, - { - "method": "GET", - "path": "/expotokens/send", - "handler": "Expotoken.send", - "config": { - "policies": [] - } - }, - { - "method": "GET", - "path": "/expotokens/count", - "handler": "Expotoken.count", - "config": { - "policies": [] - } - }, - { - "method": "GET", - "path": "/expotokens/:id", - "handler": "Expotoken.findOne", - "config": { - "policies": [] - } - }, - { - "method": "POST", - "path": "/expotokens", - "handler": "Expotoken.create", - "config": { - "policies": [] - } - }, - { - "method": "PUT", - "path": "/expotokens/:id", - "handler": "Expotoken.update", - "config": { - "policies": [] - } - }, - { - "method": "DELETE", - "path": "/expotokens/:id", - "handler": "Expotoken.delete", - "config": { - "policies": [] - } - } - ] -} diff --git a/api/expotoken/controllers/Expotoken.js b/api/expotoken/controllers/Expotoken.js deleted file mode 100644 index 5781eeb..0000000 --- a/api/expotoken/controllers/Expotoken.js +++ /dev/null @@ -1,36 +0,0 @@ -'use strict'; - -/** - * Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/controllers.html#core-controllers) - * to customize this controller - */ - -module.exports = { - - create: async ctx => { - /** - * Check if token already exist - */ - const results = await strapi.services.expotoken.find({token: ctx.request.body.token}); - - if (results.length) { - return await ctx.response.conflict('Token already exist'); - } else { - /** - * Token doesn't exist, well... we add it ! - */ - return await strapi.services.expotoken.create(ctx.request.body); - } - }, - - send: async (ctx, params) => { - /** - * params = { - * customer - * title - * body - * } - */ - return await strapi.plugins.automation.controllers.expo.send(ctx, params); - } -}; diff --git a/api/expotoken/services/Expotoken.js b/api/expotoken/services/Expotoken.js deleted file mode 100644 index 8564ba3..0000000 --- a/api/expotoken/services/Expotoken.js +++ /dev/null @@ -1,8 +0,0 @@ -'use strict'; - -/** - * Read the documentation (https://strapi.io/documentation/3.0.0-beta.x/guides/services.html#core-services) - * to customize this service - */ - -module.exports = {}; diff --git a/config/functions/cron.js b/config/functions/cron.js new file mode 100644 index 0000000..20be7cb --- /dev/null +++ b/config/functions/cron.js @@ -0,0 +1,11 @@ +'use strict'; + +module.exports = { + /** + * Check every 10 minutes pending expo notifications + */ + + '*/10 * * * *': () => { + strapi.plugins['notification-expo'].services.expo.sendPendingNotification(); + }, +}; diff --git a/config/policies/isAdmin.js b/config/policies/isAdmin.js new file mode 100644 index 0000000..6e2903b --- /dev/null +++ b/config/policies/isAdmin.js @@ -0,0 +1,17 @@ +'use strict'; + +module.exports = async (ctx, next) => { + if (!ctx.state.user) { + ctx.unauthorized('Access refused : Please be logged in.'); + } + + if (ctx.state.user.roles) { + for (let i = 0; ctx.state.user.roles[i]; i++) { + if (ctx.state.user.roles[i].code === 'strapi-super-admin') { + return await next(); + } + } + } + + return ctx.unauthorized('Access refused : You are not and administrator.'); +}; diff --git a/config/policies/isLogged.js b/config/policies/isLogged.js new file mode 100644 index 0000000..8578af7 --- /dev/null +++ b/config/policies/isLogged.js @@ -0,0 +1,8 @@ +'use strict'; + +module.exports = async (ctx, next) => { + if (!ctx.state.user) { + ctx.unauthorized('Access refused : Please be logged in.'); + } + return await next(); +}; diff --git a/config/routes.json b/config/routes.json new file mode 100644 index 0000000..f82394e --- /dev/null +++ b/config/routes.json @@ -0,0 +1,108 @@ +{ + "routes": [ + { + "method": "POST", + "path": "/expo/send", + "handler": "expo.send", + "config": { + "policies": [] + } + }, + { + "method": "GET", + "path": "/expo/sendPendingNotification", + "handler": "expo.sendPendingNotification", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "GET", + "path": "/expotokens", + "handler": "expotoken.find", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "GET", + "path": "/expotokens/count", + "handler": "expotoken.count", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "GET", + "path": "/expotokens/:id", + "handler": "expotoken.findOne", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "POST", + "path": "/expotokens", + "handler": "Expotoken.create", + "config": { + "policies": ["isLogged"] + } + }, + { + "method": "DELETE", + "path": "/expotokens/:id", + "handler": "expotoken.delete", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "GET", + "path": "/exponotifications", + "handler": "exponotification.find", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "GET", + "path": "/exponotifications/count", + "handler": "exponotification.count", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "GET", + "path": "/exponotifications/:id", + "handler": "exponotification.findOne", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "PUT", + "path": "/exponotifications/:id", + "handler": "exponotification.update", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "POST", + "path": "/exponotifications", + "handler": "exponotification.create", + "config": { + "policies": ["isAdmin"] + } + }, + { + "method": "DELETE", + "path": "/exponotifications/:id", + "handler": "exponotification.delete", + "config": { + "policies": ["isAdmin"] + } + } + ] +} diff --git a/controllers/expo.js b/controllers/expo.js new file mode 100644 index 0000000..bada42b --- /dev/null +++ b/controllers/expo.js @@ -0,0 +1,21 @@ +'use strict'; + +module.exports = { + /** + * Send direct expo notification from an other api controllers/services + * + * @returns {Promise<*>} + */ + + async send(ctx, params) { + return strapi.plugins['notification-expo'].services.expo.send(ctx, params); + }, + + /** + * Send pending notification (use for test or execute manually the cron task) + * @returns {Promise<*|void>} + */ + async sendPendingNotification() { + return strapi.plugins['notification-expo'].services.expo.sendPendingNotification(); + }, +}; diff --git a/controllers/exponotification.js b/controllers/exponotification.js new file mode 100644 index 0000000..c7367f8 --- /dev/null +++ b/controllers/exponotification.js @@ -0,0 +1,121 @@ +'use strict'; + +const _ = require('lodash'); +const { parseMultipartData, sanitizeEntity } = require('strapi-utils'); + +module.exports = { + /** + * Retrieve records. + * + * @return {Object|Array} + */ + + async find(ctx) { + const method = _.has(ctx.query, '_q') ? 'searchPage' : 'findPage'; + + const { results, pagination } = await strapi.plugins[ + 'notification-expo' + ].services.exponotification[method](ctx.query); + + ctx.body = { + data: { + results: results.map((entity) => + sanitizeEntity(entity, { + model: strapi.plugins['notification-expo'].models.exponotification, + }) + ), + pagination, + }, + }; + }, + + /** + * Retrieve a record. + * + * @return {Object} + */ + + async findOne(ctx) { + const { id } = ctx.params; + + const entity = await strapi.plugins['notification-expo'].services.exponotification.findOne({ + id, + }); + return sanitizeEntity(entity, { + model: strapi.plugins['notification-expo'].models.exponotification, + }); + }, + + /** + * Count records. + * + * @return {Number} + */ + + count(ctx) { + if (ctx.query._q) { + return strapi.plugins['notification-expo'].services.exponotification.countSearch(ctx.query); + } + return strapi.plugins['notification-expo'].services.exponotification.count(ctx.query); + }, + + /** + * Create a record + * + * @param ctx + * @return {Object} + */ + + async create(ctx) { + let entity; + + if (ctx.is('multipart')) { + const { data, files } = parseMultipartData(ctx); + entity = await strapi.plugins['notification-expo'].services.exponotification.create(data, { + files, + }); + } else { + entity = await strapi.plugins['notification-expo'].services.exponotification.create( + ctx.request.body + ); + } + return sanitizeEntity(entity, { + model: strapi.plugins['notification-expo'].models.exponotification, + }); + }, + + /** + * Update a record. + * + * @return {Object} + */ + + async update(ctx) { + const { id } = ctx.params; + + const entity = await strapi.plugins['notification-expo'].services.exponotification.update( + { id }, + ctx.request.body + ); + return sanitizeEntity(entity, { + model: strapi.plugins['notification-expo'].models.exponotification, + }); + }, + + /** + * Destroy a record. + * + * @return {Object} + */ + + async delete(ctx) { + const { id } = ctx.params; + + const entity = await strapi.plugins['notification-expo'].services.exponotification.delete({ + id, + }); + return sanitizeEntity(entity, { + model: strapi.plugins['notification-expo'].models.exponotification, + }); + }, +}; diff --git a/controllers/expotoken.js b/controllers/expotoken.js new file mode 100644 index 0000000..e5a464f --- /dev/null +++ b/controllers/expotoken.js @@ -0,0 +1,110 @@ +'use strict'; + +const { sanitizeEntity } = require('strapi-utils'); + +module.exports = { + /** + * Retrieve records. + * + * @return {Object|Array} + */ + + async find(ctx) { + let entities; + if (ctx.query._q) { + entities = await strapi.plugins['notification-expo'].services.expotoken.search(ctx.query); + } else { + entities = await strapi.plugins['notification-expo'].services.expotoken.find(ctx.query); + } + + return entities.map((entity) => + sanitizeEntity(entity, { model: strapi.plugins['notification-expo'].models.expotoken }) + ); + }, + + /** + * Retrieve a record. + * + * @return {Object} + */ + + async findOne(ctx) { + const { id } = ctx.params; + + const entity = await strapi.plugins['notification-expo'].services.expotoken.findOne({ id }); + return sanitizeEntity(entity, { model: strapi.plugins['notification-expo'].models.expotoken }); + }, + + /** + * Count records. + * + * @return {Number} + */ + + async count(ctx) { + if (ctx.query._q) { + return strapi.plugins['notification-expo'].services.expotoken.countSearch(ctx.query); + } + return strapi.plugins['notification-expo'].services.expotoken.count(ctx.query); + }, + + /** + * Create a new expo tokens entry for logged customer + * @param ctx + * @returns {Promise<*>} + */ + async create(ctx) { + let entity; + + /** + * Check if token already exist + */ + const results = await strapi.plugins['notification-expo'].services.expotoken.find({ + token: ctx.request.body.token, + }); + + if (results.length) { + return await ctx.response.conflict('Token already exist'); + } else { + /** + * Token doesn't exist, well... we add it ! + */ + entity = await strapi.plugins['notification-expo'].services.expotoken.create({ + ...ctx.request.body, + user: ctx.state.user.id, + }); + } + return sanitizeEntity(entity, { model: strapi.plugins['notification-expo'].models.expotoken }); + }, + + /** + * Update a record. + * + * @return {Object} + */ + + async update(ctx) { + const { id } = ctx.params; + + let entity; + entity = await strapi.plugins['notification-expo'].services.expotoken.update( + { id }, + ctx.request.body + ); + + return sanitizeEntity(entity, { model: strapi.plugins['notification-expo'].models.expotoken }); + }, + + /** + * Destroy a record. + * + * @return {Object} + */ + + async delete(ctx) { + const { id } = ctx.params; + + const entity = await strapi.plugins['notification-expo'].services.expotoken.delete({ id }); + return sanitizeEntity(entity, { model: strapi.plugins['notification-expo'].models.expotoken }); + }, +}; diff --git a/middlewares/expoCron/index.js b/middlewares/expoCron/index.js new file mode 100644 index 0000000..2a88605 --- /dev/null +++ b/middlewares/expoCron/index.js @@ -0,0 +1,44 @@ +'use strict'; + +const _ = require('lodash'); +const cron = require('node-schedule'); + +module.exports = (strapi) => { + return { + initialize() { + const scheduleTask = (taskExpression, taskValue) => { + // tricks for end of object with __filename__ + if (taskExpression === '__filename__') return; + + if (_.isFunction(taskValue)) { + return cron.scheduleJob(taskExpression, taskValue); + } + + const options = _.get(taskValue, 'options', {}); + + cron.scheduleJob( + { + rule: taskExpression, + ...options, + }, + taskValue.task + ); + }; + + _.forEach(_.keys(strapi.plugins), (pluginName) => { + if ( + strapi.plugins[pluginName].config && + strapi.plugins[pluginName].config.functions && + strapi.plugins[pluginName].config.functions.cron + ) { + const pluginCron = strapi.plugins[pluginName].config.functions.cron; + if (pluginCron) { + _.forEach(_.entries(pluginCron), ([taskExpression, taskValue]) => { + scheduleTask(taskExpression, taskValue); + }); + } + } + }); + }, + }; +}; diff --git a/models/exponotification.js b/models/exponotification.js new file mode 100644 index 0000000..4901821 --- /dev/null +++ b/models/exponotification.js @@ -0,0 +1,44 @@ +'use strict'; + +/** + * Lifecycle callbacks for the `Exponotification` model. + */ + +module.exports = { + // Before saving a value. + // Fired before an `insert` or `update` query. + // beforeSave: async (model, attrs, options) => {}, + // After saving a value. + // Fired after an `insert` or `update` query. + // afterSave: async (model, response, options) => {}, + // Before fetching a value. + // Fired before a `fetch` operation. + // beforeFetch: async (model, columns, options) => {}, + // After fetching a value. + // Fired after a `fetch` operation. + // afterFetch: async (model, response, options) => {}, + // Before fetching all values. + // Fired before a `fetchAll` operation. + // beforeFetchAll: async (model, columns, options) => {}, + // After fetching all values. + // Fired after a `fetchAll` operation. + // afterFetchAll: async (model, response, options) => {}, + // Before creating a value. + // Fired before an `insert` query. + // beforeCreate: async (model, attrs, options) => {}, + // After creating a value. + // Fired after an `insert` query. + // afterCreate: async (model, attrs, options) => {}, + // Before updating a value. + // Fired before an `update` query. + // beforeUpdate: async (model, attrs, options) => {}, + // After updating a value. + // Fired after an `update` query. + // afterUpdate: async (model, attrs, options) => {}, + // Before destroying a value. + // Fired before a `delete` query. + // beforeDestroy: async (model, attrs, options) => {}, + // After destroying a value. + // Fired after a `delete` query. + // afterDestroy: async (model, attrs, options) => {} +}; diff --git a/models/exponotification.settings.json b/models/exponotification.settings.json new file mode 100644 index 0000000..17ac7ca --- /dev/null +++ b/models/exponotification.settings.json @@ -0,0 +1,66 @@ +{ + "kind": "collectionType", + "connection": "default", + "collectionName": "exponotifications", + "info": { + "name": "exponotification", + "description": "" + }, + "options": { + "increments": true, + "timestamps": [ + "created_at", + "updated_at" + ], + "comment": "", + "draftAndPublish": true + }, + "attributes": { + "title": { + "type": "string", + "required": true, + "maxLength": 40 + }, + "body": { + "type": "string", + "required": true, + "maxLength": 178 + }, + "data": { + "type": "json" + }, + "data_url": { + "type": "string" + }, + "platform": { + "type": "enumeration", + "enum": [ + "all", + "android", + "ios" + ], + "default": "all", + "required": true + }, + "status": { + "type": "enumeration", + "enum": [ + "pending", + "waiting", + "finished", + "canceled", + "failed" + ], + "default": "pending", + "required": true + }, + "total": { + "type": "integer", + "default": "0" + }, + "users": { + "collection": "user", + "plugin": "users-permissions" + } + } +} diff --git a/api/expotoken/models/Expotoken.js b/models/expotoken.js similarity index 99% rename from api/expotoken/models/Expotoken.js rename to models/expotoken.js index 157160c..a1ae0e4 100644 --- a/api/expotoken/models/Expotoken.js +++ b/models/expotoken.js @@ -8,47 +8,36 @@ module.exports = { // Before saving a value. // Fired before an `insert` or `update` query. // beforeSave: async (model, attrs, options) => {}, - // After saving a value. // Fired after an `insert` or `update` query. // afterSave: async (model, response, options) => {}, - // Before fetching a value. // Fired before a `fetch` operation. // beforeFetch: async (model, columns, options) => {}, - // After fetching a value. // Fired after a `fetch` operation. // afterFetch: async (model, response, options) => {}, - // Before fetching all values. // Fired before a `fetchAll` operation. // beforeFetchAll: async (model, columns, options) => {}, - // After fetching all values. // Fired after a `fetchAll` operation. // afterFetchAll: async (model, response, options) => {}, - // Before creating a value. // Fired before an `insert` query. // beforeCreate: async (model, attrs, options) => {}, - // After creating a value. // Fired after an `insert` query. // afterCreate: async (model, attrs, options) => {}, - // Before updating a value. // Fired before an `update` query. // beforeUpdate: async (model, attrs, options) => {}, - // After updating a value. // Fired after an `update` query. // afterUpdate: async (model, attrs, options) => {}, - // Before destroying a value. // Fired before a `delete` query. // beforeDestroy: async (model, attrs, options) => {}, - // After destroying a value. // Fired after a `delete` query. // afterDestroy: async (model, attrs, options) => {} diff --git a/api/expotoken/models/Expotoken.settings.json b/models/expotoken.settings.json similarity index 65% rename from api/expotoken/models/Expotoken.settings.json rename to models/expotoken.settings.json index 2be8657..1b7cf13 100644 --- a/api/expotoken/models/Expotoken.settings.json +++ b/models/expotoken.settings.json @@ -12,7 +12,8 @@ "created_at", "updated_at" ], - "comment": "" + "comment": "", + "draftAndPublish": false }, "attributes": { "token": { @@ -20,10 +21,17 @@ "required": true, "unique": true }, - "customer": { - "via": "expotokens", + "platform": { + "type": "enumeration", + "enum": [ + "android", + "ios" + ] + }, + "user": { "plugin": "users-permissions", - "model": "user" + "model": "user", + "via": "expotokens" } } } diff --git a/package.json b/package.json new file mode 100644 index 0000000..3093455 --- /dev/null +++ b/package.json @@ -0,0 +1,62 @@ +{ + "name": "strapi-plugin-notification-expo", + "version": "1.0.0-beta.1", + "description": "(Non-official) Expo notification for Strapi", + "keywords": [ + "strapi", + "plugin", + "notification", + "expo" + ], + "strapi": { + "name": "Notification", + "icon": "bell", + "description": "(Non-official) Expo notification for Strapi" + }, + "scripts": { + "lint": "eslint .", + "coverage": "nyc npm run test" + }, + "author": { + "name": "Vanessa Pasque", + "email": "lith@amykron.com" + }, + "maintainers": [ + { + "name": "Vanessa Pasque", + "email": "lith@amykron.com" + } + ], + "dependencies": { + "dayjs": "^1.10.4", + "expo-server-sdk": "3.6.0", + "lodash": "^4.17.20", + "node-schedule": "^2.0.0", + "strapi-utils": "^3.5.0" + }, + "engines": { + "node": ">=10.16.0 <=14.x.x", + "npm": ">=6.0.0" + }, + "homepage": "https://github.com/Lith/strapi-plugin-notification-expo#readme", + "license": "MIT", + "devDependencies": { + "babel-eslint": "^10.1.0", + "codecov": "^3.8.1", + "eslint": "^7.20.0", + "eslint-config-airbnb": "^18.2.1", + "eslint-config-airbnb-base": "^14.2.1", + "eslint-config-prettier": "^7.2.0", + "eslint-plugin-import": "^2.22.1", + "eslint-plugin-jsx-a11y": "^6.4.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.3.1", + "eslint-plugin-promise": "^4.3.1", + "eslint-plugin-react": "^7.22.0", + "eslint-plugin-react-hooks": "^4.2.0", + "eslint-plugin-redux-saga": "^1.2.1", + "nyc": "^15.1.0", + "prettier": "^2.2.1", + "redux-saga": "^1.1.3" + } +} diff --git a/plugins/notification/config/routes.json b/plugins/notification/config/routes.json deleted file mode 100644 index 63e4138..0000000 --- a/plugins/notification/config/routes.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "routes": [ - { - "method": "POST", - "path": "/expo/send", - "handler": "Expo.send", - "config": { - "policies": [] - } - } - ] -} diff --git a/plugins/notification/controllers/Expo.js b/plugins/notification/controllers/Expo.js deleted file mode 100644 index 6abb7e2..0000000 --- a/plugins/notification/controllers/Expo.js +++ /dev/null @@ -1,11 +0,0 @@ -'use strict'; - -module.exports = { - - /** - * Send expo notification - */ - send: async (ctx, params) => { - return strapi.plugins.automation.services.expo.send(ctx, params); - } -}; diff --git a/plugins/notification/package.json b/plugins/notification/package.json deleted file mode 100644 index 3c8762e..0000000 --- a/plugins/notification/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "strapi-plugin-notification", - "version": "1.0.0", - "description": "This is the description of the plugin.", - "strapi": { - "name": "notification", - "icon": "bell", - "description": "Description of notification plugin." - }, - "dependencies": {}, - "author": { - "name": "Vanessa Pasque", - "email": "lith@amykron.com", - "url": "" - }, - "maintainers": [ - { - "name": "Vanessa Pasque", - "email": "lith@amykron.com", - "url": "" - } - ], - "dependencies": { - "expo-server-sdk": "3.6.0" - }, - "engines": { - "node": "^10.0.0", - "npm": ">= 6.0.0" - }, - "license": "MIT" -} diff --git a/plugins/notification/services/Expo.js b/plugins/notification/services/Expo.js deleted file mode 100644 index 69f562a..0000000 --- a/plugins/notification/services/Expo.js +++ /dev/null @@ -1,85 +0,0 @@ -'use strict'; - -/** - * Expo.js service - * - * @description: A set of functions similar to controller's actions to avoid code duplication. - */ - -const {Expo} = require('expo-server-sdk'); - -module.exports = { - - send: async (ctx, params) => { - - let expo = new Expo(); - - // @infos - change this part by your own user table - const pushTokens = await strapi.services.expotoken.find({user_id: params.id}); - - let messages = []; - for (let pushToken of pushTokens) { - if (!Expo.isExpoPushToken(pushToken.token)) { - strapi.log.fatal('[EXPO][ERROR] ' + `Push token ${pushToken.token} is not a valid Expo push token`); - continue; - } - - messages.push({ - to: pushToken.token, - title: params.title, - body: params.body, - data: params.data, - priority: 'high', - //channelId: params.channelId ? params.channelId : 'default' - }); - } - - if (!messages.length) { - return; - } - - let chunks = expo.chunkPushNotifications(messages); - let tickets = []; - (async () => { - for (let chunk of chunks) { - try { - let ticketChunk = await expo.sendPushNotificationsAsync(chunk); - tickets.push(...ticketChunk); - } catch (error) { - strapi.log.fatal('[EXPO][ERROR] ' + error); - } - } - })(); - - /** - * Todo - manage receipts - */ - let receiptIds = []; - for (let ticket of tickets) { - if (ticket.id) { - receiptIds.push(ticket.id); - } - } - - let receiptIdChunks = expo.chunkPushNotificationReceiptIds(receiptIds); - (async () => { - for (let chunk of receiptIdChunks) { - try { - let receipts = await expo.getPushNotificationReceiptsAsync(chunk); - - for (let receipt of receipts) { - if (receipt.status === 'error') { - strapi.log.fatal(`There was an error sending a notification: ${receipt.message}`); - if (receipt.details && receipt.details.error) { - strapi.log.fatal(`The error code is ${receipt.details.error}`); - } - } - } - } catch (error) { - strapi.log.fatal('[EXPO][ERROR] ' + error); - } - } - })(); - } - -}; diff --git a/services/expo.js b/services/expo.js new file mode 100644 index 0000000..2a0b34a --- /dev/null +++ b/services/expo.js @@ -0,0 +1,86 @@ +'use strict'; + +/** + * expo.js service + * + * @description: A set of functions similar to controller's actions to avoid code duplication. + */ + +const _ = require('lodash'); +const notificationMessage = require('./utils/notificationMessage'); + +module.exports = { + /** + * Method used for send notification to specific users from api controllers & services + * Never use this method with Strapi ADMIN + * + * @returns {Promise} + */ + + async send(ctx, params) { + // @todo - manage expo_access_token + // let expo = new Expo({ accessToken: process.env.EXPO_ACCESS_TOKEN }); + + const pushTokens = await strapi.plugins['notification-expo'].services.expotoken.find({ + user: params.id, + }); + await notificationMessage.send(ctx, params, pushTokens); + }, + + /** + * Send expo notification + * @param notification + * @returns {Promise} + */ + + async sendNotification(params) { + let expotokens = []; + + if (params.users && params.users.length) { + const users = params.users.map((user) => user.id); + expotokens = await strapi + .query('expotoken', 'notification-expo') + .find({ user_in: users }, []); + } + + if (!expotokens || !expotokens.length) return; + + await strapi + .query('exponotification', 'notification-expo') + .update({ id: params.id }, { status: 'waiting' }); + const state = await notificationMessage.send( + params, + expotokens.map((item) => item.token) + ); + if (state) { + await strapi + .query('exponotification', 'notification-expo') + .update({ id: params.id }, { status: 'finished' }); + } else { + await strapi + .query('exponotification', 'notification-expo') + .update({ id: params.id }, { status: 'failed' }); + } + }, + + /** + * Send pending notification + * @returns {Promise} + */ + + sendPendingNotification: async () => { + const params = { + status: 'pending', + total_gt: 0, + published_at_lte: new Date(), + }; + + const notifications = await strapi + .query('exponotification', 'notification-expo') + .find(params, ['users']); + + _.forEach(notifications, async (notification) => { + await strapi.plugins['notification-expo'].services.expo.sendNotification(notification); + }); + }, +}; diff --git a/services/exponotification.js b/services/exponotification.js new file mode 100644 index 0000000..d8f848e --- /dev/null +++ b/services/exponotification.js @@ -0,0 +1,139 @@ +'use strict'; + +const { contentTypes: contentTypesUtils } = require('strapi-utils'); +const usersByPlatform = require('./utils/usersByPlatform'); + +module.exports = { + /** + * Promise to fetch all records + * + * @return {Promise} + */ + + find(params, populate) { + return strapi.query('exponotification', 'notification-expo').find(params, populate); + }, + + /** + * Find many records (paginated) + * + * @returns {Promise} + */ + + async findPage(params) { + return strapi.query('exponotification', 'notification-expo').findPage(params); + }, + + /** + * Promise to fetch record + * + * @return {Promise} + */ + + findOne(params, populate) { + // Select field to populate. + return strapi.query('exponotification', 'notification-expo').findOne(params, populate); + }, + + /** + * Promise to count record + * + * @return {Promise} + */ + + count: (params) => { + return strapi.query('exponotification', 'notification-expo').count(params); + }, + + /** + * Promise to add a/an notification. + * + * @return {Promise} + */ + + async create(data) { + const isDraft = contentTypesUtils.isDraft( + data, + strapi.plugins['notification-expo'].models.exponotification + ); + + const validData = await strapi.entityValidator.validateEntityCreation( + strapi.plugins['notification-expo'].models.exponotification, + data, + { isDraft } + ); + + const users = await usersByPlatform.get(data); + return strapi + .query('exponotification', 'notification-expo') + .create({ ...validData, users, total: users.length }); + }, + + /** + * Promise to edit record + * + * @return {Promise} + */ + + async update(params, data) { + const existingEntry = await strapi + .query('exponotification', 'notification-expo') + .findOne(params); + + const isDraft = contentTypesUtils.isDraft( + existingEntry, + strapi.plugins['notification-expo'].models.exponotification + ); + + const validData = await strapi.entityValidator.validateEntityUpdate( + strapi.plugins['notification-expo'].models.exponotification, + data, + { isDraft } + ); + + const users = await usersByPlatform.get(data); + return strapi + .query('exponotification', 'notification-expo') + .update(params, { ...validData, users, total: users.length }); + }, + + /** + * Promise to delete a record + * + * @return {Promise} + */ + + delete(params) { + return strapi.query('exponotification', 'notification-expo').delete(params); + }, + + /** + * Promise to search records + * + * @return {Promise} + */ + + search(params) { + return strapi.query('exponotification', 'notification-expo').search(params); + }, + + /** + * Search many records (paginated) + * + * @returns {Promise} + */ + + async searchPage(params) { + return strapi.query('exponotification', 'notification-expo').searchPage(params); + }, + + /** + * Promise to count searched records + * + * @return {Promise} + */ + + countSearch(params) { + return strapi.query('exponotification', 'notification-expo').countSearch(params); + }, +}; diff --git a/services/expotoken.js b/services/expotoken.js new file mode 100644 index 0000000..cd89c97 --- /dev/null +++ b/services/expotoken.js @@ -0,0 +1,99 @@ +'use strict'; + +const { isDraft } = require('strapi-utils').contentTypes; + +module.exports = { + /** + * Promise to fetch all records + * + * @return {Promise} + */ + + find(params, populate) { + return strapi.query('expotoken', 'notification-expo').find(params, populate); + }, + + /** + * Promise to fetch record + * + * @return {Promise} + */ + + findOne(params, populate) { + // Select field to populate. + return strapi.query('expotoken', 'notification-expo').findOne(params, populate); + }, + + /** + * Promise to count record + * + * @return {Promise} + */ + + count: (params) => { + return strapi.query('expotoken', 'notification-expo').count(params); + }, + + /** + * Promise to add record + * + * @return {Promise} + */ + async create(data) { + const validData = await strapi.entityValidator.validateEntityCreation( + strapi.plugins['notification-expo'].models.expotoken, + data, + { isDraft } + ); + + return strapi.query('expotoken', 'notification-expo').create(validData); + }, + + /** + * Promise to edit record + * + * @return {Promise} + */ + async update(params, data) { + const existingEntry = await strapi.query('expotoken', 'notification-expo').findOne(params); + + const isDraft = isDraft(existingEntry, strapi.plugins['notification-expo'].models.expotoken); + const validData = await strapi.entityValidator.validateEntityUpdate( + strapi.plugins['notification-expo'].models.expotoken, + data, + { isDraft } + ); + + return strapi.query('expotoken', 'notification-expo').update(params, validData); + }, + + /** + * Promise to delete a record + * + * @return {Promise} + */ + + delete(params) { + return strapi.query('expotoken', 'notification-expo').delete(params); + }, + + /** + * Promise to search records + * + * @return {Promise} + */ + + search(params) { + return strapi.query('expotoken', 'notification-expo').search(params); + }, + + /** + * Promise to count expo token + * + * @return {Promise} + */ + + countSearch(params) { + return strapi.query('expotoken', 'notification-expo').countSearch(params); + }, +}; diff --git a/services/utils/notificationMessage.js b/services/utils/notificationMessage.js new file mode 100644 index 0000000..5a3fad9 --- /dev/null +++ b/services/utils/notificationMessage.js @@ -0,0 +1,73 @@ +'use strict'; + +const { Expo } = require('expo-server-sdk'); + +module.exports = { + async send(params, pushTokens) { + const expo = new Expo(); + const messages = []; + + pushTokens.map((pushToken) => { + if (!Expo.isExpoPushToken(pushToken)) { + strapi.log.fatal( + '[EXPO][ERROR] ' + `Push token ${pushToken} is not a valid Expo push token` + ); + return false; + } + + messages.push({ + to: pushToken, + sound: 'default', + title: params.title, + body: params.body, + data: params.data ? params.data : params.data_url ? { url: params.data_url } : {}, + }); + }); + + if (!messages.length) { + return false; + } + + const chunks = expo.chunkPushNotifications(messages); + const tickets = []; + await (async () => { + chunks.map(async (chunk) => { + try { + const ticketChunk = await expo.sendPushNotificationsAsync(chunk); + tickets.push(...ticketChunk); + } catch (error) { + strapi.log.fatal('[EXPO][ERROR] ' + error); + } + }); + })(); + + const receiptIds = []; + tickets.map((ticket) => { + if (ticket.id) { + receiptIds.push(ticket.id); + } + }); + + const receiptIdChunks = expo.chunkPushNotificationReceiptIds(receiptIds); + await (async () => { + receiptIdChunks.map(async (chunk) => { + try { + const receipts = await expo.getPushNotificationReceiptsAsync(chunk); + + receipts.map((receipt) => { + if (receipt.status === 'error') { + strapi.log.fatal(`There was an error sending a notification: ${receipt.message}`); + if (receipt.details && receipt.details.error) { + strapi.log.fatal(`The error code is ${receipt.details.error}`); + } + } + }); + } catch (error) { + strapi.log.fatal('[EXPO][ERROR] ' + error); + } + }); + + return true; + })(); + }, +}; diff --git a/services/utils/usersByPlatform.js b/services/utils/usersByPlatform.js new file mode 100644 index 0000000..2dcf081 --- /dev/null +++ b/services/utils/usersByPlatform.js @@ -0,0 +1,33 @@ +'use strict'; + +module.exports = { + async get(data) { + /** + * Retrieve all users by platform selected + */ + const { platform } = data; + const users = []; + await strapi + .query('expotoken', 'notification-expo') + .model.query((qb) => { + if (platform === 'ios' || platform === 'android') { + qb.select('user').where('platform', platform); + } else { + qb.select('user'); + } + }) + .fetchAll({ + withRelated: [], + }) + .then((response) => { + response.toJSON().map((item) => { + users.push(item.user); + }); + }) + .catch((e) => { + strapi.log.fatal(e); + }); + + return users; + }, +}; diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..80d1351 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,2610 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" + integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw== + dependencies: + "@babel/highlight" "^7.10.4" + +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" + integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== + dependencies: + "@babel/highlight" "^7.12.13" + +"@babel/core@^7.7.5": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.12.16.tgz#8c6ba456b23b680a6493ddcfcd9d3c3ad51cab7c" + integrity sha512-t/hHIB504wWceOeaOoONOhu+gX+hpjfeN6YRBT209X/4sibZQfSF1I0HFRRlBe97UZZosGx5XwUg1ZgNbelmNw== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.12.15" + "@babel/helper-module-transforms" "^7.12.13" + "@babel/helpers" "^7.12.13" + "@babel/parser" "^7.12.16" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.12.13" + "@babel/types" "^7.12.13" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.2" + lodash "^4.17.19" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.12.13", "@babel/generator@^7.12.15": + version "7.12.15" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.12.15.tgz#4617b5d0b25cc572474cc1aafee1edeaf9b5368f" + integrity sha512-6F2xHxBiFXWNSGb7vyCUTBF8RCLY66rS0zEPcP8t/nQyXjha5EuK4z7H5o7fWG8B4M7y6mqVWq1J+1PuwRhecQ== + dependencies: + "@babel/types" "^7.12.13" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-function-name@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" + integrity sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA== + dependencies: + "@babel/helper-get-function-arity" "^7.12.13" + "@babel/template" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/helper-get-function-arity@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" + integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-member-expression-to-functions@^7.12.13": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.12.16.tgz#41e0916b99f8d5f43da4f05d85f4930fa3d62b22" + integrity sha512-zYoZC1uvebBFmj1wFAlXwt35JLEgecefATtKp20xalwEK8vHAixLBXTGxNrVGEmTT+gzOThUgr8UEdgtalc1BQ== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-module-imports@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.12.13.tgz#ec67e4404f41750463e455cc3203f6a32e93fcb0" + integrity sha512-NGmfvRp9Rqxy0uHSSVP+SRIW1q31a7Ji10cLBcqSDUngGentY4FRiHOFZFE1CLU5eiL0oE8reH7Tg1y99TDM/g== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-module-transforms@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.12.13.tgz#01afb052dcad2044289b7b20beb3fa8bd0265bea" + integrity sha512-acKF7EjqOR67ASIlDTupwkKM1eUisNAjaSduo5Cz+793ikfnpe7p4Q7B7EWU2PCoSTPWsQkR7hRUWEIZPiVLGA== + dependencies: + "@babel/helper-module-imports" "^7.12.13" + "@babel/helper-replace-supers" "^7.12.13" + "@babel/helper-simple-access" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/helper-validator-identifier" "^7.12.11" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.12.13" + "@babel/types" "^7.12.13" + lodash "^4.17.19" + +"@babel/helper-optimise-call-expression@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" + integrity sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-replace-supers@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.12.13.tgz#00ec4fb6862546bd3d0aff9aac56074277173121" + integrity sha512-pctAOIAMVStI2TMLhozPKbf5yTEXc0OJa0eENheb4w09SrgOWEs+P4nTOZYJQCqs8JlErGLDPDJTiGIp3ygbLg== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.12.13" + "@babel/helper-optimise-call-expression" "^7.12.13" + "@babel/traverse" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/helper-simple-access@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.12.13.tgz#8478bcc5cacf6aa1672b251c1d2dde5ccd61a6c4" + integrity sha512-0ski5dyYIHEfwpWGx5GPWhH35j342JaflmCeQmsPWcrOQDtCN6C1zKAVRFVbK53lPW2c9TsuLLSUDf0tIGJ5hA== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-split-export-declaration@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" + integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + +"@babel/helpers@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.12.13.tgz#3c75e993632e4dadc0274eae219c73eb7645ba47" + integrity sha512-oohVzLRZ3GQEk4Cjhfs9YkJA4TdIDTObdBEZGrd6F/T0GPSnuV6l22eMcxlvcvzVIPH3VTtxbseudM1zIE+rPQ== + dependencies: + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/highlight@^7.10.4", "@babel/highlight@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.12.13.tgz#8ab538393e00370b26271b01fa08f7f27f2e795c" + integrity sha512-kocDQvIbgMKlWxXe9fof3TQ+gkIPOUSEYhJjqUjvKMez3krV7vbzYCDq39Oj11UAVK7JqPVGQPlgE85dPNlQww== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.12.13", "@babel/parser@^7.12.16", "@babel/parser@^7.7.0": + version "7.12.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.16.tgz#cc31257419d2c3189d394081635703f549fc1ed4" + integrity sha512-c/+u9cqV6F0+4Hpq01jnJO+GLp2DdT63ppz9Xa+6cHaajM9VFzK/iDXiKK65YtpeVwu+ctfS6iqlMqRgQRzeCw== + +"@babel/runtime-corejs3@^7.10.2": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.12.13.tgz#53d09813b7c20d616caf258e9325550ff701c039" + integrity sha512-8fSpqYRETHATtNitsCXq8QQbKJP31/KnDl2Wz2Vtui9nKzjss2ysuZtyVsWjBtvkeEFo346gkwjYPab1hvrXkQ== + dependencies: + core-js-pure "^3.0.0" + regenerator-runtime "^0.13.4" + +"@babel/runtime@^7.10.2", "@babel/runtime@^7.10.5", "@babel/runtime@^7.11.2", "@babel/runtime@^7.6.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.13.tgz#0a21452352b02542db0ffb928ac2d3ca7cb6d66d" + integrity sha512-8+3UMPBrjFa/6TtKi/7sehPKqfAm4g6K+YQjyyFOLUTxzOngcRZTlAVY8sc2CORJYqdHQY8gRPHmn+qo15rCBw== + dependencies: + regenerator-runtime "^0.13.4" + +"@babel/template@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" + integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/parser" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/traverse@^7.12.13", "@babel/traverse@^7.7.0": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.13.tgz#689f0e4b4c08587ad26622832632735fb8c4e0c0" + integrity sha512-3Zb4w7eE/OslI0fTp8c7b286/cQps3+vdLW3UcwC8VSJC6GbKn55aeVVu2QJNuCDoeKyptLOFrPq8WqZZBodyA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.12.13" + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.12.13" + "@babel/types" "^7.12.13" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + +"@babel/types@^7.12.13", "@babel/types@^7.7.0": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.12.13.tgz#8be1aa8f2c876da11a9cf650c0ecf656913ad611" + integrity sha512-oKrdZTld2im1z8bDwTOQvUbxKwE+854zc16qWZQlcTqMN00pWxHQ4ZeOq0yDMnisOpRykH2/5Qqcrk/OlbAjiQ== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + lodash "^4.17.19" + to-fast-properties "^2.0.0" + +"@eslint/eslintrc@^0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.3.0.tgz#d736d6963d7003b6514e6324bec9c602ac340318" + integrity sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.20" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@redux-saga/core@^1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@redux-saga/core/-/core-1.1.3.tgz#3085097b57a4ea8db5528d58673f20ce0950f6a4" + integrity sha512-8tInBftak8TPzE6X13ABmEtRJGjtK17w7VUs7qV17S8hCO5S3+aUTWZ/DBsBJPdE8Z5jOPwYALyvofgq1Ws+kg== + dependencies: + "@babel/runtime" "^7.6.3" + "@redux-saga/deferred" "^1.1.2" + "@redux-saga/delay-p" "^1.1.2" + "@redux-saga/is" "^1.1.2" + "@redux-saga/symbols" "^1.1.2" + "@redux-saga/types" "^1.1.0" + redux "^4.0.4" + typescript-tuple "^2.2.1" + +"@redux-saga/deferred@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@redux-saga/deferred/-/deferred-1.1.2.tgz#59937a0eba71fff289f1310233bc518117a71888" + integrity sha512-908rDLHFN2UUzt2jb4uOzj6afpjgJe3MjICaUNO3bvkV/kN/cNeI9PMr8BsFXB/MR8WTAZQq/PlTq8Kww3TBSQ== + +"@redux-saga/delay-p@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@redux-saga/delay-p/-/delay-p-1.1.2.tgz#8f515f4b009b05b02a37a7c3d0ca9ddc157bb355" + integrity sha512-ojc+1IoC6OP65Ts5+ZHbEYdrohmIw1j9P7HS9MOJezqMYtCDgpkoqB5enAAZrNtnbSL6gVCWPHaoaTY5KeO0/g== + dependencies: + "@redux-saga/symbols" "^1.1.2" + +"@redux-saga/is@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@redux-saga/is/-/is-1.1.2.tgz#ae6c8421f58fcba80faf7cadb7d65b303b97e58e" + integrity sha512-OLbunKVsCVNTKEf2cH4TYyNbbPgvmZ52iaxBD4I1fTif4+MTXMa4/Z07L83zW/hTCXwpSZvXogqMqLfex2Tg6w== + dependencies: + "@redux-saga/symbols" "^1.1.2" + "@redux-saga/types" "^1.1.0" + +"@redux-saga/symbols@^1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@redux-saga/symbols/-/symbols-1.1.2.tgz#216a672a487fc256872b8034835afc22a2d0595d" + integrity sha512-EfdGnF423glv3uMwLsGAtE6bg+R9MdqlHEzExnfagXPrIiuxwr3bdiAwz3gi+PsrQ3yBlaBpfGLtDG8rf3LgQQ== + +"@redux-saga/types@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@redux-saga/types/-/types-1.1.0.tgz#0e81ce56b4883b4b2a3001ebe1ab298b84237204" + integrity sha512-afmTuJrylUU/0OtqzaRkbyYFFNgCF73Bvel/sw90pvGrWIZ+vyoIJqA6eMSoA6+nb443kTmulmBtC9NerXboNg== + +"@sindresorhus/slugify@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/slugify/-/slugify-1.1.0.tgz#2f195365d9b953384305b62664b44b4036c49430" + integrity sha512-ujZRbmmizX26yS/HnB3P9QNlNa4+UvHh+rIse3RbOXLp8yl6n1TxB4t7NHggtVgS8QmmOtzXo48kCxZGACpkPw== + dependencies: + "@sindresorhus/transliterate" "^0.1.1" + escape-string-regexp "^4.0.0" + +"@sindresorhus/transliterate@^0.1.1": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@sindresorhus/transliterate/-/transliterate-0.1.1.tgz#779b31244781d3c898f185b61d58c89e7c782674" + integrity sha512-QSdIQ5keUFAZ3KLbfbsntW39ox0Ym8183RqTwBq/ZEFoN3NQAtGV+qWaNdzKpIDHgj9J2CQ2iNDRVU11Zyr7MQ== + dependencies: + escape-string-regexp "^2.0.0" + lodash.deburr "^4.1.0" + +"@tootallnate/once@1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" + integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= + +acorn-jsx@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +agent-base@5: + version "5.1.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-5.1.1.tgz#e8fb3f242959db44d63be665db7a8e739537a32c" + integrity sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g== + +agent-base@6: + version "6.0.2" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== + dependencies: + debug "4" + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ajv@^7.0.2: + version "7.1.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-7.1.0.tgz#f982ea7933dc7f1012eae9eec5a86687d805421b" + integrity sha512-svS9uILze/cXbH0z2myCK2Brqprx/+JJYK5pHicT/GQiBfzzhUVAIT6MwqJg8y4xV/zoGsUeuPuwtoiKSGE15g== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== + dependencies: + default-require-extensions "^3.0.0" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argv@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/argv/-/argv-0.0.2.tgz#ecbd16f8949b157183711b1bda334f37840185ab" + integrity sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas= + +aria-query@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-4.2.2.tgz#0d2ca6c9aceb56b8977e9fed6aed7e15bbd2f83b" + integrity sha512-o/HelwhuKpTj/frsOsbNLNgnNGVIFsVP/SW2BSF14gVl7kAfMOJ6/8wUAUvG1R1NHKrfG+2sHZTu0yauT1qBrA== + dependencies: + "@babel/runtime" "^7.10.2" + "@babel/runtime-corejs3" "^7.10.2" + +array-includes@^3.1.1, array-includes@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.2.tgz#a8db03e0b88c8c6aeddc49cb132f9bcab4ebf9c8" + integrity sha512-w2GspexNQpx+PutG3QpT437/BenZBj0M/MZGn5mzv/MofYqo0xmRHzn4lFsoDlWJ+THYsGJmFlW68WlDFx7VRw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + get-intrinsic "^1.0.1" + is-string "^1.0.5" + +array.prototype.flat@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz#6ef638b43312bd401b4c6199fdec7e2dc9e9a123" + integrity sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + +array.prototype.flatmap@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz#94cfd47cc1556ec0747d97f7c7738c58122004c9" + integrity sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + function-bind "^1.1.1" + +ast-types-flow@^0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" + integrity sha1-9wtzXGvKGlycItmCw+Oef+ujva0= + +astral-regex@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" + integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== + +axe-core@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.1.2.tgz#7cf783331320098bfbef620df3b3c770147bc224" + integrity sha512-V+Nq70NxKhYt89ArVcaNL9FDryB3vQOd+BFXZIfO3RP6rwtj+2yqqqdHEkacutglPaZLkJeuXKCjCJDMGPtPqg== + +axobject-query@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.2.0.tgz#943d47e10c0b704aa42275e20edf3722648989be" + integrity sha512-Td525n+iPOOyUQIeBfcASuG6uJsDOITl7Mds5gFyerkWiX7qhUTdYUBlSgNMyVqtSJqwpt1kXGLdUt6SykLMRA== + +babel-eslint@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" + integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.7.0" + "@babel/traverse" "^7.7.0" + "@babel/types" "^7.7.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== + dependencies: + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +chalk@^2.0.0, chalk@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +codecov@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/codecov/-/codecov-3.8.1.tgz#06fe026b75525ed1ce864d4a34f1010c52c51546" + integrity sha512-Qm7ltx1pzLPsliZY81jyaQ80dcNR4/JpcX0IHCIWrHBXgseySqbdbYfkdiXd7o/xmzQpGRVCKGYeTrHUpn6Dcw== + dependencies: + argv "0.0.2" + ignore-walk "3.0.3" + js-yaml "3.14.0" + teeny-request "6.0.1" + urlgrey "0.4.4" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +confusing-browser-globals@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59" + integrity sha512-gNld/3lySHwuhaVluJUKLePYirM3QNCKzVxqAdhJII9/WXKVX5PURzMVJspS1jTslSqjeuG4KMVTSouit5YPHA== + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +core-js-pure@^3.0.0: + version "3.8.3" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.8.3.tgz#10e9e3b2592ecaede4283e8f3ad7020811587c02" + integrity sha512-V5qQZVAr9K0xu7jXg1M7qTEwuxUgqr7dUOezGaNa7i+Xn9oXAU/d1fzqD9ObuwpVQOaorO5s70ckyi1woP9lVA== + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cron-parser@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cron-parser/-/cron-parser-3.1.0.tgz#665ef742315443a6c54ada278cd795f2d75869b5" + integrity sha512-4Spe1gRbiQza3BqklhB/8dMi8PZAWalhLK1p+k3iYJjcxIK6t4YYGL0lKdHT0e743jDTJEDBz1NEAzY88kyNWQ== + dependencies: + is-nan "^1.3.0" + luxon "^1.25.0" + +cross-spawn@^7.0.0, cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +damerau-levenshtein@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz#143c1641cb3d85c60c32329e26899adea8701791" + integrity sha512-JVrozIeElnj3QzfUIt8tB8YMluBJom4Vw9qTPpjGYQ9fYlB3D/rb6OordUxf3xeFB35LKWs0xqcO5U6ySvBtug== + +date-fns@^2.8.1: + version "2.17.0" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.17.0.tgz#afa55daea539239db0a64e236ce716ef3d681ba1" + integrity sha512-ZEhqxUtEZeGgg9eHNSOAJ8O9xqSgiJdrL0lzSSfMF54x6KXWJiOH/xntSJ9YomJPrYH/p08t6gWjGWq1SDJlSA== + +dayjs@^1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" + integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw== + +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + +debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +deep-is@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +default-require-extensions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== + dependencies: + strip-bom "^4.0.0" + +define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.0.0: + version "9.2.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.1.tgz#c9b25604256bb3428964bead3ab63069d736f7ee" + integrity sha512-117l1H6U4X3Krn+MrzYrL57d5H7siRHWraBs7s+LjRuFK7Fe7hJqnJ0skWlinqsycVLU5YAo6L8CsEYQ0V5prg== + +end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.18.0-next.1: + version "1.18.0-next.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.2.tgz#088101a55f0541f595e7e057199e27ddc8f3a5c2" + integrity sha512-Ih4ZMFHEtZupnUh6497zEL4y2+w8+1ljnCyaTa+adcoafI1GOvMwFlDjBLfWR7y9VLfrjRJe9ocuHY1PSR9jjw== + dependencies: + call-bind "^1.0.2" + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.1" + is-regex "^1.1.1" + object-inspect "^1.9.0" + object-keys "^1.1.1" + object.assign "^4.1.2" + string.prototype.trimend "^1.0.3" + string.prototype.trimstart "^1.0.3" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-airbnb-base@^14.2.1: + version "14.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e" + integrity sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA== + dependencies: + confusing-browser-globals "^1.0.10" + object.assign "^4.1.2" + object.entries "^1.1.2" + +eslint-config-airbnb@^18.2.1: + version "18.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.2.1.tgz#b7fe2b42f9f8173e825b73c8014b592e449c98d9" + integrity sha512-glZNDEZ36VdlZWoxn/bUR1r/sdFKPd1mHPbqUtkctgNG4yT2DLLtJ3D+yCV+jzZCc2V1nBVkmdknOJBZ5Hc0fg== + dependencies: + eslint-config-airbnb-base "^14.2.1" + object.assign "^4.1.2" + object.entries "^1.1.2" + +eslint-config-prettier@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-7.2.0.tgz#f4a4bd2832e810e8cc7c1411ec85b3e85c0c53f9" + integrity sha512-rV4Qu0C3nfJKPOAhFujFxB7RMP+URFyQqqOZW9DMRD7ZDTFyjaIlETU3xzHELt++4ugC0+Jm084HQYkkJe+Ivg== + +eslint-import-resolver-node@^0.3.4: + version "0.3.4" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717" + integrity sha512-ogtf+5AB/O+nM6DIeBUNr2fuT7ot9Qg/1harBfBtaP13ekEWFQEEMP94BCB7zaNW3gyY+8SHYF00rnqYwXKWOA== + dependencies: + debug "^2.6.9" + resolve "^1.13.1" + +eslint-module-utils@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz#579ebd094f56af7797d19c9866c9c9486629bfa6" + integrity sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA== + dependencies: + debug "^2.6.9" + pkg-dir "^2.0.0" + +eslint-plugin-es@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + +eslint-plugin-import@^2.22.1: + version "2.22.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702" + integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw== + dependencies: + array-includes "^3.1.1" + array.prototype.flat "^1.2.3" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.4" + eslint-module-utils "^2.6.0" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.1" + read-pkg-up "^2.0.0" + resolve "^1.17.0" + tsconfig-paths "^3.9.0" + +eslint-plugin-jsx-a11y@^6.4.1: + version "6.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.4.1.tgz#a2d84caa49756942f42f1ffab9002436391718fd" + integrity sha512-0rGPJBbwHoGNPU73/QCLP/vveMlM1b1Z9PponxO87jfr6tuH5ligXbDT6nHSSzBC8ovX2Z+BQu7Bk5D/Xgq9zg== + dependencies: + "@babel/runtime" "^7.11.2" + aria-query "^4.2.2" + array-includes "^3.1.1" + ast-types-flow "^0.0.7" + axe-core "^4.0.2" + axobject-query "^2.2.0" + damerau-levenshtein "^1.0.6" + emoji-regex "^9.0.0" + has "^1.0.3" + jsx-ast-utils "^3.1.0" + language-tags "^1.0.5" + +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-prettier@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.3.1.tgz#7079cfa2497078905011e6f82e8dd8453d1371b7" + integrity sha512-Rq3jkcFY8RYeQLgk2cCwuc0P7SEFwDravPhsJZOQ5N4YI4DSg50NyqJ/9gdZHzQlHf8MvafSesbNJCcP/FF6pQ== + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-plugin-promise@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.3.1.tgz#61485df2a359e03149fdafc0a68b0e030ad2ac45" + integrity sha512-bY2sGqyptzFBDLh/GMbAxfdJC+b0f23ME63FOE4+Jao0oZ3E1LEwFtWJX/1pGMJLiTtrSSern2CRM/g+dfc0eQ== + +eslint-plugin-react-hooks@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.2.0.tgz#8c229c268d468956334c943bb45fc860280f5556" + integrity sha512-623WEiZJqxR7VdxFCKLI6d6LLpwJkGPYKODnkH3D7WpOG5KM8yWueBd8TLsNAetEJNF5iJmolaAKO3F8yzyVBQ== + +eslint-plugin-react@^7.22.0: + version "7.22.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.22.0.tgz#3d1c542d1d3169c45421c1215d9470e341707269" + integrity sha512-p30tuX3VS+NWv9nQot9xIGAHBXR0+xJVaZriEsHoJrASGCJZDJ8JLNM0YqKqI0AKm6Uxaa1VUHoNEibxRCMQHA== + dependencies: + array-includes "^3.1.1" + array.prototype.flatmap "^1.2.3" + doctrine "^2.1.0" + has "^1.0.3" + jsx-ast-utils "^2.4.1 || ^3.0.0" + object.entries "^1.1.2" + object.fromentries "^2.0.2" + object.values "^1.1.1" + prop-types "^15.7.2" + resolve "^1.18.1" + string.prototype.matchall "^4.0.2" + +eslint-plugin-redux-saga@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-redux-saga/-/eslint-plugin-redux-saga-1.2.1.tgz#fbfe7ca6bd3771a0e11639d9b7474b7b25ed5375" + integrity sha512-3ZifHQ3N07bopp7MlpID4JxnDwCazcaPMHFP9l2TDEfSUtvr0U41xtb/e0wWlgxPgrs5cmztHWhLXn8HEPkb5Q== + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.20.0: + version "7.20.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.20.0.tgz#db07c4ca4eda2e2316e7aa57ac7fc91ec550bdc7" + integrity sha512-qGi0CTcOGP2OtCQBgWZlQjcTuP0XkIpYFj25XtRTQSHC+umNnp7UMshr2G8SLsRFYDdAPFeHOsiteadmMH02Yw== + dependencies: + "@babel/code-frame" "7.12.11" + "@eslint/eslintrc" "^0.3.0" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.1" + esquery "^1.4.0" + esutils "^2.0.2" + file-entry-cache "^6.0.0" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.20" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^6.0.4" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0, espree@^7.3.1: + version "7.3.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6" + integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.3.1" + eslint-visitor-keys "^1.3.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +expo-server-sdk@3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/expo-server-sdk/-/expo-server-sdk-3.6.0.tgz#b13e5e77f622d11009bdd533df857b08225a4d00" + integrity sha512-GyA0BTcFBKk/5gTEO4WOScP9hEttR+GitrcOIl7XwXwE1FHFvbluKiUc9yEjsfEYMgyd78+XhSpGVGQnutGOdA== + dependencies: + node-fetch "^2.6.0" + promise-limit "^2.7.0" + +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== + +fast-json-parse@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/fast-json-parse/-/fast-json-parse-1.0.3.tgz#43e5c61ee4efa9265633046b770fb682a7577c4d" + integrity sha512-FRWsaZRWEJ1ESVNbDWmsAlqDk96gPQezzLghafp5J4GUKjbCz3OkAHuZs5TuPEtkbVQERysLp9xv6c24fBm8Aw== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +fast-safe-stringify@^1.0.8, fast-safe-stringify@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-1.2.3.tgz#9fe22c37fb2f7f86f06b8f004377dbf8f1ee7bc1" + integrity sha512-QJYT/i0QYoiZBQ71ivxdyTqkwKkQ0oxACXHYxH2zYHJEgzi2LsbjgvtzTbLi1SZcF190Db2YP7I7eTsU2egOlw== + +file-entry-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.0.tgz#7921a89c391c6d93efec2169ac6bf300c527ea0a" + integrity sha512-fqoO76jZ3ZnYrXLDRxBR1YvOvc0k844kcOg40bgsPrE25LAb/PDqTY+ho64Xh2c8ZXgIKldchCFHczG2UVRcWA== + dependencies: + flat-cache "^3.0.4" + +find-cache-dir@^3.2.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880" + integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatstr@^1.0.5: + version "1.0.12" + resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" + integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== + +flatted@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469" + integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA== + +fn-name@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/fn-name/-/fn-name-3.0.0.tgz#0596707f635929634d791f452309ab41558e3c5c" + integrity sha512-eNMNr5exLoavuAMhIUVsOKF79SWd/zG104ef6sxBTSw+cZc6BXdQXDvYcGvp0VbxVVSp1XDUNoz7mg1xMtSznA== + +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^3.0.2" + +fromentries@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" + integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gensync@^1.0.0-beta.1: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.1, get-intrinsic@^1.0.2, get-intrinsic@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +glob-parent@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + +graceful-fs@^4.1.15, graceful-fs@^4.1.2: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hasha@^5.0.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + +hosted-git-info@^2.1.4: + version "2.8.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +http-proxy-agent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" + integrity sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg== + dependencies: + "@tootallnate/once" "1" + agent-base "6" + debug "4" + +https-proxy-agent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-4.0.0.tgz#702b71fb5520a132a66de1f67541d9e62154d82b" + integrity sha512-zoDhWrkR3of1l9QAL8/scJZyLu8j/gBkcwcaQOZh7Gyh/+uJQzGVETdgT30akuwkpL8HTRfssqI3BZuV18teDg== + dependencies: + agent-base "5" + debug "4" + +ignore-walk@3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + dependencies: + minimatch "^3.0.4" + +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.1: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" + integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== + dependencies: + get-intrinsic "^1.1.0" + has "^1.0.3" + side-channel "^1.0.4" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.3.tgz#8b1e0500b73a1d76c70487636f368e519de8db8e" + integrity sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ== + +is-core-module@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== + dependencies: + has "^1.0.3" + +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-nan@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-nan/-/is-nan-1.3.2.tgz#043a54adea31748b55b6cd4e09aadafa69bd9e1d" + integrity sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +is-negative-zero@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" + integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== + +is-regex@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.2.tgz#81c8ebde4db142f2cf1c53fc86d6a45788266251" + integrity sha512-axvdhb5pdhEVThqJzYXwMlVuZwC+FF2DpcOhTS+y/8jVq4trxyPgfcwIxIKiyeuLlSQYKkmUaPQJ8ZE4yNKXDg== + dependencies: + call-bind "^1.0.2" + has-symbols "^1.0.1" + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-string@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.5.tgz#40493ed198ef3ff477b8c7f92f644ec82a5cd3a6" + integrity sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ== + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.0.0-alpha.1: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" + +istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-processinfo@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz#e1426514662244b2f25df728e8fd1ba35fe53b9c" + integrity sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw== + dependencies: + archy "^1.0.0" + cross-spawn "^7.0.0" + istanbul-lib-coverage "^3.0.0-alpha.1" + make-dir "^3.0.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^3.3.3" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@3.14.0: + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + +"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz#41108d2cec408c3453c1bbe8a4aae9e1e2bd8f82" + integrity sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q== + dependencies: + array-includes "^3.1.2" + object.assign "^4.1.2" + +language-subtag-registry@~0.3.2: + version "0.3.21" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.21.tgz#04ac218bea46f04cb039084602c6da9e788dd45a" + integrity sha512-L0IqwlIXjilBVVYKFT37X9Ih11Um5NEl9cbJIuU/SwP/zEEAbBPOnEeeuxVMf45ydWQRDQN3Nqc96OgbH1K+Pg== + +language-tags@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.5.tgz#d321dbc4da30ba8bf3024e040fa5c14661f9193a" + integrity sha1-0yHbxNowuovzAk4ED6XBRmH5GTo= + dependencies: + language-subtag-registry "~0.3.2" + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash-es@^4.17.11: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.20.tgz#29f6332eefc60e849f869c264bc71126ad61e8f7" + integrity sha512-JD1COMZsq8maT6mnuz1UMV0jvYD0E0aUsSOdrr1/nAG3dhqQXwRRgeW0cSqH1U43INKcqxaiVIQNOUDld7gRDA== + +lodash.deburr@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/lodash.deburr/-/lodash.deburr-4.1.0.tgz#ddb1bbb3ef07458c0177ba07de14422cb033ff9b" + integrity sha1-3bG7s+8HRYwBd7oH3hRCLLAz/5s= + +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI= + +lodash@4.17.20, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + +long-timeout@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/long-timeout/-/long-timeout-0.1.1.tgz#9721d788b47e0bcb5a24c2e2bee1a0da55dab514" + integrity sha1-lyHXiLR+C8taJMLivuGg2lXatRQ= + +loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +luxon@^1.25.0: + version "1.26.0" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-1.26.0.tgz#d3692361fda51473948252061d0f8561df02b578" + integrity sha512-+V5QIQ5f6CDXQpWNICELwjwuHdqeJM1UenlZWx5ujcRMc9venvluCjFb4t5NYLhb6IhkbMVOxzVuOqkgMxee2A== + +make-dir@^3.0.0, make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +node-fetch@^2.2.0, node-fetch@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + +node-preload@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" + +node-schedule@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/node-schedule/-/node-schedule-2.0.0.tgz#73ab4957d056c63708409cc1fab676e0e149c191" + integrity sha512-cHc9KEcfiuXxYDU+HjsBVo2FkWL1jRAUoczFoMIzRBpOA4p/NRHuuLs85AWOLgKsHtSPjN8csvwIxc2SqMv+CQ== + dependencies: + cron-parser "^3.1.0" + long-timeout "0.1.1" + sorted-array-functions "^1.3.0" + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +nyc@^15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" + integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== + dependencies: + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^2.0.0" + get-package-type "^0.1.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + make-dir "^3.0.0" + node-preload "^0.2.1" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + yargs "^15.0.2" + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-inspect@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a" + integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw== + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" + integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + has-symbols "^1.0.1" + object-keys "^1.1.1" + +object.entries@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.3.tgz#c601c7f168b62374541a07ddbd3e2d5e4f7711a6" + integrity sha512-ym7h7OZebNS96hn5IJeyUmaWhaSM4SVtAPPfNLQEI2MYWCO2egsITb9nab2+i/Pwibx+R0mtn+ltKJXRSeTMGg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has "^1.0.3" + +object.fromentries@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.3.tgz#13cefcffa702dc67750314a3305e8cb3fad1d072" + integrity sha512-IDUSMXs6LOSJBWE++L0lzIbSqHl9KDCfff2x/JSEIDtEUavUnyMYC2ZGay/04Zq4UT8lvd4xNhU4/YHKibAOlw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has "^1.0.3" + +object.values@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.2.tgz#7a2015e06fcb0f546bd652486ce8583a4731c731" + integrity sha512-MYC0jvJopr8EK6dPBiO8Nb9mvjdypOachO5REGk6MXzujbBrAisKo3HmdEI6kZDL6fC31Mwee/5YbtMebixeag== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has "^1.0.3" + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pino-std-serializers@^2.0.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/pino-std-serializers/-/pino-std-serializers-2.5.0.tgz#40ead781c65a0ce7ecd9c1c33f409d31fe712315" + integrity sha512-wXqbqSrIhE58TdrxxlfLwU9eDhrzppQDvGhBEr1gYbzzM4KKo3Y63gSjiDXRKLVS2UOXdPNR2v+KnQgNrs+xUg== + +pino@^4.7.1: + version "4.17.6" + resolved "https://registry.yarnpkg.com/pino/-/pino-4.17.6.tgz#8c237f3a29f4104f89321c25037deab6a7998fb4" + integrity sha512-LFDwmhyWLBnmwO/2UFbWu1jEGVDzaPupaVdx0XcZ3tIAx1EDEBauzxXf2S0UcFK7oe+X9MApjH0hx9U1XMgfCA== + dependencies: + chalk "^2.4.1" + fast-json-parse "^1.0.3" + fast-safe-stringify "^1.2.3" + flatstr "^1.0.5" + pino-std-serializers "^2.0.0" + pump "^3.0.0" + quick-format-unescaped "^1.1.2" + split2 "^2.2.0" + +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pluralize@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1" + integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA== + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== + dependencies: + fast-diff "^1.1.2" + +prettier@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5" + integrity sha512-PqyhM2yCjg/oKkFPtTGUojv7gnZAoG80ttl45O6x2Ug/rMJw4wcc9k6aaf2hibP7BGVCCM33gZoGjyvt9mm16Q== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process-on-spawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== + dependencies: + fromentries "^1.2.0" + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise-limit@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/promise-limit/-/promise-limit-2.7.0.tgz#eb5737c33342a030eaeaecea9b3d3a93cb592b26" + integrity sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw== + +prop-types@^15.7.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + +property-expr@^2.0.2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.4.tgz#37b925478e58965031bb612ec5b3260f8241e910" + integrity sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg== + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +quick-format-unescaped@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-1.1.2.tgz#0ca581de3174becef25ac3c2e8956342381db698" + integrity sha1-DKWB3jF0vs7yWsPC6JVjQjgdtpg= + dependencies: + fast-safe-stringify "^1.0.8" + +react-is@^16.8.1: + version "16.13.1" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" + integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +redux-saga@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/redux-saga/-/redux-saga-1.1.3.tgz#9f3e6aebd3c994bbc0f6901a625f9a42b51d1112" + integrity sha512-RkSn/z0mwaSa5/xH/hQLo8gNf4tlvT18qXDNvedihLcfzh+jMchDgaariQoehCpgRltEm4zHKJyINEz6aqswTw== + dependencies: + "@redux-saga/core" "^1.1.3" + +redux@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/redux/-/redux-4.0.5.tgz#4db5de5816e17891de8a80c424232d06f051d93f" + integrity sha512-VSz1uMAH24DM6MF72vcojpYPtrTUu3ByVWfPL1nPfVRb5mZVTve5GnNCUV53QM/BZ66xfWrm0CTWoM+Xlz8V1w== + dependencies: + loose-envify "^1.4.0" + symbol-observable "^1.2.0" + +regenerator-runtime@^0.13.4: + version "0.13.7" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" + integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== + +regexp.prototype.flags@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" + integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.3" + +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA= + dependencies: + es6-error "^4.0.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.18.1: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + +rimraf@^3.0.0, rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +"semver@2 || 3 || 4 || 5", semver@^5.4.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, semver@^6.1.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^7.2.1: + version "7.3.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" + integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== + dependencies: + lru-cache "^6.0.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.3, side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== + +slice-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-4.0.0.tgz#500e8dd0fd55b05815086255b3195adf2a45fe6b" + integrity sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ== + dependencies: + ansi-styles "^4.0.0" + astral-regex "^2.0.0" + is-fullwidth-code-point "^3.0.0" + +sorted-array-functions@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/sorted-array-functions/-/sorted-array-functions-1.3.0.tgz#8605695563294dffb2c9796d602bd8459f7a0dd5" + integrity sha512-2sqgzeFlid6N4Z2fUQ1cvFmTOLRi/sEDzSQ0OKYchqgoPmQBVyM3959qYx3fpS6Esef80KjmpgPeEr028dP3OA== + +source-map@^0.5.0: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== + dependencies: + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + which "^2.0.1" + +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65" + integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ== + +split2@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" + integrity sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw== + dependencies: + through2 "^2.0.2" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +strapi-utils@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/strapi-utils/-/strapi-utils-3.5.0.tgz#7711b4adc2a6fd62449c0d3767d0429f840395ce" + integrity sha512-gTFeMizT1vAFuncRkP6T1eBGXx5xvfyACyILKrmI2an3K+dCRuGmpVKR7OP6cLsjT3IjW0GjDYs2roAvOBr+mw== + dependencies: + "@sindresorhus/slugify" "1.1.0" + date-fns "^2.8.1" + lodash "4.17.20" + pino "^4.7.1" + pluralize "^8.0.0" + yup "0.29.3" + +stream-events@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" + integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== + dependencies: + stubs "^3.0.0" + +string-width@^4.1.0, string-width@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.matchall@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.3.tgz#24243399bc31b0a49d19e2b74171a15653ec996a" + integrity sha512-OBxYDA2ifZQ2e13cP82dWFMaCV9CGF8GzmN4fljBVw5O5wep0lu4gacm1OL6MjROoUnB8VbkWRThqkV2YFLNxw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + es-abstract "^1.18.0-next.1" + has-symbols "^1.0.1" + internal-slot "^1.0.2" + regexp.prototype.flags "^1.3.0" + side-channel "^1.0.3" + +string.prototype.trimend@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.3.tgz#a22bd53cca5c7cf44d7c9d5c732118873d6cd18b" + integrity sha512-ayH0pB+uf0U28CtjlLvL7NaohvR1amUvVZk+y3DYb0Ey2PUV5zPkkKy9+U1ndVEIXO8hNg18eIv9Jntbii+dKw== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +string.prototype.trimstart@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.3.tgz#9b4cb590e123bb36564401d59824298de50fd5aa" + integrity sha512-oBIBUy5lea5tt0ovtOFiEQaBkoBBkyJhZXzJYrSmDo5IUUqbOPvVezuRs/agBIdZ2p2Eo1FD6bD9USyBLfl3xg== + dependencies: + call-bind "^1.0.0" + define-properties "^1.1.3" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +stubs@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/stubs/-/stubs-3.0.0.tgz#e8d2ba1fa9c90570303c030b6900f7d5f89abe5b" + integrity sha1-6NK6H6nJBXAwPAMLaQD31fiavls= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +symbol-observable@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" + integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== + +synchronous-promise@^2.0.13: + version "2.0.15" + resolved "https://registry.yarnpkg.com/synchronous-promise/-/synchronous-promise-2.0.15.tgz#07ca1822b9de0001f5ff73595f3d08c4f720eb8e" + integrity sha512-k8uzYIkIVwmT+TcglpdN50pS2y1BDcUnBPK9iJeGu0Pl1lOI8pD6wtzgw91Pjpe+RxtTncw32tLxs/R0yNL2Mg== + +table@^6.0.4: + version "6.0.7" + resolved "https://registry.yarnpkg.com/table/-/table-6.0.7.tgz#e45897ffbcc1bcf9e8a87bf420f2c9e5a7a52a34" + integrity sha512-rxZevLGTUzWna/qBLObOe16kB2RTnnbhciwgPbMMlazz1yZGVEgnZK762xyVdVznhqxrfCeBMmMkgOOaPwjH7g== + dependencies: + ajv "^7.0.2" + lodash "^4.17.20" + slice-ansi "^4.0.0" + string-width "^4.2.0" + +teeny-request@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-6.0.1.tgz#9b1f512cef152945827ba7e34f62523a4ce2c5b0" + integrity sha512-TAK0c9a00ELOqLrZ49cFxvPVogMUFaWY8dUsQc/0CuQPGF+BOxOQzXfE413BAk2kLomwNplvdtMpeaeGWmoc2g== + dependencies: + http-proxy-agent "^4.0.0" + https-proxy-agent "^4.0.0" + node-fetch "^2.2.0" + stream-events "^1.0.5" + uuid "^3.3.2" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through2@^2.0.2: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +toposort@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330" + integrity sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= + +tsconfig-paths@^3.9.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.9.0.tgz#098547a6c4448807e8fcb8eae081064ee9a3c90b" + integrity sha512-dRcuzokWhajtZWkQsDVKbWyY+jgcLC5sqJhg2PSgf4ZkH2aHPvaOY8YWGhmjb68b5qqTfasSsDO9k7RUiEmZAw== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.1" + minimist "^1.2.0" + strip-bom "^3.0.0" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.8.0, type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript-compare@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/typescript-compare/-/typescript-compare-0.0.2.tgz#7ee40a400a406c2ea0a7e551efd3309021d5f425" + integrity sha512-8ja4j7pMHkfLJQO2/8tut7ub+J3Lw2S3061eJLFQcvs3tsmJKp8KG5NtpLn7KcY2w08edF74BSVN7qJS0U6oHA== + dependencies: + typescript-logic "^0.0.0" + +typescript-logic@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/typescript-logic/-/typescript-logic-0.0.0.tgz#66ebd82a2548f2b444a43667bec120b496890196" + integrity sha512-zXFars5LUkI3zP492ls0VskH3TtdeHCqu0i7/duGt60i5IGPIpAHE/DWo5FqJ6EjQ15YKXrt+AETjv60Dat34Q== + +typescript-tuple@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/typescript-tuple/-/typescript-tuple-2.2.1.tgz#7d9813fb4b355f69ac55032e0363e8bb0f04dad2" + integrity sha512-Zcr0lbt8z5ZdEzERHAMAniTiIKerFCMgd7yjq1fPnDJ43et/k9twIFQMUYff9k5oXcsQ0WpvFcgzK2ZKASoW6Q== + dependencies: + typescript-compare "^0.0.2" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +urlgrey@0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/urlgrey/-/urlgrey-0.4.4.tgz#892fe95960805e85519f1cd4389f2cb4cbb7652f" + integrity sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8= + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +uuid@^3.3.2, uuid@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +v8-compile-cache@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" + integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" + integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^15.0.2: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yup@0.29.3: + version "0.29.3" + resolved "https://registry.yarnpkg.com/yup/-/yup-0.29.3.tgz#69a30fd3f1c19f5d9e31b1cf1c2b851ce8045fea" + integrity sha512-RNUGiZ/sQ37CkhzKFoedkeMfJM0vNQyaz+wRZJzxdKE7VfDeVKH8bb4rr7XhRLbHJz5hSjoDNwMEIaKhuMZ8gQ== + dependencies: + "@babel/runtime" "^7.10.5" + fn-name "~3.0.0" + lodash "^4.17.15" + lodash-es "^4.17.11" + property-expr "^2.0.2" + synchronous-promise "^2.0.13" + toposort "^2.0.2"